main.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import os
  2. import datetime
  3. import json
  4. from google_auth_oauthlib.flow import InstalledAppFlow
  5. from googleapiclient.discovery import build
  6. import subprocess
  7. # OAuth 2.0 scopes
  8. SCOPES = ["https://www.googleapis.com/auth/youtube.readonly"]
  9. # Output directory for Emby
  10. OUTPUT_DIR = "/media/media/YouTube"
  11. # Days to look back for videos
  12. DAYS_BACK = 5
  13. def authenticate_youtube():
  14. """Authenticate the user and return a YouTube client."""
  15. flow = InstalledAppFlow.from_client_secrets_file("client_secret.json", SCOPES)
  16. creds = flow.run_local_server(port=0)
  17. youtube = build("youtube", "v3", credentials=creds)
  18. return youtube
  19. def get_subscribed_channels(youtube):
  20. """Fetch the list of subscribed channels."""
  21. channels = []
  22. request = youtube.subscriptions().list(
  23. part="snippet",
  24. mine=True,
  25. maxResults=50
  26. )
  27. while request:
  28. response = request.execute()
  29. for item in response["items"]:
  30. channels.append(item["snippet"]["resourceId"]["channelId"])
  31. request = youtube.subscriptions().list_next(request, response)
  32. return channels
  33. def get_recent_videos(youtube, channel_id):
  34. """Fetch videos from a channel published in the last `DAYS_BACK` days."""
  35. recent_videos = []
  36. published_after = (datetime.datetime.now() - datetime.timedelta(days=DAYS_BACK)).isoformat("T") + "Z"
  37. request = youtube.search().list(
  38. part="snippet",
  39. channelId=channel_id,
  40. publishedAfter=published_after,
  41. maxResults=50,
  42. type="video",
  43. order="date"
  44. )
  45. response = request.execute()
  46. for item in response["items"]:
  47. recent_videos.append({
  48. "video_id": item["id"]["videoId"],
  49. "title": item["snippet"]["title"],
  50. "description": item["snippet"]["description"],
  51. "published_at": item["snippet"]["publishedAt"],
  52. "channel_title": item["snippet"]["channelTitle"]
  53. })
  54. return recent_videos
  55. def download_video(video_id, output_path):
  56. """Download a YouTube video using yt-dlp."""
  57. command = [
  58. "yt-dlp",
  59. f"https://www.youtube.com/watch?v={video_id}",
  60. "-o", os.path.join(output_path, "%(title)s.%(ext)s")
  61. ]
  62. subprocess.run(command, check=True)
  63. def create_nfo_file(video_data, file_path):
  64. """Create an Emby-compatible NFO file."""
  65. nfo_content = f"""<?xml version="1.0" encoding="utf-8" standalone="yes"?>
  66. <movie>
  67. <title>{video_data['title']}</title>
  68. <plot>{video_data['description']}</plot>
  69. <year>{video_data['published_at'][:4]}</year>
  70. <premiered>{video_data['published_at']}</premiered>
  71. <studio>{video_data['channel_title']}</studio>
  72. </movie>
  73. """
  74. with open(file_path, "w", encoding="utf-8") as nfo_file:
  75. nfo_file.write(nfo_content)
  76. def main():
  77. # Authenticate YouTube API
  78. print("Authenticating...")
  79. youtube = authenticate_youtube()
  80. if not os.path.exists(OUTPUT_DIR):
  81. os.makedirs(OUTPUT_DIR)
  82. # Fetch subscribed channels
  83. print("Fetching subscribed channels...")
  84. channels = get_subscribed_channels(youtube)
  85. # Fetch and process recent videos
  86. for channel_id in channels:
  87. print(f"Fetching recent videos for channel: {channel_id}")
  88. videos = get_recent_videos(youtube, channel_id)
  89. for video in videos:
  90. print(f"Processing video: {video['title']}")
  91. # Create a folder for the video
  92. video_dir = os.path.join(OUTPUT_DIR, video["title"].replace("/", "_"))
  93. os.makedirs(video_dir, exist_ok=True)
  94. # Download the video
  95. download_video(video["video_id"], video_dir)
  96. # Create the NFO file
  97. nfo_file_path = os.path.join(video_dir, "movie.nfo")
  98. create_nfo_file(video, nfo_file_path)
  99. print("All videos processed successfully!")
  100. if __name__ == "__main__":
  101. main()