-
Notifications
You must be signed in to change notification settings - Fork 248
feat(drive): Add update_drive_file function with OAuth fixes and comprehensive file management #221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
f035c8a
3fba86b
9a08a63
4864e1b
d58bac2
8ae82ce
d4263dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -493,4 +493,152 @@ async def check_drive_file_public_access( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Fix: Drive → Share → 'Anyone with the link' → 'Viewer'" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return "\n".join(output_parts) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return "\n".join(output_parts) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @server.tool() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @handle_http_errors("update_drive_file", is_read_only=False, service_type="drive") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @require_google_service("drive", "drive_file") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async def update_drive_file( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| service, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user_google_email: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file_id: str, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # File metadata updates | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mime_type: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Folder organization | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| add_parents: Optional[str] = None, # Comma-separated folder IDs to add | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| remove_parents: Optional[str] = None, # Comma-separated folder IDs to remove | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # File status | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| starred: Optional[bool] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| trashed: Optional[bool] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Sharing and permissions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| writers_can_share: Optional[bool] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| copy_requires_writer_permission: Optional[bool] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Custom properties | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| properties: Optional[dict] = None, # User-visible custom properties | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> str: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Updates metadata and properties of a Google Drive file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| user_google_email (str): The user's Google email address. Required. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file_id (str): The ID of the file to update. Required. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name (Optional[str]): New name for the file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description (Optional[str]): New description for the file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mime_type (Optional[str]): New MIME type (note: changing type may require content upload). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| add_parents (Optional[str]): Comma-separated folder IDs to add as parents. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| remove_parents (Optional[str]): Comma-separated folder IDs to remove from parents. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| starred (Optional[bool]): Whether to star/unstar the file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| trashed (Optional[bool]): Whether to move file to/from trash. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| writers_can_share (Optional[bool]): Whether editors can share the file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| copy_requires_writer_permission (Optional[bool]): Whether copying requires writer permission. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| properties (Optional[dict]): Custom key-value properties for the file. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| str: Confirmation message with details of the updates applied. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| logger.info(f"[update_drive_file] Updating file {file_id} for {user_google_email}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # First, get current file info for reference | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| current_file = await asyncio.to_thread( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| service.files().get( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fileId=file_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fields="id, name, description, mimeType, parents, starred, trashed, webViewLink", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| supportsAllDrives=True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ).execute | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Build the update body with only specified fields | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update_body = {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if name is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update_body['name'] = name | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if description is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update_body['description'] = description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if mime_type is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update_body['mimeType'] = mime_type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if starred is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update_body['starred'] = starred | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if trashed is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update_body['trashed'] = trashed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if writers_can_share is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update_body['writersCanShare'] = writers_can_share | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if copy_requires_writer_permission is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update_body['copyRequiresWriterPermission'] = copy_requires_writer_permission | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if properties is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update_body['properties'] = properties | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Build query parameters for parent changes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| query_params = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'fileId': file_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'supportsAllDrives': True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'fields': 'id, name, description, mimeType, parents, starred, trashed, webViewLink, writersCanShare, copyRequiresWriterPermission, properties' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if add_parents: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| query_params['addParents'] = add_parents | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if remove_parents: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| query_params['removeParents'] = remove_parents | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Only include body if there are updates | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if update_body: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| query_params['body'] = update_body | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Perform the update | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| updated_file = await asyncio.to_thread( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| service.files().update(**query_params).execute | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+659
to
+666
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if update_body: | |
| query_params['body'] = update_body | |
| # Perform the update | |
| updated_file = await asyncio.to_thread( | |
| service.files().update(**query_params).execute | |
| ) | |
| # Perform the update | |
| if update_body: | |
| updated_file = await asyncio.to_thread( | |
| service.files().update(body=update_body, **query_params).execute | |
| ) | |
| else: | |
| updated_file = await asyncio.to_thread( | |
| service.files().update(**query_params).execute | |
| ) | |
Copilot
AI
Oct 7, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API call structure is incorrect. The body parameter (if present in query_params) should be passed separately as the body argument to update(), not unpacked with other query parameters.
| if update_body: | |
| query_params['body'] = update_body | |
| # Perform the update | |
| updated_file = await asyncio.to_thread( | |
| service.files().update(**query_params).execute | |
| ) | |
| # Build response message | |
| output_parts = [f"✅ Successfully updated file: {updated_file.get('name', current_file['name'])}"] | |
| output_parts.append(f" File ID: {file_id}") | |
| # Report what changed | |
| # Perform the update | |
| # Perform the update | |
| if update_body: | |
| updated_file = await asyncio.to_thread( | |
| service.files().update(body=update_body, **query_params).execute | |
| ) | |
| else: | |
| updated_file = await asyncio.to_thread( | |
| service.files().update(**query_params).execute | |
| ) | |
| service.files().update(body=update_body, **query_params).execute | |
| ) | |
| else: | |
| updated_file = await asyncio.to_thread( | |
| service.files().update(**query_params).execute | |
| ) | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| #!/usr/bin/env python | ||
| """ | ||
| Direct test of update_drive_file function to verify OAuth scope fix | ||
| """ | ||
| import asyncio | ||
| from gdrive.drive_tools import update_drive_file | ||
| from auth.google_auth import get_google_service | ||
|
|
||
|
|
||
| async def test_update(): | ||
| """Test the update_drive_file function with all parameters""" | ||
|
|
||
| # Test parameters - replace with actual IDs | ||
| file_id = "YOUR_FILE_ID_HERE" # e.g., "1abc2def3ghi..." | ||
| folder_id = "YOUR_FOLDER_ID_HERE" # e.g., "1xyz2uvw3rst..." | ||
|
|
||
| # Get the service | ||
| service = await get_google_service( | ||
| "[email protected]", | ||
| "drive", | ||
| "drive_file" # Using correct scope | ||
| ) | ||
|
|
||
| # Call update_drive_file directly | ||
| result = await update_drive_file( | ||
| service=service, | ||
| user_google_email="[email protected]", | ||
| file_id=file_id, | ||
| name="Updated Test Document - OAuth Fixed", | ||
| description="Testing update_drive_file with all parameters after fixing OAuth scope issue", | ||
| add_parents=folder_id, | ||
| starred=True, | ||
| writers_can_share=True, | ||
| copy_requires_writer_permission=False, | ||
| properties={ | ||
| "test_key": "test_value", | ||
| "updated_by": "mcp_server", | ||
| "update_timestamp": "2025-01-29" | ||
| } | ||
| ) | ||
|
|
||
| print(result) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| asyncio.run(test_update()) |
Uh oh!
There was an error while loading. Please reload this page.