sgbaird commited on
Commit
ba694bf
·
verified ·
1 Parent(s): 5a16847

Update yt_utils.py

Browse files

https://chatgpt.com/share/692e08b6-c7fc-8007-9a16-6756e42b3a62

Files changed (1) hide show
  1. yt_utils.py +91 -55
yt_utils.py CHANGED
@@ -1,82 +1,118 @@
1
- import requests
2
  import os
 
3
 
4
  YT_API_KEY = os.getenv("YT_API_KEY")
5
 
 
6
  def get_latest_video_id(channel_id, device_name=None, playlist_id=None):
 
 
 
 
 
 
 
 
7
  if device_name is None and playlist_id is None:
8
- raise Exception("Must specify either device_name or playlist_id")
9
 
10
  if device_name is not None and playlist_id is not None:
 
11
  print("Both device_name and playlist_id entered.. device_name will be ignored.")
12
 
 
 
 
13
  if playlist_id is None:
14
- # Step 1: get all playlists from the channel (note that 'playlists' in url)
15
- url = 'https://www.googleapis.com/youtube/v3/playlists'
16
- params = {
17
- 'part': 'snippet',
18
- 'channelId': channel_id, # Fixed: was CHANNEL_ID (undefined variable)
19
- 'maxResults': 1000,
20
- 'key': YT_API_KEY
21
  }
22
- res = requests.get(url, params=params)
 
23
  res.raise_for_status()
24
  playlists = res.json().get("items", [])
25
 
26
  for p in playlists:
27
- if device_name.lower() in p["snippet"]["title"].lower():
 
28
  playlist_id = p["id"]
29
  break
30
 
31
  if not playlist_id:
32
  raise Exception(f"No playlist found matching device name '{device_name}'")
33
 
34
- # Step 2: Use search API instead of playlistItems to get the most recent video by publication date
35
- url = 'https://www.googleapis.com/youtube/v3/search'
36
- params = {
37
- 'part': 'snippet',
38
- 'channelId': channel_id,
39
- 'maxResults': 1,
40
- 'order': 'date', # This sorts by publication date (newest first)
41
- 'type': 'video', # Only return videos
42
- 'key': YT_API_KEY
43
- }
44
-
45
- # If we have a playlist_id, we need to get videos from that specific playlist
46
- # Note: To properly filter by both channel and playlist, we need an additional step
47
  if playlist_id:
48
- # First get videos from the playlist
49
- playlist_url = 'https://www.googleapis.com/youtube/v3/playlistItems'
50
- playlist_params = {
51
- 'part': 'snippet,contentDetails',
52
- 'playlistId': playlist_id,
53
- 'maxResults': 10, # Get several videos to ensure we find the latest
54
- 'key': YT_API_KEY
55
- }
56
-
57
- playlist_res = requests.get(playlist_url, params=playlist_params)
58
- playlist_res.raise_for_status()
59
- playlist_items = playlist_res.json().get("items", [])
60
-
61
- if not playlist_items:
62
- return None
63
-
64
- # Sort by publish date (newest first)
65
- sorted_items = sorted(
66
- playlist_items,
67
- key=lambda x: x["snippet"].get("publishedAt", ""),
68
- reverse=True
69
- )
70
-
71
- # Return the newest video ID
72
- return sorted_items[0]["snippet"]["resourceId"]["videoId"]
73
-
74
- # If we're not filtering by playlist, just use the search API
75
- res = requests.get(url, params=params)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  res.raise_for_status()
77
  items = res.json().get("items", [])
78
-
79
  if not items:
80
  return None
81
-
82
- return items[0]["id"]["videoId"] # Note the different path to videoId for search results
 
 
1
  import os
2
+ import requests
3
 
4
  YT_API_KEY = os.getenv("YT_API_KEY")
5
 
6
+
7
  def get_latest_video_id(channel_id, device_name=None, playlist_id=None):
8
+ """
9
+ Return the videoId of the most recently published video from either:
10
+ - a specific playlist (if playlist_id is provided or can be resolved from device_name), or
11
+ - the channel (if only channel_id is provided).
12
+
13
+ This does NOT rely on playlist UI ordering; it walks the whole playlist and
14
+ picks the newest item by snippet.publishedAt.
15
+ """
16
  if device_name is None and playlist_id is None:
17
+ raise ValueError("Must specify either device_name or playlist_id")
18
 
19
  if device_name is not None and playlist_id is not None:
20
+ # Keep existing behavior
21
  print("Both device_name and playlist_id entered.. device_name will be ignored.")
22
 
23
+ # ------------------------------------------------------------------
24
+ # 1) If we only know the device_name, resolve playlist_id from channel
25
+ # ------------------------------------------------------------------
26
  if playlist_id is None:
27
+ playlists_url = "https://www.googleapis.com/youtube/v3/playlists"
28
+ playlists_params = {
29
+ "part": "snippet",
30
+ "channelId": channel_id,
31
+ "maxResults": 50,
32
+ "key": YT_API_KEY,
 
33
  }
34
+
35
+ res = requests.get(playlists_url, params=playlists_params)
36
  res.raise_for_status()
37
  playlists = res.json().get("items", [])
38
 
39
  for p in playlists:
40
+ title = p["snippet"]["title"].lower()
41
+ if device_name.lower() in title:
42
  playlist_id = p["id"]
43
  break
44
 
45
  if not playlist_id:
46
  raise Exception(f"No playlist found matching device name '{device_name}'")
47
 
48
+ # ------------------------------------------------------------------
49
+ # 2) If we have a playlist_id, walk ALL pages and find newest item
50
+ # ------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
51
  if playlist_id:
52
+ playlist_url = "https://www.googleapis.com/youtube/v3/playlistItems"
53
+ latest_video_id = None
54
+ latest_published_at = None
55
+ page_token = None
56
+
57
+ while True:
58
+ playlist_params = {
59
+ "part": "snippet,contentDetails",
60
+ "playlistId": playlist_id,
61
+ "maxResults": 50, # API max
62
+ "key": YT_API_KEY,
63
+ }
64
+ if page_token:
65
+ playlist_params["pageToken"] = page_token
66
+
67
+ playlist_res = requests.get(playlist_url, params=playlist_params)
68
+ playlist_res.raise_for_status()
69
+ data = playlist_res.json()
70
+
71
+ for item in data.get("items", []):
72
+ snippet = item.get("snippet", {})
73
+ published_at = snippet.get("publishedAt")
74
+ if not published_at:
75
+ continue
76
+
77
+ # For playlistItems, videoId lives in contentDetails.videoId
78
+ video_id = item.get("contentDetails", {}).get("videoId")
79
+ if not video_id:
80
+ # Fallback to snippet.resourceId if needed
81
+ video_id = (
82
+ snippet.get("resourceId", {}) or {}
83
+ ).get("videoId")
84
+
85
+ if not video_id:
86
+ continue
87
+
88
+ if latest_published_at is None or published_at > latest_published_at:
89
+ latest_published_at = published_at
90
+ latest_video_id = video_id
91
+
92
+ page_token = data.get("nextPageToken")
93
+ if not page_token:
94
+ break
95
+
96
+ return latest_video_id
97
+
98
+ # ------------------------------------------------------------------
99
+ # 3) Fallback: no playlist, just get latest video on the channel
100
+ # ------------------------------------------------------------------
101
+ search_url = "https://www.googleapis.com/youtube/v3/search"
102
+ search_params = {
103
+ "part": "snippet",
104
+ "channelId": channel_id,
105
+ "maxResults": 1,
106
+ "order": "date", # newest first
107
+ "type": "video",
108
+ "key": YT_API_KEY,
109
+ }
110
+
111
+ res = requests.get(search_url, params=search_params)
112
  res.raise_for_status()
113
  items = res.json().get("items", [])
114
+
115
  if not items:
116
  return None
117
+
118
+ return items[0]["id"]["videoId"]