-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathyoutube_client.py
More file actions
87 lines (77 loc) · 2.82 KB
/
youtube_client.py
File metadata and controls
87 lines (77 loc) · 2.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import os
import time
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from dotenv import load_dotenv
from collections import deque
load_dotenv()
API_KEY = os.getenv("YOUTUBE_API_KEY")
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
class YouTubeClient:
def __init__(self):
self.youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=API_KEY)
self.rate_limit = deque(maxlen=100)
def _rate_limit(self):
while len(self.rate_limit) == 100 and time.time() - self.rate_limit[0] < 100:
time.sleep(1)
self.rate_limit.append(time.time())
def get_channel_id_from_handle(self, handle: str) -> str:
"""Convert a YouTube handle (e.g. @channelname) to channel ID"""
self._rate_limit()
try:
# Remove @ if present
handle = handle.lstrip('@')
response = self.youtube.search().list(
q=f"@{handle}",
type='channel',
part='id',
maxResults=1
).execute()
items = response.get('items', [])
if items:
return items[0]['id']['channelId']
return None
except HttpError as e:
if e.resp.status in [403, 500, 503]:
time.sleep(5)
return self.get_channel_id_from_handle(handle)
else:
raise e
def get_latest_videos(self, channel_id: str, max_results=10):
self._rate_limit()
try:
response = self.youtube.search().list(
channelId=channel_id,
part="snippet",
order="date",
type="video", # Add type parameter to only get videos
maxResults=max_results
).execute()
# Filter out any remaining non-video items
items = response.get("items", [])
videos = [
item for item in items
if item.get("id", {}).get("kind") == "youtube#video"
]
return videos
except HttpError as e:
if e.resp.status in [403, 500, 503]:
time.sleep(5)
return self.get_latest_videos(channel_id, max_results)
else:
raise e
def get_video_details(self, video_id: str):
self._rate_limit()
try:
response = self.youtube.videos().list(
part="snippet",
id=video_id
).execute()
return response.get("items", [])
except HttpError as e:
if e.resp.status in [403, 500, 503]:
time.sleep(5)
return self.get_video_details(video_id)
else:
raise e