89 lines
3.2 KiB
Python
89 lines
3.2 KiB
Python
import os
|
|
import pickle, logging
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
|
from google.auth.transport.requests import Request
|
|
from googleapiclient.discovery import build
|
|
from googleapiclient.http import MediaFileUpload
|
|
from modules.title_utils import get_output_filename, generate_montage_title
|
|
|
|
# Define OAuth scopes and token paths
|
|
SCOPES = ["https://www.googleapis.com/auth/youtube.upload"]
|
|
TOKEN_PATH = Path("token.pickle")
|
|
CLIENT_SECRETS_FILE = Path("client_secrets.json")
|
|
|
|
def authenticate_youtube():
|
|
"""Handles YouTube OAuth flow and returns a service client."""
|
|
creds = None
|
|
|
|
if TOKEN_PATH.exists():
|
|
with open(TOKEN_PATH, "rb") as token_file:
|
|
creds = pickle.load(token_file)
|
|
|
|
if not creds or not creds.valid:
|
|
if creds and creds.expired and creds.refresh_token:
|
|
creds.refresh(Request())
|
|
else:
|
|
if not CLIENT_SECRETS_FILE.exists():
|
|
raise FileNotFoundError("client_secrets.json not found.")
|
|
flow = InstalledAppFlow.from_client_secrets_file(
|
|
str(CLIENT_SECRETS_FILE), SCOPES
|
|
)
|
|
creds = flow.run_local_server(port=0)
|
|
with open(TOKEN_PATH, "wb") as token_file:
|
|
pickle.dump(creds, token_file)
|
|
|
|
return build("youtube", "v3", credentials=creds)
|
|
|
|
def generate_description(clip_path: Path, stream_date: datetime, is_montage: bool = False) -> str:
|
|
"""Creates a dynamic and fun YouTube description."""
|
|
kill_count_guess = sum(word.isdigit() for word in clip_path.stem.split())
|
|
date_str = stream_date.strftime("%B %d, %Y")
|
|
|
|
intro = "Gramps is back in Fortnite with another spicy highlight! 🦥"
|
|
if is_montage:
|
|
body = (
|
|
f"This reel features an outrageous compilation of top plays from our {date_str} stream.\n"
|
|
f"{kill_count_guess} eliminations of stupendous magnitude that must be seen to be believed!"
|
|
)
|
|
else:
|
|
body = (
|
|
f"Recorded live on {date_str}, this clip captures one of many wild moments "
|
|
"from the battlefield. Grab your popcorn. 🎮"
|
|
)
|
|
|
|
hashtags = "#Fortnite #Gaming #SeniorGamer #LlamaChileShop #EpicMoments"
|
|
|
|
return f"{intro}\n\n{body}\n\nSubscribe for more: https://youtube.com/@llamachileshop\n{hashtags}"
|
|
|
|
def upload_to_youtube(video_path: Path, title: str, description: str, is_short: bool = False) -> str:
|
|
"""Uploads the video to YouTube and returns the video URL."""
|
|
youtube = authenticate_youtube()
|
|
|
|
request_body = {
|
|
"snippet": {
|
|
"title": title,
|
|
"description": description,
|
|
"tags": ["Fortnite", "Gaming", "Senior Gamer", "LlamaChileShop"],
|
|
"categoryId": "20", # Gaming
|
|
},
|
|
"status": {
|
|
"privacyStatus": "private",
|
|
"selfDeclaredMadeForKids": False,
|
|
}
|
|
}
|
|
|
|
media = MediaFileUpload(str(video_path), mimetype="video/mp4", resumable=True)
|
|
|
|
request = youtube.videos().insert(
|
|
part="snippet,status",
|
|
body=request_body,
|
|
media_body=media
|
|
)
|
|
|
|
response = request.execute()
|
|
video_id = response["id"]
|
|
return f"https://youtu.be/{video_id}"
|