auth.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. from google_auth_oauthlib.flow import InstalledAppFlow
  2. from google.auth.transport.requests import Request
  3. import os
  4. import pickle
  5. import requests
  6. import logging
  7. from pathlib import Path
  8. # OAuth 2.0 scopes
  9. SCOPES = ["https://www.googleapis.com/auth/youtube.readonly"]
  10. # Configure logging
  11. logger = logging.getLogger(__name__)
  12. def get_token():
  13. """Perform OAuth authentication and save the token."""
  14. creds = None
  15. # The token file to save credentials
  16. token_file = "youtube_token.pickle"
  17. # Check if token file exists
  18. if os.path.exists(token_file):
  19. with open(token_file, "rb") as token:
  20. creds = pickle.load(token)
  21. # If no valid credentials, authenticate user
  22. if not creds or not creds.valid:
  23. if creds and creds.expired and creds.refresh_token:
  24. creds.refresh(Request())
  25. else:
  26. flow = InstalledAppFlow.from_client_secrets_file("client_secret.json", SCOPES)
  27. creds = flow.run_local_server(port=8080)
  28. # Save the credentials to a file
  29. with open(token_file, "wb") as token:
  30. pickle.dump(creds, token)
  31. print(f"Token saved to {token_file}")
  32. else:
  33. print("Token already exists and is valid.")
  34. return creds
  35. def create_cookies_from_token(output_file="youtube_cookies.txt"):
  36. """Create a cookies file using the OAuth token for yt-dlp authentication."""
  37. try:
  38. # Get valid credentials
  39. creds = get_token()
  40. if not creds:
  41. logger.error("No valid credentials available")
  42. return False
  43. # Create a session with the OAuth token
  44. session = requests.Session()
  45. # Add authorization header
  46. headers = {
  47. 'Authorization': f'Bearer {creds.token}',
  48. 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
  49. }
  50. session.headers.update(headers)
  51. # Make a request to YouTube to establish session
  52. try:
  53. response = session.get('https://www.youtube.com/', timeout=30)
  54. if response.status_code == 200:
  55. logger.info("Successfully authenticated with YouTube using OAuth token")
  56. # Extract cookies from the session
  57. cookies_content = "# Netscape HTTP Cookie File\n# Generated from OAuth token\n\n"
  58. for cookie in session.cookies:
  59. # Convert cookie to Netscape format
  60. domain = cookie.domain if cookie.domain else '.youtube.com'
  61. flag = 'TRUE' if domain.startswith('.') else 'FALSE'
  62. path = cookie.path if cookie.path else '/'
  63. secure = 'TRUE' if cookie.secure else 'FALSE'
  64. expires = str(int(cookie.expires)) if cookie.expires else '0'
  65. cookies_content += f"{domain}\t{flag}\t{path}\t{secure}\t{expires}\t{cookie.name}\t{cookie.value}\n"
  66. # Add essential YouTube cookies if they're missing
  67. essential_cookies = [
  68. ('.youtube.com', 'TRUE', '/', 'FALSE', '0', 'PREF', 'f1=50000000&hl=en'),
  69. ('.youtube.com', 'TRUE', '/', 'FALSE', '0', 'CONSENT', 'YES+'),
  70. ]
  71. for domain, flag, path, secure, expires, name, value in essential_cookies:
  72. if name not in [c.name for c in session.cookies]:
  73. cookies_content += f"{domain}\t{flag}\t{path}\t{secure}\t{expires}\t{name}\t{value}\n"
  74. # Write cookies file
  75. with open(output_file, 'w') as f:
  76. f.write(cookies_content)
  77. logger.info(f"Cookies file created: {output_file}")
  78. return True
  79. else:
  80. logger.error(f"Failed to authenticate with YouTube: {response.status_code}")
  81. return False
  82. except requests.RequestException as e:
  83. logger.error(f"Error making request to YouTube: {e}")
  84. return False
  85. except Exception as e:
  86. logger.error(f"Error creating cookies from token: {e}")
  87. return False
  88. def get_oauth_headers():
  89. """Get OAuth authorization headers for API requests."""
  90. try:
  91. creds = get_token()
  92. if not creds or not creds.valid:
  93. return None
  94. return {
  95. 'Authorization': f'Bearer {creds.token}',
  96. 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
  97. }
  98. except Exception as e:
  99. logger.error(f"Error getting OAuth headers: {e}")
  100. return None
  101. if __name__ == "__main__":
  102. import sys
  103. # Set up logging
  104. logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
  105. if "--create-cookies" in sys.argv:
  106. # Create cookies file from OAuth token
  107. output_file = "youtube_cookies.txt"
  108. if "--output" in sys.argv:
  109. output_idx = sys.argv.index("--output") + 1
  110. if output_idx < len(sys.argv):
  111. output_file = sys.argv[output_idx]
  112. print("Creating cookies file from OAuth token...")
  113. success = create_cookies_from_token(output_file)
  114. if success:
  115. print(f"✅ Cookies file created successfully: {output_file}")
  116. print("This file can now be used with yt-dlp for authentication")
  117. else:
  118. print("❌ Failed to create cookies file")
  119. sys.exit(1)
  120. else:
  121. # Default behavior - just get/refresh token
  122. creds = get_token()
  123. if creds:
  124. print("✅ OAuth token is valid and ready")
  125. print("💡 To create cookies for yt-dlp, run: python3 auth.py --create-cookies")
  126. else:
  127. print("❌ Failed to get valid OAuth token")
  128. sys.exit(1)