host pro, добавил в телеграмм сообщение о статусе запросов раз в 5 минут
This commit is contained in:
120
get_data.py
120
get_data.py
@@ -354,6 +354,11 @@ def results_consumer():
|
||||
game["data"]["result"]["game"]["fullScore"] = payload["result"][
|
||||
"fullScore"
|
||||
]
|
||||
game["data"]["result"]["game"]["score"] = payload["result"][
|
||||
"teams"
|
||||
][0]["total"]["points"] + ":" + payload["result"][
|
||||
"teams"
|
||||
][1]["total"]["points"]
|
||||
for team in game["data"]["result"]["teams"]:
|
||||
if team["teamNumber"] != 0:
|
||||
box_team = [
|
||||
@@ -579,6 +584,112 @@ def extract_game_datetime(game_item: dict) -> datetime | None:
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def build_pretty_status_message():
|
||||
"""
|
||||
Собирает одно красивое сообщение про текущее состояние онлайна.
|
||||
Если game ещё нет — шлём хотя бы статусы источников.
|
||||
"""
|
||||
lines = []
|
||||
lines.append(f"🏀 <b>{LEAGUE.upper()}</b> • {TEAM}")
|
||||
lines.append(f"📌 Game ID: <code>{GAME_ID}</code>")
|
||||
lines.append(f"🕒 {datetime.now().strftime('%d.%m.%Y %H:%M:%S')}")
|
||||
|
||||
# сначала попробуем собрать нормальный game
|
||||
game_wrap = latest_data.get("game")
|
||||
has_game = False
|
||||
if game_wrap:
|
||||
game_data = game_wrap.get("data") or game_wrap
|
||||
result = game_data.get("result") or {}
|
||||
game_info = result.get("game") or {}
|
||||
|
||||
|
||||
team1_name = game_data["team1"]["name"]
|
||||
team2_name = game_data["team2"]["name"]
|
||||
|
||||
score_now = game_info.get("score") or ""
|
||||
full_score = game_info.get("fullScore") or ""
|
||||
|
||||
lines.append(f"👥 {team1_name} vs {team2_name}")
|
||||
if score_now:
|
||||
lines.append(f"🔢 Score: <b>{score_now}</b>")
|
||||
|
||||
if isinstance(full_score, str) and full_score:
|
||||
quarters = full_score.split(",")
|
||||
q_text = " | ".join(
|
||||
f"Q{i+1} {q}" for i, q in enumerate(quarters) if q
|
||||
)
|
||||
if q_text:
|
||||
lines.append(f"🧱 By quarters: {q_text}")
|
||||
|
||||
has_game = True
|
||||
|
||||
# live-status отдельно
|
||||
ls = latest_data.get("live-status", {})
|
||||
ls_raw = ls.get("data") or {}
|
||||
ls_status = (
|
||||
ls_raw.get("status")
|
||||
or ls_raw.get("gameStatus")
|
||||
or ls_raw.get("state")
|
||||
or "—"
|
||||
)
|
||||
lines.append(f"🟢 LIVE status: <b>{ls_status}</b>")
|
||||
|
||||
# добавим блок по источникам — это как раз “состояние запросов”
|
||||
sort_order = ["game", "live-status", "box-score", "play-by-play"]
|
||||
keys = [k for k in sort_order if k in latest_data] + sorted(
|
||||
[k for k in latest_data if k not in sort_order]
|
||||
)
|
||||
src_lines = []
|
||||
for k in keys:
|
||||
d = latest_data.get(k) or {}
|
||||
ts = d.get("ts", "—")
|
||||
dat = d.get("data")
|
||||
if isinstance(dat, dict) and "status" in dat:
|
||||
st = dat["status"]
|
||||
else:
|
||||
st = dat
|
||||
src_lines.append(f"• <b>{k}</b>: {st} ({ts})")
|
||||
|
||||
if src_lines:
|
||||
lines.append("📡 Sources:")
|
||||
lines.extend(src_lines)
|
||||
|
||||
# даже если game не успел — мы всё равно что-то вернём
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def status_broadcaster():
|
||||
"""
|
||||
Если матч live — сразу шлём статус.
|
||||
Потом — раз в 5 минут.
|
||||
Если матч не live — ждём и проверяем снова.
|
||||
"""
|
||||
INTERVAL = 300 # 5 минут
|
||||
last_text = None
|
||||
first_live_sent = False
|
||||
|
||||
while not stop_event.is_set():
|
||||
# если игра не идёт — спим по чуть-чуть и крутимся
|
||||
if STATUS not in ("live", "live_soon"):
|
||||
first_live_sent = False # чтобы при новом лайве снова сразу отправить
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
||||
# сюда попадаем только если live
|
||||
text = build_pretty_status_message()
|
||||
if text and text != last_text:
|
||||
logger.info(text)
|
||||
last_text = text
|
||||
first_live_sent = True
|
||||
|
||||
# после первого лайва ждём 5 минут, а до него — 10 секунд
|
||||
wait_sec = INTERVAL if first_live_sent else 10
|
||||
for _ in range(wait_sec):
|
||||
if stop_event.is_set():
|
||||
break
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
@@ -627,6 +738,12 @@ async def lifespan(app: FastAPI):
|
||||
daemon=True,
|
||||
)
|
||||
thread_result_consumer.start()
|
||||
|
||||
thread_status_broadcaster = threading.Thread(
|
||||
target=status_broadcaster,
|
||||
daemon=True,
|
||||
)
|
||||
thread_status_broadcaster.start()
|
||||
|
||||
# 5. Подготовим онлайн и офлайн наборы (как у тебя)
|
||||
threads_live = [
|
||||
@@ -754,10 +871,11 @@ async def lifespan(app: FastAPI):
|
||||
yield
|
||||
|
||||
# -------- shutdown --------
|
||||
stop_event.set() # завершить consumer
|
||||
stop_event.set()
|
||||
stop_live_threads()
|
||||
stop_offline_threads()
|
||||
thread_result_consumer.join(timeout=1)
|
||||
thread_status_broadcaster.join(timeout=1)
|
||||
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
|
||||
Reference in New Issue
Block a user