import os import sys import time import requests from dotenv import load_dotenv # Load local environment settings load_dotenv() # Import helper functions and config from vod_backfiller sys.path.append(os.path.dirname(os.path.abspath(__file__))) from vod_backfiller import get_vod_details, download_vod_chat, headers, API_URL, TWITCH_CHANNEL def backfill_single_vod(vod_id): print(f"\n=========================================================") print(f" Начинаем обработку VOD: {vod_id}...") print(f"=========================================================") # 1. Fetch metadata print("[Sync] Получение метаданных VOD...") details = get_vod_details(vod_id) if not details: print(f"[Error] Не удалось получить информацию о VOD {vod_id}. Пропускаем.") return False title = details.get("title", "Архивный стрим") created_at_raw = details.get("createdAt") # e.g. "2026-06-09T17:15:30Z" length_seconds = details.get("lengthSeconds", 0) # timezone-safe calculation using datetime from datetime import datetime, timedelta created_at = created_at_raw.replace("+00:00", "").replace("Z", "") + "Z" dt_start = datetime.fromisoformat(created_at_raw.replace("Z", "+00:00")) dt_end = dt_start + timedelta(seconds=length_seconds) end_time = dt_end.strftime("%Y-%m-%dT%H:%M:%SZ") print(f"Название: {title}") print(f"Начало: {created_at}") print(f"Длительность: {length_seconds // 3600}ч {(length_seconds % 3600) // 60}м") # 2. Sync stream record in DB print("\n[Sync] Регистрация сессии стрима на бэкенде...") try: url = f"{API_URL}/api/streams/sync-vod-direct" payload = { "twitchStreamId": f"vod-{vod_id}", "title": title, "category": "Архив", "startTime": created_at, "endTime": end_time } res = requests.post(url, json=payload, headers=headers, timeout=5) if res.status_code != 200: print(f"[Error] Не удалось синхронизировать сессию стрима: {res.status_code} - {res.text}") return False print("-> Сессия стрима успешно зарегистрирована в базе!") except Exception as e: print(f"[Error] Ошибка сети при обращении к бэкенду: {e}") return False # 3. Check for existing backfill status chat_start_offset = 0 try: status_url = f"{API_URL}/api/streams/backfill-status?twitchStreamId=vod-{vod_id}" res = requests.get(status_url, headers=headers, timeout=5) if res.status_code == 200: status_data = res.json() msg_count = status_data.get("messageCount", 0) latest_msg_ts = status_data.get("latestMessageTimestamp") if msg_count > 0 and latest_msg_ts: from datetime import datetime clean_ts = latest_msg_ts.replace('Z', '+00:00') latest_epoch = datetime.fromisoformat(clean_ts).timestamp() clean_created = created_at.replace('Z', '+00:00') created_epoch = datetime.fromisoformat(clean_created).timestamp() diff = int(latest_epoch - created_epoch) if diff > 0: chat_start_offset = diff print(f"[Sync] Найден существующий чат в базе ({msg_count} сообщений). Возобновляем загрузку с секунды {chat_start_offset}...") except Exception as e: print(f"[Sync Warning] Не удалось получить статус дозаписи: {e}") # 4. Download and Upload Chat comments chat_comments = download_vod_chat(vod_id, start_offset=chat_start_offset) if chat_comments: print("\n[Sync] Отправка чата на сервер (пакетами по 100 сообщений)...") batch_size = 100 for i in range(0, len(chat_comments), batch_size): batch = chat_comments[i:i+batch_size] try: url = f"{API_URL}/api/log/messages" res = requests.post(url, json={"messages": batch}, headers=headers, timeout=5) if res.status_code == 200: print(f"-> Отправлено сообщений: {i + len(batch)} / {len(chat_comments)}", end="\r") else: print(f"\n-> Ошибка отправки пакета: {res.status_code}") except Exception as e: print(f"\n-> Ошибка сети при отправке пакета: {e}") print("\n-> Синхронизация чата успешно завершена!") else: print("\n-> Новых сообщений для загрузки не найдено.") # 5. Mark Completed on Server try: url_mark = f"{API_URL}/api/streams/mark-backfilled" requests.post(url_mark, json={"twitchStreamId": f"vod-{vod_id}"}, headers=headers, timeout=5) print("-> Статус импорта успешно обновлен на сервере!") except Exception as e: print(f"[Warning] Не удалось отметить стрим как импортированный: {e}") print(f"\n[Done] Обработка VOD {vod_id} завершена!") return True if __name__ == "__main__": vod_ids = ['2798809640'] print("=========================================================") print(" Автоматический импорт чатов для последних VOD ") print("=========================================================") print(f"Список VOD: {', '.join(vod_ids)}") print(f"Канал: {TWITCH_CHANNEL}") print(f"Бэкенд: {API_URL}") print("=========================================================") for vid in vod_ids: try: backfill_single_vod(vid) except Exception as e: print(f"[Error] Критическая ошибка при обработке VOD {vid}: {e}") print("\nВсе три VOD успешно обработаны!")