YouTubeLoader / bot /youtube /uploader.py
understanding's picture
Update bot/youtube/uploader.py
5a5f9a2 verified
# FILE: bot/youtube/uploader.py
# PATH: bot/youtube/uploader.py
from __future__ import annotations
import os
from typing import Any, Awaitable, Callable, Dict, Optional
from bot.youtube.metadata import build_metadata
from bot.youtube.resume import start_resumable_session, upload_resumable
ProgressCB = Callable[[int, int], Awaitable[None]]
def _watch_url(video_id: str) -> str:
vid = (video_id or "").strip()
return f"https://youtu.be/{vid}" if vid else ""
async def upload_video(
*,
access_token: str,
file_path: str,
title: str,
description: str,
privacy: str = "private",
progress_cb: Optional[ProgressCB] = None,
) -> Dict[str, Any]:
"""Upload a video to YouTube via resumable upload.
Returns:
{"ok": True, "video_id": "...", "url": "...", "response": {...}}
{"ok": False, "err": "...", "detail": "..."}
"""
if not access_token:
return {"ok": False, "err": "missing_access_token"}
if not file_path or not os.path.exists(file_path):
return {"ok": False, "err": "file_not_found"}
try:
total_bytes = int(os.path.getsize(file_path))
except Exception:
total_bytes = 0
metadata = build_metadata(title=title, description=description, privacy=privacy)
# 1) Start session
start = await start_resumable_session(
access_token=access_token,
metadata=metadata,
total_bytes=total_bytes,
)
if not (isinstance(start, dict) and start.get("ok") and start.get("session_url")):
err = start.get("err", "start_failed") if isinstance(start, dict) else "start_failed"
detail = start.get("detail") if isinstance(start, dict) else None
out: Dict[str, Any] = {"ok": False, "err": err}
if detail:
out["detail"] = str(detail)[:700]
return out
session_url = str(start["session_url"])
# 2) Upload chunks
up = await upload_resumable(
session_url=session_url,
file_path=file_path,
access_token=access_token,
total_bytes=total_bytes,
progress_cb=progress_cb,
)
if not (isinstance(up, dict) and up.get("ok")):
err = up.get("err", "upload_failed") if isinstance(up, dict) else "upload_failed"
detail = up.get("detail") if isinstance(up, dict) else None
out2: Dict[str, Any] = {"ok": False, "err": err}
if detail:
out2["detail"] = str(detail)[:900]
return out2
resp = up.get("response") if isinstance(up, dict) else None
if not isinstance(resp, dict):
resp = {}
video_id = str(resp.get("id") or resp.get("videoId") or "").strip()
url = _watch_url(video_id)
return {
"ok": True,
"video_id": video_id,
"url": url,
"response": resp,
}