yt / src /drive_uploader.py
ayush77uh's picture
Initial commit
fc4c0b5
Raw
History Blame Contribute Delete
4.89 kB
"""
Google Drive Auto-Uploader using OAuth2 refresh token.
Works with personal Google accounts (not just Workspace).
"""
import os
import json
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
import io
# Scopes required for Drive upload
SCOPES = ['https://www.googleapis.com/auth/drive']
def get_drive_service():
"""
Creates a Google Drive API service using OAuth2 refresh token.
Requires 3 env vars: GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET, GOOGLE_DRIVE_REFRESH_TOKEN
"""
client_id = os.getenv("GOOGLE_OAUTH_CLIENT_ID")
client_secret = os.getenv("GOOGLE_OAUTH_CLIENT_SECRET")
refresh_token = os.getenv("GOOGLE_DRIVE_REFRESH_TOKEN")
if not all([client_id, client_secret, refresh_token]):
missing = []
if not client_id: missing.append("GOOGLE_OAUTH_CLIENT_ID")
if not client_secret: missing.append("GOOGLE_OAUTH_CLIENT_SECRET")
if not refresh_token: missing.append("GOOGLE_DRIVE_REFRESH_TOKEN")
print(f"ERROR: Missing env vars: {', '.join(missing)}", flush=True)
return None
try:
creds = Credentials(
token=None,
refresh_token=refresh_token,
client_id=client_id,
client_secret=client_secret,
token_uri="https://oauth2.googleapis.com/token",
scopes=SCOPES
)
# Refresh the access token
creds.refresh(Request())
service = build('drive', 'v3', credentials=creds)
print("βœ… Google Drive connected (OAuth2)!", flush=True)
return service
except Exception as e:
print(f"❌ Failed to connect to Google Drive: {e}", flush=True)
return None
def upload_to_drive(file_path, folder_id=None):
"""
Uploads a file to Google Drive using the user's own account.
Args:
file_path: Path to the file to upload
folder_id: Google Drive folder ID
Returns:
The file URL on Google Drive, or None if upload failed
"""
if not folder_id:
folder_id = os.getenv("GOOGLE_DRIVE_FOLDER_ID")
if not folder_id:
print("ERROR: GOOGLE_DRIVE_FOLDER_ID not set!", flush=True)
return None
service = get_drive_service()
if not service:
return None
filename = os.path.basename(file_path)
file_size_mb = os.path.getsize(file_path) / (1024 * 1024)
print(f"πŸ“€ Uploading {filename} ({file_size_mb:.1f} MB) to Google Drive...", flush=True)
file_metadata = {
'name': filename,
'parents': [folder_id]
}
media = MediaFileUpload(
file_path,
mimetype='video/mp4',
resumable=True,
chunksize=10 * 1024 * 1024 # 10MB chunks
)
try:
file = service.files().create(
body=file_metadata,
media_body=media,
fields='id, webViewLink'
).execute()
file_id = file.get('id')
file_link = file.get('webViewLink', f"https://drive.google.com/file/d/{file_id}/view")
print(f"βœ… Upload SUCCESS: {filename}", flush=True)
print(f"πŸ“Ž Link: {file_link}", flush=True)
return file_link
except Exception as e:
print(f"❌ Upload FAILED: {e}", flush=True)
return None
def list_files(folder_id):
"""
Lists files in a specific Google Drive folder.
"""
service = get_drive_service()
if not service:
return []
try:
results = service.files().list(
q=f"'{folder_id}' in parents and trashed=false",
fields="files(id, name, mimeType)",
pageSize=100
).execute()
files = results.get('files', [])
return files
except Exception as e:
print(f"❌ Failed to list files: {e}", flush=True)
return []
def download_file(file_id, destination_path):
"""
Downloads a file from Google Drive to a local path.
"""
service = get_drive_service()
if not service:
return False
try:
request = service.files().get_media(fileId=file_id)
print(f"⬇️ Downloading file to {destination_path}...", flush=True)
with open(destination_path, 'wb') as f:
downloader = MediaIoBaseDownload(f, request)
done = False
while done is False:
status, done = downloader.next_chunk()
# print(f"Download {int(status.progress() * 100)}%.", flush=True)
print(f"βœ… Download complete: {destination_path}", flush=True)
return True
except Exception as e:
print(f"❌ Download FAILED: {e}", flush=True)
return False