|
|
import os |
|
|
import requests |
|
|
|
|
|
YT_API_KEY = os.getenv("YT_API_KEY") |
|
|
|
|
|
|
|
|
def get_latest_video_id(channel_id, device_name=None, playlist_id=None): |
|
|
""" |
|
|
Return the videoId of the most recently published video from either: |
|
|
- a specific playlist (if playlist_id is provided or can be resolved from device_name), or |
|
|
- the channel (if only channel_id is provided). |
|
|
|
|
|
This does NOT rely on playlist UI ordering; it walks the whole playlist and |
|
|
picks the newest item by snippet.publishedAt. |
|
|
""" |
|
|
if device_name is None and playlist_id is None: |
|
|
raise ValueError("Must specify either device_name or playlist_id") |
|
|
|
|
|
if device_name is not None and playlist_id is not None: |
|
|
|
|
|
print("Both device_name and playlist_id entered.. device_name will be ignored.") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if playlist_id is None: |
|
|
playlists_url = "https://www.googleapis.com/youtube/v3/playlists" |
|
|
playlists_params = { |
|
|
"part": "snippet", |
|
|
"channelId": channel_id, |
|
|
"maxResults": 50, |
|
|
"key": YT_API_KEY, |
|
|
} |
|
|
|
|
|
res = requests.get(playlists_url, params=playlists_params) |
|
|
res.raise_for_status() |
|
|
playlists = res.json().get("items", []) |
|
|
|
|
|
for p in playlists: |
|
|
title = p["snippet"]["title"].lower() |
|
|
if device_name.lower() in title: |
|
|
playlist_id = p["id"] |
|
|
break |
|
|
|
|
|
if not playlist_id: |
|
|
raise Exception(f"No playlist found matching device name '{device_name}'") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if playlist_id: |
|
|
playlist_url = "https://www.googleapis.com/youtube/v3/playlistItems" |
|
|
latest_video_id = None |
|
|
latest_published_at = None |
|
|
page_token = None |
|
|
|
|
|
while True: |
|
|
playlist_params = { |
|
|
"part": "snippet,contentDetails", |
|
|
"playlistId": playlist_id, |
|
|
"maxResults": 50, |
|
|
"key": YT_API_KEY, |
|
|
} |
|
|
if page_token: |
|
|
playlist_params["pageToken"] = page_token |
|
|
|
|
|
playlist_res = requests.get(playlist_url, params=playlist_params) |
|
|
playlist_res.raise_for_status() |
|
|
data = playlist_res.json() |
|
|
|
|
|
for item in data.get("items", []): |
|
|
snippet = item.get("snippet", {}) |
|
|
published_at = snippet.get("publishedAt") |
|
|
if not published_at: |
|
|
continue |
|
|
|
|
|
|
|
|
video_id = item.get("contentDetails", {}).get("videoId") |
|
|
if not video_id: |
|
|
|
|
|
video_id = ( |
|
|
snippet.get("resourceId", {}) or {} |
|
|
).get("videoId") |
|
|
|
|
|
if not video_id: |
|
|
continue |
|
|
|
|
|
if latest_published_at is None or published_at > latest_published_at: |
|
|
latest_published_at = published_at |
|
|
latest_video_id = video_id |
|
|
|
|
|
page_token = data.get("nextPageToken") |
|
|
if not page_token: |
|
|
break |
|
|
|
|
|
return latest_video_id |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
search_url = "https://www.googleapis.com/youtube/v3/search" |
|
|
search_params = { |
|
|
"part": "snippet", |
|
|
"channelId": channel_id, |
|
|
"maxResults": 1, |
|
|
"order": "date", |
|
|
"type": "video", |
|
|
"key": YT_API_KEY, |
|
|
} |
|
|
|
|
|
res = requests.get(search_url, params=search_params) |
|
|
res.raise_for_status() |
|
|
items = res.json().get("items", []) |
|
|
|
|
|
if not items: |
|
|
return None |
|
|
|
|
|
return items[0]["id"]["videoId"] |
|
|
|