Auction metadata: - Listing model gains buying_format + ends_at fields - Migration 002 adds columns to existing databases - scraper.py: parse s-item__time-left → absolute ends_at ISO timestamp - normaliser.py: extract buyingOptions + itemEndDate from Browse API - store.py: save/get updated for new fields Easter eggs (app/ui/components/easter_eggs.py): - Konami code detector (JS → URL param → Streamlit rerun) - Web Audio API snipe call synthesis, gated behind sidebar checkbox (disabled by default for safety/accessibility) - "The Steal" gold shimmer: trust ≥ 90, price 15–30% below market, no suspicious_price flag - Auction de-emphasis: soft caption when > 1h remaining UI updates: - listing_row: steal banner + auction notice per row - Search: inject CSS, check snipe mode, "Ending soon" sort option, pass market_price from comp cache to row renderer - app.py: Konami detector + audio enable/disable sidebar toggle Tests: 22 new tests (72 total, all green)
30 lines
735 B
Python
30 lines
735 B
Python
"""Streamlit entrypoint."""
|
|
from pathlib import Path
|
|
import streamlit as st
|
|
from app.wizard import SnipeSetupWizard
|
|
|
|
st.set_page_config(
|
|
page_title="Snipe",
|
|
page_icon="🎯",
|
|
layout="wide",
|
|
initial_sidebar_state="expanded",
|
|
)
|
|
|
|
wizard = SnipeSetupWizard(env_path=Path(".env"))
|
|
if not wizard.is_configured():
|
|
wizard.run()
|
|
st.stop()
|
|
|
|
from app.ui.components.easter_eggs import inject_konami_detector
|
|
inject_konami_detector()
|
|
|
|
with st.sidebar:
|
|
st.divider()
|
|
audio_enabled = st.checkbox(
|
|
"🔊 Enable audio easter egg",
|
|
value=False,
|
|
help="Plays a synthesised sound on Konami code activation. Off by default.",
|
|
)
|
|
|
|
from app.ui.Search import render
|
|
render(audio_enabled=audio_enabled)
|