I need to create a script in python/google scripts that will replace the script in the sheet. The source script that will be used for the replacement will be saved as Google Script and will have a permanent ID. After providing the sheet ID, the script would find the .gs function with the same name and insert the source script there. I'm trying to create something like this, but every time at some stage it throws HttpError 500 when requesting .../content?alt=json returned "Internal error encountered.". Details: "Internal error encountered.">
I tried creating a google and python script, still the same effect.
import os
import time
import google.auth
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# Configuration constants
SCOPES = ['.projects'] # Required API scope
SOURCE_SCRIPT_ID = 'YOUR_SOURCE_SCRIPT_ID_HERE' # Replace with your source script ID
FILE_NAME = 'YOUR_SCRIPT_FILE_NAME_HERE' # Replace with your script file name
def authenticate():
"""Handle OAuth2 authentication and return credentials."""
creds = None
# Load existing credentials if available
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# Refresh or create new credentials if needed
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save credentials for next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
return creds
def get_source_file_content(creds):
"""Retrieve content of the source file from the source project."""
try:
service = build('script', 'v1', credentials=creds)
# Get content from source project
source_project = service.projects().getContent(scriptId=SOURCE_SCRIPT_ID).execute()
# Search for the specified file
for file in source_project['files']:
if file['name'] == FILE_NAME:
return file['source']
raise Exception(f"File {FILE_NAME} not found in source project.")
except HttpError as error:
print(f"API Error: {error}")
raise
def update_target_script(target_script_id, new_content, creds):
"""Update the target script with new content."""
max_retries = 3
retry_delay = 5 # Seconds between retries
for attempt in range(max_retries):
try:
service = build('script', 'v1', credentials=creds)
# Get current content of target project
target_project = service.projects().getContent(scriptId=target_script_id).execute()
# Simplify file structure for API compatibility
simplified_files = []
for file in target_project.get('files', []):
simplified_files.append({
'name': file['name'],
'type': file['type'],
'source': file['source']
})
# Update or add the target file
file_found = False
for file in simplified_files:
if file['name'] == FILE_NAME:
file['source'] = new_content
file_found = True
break
if not file_found:
simplified_files.append({
'name': FILE_NAME,
'type': 'SERVER_JS',
'source': new_content
})
# Send update request
request = {'files': simplified_files}
response = service.projects().updateContent(
scriptId=target_script_id,
body=request
).execute()
print("Script updated successfully!")
return
except HttpError as error:
if error.resp.status == 500 and attempt < max_retries - 1:
print(f"Server error. Retrying ({attempt + 1}/{max_retries})...")
time.sleep(retry_delay)
else:
raise Exception(f"Update failed: {error}")
def main():
"""Main execution flow."""
target_script_id = input("Enter target script ID: ")
creds = authenticate()
new_content = get_source_file_content(creds)
update_target_script(target_script_id, new_content, creds)
if __name__ == '__main__':
main()