import os import pickle import sys from googleapiclient.discovery import build from googleapiclient.http import MediaFileUpload from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request # If modifying these SCOPES, delete the file token.pickle. SCOPES = ['https://www.googleapis.com/auth/drive.file'] def authenticate_drive(): """Authenticate and return the Google Drive service with fallback methods.""" creds = None if os.path.exists('token.pickle'): with open('token.pickle', 'rb') as token: creds = pickle.load(token) # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: # Make sure credentials.json is from a Desktop application OAuth client flow = InstalledAppFlow.from_client_secrets_file( 'credentials.json', SCOPES) print("\n=== Google Drive Authentication Required ===") try: # First try: use a local server without opening a browser print("Attempting local server authentication...") creds = flow.run_local_server(port=0, open_browser=False) print("Authentication successful!") except Exception as local_server_error: print(f"Local server authentication failed: {local_server_error}") print("\nTrying alternative authentication method...") # Second try: Manual authentication with copy-paste auth_url, _ = flow.authorization_url(access_type='offline', include_granted_scopes='true') print(f"\nPlease go to this URL in any browser:\n\n{auth_url}\n") print("After approval, you'll be redirected to a page that says 'The authentication flow has completed.'") print("Copy the URL of that page (which contains 'code=') and paste it below.") redirect_url = input("\nEnter the full redirect URL: ").strip() # Extract the authorization code from the redirect URL try: # Find the code parameter in the URL import re code_match = re.search(r'code=([^&]+)', redirect_url) if code_match: code = code_match.group(1) flow.fetch_token(code=code) creds = flow.credentials print("Authentication successful!") else: # If we can't find a code, let the user paste just the code print("\nCouldn't extract authorization code from URL.") code = input("Please paste just the authorization code: ").strip() flow.fetch_token(code=code) creds = flow.credentials print("Authentication successful!") except Exception as e: print(f"Error processing authentication: {e}") print("Please ensure you're using a Desktop application OAuth client in Google Cloud Console.") sys.exit(1) # Save the credentials for the next run with open('token.pickle', 'wb') as token: pickle.dump(creds, token) service = build('drive', 'v3', credentials=creds) return service def get_or_create_folder(service, folder_name, parent_id=None): """Get the folder ID by name, or create it if it doesn't exist.""" query = f"name='{folder_name}' and mimeType='application/vnd.google-apps.folder' and trashed=false" if parent_id: query += f" and '{parent_id}' in parents" results = service.files().list(q=query, spaces='drive', fields="files(id, name)").execute() items = results.get('files', []) if items: return items[0]['id'] # Create folder file_metadata = { 'name': folder_name, 'mimeType': 'application/vnd.google-apps.folder' } if parent_id: file_metadata['parents'] = [parent_id] folder = service.files().create(body=file_metadata, fields='id').execute() return folder.get('id') def upload_file_to_folder(service, file_path, folder_id): """Upload a file to the specified Google Drive folder. Returns the file's webViewLink.""" file_name = os.path.basename(file_path) file_metadata = { 'name': file_name, 'parents': [folder_id] } print(f"Uploading {file_name}...") media = MediaFileUpload(file_path, resumable=True) uploaded = service.files().create( body=file_metadata, media_body=media, fields='id, webViewLink' ).execute() print(f"Successfully uploaded {file_name}") return uploaded.get('webViewLink') def upload_files_to_drive(file_paths, folder_name="Farmonaut AI Videos"): """ Authenticate and upload a list of files to a Google Drive folder. Returns a dict of {file_path: webViewLink} """ try: print("Authenticating with Google Drive...") service = authenticate_drive() print(f"Creating or finding folder: {folder_name}") folder_id = get_or_create_folder(service, folder_name) print(f"Using folder ID: {folder_id}") links = {} total_files = len(file_paths) for i, file_path in enumerate(file_paths, 1): print(f"\nProcessing file {i}/{total_files}: {os.path.basename(file_path)}") try: if os.path.exists(file_path): link = upload_file_to_folder(service, file_path, folder_id) links[file_path] = link else: links[file_path] = f"Error: File not found" print(f"Error: File not found - {file_path}") except Exception as e: links[file_path] = f"Error: {str(e)}" print(f"Error uploading {file_path}: {str(e)}") return links except Exception as e: print(f"Authentication or general error: {str(e)}") return {file_path: f"Authentication error: {str(e)}" for file_path in file_paths} def display_results(links): """Display the results in a user-friendly format.""" print("\n===== UPLOAD RESULTS =====") success_count = 0 failure_count = 0 for file_path, link in links.items(): file_name = os.path.basename(file_path) if isinstance(link, str) and link.startswith("Error"): failure_count += 1 print(f"❌ {file_name}: {link}") else: success_count += 1 print(f"✅ {file_name}: {link}") print(f"\nSummary: {success_count} files uploaded successfully, {failure_count} files failed.") if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: python gdrive_upload.py [ ...]") sys.exit(1) file_paths = sys.argv[1:] print(f"Starting upload of {len(file_paths)} files to Google Drive") links = upload_files_to_drive(file_paths) display_results(links)