|
|
|
|
|
import os |
|
|
import json |
|
|
import mimetypes |
|
|
import fnmatch |
|
|
import sys |
|
|
from google.oauth2.credentials import Credentials |
|
|
from google.oauth2 import service_account |
|
|
from google.auth.transport.requests import Request |
|
|
from googleapiclient.discovery import build |
|
|
from googleapiclient.http import MediaFileUpload |
|
|
|
|
|
FOLDER_ID = '1-8HJcWxsUUQIj9OMXQeoeULS06RA9Hg9' |
|
|
|
|
|
def get_drive_service(): |
|
|
"""Get Google Drive service with OAuth/Service Account fallback""" |
|
|
|
|
|
oauth_token = os.environ.get('GOOGLE_OAUTH_TOKEN') |
|
|
if oauth_token: |
|
|
try: |
|
|
token_info = json.loads(oauth_token) |
|
|
credentials = Credentials.from_authorized_user_info(token_info) |
|
|
if credentials.expired and credentials.refresh_token: |
|
|
credentials.refresh(Request()) |
|
|
return build('drive', 'v3', credentials=credentials) |
|
|
except Exception as e: |
|
|
print(f"OAuth failed: {e}") |
|
|
|
|
|
|
|
|
sa_key = os.environ.get('GOOGLE_SERVICE_ACCOUNT_KEY') |
|
|
if sa_key: |
|
|
try: |
|
|
credentials_info = json.loads(sa_key) |
|
|
credentials = service_account.Credentials.from_service_account_info( |
|
|
credentials_info, scopes=['https://www.googleapis.com/auth/drive.file'] |
|
|
) |
|
|
return build('drive', 'v3', credentials=credentials) |
|
|
except Exception as e: |
|
|
print(f"Service Account failed: {e}") |
|
|
|
|
|
print("Both authentication methods failed!") |
|
|
sys.exit(1) |
|
|
|
|
|
def upload_file(file_path, parent_folder_id, service): |
|
|
"""Upload or update a file""" |
|
|
file_name = os.path.basename(file_path) |
|
|
|
|
|
|
|
|
query = f"name='{file_name}' and '{parent_folder_id}' in parents and trashed=false" |
|
|
results = service.files().list(q=query).execute() |
|
|
items = results.get('files', []) |
|
|
|
|
|
media = MediaFileUpload(file_path, mimetype=mimetypes.guess_type(file_path)[0] or 'application/octet-stream') |
|
|
|
|
|
if items: |
|
|
|
|
|
service.files().update(fileId=items[0]['id'], media_body=media).execute() |
|
|
print(f'Updated: {file_name}') |
|
|
else: |
|
|
|
|
|
file_metadata = {'name': file_name, 'parents': [parent_folder_id]} |
|
|
service.files().create(body=file_metadata, media_body=media).execute() |
|
|
print(f'Uploaded: {file_name}') |
|
|
|
|
|
def create_folder(folder_name, parent_id, service): |
|
|
"""Create folder if it doesn't exist""" |
|
|
query = f"name='{folder_name}' and '{parent_id}' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false" |
|
|
results = service.files().list(q=query).execute() |
|
|
items = results.get('files', []) |
|
|
|
|
|
if items: |
|
|
return items[0]['id'] |
|
|
|
|
|
folder_metadata = { |
|
|
'name': folder_name, |
|
|
'parents': [parent_id], |
|
|
'mimeType': 'application/vnd.google-apps.folder' |
|
|
} |
|
|
folder = service.files().create(body=folder_metadata).execute() |
|
|
return folder.get('id') |
|
|
|
|
|
def upload_directory(local_path, parent_id, service): |
|
|
"""Upload directory with exclusions""" |
|
|
exclude_dirs = {'.git', '.github', 'node_modules', '__pycache__'} |
|
|
exclude_patterns = ['*.md'] |
|
|
|
|
|
uploaded = skipped = errors = 0 |
|
|
|
|
|
for root, dirs, files in os.walk(local_path): |
|
|
|
|
|
dirs[:] = [d for d in dirs if d not in exclude_dirs] |
|
|
|
|
|
|
|
|
rel_path = os.path.relpath(root, local_path) |
|
|
current_folder_id = parent_id |
|
|
|
|
|
if rel_path != '.': |
|
|
for part in rel_path.split(os.sep): |
|
|
current_folder_id = create_folder(part, current_folder_id, service) |
|
|
|
|
|
|
|
|
for file in files: |
|
|
|
|
|
if any(fnmatch.fnmatch(file, pattern) for pattern in exclude_patterns): |
|
|
print(f'Skipping: {file}') |
|
|
skipped += 1 |
|
|
continue |
|
|
|
|
|
try: |
|
|
upload_file(os.path.join(root, file), current_folder_id, service) |
|
|
uploaded += 1 |
|
|
except Exception as e: |
|
|
print(f'Error uploading {file}: {e}') |
|
|
errors += 1 |
|
|
|
|
|
return uploaded, skipped, errors |
|
|
|
|
|
def main(): |
|
|
print("Starting Google Drive upload...") |
|
|
|
|
|
|
|
|
service = get_drive_service() |
|
|
|
|
|
try: |
|
|
service.files().list(q=f"'{FOLDER_ID}' in parents", pageSize=1).execute() |
|
|
print("Folder access confirmed") |
|
|
except Exception as e: |
|
|
print(f"Cannot access folder {FOLDER_ID}: {e}") |
|
|
sys.exit(1) |
|
|
|
|
|
|
|
|
uploaded, skipped, errors = upload_directory('.', FOLDER_ID, service) |
|
|
|
|
|
print(f"\nSummary: {uploaded} uploaded, {skipped} skipped, {errors} errors") |
|
|
|
|
|
if errors > 0: |
|
|
sys.exit(1) |
|
|
print("Upload completed successfully!") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |