import asyncio import logging import aiosqlite from googleapiclient.discovery import build from googleapiclient.errors import HttpError from auth import get_credentials from db import DB_PATH log = logging.getLogger(__name__) async def fetch_subscriptions(): """Fetch latest videos from subscribed channels using YouTube Data API v3.""" try: creds = get_credentials() except FileNotFoundError as e: log.error(f"OAuth setup incomplete: {e}") return 0 except Exception as e: log.error(f"OAuth credential error: {e}") return 0 youtube = build("youtube", "v3", credentials=creds) # Step 1: Get subscribed channel IDs channel_ids = [] try: request = youtube.subscriptions().list( part="snippet", mine=True, maxResults=50, order="alphabetical" ) while request: response = request.execute() for item in response.get("items", []): cid = item["snippet"]["resourceId"]["channelId"] if cid not in channel_ids: channel_ids.append(cid) request = youtube.subscriptions().list_next(request, response) except HttpError as e: log.error(f"YouTube API error fetching subscriptions: {e}") return 0 log.info(f"Found {len(channel_ids)} subscribed channels") if not channel_ids: log.warning("No subscribed channels found. Make sure the authenticated account has subscriptions.") return 0 # Step 2: For each channel, get latest videos new_count = 0 async with aiosqlite.connect(DB_PATH) as db: for cid in channel_ids[:20]: try: req = youtube.search().list( part="snippet", channelId=cid, maxResults=10, order="date", type="video" ) resp = req.execute() for item in resp.get("items", []): vid = item["id"]["videoId"] snippet = item["snippet"] cursor = await db.execute( "SELECT 1 FROM videos WHERE video_id = ?", (vid,) ) if await cursor.fetchone(): continue pub_time = snippet.get("publishTime", "") await db.execute(""" INSERT INTO videos (video_id, title, channel_name, channel_id, url, thumbnail_url, publish_date) VALUES (?, ?, ?, ?, ?, ?, ?) """, ( vid, snippet.get("title", "Untitled"), snippet.get("channelTitle", "Unknown"), snippet.get("channelId", cid), f"https://www.youtube.com/watch?v={vid}", snippet.get("thumbnails", {}).get("high", {}).get("url", ""), pub_time[:10] if pub_time else None )) new_count += 1 log.debug(f"New video: {snippet.get('title', 'Untitled')[:50]}") except HttpError as e: log.warning(f"Channel {cid} fetch error: {e}") continue await db.commit() log.info(f"Ingestion completed. Found {new_count} new videos.") return new_count if __name__ == "__main__": import sys logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') async def main(): from db import init_db await init_db() count = await fetch_subscriptions() print(f"\nDone. {count} new videos ingested.") asyncio.run(main())