|
|
@@ -4,159 +4,118 @@ from google.oauth2 import service_account
|
|
|
import os
|
|
|
import pickle
|
|
|
import json
|
|
|
+import sqlite3
|
|
|
import subprocess
|
|
|
+import shutil
|
|
|
import tempfile
|
|
|
-import time
|
|
|
from pathlib import Path
|
|
|
+from datetime import datetime
|
|
|
+import logging
|
|
|
|
|
|
# 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:
|
|
|
+# Configure logging
|
|
|
+logger = logging.getLogger(__name__)
|
|
|
+
|
|
|
+def extract_chrome_cookies(output_file="youtube_cookies.txt"):
|
|
|
+ """Extract YouTube cookies from Chrome browser."""
|
|
|
+ try:
|
|
|
+ # Common Chrome cookie database locations
|
|
|
+ chrome_paths = [
|
|
|
+ Path.home() / ".config/google-chrome/Default/Cookies",
|
|
|
+ Path.home() / ".config/google-chrome/Profile 1/Cookies",
|
|
|
+ Path.home() / ".config/chromium/Default/Cookies",
|
|
|
+ Path.home() / "snap/chromium/common/chromium/Default/Cookies",
|
|
|
+ Path.home() / ".var/app/com.google.Chrome/config/google-chrome/Default/Cookies",
|
|
|
+ ]
|
|
|
+
|
|
|
+ # Find existing Chrome cookies database
|
|
|
+ chrome_cookies_db = None
|
|
|
+ for path in chrome_paths:
|
|
|
+ if path.exists():
|
|
|
+ chrome_cookies_db = path
|
|
|
+ logger.info(f"Found Chrome cookies database: {chrome_cookies_db}")
|
|
|
+ break
|
|
|
+
|
|
|
+ if not chrome_cookies_db:
|
|
|
+ logger.warning("Chrome cookies database not found")
|
|
|
+ return False
|
|
|
+
|
|
|
+ # Use yt-dlp to extract cookies directly from browser
|
|
|
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
|
|
|
- ]
|
|
|
-
|
|
|
+ cmd = ['yt-dlp', '--cookies-from-browser', 'chrome', '--print-to-file', 'cookies', output_file, '--no-download', 'https://www.youtube.com']
|
|
|
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
|
|
|
+ if result.returncode == 0:
|
|
|
+ logger.info(f"Successfully extracted Chrome cookies to {output_file}")
|
|
|
+ return True
|
|
|
else:
|
|
|
- print(f" ❌ Failed to extract from {browser}")
|
|
|
- # Clean up any partial cookie file
|
|
|
- if os.path.exists(cookies_file):
|
|
|
- os.remove(cookies_file)
|
|
|
-
|
|
|
+ logger.error(f"yt-dlp cookie extraction failed: {result.stderr}")
|
|
|
+ return False
|
|
|
+
|
|
|
except subprocess.TimeoutExpired:
|
|
|
- print(f" ⏰ Timeout extracting from {browser}")
|
|
|
+ logger.error("Cookie extraction timed out")
|
|
|
+ return False
|
|
|
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
|
|
|
+ logger.error(f"Error running yt-dlp cookie extraction: {e}")
|
|
|
+ return False
|
|
|
+
|
|
|
except Exception as e:
|
|
|
- print(f"❌ Failed to create cookie file: {e}")
|
|
|
- return None
|
|
|
+ logger.error(f"Error extracting Chrome cookies: {e}")
|
|
|
+ return False
|
|
|
|
|
|
-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']
|
|
|
- }
|
|
|
- ]
|
|
|
+def check_browser_cookies():
|
|
|
+ """Check which browsers have accessible cookies for YouTube."""
|
|
|
+ browsers = ['chrome', 'chromium', 'firefox', 'brave', 'edge']
|
|
|
+ available_browsers = []
|
|
|
|
|
|
- for test in test_commands:
|
|
|
+ for browser in browsers:
|
|
|
try:
|
|
|
- print(f" Testing: {test['name']}")
|
|
|
- result = subprocess.run(test['cmd'], capture_output=True, text=True, timeout=20)
|
|
|
-
|
|
|
+ # Test if browser cookies are accessible
|
|
|
+ cmd = ['yt-dlp', '--cookies-from-browser', browser, '--simulate', '--quiet', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ']
|
|
|
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
|
|
if result.returncode == 0:
|
|
|
- print(f" ✅ Success: {result.stdout.strip()}")
|
|
|
- return test['name']
|
|
|
+ available_browsers.append(browser)
|
|
|
+ logger.info(f"Browser {browser} has accessible cookies")
|
|
|
else:
|
|
|
- print(f" ❌ Failed: {result.stderr[:100]}...")
|
|
|
-
|
|
|
- except subprocess.TimeoutExpired:
|
|
|
- print(f" ⏰ Timeout")
|
|
|
- except Exception as e:
|
|
|
- print(f" ❌ Error: {e}")
|
|
|
+ logger.debug(f"Browser {browser} cookies not accessible: {result.stderr}")
|
|
|
+ except (subprocess.TimeoutExpired, subprocess.SubprocessError) as e:
|
|
|
+ logger.debug(f"Error checking {browser} cookies: {e}")
|
|
|
+ continue
|
|
|
|
|
|
- print(" ⚠️ All YouTube access tests failed")
|
|
|
- return None
|
|
|
+ return available_browsers
|
|
|
|
|
|
-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 update_cookies_from_browser(browser='chrome', output_file="youtube_cookies.txt"):
|
|
|
+ """Update cookies file from specified browser."""
|
|
|
+ try:
|
|
|
+ logger.info(f"Updating cookies from {browser} browser...")
|
|
|
+
|
|
|
+ # Use yt-dlp to extract cookies from browser
|
|
|
+ cmd = ['yt-dlp', '--cookies-from-browser', browser, '--print-to-file', 'cookies', output_file, '--no-download', 'https://www.youtube.com']
|
|
|
+ result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
|
|
+
|
|
|
+ if result.returncode == 0:
|
|
|
+ logger.info(f"Successfully updated cookies from {browser} to {output_file}")
|
|
|
+
|
|
|
+ # Verify the cookies file was created and has content
|
|
|
+ cookies_path = Path(output_file)
|
|
|
+ if cookies_path.exists() and cookies_path.stat().st_size > 0:
|
|
|
+ logger.info(f"Cookies file created: {cookies_path} ({cookies_path.stat().st_size} bytes)")
|
|
|
+ return True
|
|
|
+ else:
|
|
|
+ logger.warning("Cookies file was not created or is empty")
|
|
|
+ return False
|
|
|
+ else:
|
|
|
+ logger.error(f"Failed to extract cookies from {browser}: {result.stderr}")
|
|
|
+ return False
|
|
|
+
|
|
|
+ except subprocess.TimeoutExpired:
|
|
|
+ logger.error("Cookie extraction timed out")
|
|
|
+ return False
|
|
|
+ except Exception as e:
|
|
|
+ logger.error(f"Error updating cookies from browser: {e}")
|
|
|
+ return False
|
|
|
|
|
|
def get_service_account_token():
|
|
|
"""Authenticate using service account (no user interaction needed)."""
|
|
|
@@ -255,37 +214,53 @@ def get_token():
|
|
|
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}")
|
|
|
+ # Set up logging
|
|
|
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
|
|
+
|
|
|
+ if "--extract-cookies" in sys.argv:
|
|
|
+ # Extract cookies from Chrome
|
|
|
+ browser = 'chrome'
|
|
|
+ if "--browser" in sys.argv:
|
|
|
+ browser_idx = sys.argv.index("--browser") + 1
|
|
|
+ if browser_idx < len(sys.argv):
|
|
|
+ browser = sys.argv[browser_idx]
|
|
|
+
|
|
|
+ output_file = "youtube_cookies.txt"
|
|
|
+ if "--output" in sys.argv:
|
|
|
+ output_idx = sys.argv.index("--output") + 1
|
|
|
+ if output_idx < len(sys.argv):
|
|
|
+ output_file = sys.argv[output_idx]
|
|
|
+
|
|
|
+ print(f"Extracting cookies from {browser} browser...")
|
|
|
+ success = update_cookies_from_browser(browser, output_file)
|
|
|
+ if success:
|
|
|
+ print(f"Cookies successfully extracted to {output_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}")
|
|
|
+ print("Cookie extraction failed")
|
|
|
+ sys.exit(1)
|
|
|
+
|
|
|
+ elif "--check-browsers" in sys.argv:
|
|
|
+ # Check available browsers
|
|
|
+ print("Checking available browsers with YouTube cookies...")
|
|
|
+ browsers = check_browser_cookies()
|
|
|
+ if browsers:
|
|
|
+ print(f"Available browsers: {', '.join(browsers)}")
|
|
|
else:
|
|
|
- print("❌ YouTube access not working")
|
|
|
- sys.exit(0)
|
|
|
+ print("No browsers with accessible YouTube cookies found")
|
|
|
+
|
|
|
+ elif "--interactive" in sys.argv:
|
|
|
+ creds = get_token_interactive()
|
|
|
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")
|
|
|
+ print("To extract cookies from browser, run: python3 auth.py --extract-cookies")
|
|
|
+ print("To check available browsers, run: python3 auth.py --check-browsers")
|
|
|
|
|
|
- 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)
|
|
|
+ if "--extract-cookies" not in sys.argv and "--check-browsers" not in sys.argv:
|
|
|
+ if creds:
|
|
|
+ print("Authentication successful!")
|
|
|
+ else:
|
|
|
+ print("Authentication failed!")
|
|
|
+ sys.exit(1)
|
|
|
|