diff --git a/get_data_new.py b/get_data_new.py index 0b1eb29..ee6465c 100644 --- a/get_data_new.py +++ b/get_data_new.py @@ -409,6 +409,7 @@ def run_live_loop( render_thread.join() logger.info(f"[LIVE_THREAD] stop live loop for game_id={game_id}") + def Scores_Quarter(merged: dict, *, out_dir: str = "static") -> None: """ Поток, обновляющий JSON со счётом по четвертям. @@ -448,7 +449,6 @@ def Scores_Quarter(merged: dict, *, out_dir: str = "static") -> None: logger.error(f"Ошибка в Scores_Quarter: {e}", exc_info=True) - def poll_game_live( session, league: str, @@ -588,7 +588,6 @@ def get_data_API(session, league: str, team: str, lang: str, stop_event: threadi logger.info("Для этой команды игр сегодня нет и нет завершённой последней игры.") - def read_local_json(name: str, in_dir: str = "static"): """ Безопасно читает static/.json. @@ -657,6 +656,7 @@ def build_render_state() -> dict: } return merged + def format_time(seconds: float | int) -> str: """ Форматирует время в секундах в строку "M:SS". @@ -1569,7 +1569,6 @@ def Team_Both_Stat(merged: dict, *, out_dir: str = "static") -> None: logger.error(f"Ошибка при обработке командной статистики: {e}", exc_info=True) - def render_loop(stop_event: threading.Event, out_name: str = "game"): """ Крутится в отдельном потоке. @@ -1599,25 +1598,70 @@ def render_loop(stop_event: threading.Event, out_name: str = "game"): def main(): parser = argparse.ArgumentParser() - parser.add_argument("--league", default="vtb") + parser.add_argument("--league", required=True) parser.add_argument("--team", required=True) parser.add_argument("--lang", default="en") args = parser.parse_args() - session = create_session() + # бесконечный дневной цикл + while True: + # на каждый цикл — новая сессия и новый stop_event + session = create_session() + stop_event = threading.Event() - # единый флаг остановки на ВСЮ программу - stop_event = threading.Event() + try: + # один полный прогон логики дня: + # - обновить сезоны/календарь + # - если есть матч и он лайв -> отследить до финала + # - записать статику для последней игры, если она уже завершилась + get_data_API(session, args.league, args.team, args.lang, stop_event) + except KeyboardInterrupt: + # оператор сказал "хватит" + logger.info("KeyboardInterrupt -> останавливаемся сразу") + stop_event.set() + break + except Exception as e: + # не падаем навсегда от любой ошибки, просто логируем + logger.exception(f"main-loop crash: {e}") - try: - get_data_API(session, args.league, args.team, args.lang, stop_event) - except KeyboardInterrupt: - # ручное прерывание: просим все рабочие циклы сворачиваться - logger.info("KeyboardInterrupt: stopping...") - stop_event.set() - except Exception as e: - logger.exception(f"Fatal in main(): {e}") - stop_event.set() + # сюда мы попадаем всегда, даже если: + # - сегодня не было матча + # - матч был, но ещё не начался + # - матч уже давно закончился + # - матч только что отследили в онлайне до свистка + + now = datetime.now(APP_TZ) + + # время следующего старта: завтра в 00:05 по APP_TZ (Europe/Moscow в коде) + tomorrow = (now + timedelta(days=1)).replace( + hour=0, minute=5, second=0, microsecond=0 + ) + + # если вдруг сейчас уже >00:05 (например мы запустились в 00:10), + # то завтра уже будет +1 день от текущей даты, но нам это и нужно. + sleep_seconds = (tomorrow - now).total_seconds() + if sleep_seconds < 0: + # это теоретический случай, если .replace() попал в прошлое; + # подстрахуемся: спать до 00:05 следующего дня +1 + tomorrow = (now + timedelta(days=2)).replace( + hour=0, minute=5, second=0, microsecond=0 + ) + sleep_seconds = (tomorrow - now).total_seconds() + + logger.info( + f"Работа за день завершена. Спим до {tomorrow.strftime('%d.%m %H:%M')} " + f"(~{round(sleep_seconds/3600, 2)} ч)." + ) + + # мягкий сон. если во время сна дадут Ctrl+C — просто выходим. + try: + time.sleep(sleep_seconds) + except KeyboardInterrupt: + logger.info("KeyboardInterrupt во время сна -> выходим.") + break + + # после пробуждения while True просто идёт на новую итерацию + # и запускает новую сессию / новый stop_event / новый get_data_API