NEXT ATTEMPT:
Assume that I have a directory with jpg image files, and the oldest image (time stamp) should be slide #1, and the newest image slide #N to be inserted in a google slides presentation. I am using the API
The installation on windows 10 was apparently Okay.
The issue reported before has been fixed, thanks to the person that helped me.
Next, this python code is to check if the API works for me: (modified compared to the first time I created this post)
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import library_JP
# If modifying these scopes, delete the file token.pickle.
#SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']
SCOPES = ['https://www.googleapis.com/auth/presentations']
# The ID of a sample presentation.
PRESENTATION_ID = '1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc'
def main():
"""Shows basic usage of the Slides API.
Prints the number of slides and elments in a sample presentation.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
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:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('slides', 'v1', credentials=creds)
# Call the Slides API
IMAGE_URL = ('https://www.google.com/images/branding/'
'googlelogo/2x/googlelogo_color_272x92dp.png')
requests = []
page_id = '3b330c04-6eb2-11eb-9439-0242ac130002'
image_id = 'MyImage_01'
emu4M = {
'magnitude': 4000000,
'unit': 'EMU',
}
requests.append({
'createImage': {
'objectId': image_id,
'url': IMAGE_URL,
'elementProperties': {
'pageObjectId': page_id,
'size': {
'height': emu4M,
'width': emu4M
},
'transform': {
'scaleX': 1,
'scaleY': 1,
'translateX': 100000,
'translateY': 100000,
'unit': 'EMU'
}
}
}
})
title = 'JP_february13-2021 '
body = {
'title': title, 'requests': requests
}
# presentation = slides_service.presentations() \
presentation = service.presentations() \
.create(body=body).execute()
print('Created presentation with ID: {0}'.format(
presentation.get('presentationId')))
response = slides_service.presentations() \
.batchUpdate(presentationId=presentation_id, body=body).execute()
create_image_response = response.get('replies')[0].get('createImage')
print('Created image with ID: {0}'.format(
create_image_response.get('objectId')))
if __name__ == '__main__':
main()
Note I have included the code at https://github.com/googleworkspace/python-samples/blob/master/slides/snippets/slides_snippets.py
as follows:
import library_JP
There is now a new issue:
python quickstart_JP1.py
Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=162352680285-0i0fmpq50gqgsm1d796mmdim3c3oe874.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A53854%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fpresentations&state=I7dMBbrWmZjVXBwyk0i1mAqLFWonhS&access_type=offline
Traceback (most recent call last):
File "quickstart_JP1.py", line 91, in <module>
main()
File "quickstart_JP1.py", line 77, in main
.create(body=body).execute()
File "C:\Users\joepareti54\anaconda3\lib\site-packages\googleapiclient\_helpers.py", line 134, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\joepareti54\anaconda3\lib\site-packages\googleapiclient\http.py", line 915, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://slides.googleapis.com/v1/presentations?alt=json returned "Invalid JSON payload received. Unknown name "requests": Cannot find field.". Details: "[{'#type': 'type.googleapis.com/google.rpc.BadRequest', 'fieldViolations': [{'description': 'Invalid JSON payload received. Unknown name "requests": Cannot find field.'}]}]">
this code works; it is important to delete token.pickle and to have the following entry:
SCOPES = ['https://www.googleapis.com/auth/presentations']
instead of
SCOPES = ['https://www.googleapis.com/auth/presentations.readonly'] ```
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
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/presentations.readonly']
SCOPES = ['https://www.googleapis.com/auth/presentations']
# The ID of a sample presentation.
PRESENTATION_ID = '1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc'
def main():
"""Shows basic usage of the Slides API.
Prints the number of slides and elments in a sample presentation.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
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:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('slides', 'v1', credentials=creds)
# Call the Slides API
title = 'JP_february13-2021 '
body = {
'title': title
}
# presentation = slides_service.presentations() \
presentation = service.presentations() \
.create(body=body).execute()
print('Created presentation with ID: {0}'.format(
presentation.get('presentationId')))
# print('The presentation contains {} slides:'.format(len(slides)))
# for i, slide in enumerate(slides):
# print('- Slide #{} contains {} elements.'.format(
# i + 1, len(slide.get('pageElements'))))
if __name__ == '__main__':
main()
However, the next version where I try to include images in the presentation does
NOT work.
Related
headers = {"Authorization": "Bearer " + ACCESS_TOKEN}
folder=Folder_id // google drive folder Id
para = {"title": assignment_file_name,
"parents": [{"id": "root"}, {'id': folder}]}
files = {
"data": ("metadata", json.dumps(para), "application/json; charset=UTF-8"),
"file": assignment_file.stream.read()
}
response = requests.get("https://drive.google.com/drive/folders/"+Folder_id,
headers= headers, files=files)
I want to upload file fetched from requests to google drive folder.
But From where to get this ACCESS_TOKEN in the headers variable?
The access token is the result of the Oauth2 request. When you want to access private user data you must first ask for the users consent to your application accessing their data. To do this we use Oauth2. If you are interested in knowing how it works i have a video on it Understanding Oauth2 with curl..
Rather then coding all this manually you should consider using the Google Api python client library. As shown in the official Python quickstart for Drive api will walk you though how to create credentials (be sure to enable drive api) for your application and then how to request access of the user.
from __future__ import print_function
import os.path
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
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# 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:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
return
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
except HttpError as error:
# TODO(developer) - Handle errors from drive API.
print(f'An error occurred: {error}')
if __name__ == '__main__':
main()
I'm trying to apply filter on my google sheet using python sheets API. I'm getting this error, and there are no any hints to debug this error. My code looks like this. I tried to print the requests body, which is exactly in the same format as that suggested on API documentation(https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#setbasicfilterrequest).
My code looks like this :
from __future__ import print_function
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
import pandas as pd
import json
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
# The ID and range of a sample spreadsheet.
SAMPLE_SPREADSHEET_ID = '1ViILuxI3MD3vT7efWYDmlo5A67dIIDJbWXh6Pm9myPQ'
SAMPLE_RANGE_NAME = 'Sheet1!A2:I'
def main():
"""Shows basic usage of the Sheets API.
Prints values from a sample spreadsheet.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# 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:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
service = build('sheets', 'v4', credentials=creds)
_filter = {
"range": {
"sheetId": 0,
"startRowIndex": 1,
"startColumnIndex": 9,
"endColumnIndex": 10
},
"criteria" : {
9 : {
"hiddenValues" : [
"Closed"
]
}
}
}
setBasicFilterRequest = {
'setBasicFilter' : {
'filter' : _filter
}
}
body = {
'requests' : [setBasicFilterRequest],
'includeSpreadsheetInResponse' : True,
}
# print(json.dumps(body, indent=4))
resp = service.spreadsheets() \
.batchUpdate(spreadsheetId="Sheet1", body=body).execute()
print(resp)
if __name__ == '__main__':
main()
I'm getting following error when I run this :
Traceback (most recent call last):
File "poll_sheets.py", line 79, in <module>
main()
File "poll_sheets.py", line 72, in main
resp = service.spreadsheets() \
File "/Users/mike/Desktop/redash/myenv/lib/python3.8/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
return wrapped(*args, **kwargs)
File "/Users/mike/Desktop/redash/myenv/lib/python3.8/site-packages/googleapiclient/http.py", line 920, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://sheets.googleapis.com/v4/spreadsheets/Sheet1:batchUpdate?alt=json returned "Requested entity was not found.". Details: "Requested entity was not found.">
(myenv) (base) mike#Mikes-MacBook-Pro redash %
Modification points:
When I saw your script, it seems that SAMPLE_SPREADSHEET_ID is not used.
About resp = service.spreadsheets().batchUpdate(spreadsheetId="Sheet1", body=body).execute(), it seems that you use the sheet name as the Spreadsheet ID. I think that this is the reason of your issue.
When above points are reflected to your script, it becomes as follows.
Modified script:
From:
resp = service.spreadsheets().batchUpdate(spreadsheetId="Sheet1", body=body).execute()
To:
resp = service.spreadsheets().batchUpdate(spreadsheetId=SAMPLE_SPREADSHEET_ID, body=body).execute()
Note:
When you run above modified script and the same error occurs, please confirm the Spreadsheet ID again.
Reference:
Method: spreadsheets.batchUpdate
I started working with the Google Drive Changes API (https://developers.google.com/drive/api/v3/reference/changes). While my code can track all changes happening in My Drive, I cannot seem to filter out only specific changes like creation of new files. Whenever I'm uploading a file to a folder, there are 2 changes occurring, one which says about the change in file, and the other which says about the change in the folder.
My code so far is as follows:
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import schedule
import time
# If modifying these scopes, delete the file token.pickle.
SCOPES = [
'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/drive.metadata.readonly',
'https://www.googleapis.com/auth/drive.appdata',
'https://www.googleapis.com/auth/drive.metadata',
'https://www.googleapis.com/auth/drive.photos.readonly',
]
def job():
print("Inside job()")
global saved_start_page_token
page_token = saved_start_page_token
while page_token is not None:
response = service.changes().list(pageToken=page_token, spaces='drive', restrictToMyDrive=True).execute()
for change in response.get('changes'):
# Process change
file_id = change.get('fileId')
print('Change found for file: %s' % file_id)
print('Change type: %s' % change.get('changeType'))
print('Filename: %s' % change.get('file').get('name'))
if 'newStartPageToken' in response:
# Last page, save this token for the next polling interval
saved_start_page_token = response.get('newStartPageToken')
page_token = response.get('nextPageToken')
def main():
creds = None
pickle_file = 'token.pickle'
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists(pickle_file):
with open(pickle_file, '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:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(pickle_file, 'wb') as token:
pickle.dump(creds, token)
global service
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
response = service.changes().getStartPageToken().execute()
global saved_start_page_token
saved_start_page_token = response.get('startPageToken')
schedule.every().minute.do(job)
while True:
schedule.run_pending()
time.sleep(1)
if __name__ == '__main__':
main()
Can I filter out changes to only show file/folder creation changes?
Currently, I am able to retrieve the Folders/Directory that owned by me and its returning a list of result as expected.
Here is the code snippet,
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
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',
'https://www.googleapis.com/auth/drive.file',
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/drive.metadata.readonly',
'https://www.googleapis.com/auth/drive.appdata',
'https://www.googleapis.com/auth/drive.metadata',
'https://www.googleapis.com/auth/drive.photos.readonly']
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
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:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
queries = [
"mimeType = 'application/vnd.google-apps.folder'",
"'my_email#gmail.com' in owners"
]
drive_str_query = queries[0] if len(queries) == 1 else " and ".join(queries)
results = service.files().list(q=drive_str_query,
pageSize=1000,
spaces='drive',
fields="nextPageToken, files(*)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print(item)
if __name__ == '__main__':
main()
This snippet returns data with sufficient fields as mentioned in here, But, it doesn't include a relative/absolute path to the Folder/Directory
Is there any way to findout the path to the directory/folder?
I get this error whenever I try running that code : HttpError 404 when requesting https://sheets.googleapis.com/v4/spreadsheets/1KpJw640oNNwVfEasGoSffrfoyC7i1ryHakdWZmr-AX4/values:batchUpdate?alt=json returned "Requested entity was not found.">
I am trying to update a Google Sheet file with the help of this API but the only scope that I manage using is "readonly". I tried deleting the token.pickle file : I get identified so the request isn't requiring authentification credentials. But I don't know why I would still get an error. So basically all I can do is extracting data from a sheet but not overwrite cells.
from __future__ import print_function
from pprint import pprint
from googleapiclient import discovery
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
SCOPES = ['https:// www.googleapis.com/auth/spreadsheets'] #what I have changed from the Python Quickstart code from the Google Sheets API website
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
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()
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = discovery.build('sheets', 'v4', credentials=creds)
spreadsheet_id = '1KpJw640oNNwVfEasGoSffrfoyC7i1ryHakdWZmr-AX4' #this id is correct and still I get an error
batch_update_values_request_body = {
'value_input_option': 'USER_ENTERED',
'data': [
{
"range": "Control Panel!A:B",
"majorDimension": "ROWS",
"values": [[1,2]]
}
],
}
request = service.spreadsheets().values().batchUpdate(spreadsheetId=spreadsheet_id,
body=batch_update_values_request_body)
response = request.execute()
pprint(response)