import os import datetime import pickle from googleapiclient.discovery import build import subprocess from google.auth.transport.requests import Request # Output directory for Emby OUTPUT_DIR = "/media/media/YouTube" # Days to look back for videos DAYS_BACK = 5 # Token file TOKEN_FILE = "youtube_token.pickle" def authenticate_with_token(): """Authenticate using the saved token.""" if not os.path.exists(TOKEN_FILE): raise FileNotFoundError(f"Token file '{TOKEN_FILE}' not found. Please run the token retrieval script first.") with open(TOKEN_FILE, "rb") as token: creds = pickle.load(token) # Refresh the token if needed if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) youtube = build("youtube", "v3", credentials=creds) return youtube def get_subscribed_channels(youtube): """Fetch the list of subscribed channels.""" channels = [] request = youtube.subscriptions().list( part="snippet", mine=True, maxResults=50 ) while request: response = request.execute() for item in response["items"]: channels.append(item["snippet"]["resourceId"]["channelId"]) request = youtube.subscriptions().list_next(request, response) return channels def get_recent_videos(youtube, channel_id): """Fetch videos from a channel published in the last `DAYS_BACK` days.""" recent_videos = [] published_after = (datetime.datetime.now() - datetime.timedelta(days=DAYS_BACK)).isoformat("T") + "Z" request = youtube.search().list( part="snippet", channelId=channel_id, publishedAfter=published_after, maxResults=50, type="video", order="date" ) response = request.execute() for item in response["items"]: recent_videos.append({ "video_id": item["id"]["videoId"], "title": item["snippet"]["title"], "description": item["snippet"]["description"], "published_at": item["snippet"]["publishedAt"], "channel_title": item["snippet"]["channelTitle"] }) return recent_videos def download_video(video_id, output_path): """Download a YouTube video using yt-dlp.""" command = [ "yt-dlp", f"https://www.youtube.com/watch?v={video_id}", "-o", os.path.join(output_path, "%(title)s.%(ext)s") ] subprocess.run(command, check=True) def create_nfo_file(video_data, file_path): """Create an Emby-compatible NFO file.""" nfo_content = f""" {video_data['title']} {video_data['description']} {video_data['published_at'][:4]} {video_data['published_at']} {video_data['channel_title']} """ with open(file_path, "w", encoding="utf-8") as nfo_file: nfo_file.write(nfo_content) def main(): # Authenticate YouTube API print("Authenticating with token...") youtube = authenticate_with_token() if not os.path.exists(OUTPUT_DIR): os.makedirs(OUTPUT_DIR) # Fetch subscribed channels print("Fetching subscribed channels...") channels = get_subscribed_channels(youtube) # Fetch and process recent videos for channel_id in channels: print(f"Fetching recent videos for channel: {channel_id}") videos = get_recent_videos(youtube, channel_id) for video in videos: print(f"Processing video: {video['title']}") # Create a folder for the video video_dir = os.path.join(OUTPUT_DIR, video["title"].replace("/", "_")) os.makedirs(video_dir, exist_ok=True) # Download the video download_video(video["video_id"], video_dir) # Create the NFO file nfo_file_path = os.path.join(video_dir, "movie.nfo") create_nfo_file(video, nfo_file_path) print("All videos processed successfully!") if __name__ == "__main__": main()