from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request from google.oauth2 import service_account import os import pickle import json import subprocess import tempfile import time from pathlib import Path # OAuth 2.0 scopes SCOPES = ["https://www.googleapis.com/auth/youtube.readonly"] def extract_cookies_from_browser(): """Extract cookies from browsers to bypass YouTube bot detection.""" print("๐Ÿช Attempting to extract cookies from browsers...") # Try different browsers in order of preference browsers = ['chrome', 'firefox', 'edge', 'safari', 'opera', 'brave'] cookies_file = "youtube_cookies.txt" for browser in browsers: try: print(f" Trying {browser}...") # Use yt-dlp's built-in cookie extraction cmd = [ 'yt-dlp', '--cookies-from-browser', browser, '--cookies', cookies_file, '--simulate', '--no-warnings', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' # Test video ] result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) if result.returncode == 0 and os.path.exists(cookies_file): print(f" โœ… Successfully extracted cookies from {browser}") return cookies_file else: print(f" โŒ Failed to extract from {browser}") # Clean up any partial cookie file if os.path.exists(cookies_file): os.remove(cookies_file) except subprocess.TimeoutExpired: print(f" โฐ Timeout extracting from {browser}") except Exception as e: print(f" โŒ Error with {browser}: {e}") print(" โš ๏ธ Could not extract cookies from any browser") return None def generate_youtube_cookies(): """Generate or update YouTube cookies for yt-dlp.""" cookies_file = "youtube_cookies.txt" # Check if cookies file already exists and is recent if os.path.exists(cookies_file): file_age = time.time() - os.path.getmtime(cookies_file) if file_age < 3600: # Less than 1 hour old print(f"โœ… Using existing cookies file (age: {file_age/60:.1f} minutes)") return cookies_file else: print(f"๐Ÿ”„ Cookies file is {file_age/3600:.1f} hours old, refreshing...") # Try to extract fresh cookies result = extract_cookies_from_browser() if result: return result # If extraction failed, try manual cookie creation print("๐Ÿ”ง Attempting manual cookie setup...") return create_manual_cookies() def create_manual_cookies(): """Create a basic cookie file for YouTube.""" cookies_file = "youtube_cookies.txt" # Create a basic Netscape-format cookie file # This won't have real session cookies but may help with some requests cookie_content = """# Netscape HTTP Cookie File # This is a generated file! Do not edit. .youtube.com TRUE / FALSE 0 PREF f1=50000000 .youtube.com TRUE / FALSE 0 VISITOR_INFO1_LIVE .youtube.com TRUE / TRUE 0 YSC .google.com TRUE / FALSE 0 NID """ try: with open(cookies_file, 'w') as f: f.write(cookie_content) print(f"๐Ÿ“ Created basic cookie file: {cookies_file}") return cookies_file except Exception as e: print(f"โŒ Failed to create cookie file: {e}") return None def test_youtube_access(): """Test if YouTube access works with current authentication.""" print("๐Ÿงช Testing YouTube access...") cookies_file = "youtube_cookies.txt" test_commands = [ # Test with cookies { 'name': 'With Cookies', 'cmd': ['yt-dlp', '--cookies', cookies_file, '--simulate', '--print', 'title', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'] }, # Test with browser extraction { 'name': 'Browser Extraction', 'cmd': ['yt-dlp', '--cookies-from-browser', 'chrome', '--simulate', '--print', 'title', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'] }, # Test with user agent { 'name': 'Custom User Agent', 'cmd': ['yt-dlp', '--user-agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', '--simulate', '--print', 'title', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'] } ] for test in test_commands: try: print(f" Testing: {test['name']}") result = subprocess.run(test['cmd'], capture_output=True, text=True, timeout=20) if result.returncode == 0: print(f" โœ… Success: {result.stdout.strip()}") return test['name'] else: print(f" โŒ Failed: {result.stderr[:100]}...") except subprocess.TimeoutExpired: print(f" โฐ Timeout") except Exception as e: print(f" โŒ Error: {e}") print(" โš ๏ธ All YouTube access tests failed") return None def setup_youtube_access(): """Setup YouTube access with cookie authentication.""" print("๐Ÿ”ง Setting up YouTube access with cookie authentication...") # Generate cookies cookies_file = generate_youtube_cookies() if cookies_file: # Test the access working_method = test_youtube_access() if working_method: print(f"โœ… YouTube access working with: {working_method}") return cookies_file print("โš ๏ธ YouTube access setup incomplete - may encounter bot detection") return None def get_service_account_token(): """Authenticate using service account (no user interaction needed).""" service_account_file = "service_account.json" if not os.path.exists(service_account_file): print(f"Service account file {service_account_file} not found.") print("To use service account authentication:") print("1. Go to Google Cloud Console") print("2. Navigate to IAM & Admin > Service Accounts") print("3. Create a new service account") print("4. Download the JSON key file as 'service_account.json'") return None try: creds = service_account.Credentials.from_service_account_file( service_account_file, scopes=SCOPES) print("Service account authentication successful!") return creds except Exception as e: print(f"Service account authentication failed: {e}") return None def get_token_interactive(): """Perform OAuth authentication with user interaction.""" creds = None token_file = "youtube_token.pickle" # Check if token file exists if os.path.exists(token_file): with open(token_file, "rb") as token: creds = pickle.load(token) # If no valid credentials, authenticate user if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: try: creds.refresh(Request()) print("Token refreshed successfully!") except Exception as e: print(f"Token refresh failed: {e}") creds = None if not creds: print("Starting interactive authentication...") flow = InstalledAppFlow.from_client_secrets_file("client_secret.json", SCOPES) creds = flow.run_local_server(port=8080) # Save the credentials to a file with open(token_file, "wb") as token: pickle.dump(creds, token) print(f"Token saved to {token_file}") else: print("Token already exists and is valid.") return creds def get_token_non_interactive(): """Try non-interactive authentication methods first.""" # Try service account first creds = get_service_account_token() if creds: return creds # Try existing saved token token_file = "youtube_token.pickle" if os.path.exists(token_file): try: with open(token_file, "rb") as token: creds = pickle.load(token) if creds and creds.valid: print("Using existing valid token.") return creds elif creds and creds.expired and creds.refresh_token: try: creds.refresh(Request()) print("Token refreshed successfully!") # Save refreshed token with open(token_file, "wb") as token: pickle.dump(creds, token) return creds except Exception as e: print(f"Token refresh failed: {e}") except Exception as e: print(f"Error loading saved token: {e}") print("No valid non-interactive authentication method available.") print("Run with --interactive flag or set up service account authentication.") return None def get_token(): """Main authentication function - tries non-interactive first.""" return get_token_non_interactive() if __name__ == "__main__": import sys if "--interactive" in sys.argv: creds = get_token_interactive() elif "--cookies" in sys.argv: print("๐Ÿช Setting up YouTube cookies...") cookies_file = setup_youtube_access() if cookies_file: print(f"โœ… Cookie setup complete: {cookies_file}") else: print("โŒ Cookie setup failed") sys.exit(0) elif "--test" in sys.argv: print("๐Ÿงช Testing YouTube access...") working_method = test_youtube_access() if working_method: print(f"โœ… YouTube access working with: {working_method}") else: print("โŒ YouTube access not working") sys.exit(0) else: creds = get_token_non_interactive() if not creds: print("\nTo authenticate interactively, run: python3 auth.py --interactive") print("To setup YouTube cookies, run: python3 auth.py --cookies") print("To test YouTube access, run: python3 auth.py --test") if creds: print("Authentication successful!") # Also setup cookies when authenticating print("\n๐Ÿช Setting up YouTube cookies for bot detection bypass...") setup_youtube_access() else: print("Authentication failed!") sys.exit(1)