Spaces:
Sleeping
Sleeping
File size: 6,488 Bytes
81cc161 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | 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 успешно обработаны!")
|