Compare commits
2
Commits
2de2c461e2
...
afe6490d20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afe6490d20 | ||
|
|
8bf85fea2e |
No files matched your search
@@ -6,10 +6,10 @@ import time
|
|||||||
|
|
||||||
from package.database import Database
|
from package.database import Database
|
||||||
|
|
||||||
import uploader
|
import package.youtube.uploader as uploader
|
||||||
from uploader import CategoryId
|
from package.youtube.uploader import CategoryId
|
||||||
|
|
||||||
import youtube_hashtags
|
import package.youtube.hashtags as hashtags
|
||||||
import package.transcribe_video as transcribe_video
|
import package.transcribe_video as transcribe_video
|
||||||
|
|
||||||
CHANNEL_NAME = 'teampgp' # Replace with the streamer's username
|
CHANNEL_NAME = 'teampgp' # Replace with the streamer's username
|
||||||
@@ -43,7 +43,7 @@ def top_hashtags(id: str):
|
|||||||
print(f"Transcribe file not found {file_srt}")
|
print(f"Transcribe file not found {file_srt}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
tags = youtube_hashtags.get_top_hashtags(file_srt)
|
tags = hashtags.get_top_hashtags(file_srt)
|
||||||
return tags
|
return tags
|
||||||
|
|
||||||
def download():
|
def download():
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ from datetime import datetime
|
|||||||
|
|
||||||
from package.database import Database
|
from package.database import Database
|
||||||
|
|
||||||
import uploader
|
import package.youtube.uploader as uploader
|
||||||
from uploader import CategoryId
|
from package.youtube.uploader import CategoryId
|
||||||
|
|
||||||
CHANNEL_NAME = 'teampgp' # Replace with the streamer's username
|
CHANNEL_NAME = 'teampgp' # Replace with the streamer's username
|
||||||
DB = Database("clips")
|
DB = Database("clips")
|
||||||
@@ -49,9 +49,9 @@ def top_hashtags(slug: str):
|
|||||||
print(f"Transcribe file not found {file_srt}")
|
print(f"Transcribe file not found {file_srt}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
import youtube_hashtags
|
import package.youtube.hashtags as hashtags
|
||||||
|
|
||||||
return youtube_hashtags.get_top_hashtags(file_srt)
|
return hashtags.get_top_hashtags(file_srt)
|
||||||
|
|
||||||
|
|
||||||
def download_clips():
|
def download_clips():
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ os.makedirs(CACHE_DIR, exist_ok=True)
|
|||||||
|
|
||||||
# 3. Expose Database Tools (Added)
|
# 3. Expose Database Tools (Added)
|
||||||
# Replace 'DatabaseClient' and 'connect_to_db' with your actual class/function names
|
# Replace 'DatabaseClient' and 'connect_to_db' with your actual class/function names
|
||||||
from .build_videos import main as build_videos
|
from .build_videos import build_videos
|
||||||
from .config import CHANNEL_NAME, DB
|
from .config import CHANNEL_NAME, DB
|
||||||
from .database import Database
|
from .database import Database
|
||||||
from .transcribe_video import transcribe_to_srt
|
from .transcribe_video import transcribe_to_srt
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import youtube_short
|
import package.youtube.shorts as yt_shorts
|
||||||
import package.transcribe_video as transcribe_video
|
import package.transcribe_video as transcribe_video
|
||||||
import package.twitch.chat_vod as chat_vod
|
import package.twitch.chat_vod as chat_vod
|
||||||
from package.config import DB as DB
|
from package.config import DB as DB
|
||||||
@@ -108,16 +108,16 @@ def build_shorts():
|
|||||||
print(f"🚀 Processing: Clip to Youtube Short {title}")
|
print(f"🚀 Processing: Clip to Youtube Short {title}")
|
||||||
print("====================================================")
|
print("====================================================")
|
||||||
|
|
||||||
youtube_short.fit_to_9_16_letterbox(target_dir, top_txt, f"Clipped By: {creator_name}.")
|
yt_shorts.fit_to_9_16_letterbox(target_dir, top_txt, f"Clipped By: {creator_name}.")
|
||||||
|
|
||||||
print("====================================================")
|
print("====================================================")
|
||||||
print(f"✅ Processing: Clip to Youtube Short Done.")
|
print(f"✅ Processing: Clip to Youtube Short Done.")
|
||||||
print("====================================================")
|
print("====================================================")
|
||||||
|
|
||||||
def main():
|
def build_videos():
|
||||||
build_shorts()
|
build_shorts()
|
||||||
build_transcribe()
|
build_transcribe()
|
||||||
build_chat_video()
|
build_chat_video()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
build_videos()
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
# Expose components from individual modules using relative imports
|
# Expose components from individual modules using relative imports
|
||||||
from .chat_vod import combine_twitch_vod_and_chat
|
from .chat_vod import combine_twitch_vod_and_chat
|
||||||
from .download_thumbnails import main as download_thumbnails
|
from .download_thumbnails import download_thumbnails
|
||||||
from .download_videos import main as download_videos
|
from .download_videos import download_videos
|
||||||
from .video_info import main as video_info
|
from .video_info import video_info
|
||||||
|
|
||||||
# Explicitly define what is exposed when importing the subpackage
|
# Explicitly define what is exposed when importing the subpackage
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import cv2
|
|||||||
import package.utils as utils
|
import package.utils as utils
|
||||||
|
|
||||||
def get_video_height(video_path: str) -> int:
|
def get_video_height(video_path: str) -> int:
|
||||||
|
"""
|
||||||
|
Gets the videos height
|
||||||
|
"""
|
||||||
# Open the video file
|
# Open the video file
|
||||||
video = cv2.VideoCapture(video_path)
|
video = cv2.VideoCapture(video_path)
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ def save_image(url: str, filename: str, stream: bool = True):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ An error occurred during file writing: {e}")
|
print(f"❌ An error occurred during file writing: {e}")
|
||||||
|
|
||||||
async def main():
|
async def download_thumbnails():
|
||||||
# Initialize connection & automatically authorize the App token
|
# Initialize connection & automatically authorize the App token
|
||||||
await config.get_twitch()
|
await config.get_twitch()
|
||||||
twitch = config.TWITCH # Twitch(APP_ID, APP_SECRET)
|
twitch = config.TWITCH # Twitch(APP_ID, APP_SECRET)
|
||||||
@@ -141,4 +141,4 @@ async def main():
|
|||||||
await download_clip_thumbnail(id, thumbnail_url)
|
await download_clip_thumbnail(id, thumbnail_url)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
asyncio.run(main())
|
asyncio.run(download_thumbnails())
|
||||||
@@ -14,7 +14,7 @@ def write_csv(data, file_name):
|
|||||||
# Write all rows at once
|
# Write all rows at once
|
||||||
writer.writerows(data)
|
writer.writerows(data)
|
||||||
|
|
||||||
def download():
|
def download_videos():
|
||||||
"""Find all undownloaded videos and clips, and download them safely."""
|
"""Find all undownloaded videos and clips, and download them safely."""
|
||||||
undownloaded = DB.get_undownloaded()
|
undownloaded = DB.get_undownloaded()
|
||||||
|
|
||||||
@@ -96,8 +96,5 @@ def download():
|
|||||||
|
|
||||||
print("Finished Downloading Pipeline.")
|
print("Finished Downloading Pipeline.")
|
||||||
|
|
||||||
def main():
|
|
||||||
download()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
download_videos()
|
||||||
@@ -40,7 +40,7 @@ async def get_game_name_by_id(game_id: str) -> str:
|
|||||||
pass
|
pass
|
||||||
return "Unknown Game"
|
return "Unknown Game"
|
||||||
|
|
||||||
async def get_vod_game_name(vod_id: str):
|
async def get_vod_game_name(vod_id: str) -> tuple:
|
||||||
"""Asynchronously query Twitch GQL endpoint for VOD game metadata."""
|
"""Asynchronously query Twitch GQL endpoint for VOD game metadata."""
|
||||||
game_id = "0"
|
game_id = "0"
|
||||||
game_name = "Unknown Game"
|
game_name = "Unknown Game"
|
||||||
@@ -83,7 +83,7 @@ async def get_vod_game_name(vod_id: str):
|
|||||||
|
|
||||||
return game_id, game_name
|
return game_id, game_name
|
||||||
|
|
||||||
async def get_streamer_vods():
|
async def get_streamer_vods() -> list:
|
||||||
await config.get_twitch()
|
await config.get_twitch()
|
||||||
|
|
||||||
print(f"Starting VOD extraction for {config.USER.display_name}...")
|
print(f"Starting VOD extraction for {config.USER.display_name}...")
|
||||||
@@ -121,7 +121,7 @@ async def get_streamer_vods():
|
|||||||
print(f"\nFinished extracting VODs. Total gathered: {len(all_vods)}")
|
print(f"\nFinished extracting VODs. Total gathered: {len(all_vods)}")
|
||||||
return all_vods
|
return all_vods
|
||||||
|
|
||||||
async def get_streamer_clips():
|
async def get_streamer_clips() -> list:
|
||||||
await config.get_twitch()
|
await config.get_twitch()
|
||||||
|
|
||||||
print(f"Starting clip extraction for {config.USER.display_name}...")
|
print(f"Starting clip extraction for {config.USER.display_name}...")
|
||||||
@@ -151,7 +151,7 @@ async def get_streamer_clips():
|
|||||||
print(f"\nFinished extracting clips. Total gathered: {len(all_clips)}")
|
print(f"\nFinished extracting clips. Total gathered: {len(all_clips)}")
|
||||||
return all_clips
|
return all_clips
|
||||||
|
|
||||||
async def main():
|
async def video_info():
|
||||||
print("--- Script Started ---")
|
print("--- Script Started ---")
|
||||||
|
|
||||||
vods_list = await get_streamer_vods()
|
vods_list = await get_streamer_vods()
|
||||||
@@ -179,4 +179,4 @@ async def main():
|
|||||||
print(f"Recent VOD: '{clips_list[0]['title']}'")
|
print(f"Recent VOD: '{clips_list[0]['title']}'")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(main())
|
asyncio.run(video_info())
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# package/youtube/__init__.py
|
||||||
|
|
||||||
|
# Expose components from individual modules using relative imports
|
||||||
|
from .find_tags import find_tags
|
||||||
|
from .hashtags import get_top_nouns
|
||||||
|
from .shorts import fit_to_9_16_letterbox
|
||||||
|
from .uploader import upload_video, CategoryId
|
||||||
|
|
||||||
|
# Explicitly define what is exposed when importing the subpackage
|
||||||
|
__all__ = [
|
||||||
|
"find_tags",
|
||||||
|
"get_top_nouns",
|
||||||
|
"fit_to_9_16_letterbox",
|
||||||
|
"upload_video",
|
||||||
|
]
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import json
|
||||||
|
|
||||||
|
from google.oauth2.credentials import Credentials
|
||||||
|
from google.auth.transport.requests import Request
|
||||||
|
|
||||||
|
CREDENTIALS = None
|
||||||
|
|
||||||
|
def load_credentials() -> Credentials:
|
||||||
|
"""Load credentials from secrets.json"""
|
||||||
|
try:
|
||||||
|
with open('secrets.json', 'r') as f:
|
||||||
|
creds_data = json.load(f)
|
||||||
|
|
||||||
|
credentials = Credentials(
|
||||||
|
token=creds_data['token'],
|
||||||
|
refresh_token=creds_data['refresh_token'],
|
||||||
|
token_uri=creds_data['token_uri'],
|
||||||
|
client_id=creds_data['client_id'],
|
||||||
|
client_secret=creds_data['client_secret'],
|
||||||
|
scopes=creds_data['scopes']
|
||||||
|
)
|
||||||
|
|
||||||
|
# Refresh token if expired
|
||||||
|
if credentials.expired:
|
||||||
|
credentials.refresh(Request())
|
||||||
|
|
||||||
|
return credentials
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("Error: secrets.json not found! Please run setup.py first.")
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading credentials: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
CREDENTIALS = load_credentials()
|
||||||
@@ -1,37 +1,12 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import json
|
from typing import Any
|
||||||
from google.oauth2.credentials import Credentials
|
|
||||||
from google.auth.transport.requests import Request
|
|
||||||
from googleapiclient.discovery import build
|
from googleapiclient.discovery import build
|
||||||
from googleapiclient.errors import HttpError
|
from googleapiclient.errors import HttpError
|
||||||
|
|
||||||
def load_credentials():
|
import package.youtube.config as config
|
||||||
"""Load credentials from secrets.json (Reused from your previous flow)"""
|
|
||||||
try:
|
|
||||||
with open('secrets.json', 'r') as f:
|
|
||||||
creds_data = json.load(f)
|
|
||||||
|
|
||||||
credentials = Credentials(
|
|
||||||
token=creds_data['token'],
|
|
||||||
refresh_token=creds_data['refresh_token'],
|
|
||||||
token_uri=creds_data['token_uri'],
|
|
||||||
client_id=creds_data['client_id'],
|
|
||||||
client_secret=creds_data['client_secret'],
|
|
||||||
scopes=creds_data['scopes']
|
|
||||||
)
|
|
||||||
|
|
||||||
if credentials.expired:
|
|
||||||
credentials.refresh(Request())
|
|
||||||
|
|
||||||
return credentials
|
|
||||||
except FileNotFoundError:
|
|
||||||
print("Error: secrets.json not found!")
|
|
||||||
return None
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error loading credentials: {str(e)}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_my_uploads_playlist_id(youtube):
|
def get_my_uploads_playlist_id(youtube: build) -> Any:
|
||||||
"""Retrieves the system upload playlist ID for the authenticated user's channel."""
|
"""Retrieves the system upload playlist ID for the authenticated user's channel."""
|
||||||
try:
|
try:
|
||||||
# mine=True automatically references the authorized account
|
# mine=True automatically references the authorized account
|
||||||
@@ -47,7 +22,7 @@ def get_my_uploads_playlist_id(youtube):
|
|||||||
print(f"API Error retrieving channel details: {str(e)}")
|
print(f"API Error retrieving channel details: {str(e)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def scan_channel_videos_for_tag(youtube, uploads_playlist_id: str, target_tag: str):
|
def scan_channel_videos_for_tag(youtube: build, uploads_playlist_id: str, target_tag: str) -> list:
|
||||||
"""
|
"""
|
||||||
Loops through all channel video uploads and filters those possessing the target tag.
|
Loops through all channel video uploads and filters those possessing the target tag.
|
||||||
"""
|
"""
|
||||||
@@ -120,12 +95,12 @@ def scan_channel_videos_for_tag(youtube, uploads_playlist_id: str, target_tag: s
|
|||||||
|
|
||||||
return matched_videos
|
return matched_videos
|
||||||
|
|
||||||
def main():
|
def find_tags():
|
||||||
credentials = load_credentials()
|
|
||||||
if not credentials:
|
if not config.CREDENTIALS:
|
||||||
return
|
return
|
||||||
|
|
||||||
youtube = build('youtube', 'v3', credentials=credentials)
|
youtube = build('youtube', 'v3', credentials=config.CREDENTIALS)
|
||||||
|
|
||||||
# 1. Fetch your dynamic uploads playlist pointer
|
# 1. Fetch your dynamic uploads playlist pointer
|
||||||
uploads_id = get_my_uploads_playlist_id(youtube)
|
uploads_id = get_my_uploads_playlist_id(youtube)
|
||||||
@@ -144,4 +119,4 @@ def main():
|
|||||||
print(f"{index}. {item['title']} -> https://youtu.be{item['id']}")
|
print(f"{index}. {item['title']} -> https://youtu.be{item['id']}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
find_tags()
|
||||||
@@ -14,7 +14,16 @@ nltk.download('punkt_tab', quiet=True)
|
|||||||
nltk.download('averaged_perceptron_tagger', quiet=True) # Required for POS tagging
|
nltk.download('averaged_perceptron_tagger', quiet=True) # Required for POS tagging
|
||||||
nltk.download('averaged_perceptron_tagger_eng', quiet=True)
|
nltk.download('averaged_perceptron_tagger_eng', quiet=True)
|
||||||
|
|
||||||
def extract_text_from_srt(file_path: str):
|
def extract_text_from_srt(file_path: str) -> str:
|
||||||
|
"""
|
||||||
|
Extracts the text from the srt file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path (str): is the path to the str file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
returns (str): returns the cleaned up text.
|
||||||
|
"""
|
||||||
with open(file_path, 'r', encoding='utf-8') as file:
|
with open(file_path, 'r', encoding='utf-8') as file:
|
||||||
content = file.read()
|
content = file.read()
|
||||||
# Remove SRT timestamps and sequence numbers
|
# Remove SRT timestamps and sequence numbers
|
||||||
@@ -22,7 +31,16 @@ def extract_text_from_srt(file_path: str):
|
|||||||
clean_text = re.sub(r'\d+', '', clean_text)
|
clean_text = re.sub(r'\d+', '', clean_text)
|
||||||
return clean_text
|
return clean_text
|
||||||
|
|
||||||
def extract_text_from_json(file_path: str):
|
def extract_text_from_json(file_path: str) -> str:
|
||||||
|
"""
|
||||||
|
Extracts the text from the json file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path (str): is the path to the json file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
returns (str): returns the cleaned up text.
|
||||||
|
"""
|
||||||
with open(file_path, "r", encoding="utf-8") as file:
|
with open(file_path, "r", encoding="utf-8") as file:
|
||||||
data = json.load(file)
|
data = json.load(file)
|
||||||
|
|
||||||
@@ -34,7 +52,17 @@ def extract_text_from_json(file_path: str):
|
|||||||
# Return a single merged string of all chat text
|
# Return a single merged string of all chat text
|
||||||
return " ".join(messages)
|
return " ".join(messages)
|
||||||
|
|
||||||
def get_top_nouns(file_path: str, top_n: int = 10):
|
def get_top_nouns(file_path: str, top_n: int = 10) -> list:
|
||||||
|
"""
|
||||||
|
Gets the top number of nouns based on past (top_n) arg.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
file_path (str): is the path to the text file.
|
||||||
|
top_n (int): is the number of nouns to return.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
returns (list): returns a list of nouns.
|
||||||
|
"""
|
||||||
# 1. Extract raw text
|
# 1. Extract raw text
|
||||||
if file_path.endswith(".srt"):
|
if file_path.endswith(".srt"):
|
||||||
raw_text = extract_text_from_srt(file_path)
|
raw_text = extract_text_from_srt(file_path)
|
||||||
@@ -126,7 +126,6 @@ def fit_to_9_16_letterbox(input_path: str, top_text: str = "TOP TEXT", bottom_te
|
|||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import os
|
import os
|
||||||
import json
|
|
||||||
import argparse
|
import argparse
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from google.oauth2.credentials import Credentials
|
|
||||||
from google_auth_oauthlib.flow import InstalledAppFlow
|
|
||||||
from google.auth.transport.requests import Request
|
|
||||||
from googleapiclient.discovery import build
|
from googleapiclient.discovery import build
|
||||||
from googleapiclient.http import MediaFileUpload
|
from googleapiclient.http import MediaFileUpload
|
||||||
from googleapiclient.errors import HttpError
|
from googleapiclient.errors import HttpError
|
||||||
|
|
||||||
|
import package.youtube.config as config
|
||||||
|
|
||||||
class CategoryId(Enum):
|
class CategoryId(Enum):
|
||||||
"""Official YouTube Category IDs for API Uploads."""
|
"""Official YouTube Category IDs for API Uploads."""
|
||||||
|
|
||||||
@@ -30,34 +29,7 @@ class CategoryId(Enum):
|
|||||||
SCIENCE_AND_TECHNOLOGY = "28"
|
SCIENCE_AND_TECHNOLOGY = "28"
|
||||||
NONPROFITS_AND_ACTIVISM = "29"
|
NONPROFITS_AND_ACTIVISM = "29"
|
||||||
|
|
||||||
def load_credentials():
|
def upload_video(file_path: str, title: str, category: CategoryId, description: str = "", privacyStatus: str = 'private', tags: list = None, release_time: datetime = None) -> bool:
|
||||||
"""Load credentials from secrets.json"""
|
|
||||||
try:
|
|
||||||
with open('secrets.json', 'r') as f:
|
|
||||||
creds_data = json.load(f)
|
|
||||||
|
|
||||||
credentials = Credentials(
|
|
||||||
token=creds_data['token'],
|
|
||||||
refresh_token=creds_data['refresh_token'],
|
|
||||||
token_uri=creds_data['token_uri'],
|
|
||||||
client_id=creds_data['client_id'],
|
|
||||||
client_secret=creds_data['client_secret'],
|
|
||||||
scopes=creds_data['scopes']
|
|
||||||
)
|
|
||||||
|
|
||||||
# Refresh token if expired
|
|
||||||
if credentials.expired:
|
|
||||||
credentials.refresh(Request())
|
|
||||||
|
|
||||||
return credentials
|
|
||||||
except FileNotFoundError:
|
|
||||||
print("Error: secrets.json not found! Please run setup.py first.")
|
|
||||||
return None
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error loading credentials: {str(e)}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def upload_video(file_path: str, title: str, category: CategoryId, description: str = "", privacyStatus: str = 'private', tags: list = None, release_time: datetime = None):
|
|
||||||
"""
|
"""
|
||||||
Upload a video to YouTube
|
Upload a video to YouTube
|
||||||
|
|
||||||
@@ -82,12 +54,11 @@ def upload_video(file_path: str, title: str, category: CategoryId, description:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Load credentials
|
# Load credentials
|
||||||
credentials = load_credentials()
|
if not config.CREDENTIALS:
|
||||||
if not credentials:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Create YouTube API client
|
# Create YouTube API client
|
||||||
youtube = build('youtube', 'v3', credentials=credentials)
|
youtube = build('youtube', 'v3', credentials=config.CREDENTIALS)
|
||||||
|
|
||||||
# Configure the status object dynamically
|
# Configure the status object dynamically
|
||||||
status_body = {
|
status_body = {
|
||||||
@@ -197,5 +168,6 @@ def main():
|
|||||||
tags=parsed_tags,
|
tags=parsed_tags,
|
||||||
release_time=release_datetime
|
release_time=release_datetime
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
@@ -5,43 +5,66 @@ anyio==4.15.1
|
|||||||
attrs==26.1.0
|
attrs==26.1.0
|
||||||
av==18.1.0
|
av==18.1.0
|
||||||
certifi==2026.7.22
|
certifi==2026.7.22
|
||||||
|
cffi==2.1.1
|
||||||
charset-normalizer==3.5.1
|
charset-normalizer==3.5.1
|
||||||
click==8.5.0
|
click==8.5.0
|
||||||
|
cloudpickle==3.1.2
|
||||||
|
cryptography==50.0.1
|
||||||
ctranslate2==4.8.2
|
ctranslate2==4.8.2
|
||||||
decorator==5.3.1
|
decorator==5.3.1
|
||||||
|
defusedxml==0.7.1
|
||||||
enum-tools==0.13.0
|
enum-tools==0.13.0
|
||||||
faster-whisper==1.2.1
|
faster-whisper==1.2.1
|
||||||
filelock==3.32.6
|
filelock==3.32.6
|
||||||
flatbuffers==25.12.19
|
flatbuffers==25.12.19
|
||||||
frozenlist==1.8.0
|
frozenlist==1.8.0
|
||||||
fsspec==2026.7.0
|
fsspec==2026.7.0
|
||||||
|
google-api-core==2.36.0
|
||||||
|
google-api-python-client==2.200.0
|
||||||
|
google-auth==2.58.0
|
||||||
|
google-auth-httplib2==0.4.2
|
||||||
|
google-auth-oauthlib==1.4.1
|
||||||
|
googleapis-common-protos==1.75.3
|
||||||
h11==0.16.0
|
h11==0.16.0
|
||||||
hf-xet==1.6.0
|
hf-xet==1.6.0
|
||||||
httpcore==1.0.9
|
httpcore==1.0.9
|
||||||
|
httplib2==0.32.0
|
||||||
httpx==0.28.1
|
httpx==0.28.1
|
||||||
huggingface_hub==1.31.0
|
huggingface_hub==1.31.0
|
||||||
idna==3.19
|
idna==3.19
|
||||||
ImageIO==2.37.4
|
ImageIO==2.37.4
|
||||||
imageio-ffmpeg==0.6.0
|
imageio-ffmpeg==0.6.0
|
||||||
|
joblib==1.6.0
|
||||||
moviepy==2.2.1
|
moviepy==2.2.1
|
||||||
multidict==6.8.0
|
multidict==6.8.0
|
||||||
|
nltk==3.10.3
|
||||||
numpy==2.5.3
|
numpy==2.5.3
|
||||||
|
oauthlib==3.3.1
|
||||||
onnxruntime==1.30.0
|
onnxruntime==1.30.0
|
||||||
opencv-python==5.0.0.93
|
opencv-python==5.0.0.93
|
||||||
|
opentelemetry-api==1.44.0
|
||||||
packaging==26.3
|
packaging==26.3
|
||||||
pillow==11.3.0
|
pillow==11.3.0
|
||||||
proglog==0.1.12
|
proglog==0.1.12
|
||||||
propcache==0.5.2
|
propcache==0.5.2
|
||||||
|
proto-plus==1.28.4
|
||||||
protobuf==7.36.1
|
protobuf==7.36.1
|
||||||
|
pyasn1==0.6.4
|
||||||
|
pyasn1_modules==0.4.2
|
||||||
|
pycparser==3.0
|
||||||
Pygments==2.21.0
|
Pygments==2.21.0
|
||||||
|
pyparsing==3.3.2
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.9.0.post0
|
||||||
python-dotenv==1.2.3
|
python-dotenv==1.2.3
|
||||||
PyYAML==6.0.3
|
PyYAML==6.0.3
|
||||||
|
regex==2026.9.10
|
||||||
requests==2.34.2
|
requests==2.34.2
|
||||||
|
requests-oauthlib==2.0.0
|
||||||
six==1.17.0
|
six==1.17.0
|
||||||
tokenizers==0.23.2
|
tokenizers==0.23.2
|
||||||
tqdm==4.70.1
|
tqdm==4.70.1
|
||||||
twitchAPI==4.5.0
|
twitchAPI==4.5.0
|
||||||
typing_extensions==4.16.0
|
typing_extensions==4.16.0
|
||||||
|
uritemplate==4.2.0
|
||||||
urllib3==2.7.0
|
urllib3==2.7.0
|
||||||
yarl==1.24.5
|
yarl==1.24.5
|
||||||
Reference in new issue
Block a user