Google API service object is not created when I make exe file - python-3.x

I'm trying to make an app that fetches data from CSV and adds events to Google Calendar using Google API Client in python. Given below is my code for creating a service object.
def create_service(client_secret_file, api_name, api_version, *scopes, prefix=''):
CLIENT_SECRET_FILE = client_secret_file
API_SERVICE_NAME = api_name
API_VERSION = api_version
SCOPES = [scope for scope in scopes[0]]
cred = None
working_dir = os.getcwd()
token_dir = 'token files'
pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}{prefix}.pickle'
### Check if token dir exists first, if not, create the folder
if not os.path.exists(os.path.join(working_dir, token_dir)):
os.mkdir(os.path.join(working_dir, token_dir))
if os.path.exists(os.path.join(working_dir, token_dir, pickle_file)):
with open(os.path.join(working_dir, token_dir, pickle_file), 'rb') as token:
cred = pickle.load(token)
if not cred or not cred.valid:
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
cred = flow.run_local_server()
with open(os.path.join(working_dir, token_dir, pickle_file), 'wb') as token:
pickle.dump(cred, token)
try:
print(CLIENT_SECRET_FILE, API_SERVICE_NAME, API_VERSION, SCOPES, cred)
service = build(serviceName=API_SERVICE_NAME, version='v3', http=SCOPES[0], developerKey="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")
# service = build(API_SERVICE_NAME, API_VERSION, credentials=cred)
print(API_SERVICE_NAME, API_VERSION, 'service created successfully')
return service
except Exception as e:
print(e)
print(f'Failed to create service instance for {API_SERVICE_NAME}')
And I create the service object using:
def main():
CLIENT_SECRET_FILE = 'client_secret.json'
API_NAME = 'calendar'
API_VERSION = 'v3'
SCOPES = ['https://www.googleapis.com/auth/calendar']
service = create_service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)
if __name__ == '__main__':
main()
input()
The code works perfectly when it's running using .py file. The main goal here to make an exe file. When I make the exe file an exception is raised in and the code directly prints print(f'Failed to create service instance for {API_SERVICE_NAME}')
Here is the output I get with .py file
And here is the output I get with .exe file
Is there any chance anyone could let me know if there is any possible solution for this?

Related

Updating custom_attributes using Python using script below

This is my first post, and am still in my early days when it comes to python, I cannot figure out why i've been getting the below error. This script can potentially be used to update custom attributes in Google Admin SDK.
**current_schemas = user['customSchemas']
KeyError: 'customSchemas'**
https://github.com/pethron/gsuite-custom-schema-update
https://medium.com/faun/how-to-update-in-bulk-g-suite-users-custom-attributes-with-google-admin-sdk-cf6841d272d9
import pickle
import os.path
import yaml
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/admin.directory.user']
API_SERVICE = 'admin'
API_VERSION = 'directory_v1'
def get_credentials():
"""Shows basic usage of the Admin SDK Directory API.
Prints the emails and names of the first 10 users in the domain.
"""
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:
credentials_path = os.path.join(os.getcwd(), 'credentials.json')
flow = InstalledAppFlow.from_client_secrets_file(
credentials_path, 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)
return creds
def update_saml_attributes(service, user, schema_config, federations, session_duration=28800):
custom_schema_roles = []
for federation in federations:
custom_schema_roles.append(
{
'type': 'work',
'value': "arn:aws:iam::{0}:role/{1},arn:aws:iam::{0}:saml-provider/{2}".format(
federation['account'], federation['role'], federation['provider'])
}
)
current_schemas = user['customSchemas']
user['customSchemas'][schema_config['name']] = {
schema_config['session']: session_duration,
schema_config['role']: custom_schema_roles
}
user.update({'customSchemas': current_schemas})
ret = service.users().update(userKey=user['id'], body=user).execute()
return ret['customSchemas']
def main():
# Load the custom schema file
custom_schema_file = os.path.join(os.getcwd(), 'custom-schema.yaml')
with open(custom_schema_file, "r") as yaml_file:
schema_config = yaml.safe_load(yaml_file)
# Load the federation file
federation_file = os.path.join(os.getcwd(), 'federation.yaml')
with open(federation_file, "r") as yaml_file:
federations = yaml.safe_load(yaml_file)
# Get credentials and build the service client
creds = get_credentials()
service = build(API_SERVICE, API_VERSION, credentials=creds)
# Call the Admin SDK Directory API
orgPath = "orgUnitPath='/'" # If need change like "orgUnitPath='/<my organizational unit>'"
results = service.users().list(customer='my_customer',
projection="full",
query=orgPath,
maxResults=2,
orderBy='email').execute()
users = results.get('users', [])
if not users:
print('No users in the domain.')
else:
print('Update users with the following customSchemas')
for user in users:
for email in user['emails']:
for federation in federations:
if federation['email'] == email['address']:
userUpdated = update_saml_attributes(service, user, schema_config, federation['federations'])
print(u'{0} {1} {2}'.format(user['primaryEmail'], user['id'], userUpdated))
if __name__ == '__main__':
main()
Any advise would be much appreciated.

How to use SlidesSnippet tool probably for google slides api python

So I am trying to automate creating google slides using SlidesSnippets
(https://github.com/gsuitedevs/python-samples/blob/master/slides/snippets/slides_snippets.py)
I have all api credentials handles and access into my api service but having a hard time understanding how to fully link the code with my slides directory
(https://docs.google.com/presentation/u/0/?tgif=d)
I have taken the code in the github and re-wrote the init section shown below:
class SlidesSnippets(object):
# def __init__(self, service, drive_service, sheets_service, credentials):
def __init__(self):
# self.credentials = credentials
self.credentials = GoogleCredentials.get_application_default()
scope = [
'https://www.googleapis.com/auth/drive',
]
self.credentials_scoped = self.credentials.create_scoped(scope)
http = self.credentials_scoped.authorize(httplib2.Http())
# self.service = service
self.service = build('slides', 'v1', http=http)
# self.drive_service = drive_service
self.drive_service = build('drive', 'v3', http=http)
# self.sheets_service = sheets_service
The comments are what was originally in the class function and then I replaced it with my details.
So when I run this code:
import slides_snippets as slides
slides_init = slides.SlidesSnippets()
slides_dict = slides_init.create_presentation("TEST")
I get this response that looks like a slides id tag and then when I go to
and when I try and go to that directory with the tag in it
(https://docs.google.com/presentation/d/OUTPUT_SLIDE_ID_FROM_create_presentation/edit)
It asks for me to request control and the powerpoint is nowhere to be seen in my slides drive.
Did I mess anything up in my SlidesSnippets init function?
I used some function to init it. Maybe it can help you.
class SlidesSnippets(object):
def init(self):
self.drive_credentials = None
self.slides_credentials = None
def drive_service(self,gdrive_SCOPES = ['https://www.googleapis.com/auth/drive.file']):
'''gdriver token'''
if os.path.exists('drivetoken.pickle'):
with open('drivetoken.pickle', 'rb') as token:
gdrive_creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not gdrive_creds or not gdrive_creds.valid:
if gdrive_creds and gdrive_creds.expired and gdrive_creds.refresh_token:
gdrive_creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', gdrive_SCOPES)
gdrive_creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('drivetoken.pickle', 'wb') as token:
pickle.dump(gdrive_creds, token)
drive_service = build('drive', 'v3', credentials=gdrive_creds)
self.drive_service,self.drive_credentials = drive_service, gdrive_creds
return self.drive_service,self.drive_credentials
def slides_service(self,slides_SCOPES = ['https://www.googleapis.com/auth/presentations']):
'''slides token'''
if os.path.exists('slidetoken.pickle'):
with open('slidetoken.pickle', 'rb') as token:
slides_creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not slides_creds or not slides_creds.valid:
if slides_creds and slides_creds.expired and slides_creds.refresh_token:
slides_creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', slides_SCOPES)
slides_creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('slidetoken.pickle', 'wb') as token:
pickle.dump(slides_creds, token)
slides_service = build('slides', 'v1', credentials=slides_creds)
self.slides_service,self.slides_credentials = slides_service, slides_creds
return self.slides_service,self.slides_credentials

why do I still receive insufficient permission error despite giving full mail scope?

import httplib2
import os
import oauth2client
from oauth2client import client, tools
from apiclient import errors, discovery
SCOPES = 'https://mail.google.com/'
APPLICATION_NAME = 'Gmail API Python List Email'
CLIENT_SECRET_FILE = 'client_secret_ishandutta2007.json'# This file will be in local dir
CREDENTIAL_FILE_NAME = 'gmail-python-email-send_ishandutta2007.json'
def get_credentials():
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir, CREDENTIAL_FILE_NAME)
store = oauth2client.file.Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
credentials = tools.run_flow(flow, store)
print(('Storing credentials to ' + credential_path))
return credentials
def ListMessagesMatchingQuery(service, user_id, query=''):
try:
response = service.users().messages().list(userId=user_id, q=query).execute()
messages = []
if 'messages' in response:
messages.extend(response['messages'])
while 'nextPageToken' in response:
page_token = response['nextPageToken']
response = service.users().messages().list(userId=user_id, q=query,
pageToken=page_token).execute()
messages.extend(response['messages'])
return messages
except errors.HttpError as error:
print('An error occurred: %s' % error)
def main():
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('gmail', 'v1', http=http)
ListMessagesMatchingQuery(service, "me", query="senior recruit")
if __name__ == '__main__':
main()
An error occurred: https://www.googleapis.com/gmail/v1/users/me/messages?q=senior+recruit&alt=json
returned "Insufficient Permission">
Found the issues,in the code above it was picking up a cached credentials from the file gmail-python-email-send_ishandutta2007.json which has permission to send mails only, changing this filename to something new fixed the issue.

Persistent authorization with youtube API for a Discord Bot

So I am trying to create a Discord bot that can create and update playlists with the youtube API. However when I go to create the playlist it say's i need to visit a URL to authorize this application, eg.
Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=523005278110-dudud40lafimhbq73h9kcamc39g14eqv.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl&state=MCgahMYze4U8Tgx35u2TGGjPdXg3fZ&prompt=consent&access_type=offline
How would I make it so this doesnt happen, and my bot has access to the account to create playlists whenever it needs to?
//client_secrets has client_id and client_secret
CLIENT_SECRETS_FILE = 'client_secret.json'
SCOPES = ['https://www.googleapis.com/auth/youtube.force-ssl']
API_SERVICE_NAME = 'youtube'
API_VERSION = 'v3'
//This should authorize me but isn't or i've done it wrong
def get_authenticated_service():
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES)
credentials = flow.run_console()
return build(API_SERVICE_NAME, API_VERSION, credentials = credentials)
//This creates the playlist
def add_playlist(youtube, args):
body = dict(
snippet=dict(
title=args[0],
description=args[1]
),
status=dict(
privacyStatus='public'
)
)
playlists_insert_response = youtube.playlists().insert(
part='snippet,status',
body=body
).execute()
print('New playlist ID: %s' % playlists_insert_response['id'])
//This is the discord.py code that is called, and then calls the playlist creation code.
class SimpleCog:
"""SimpleCog"""
def __init__(self, bot):
self.bot = bot
#commands.command(name='newPlaylist', aliases=['np','new'])
#commands.guild_only()
async def newPlaylist(self, ctx, *, operand: str):
playlistName=operand.split()[0]
playlistDesc = "Playlist created by {0.name}#{0.discriminator} for server {1}".format(ctx.author,ctx.guild)
args = [playlistName,playlistDesc]
youtube = get_authenticated_service()
try:
add_playlist(youtube, args)
except HttpError as e:
await ctx.send('An HTTP error %d occurred:\n%s' % (e.resp.status, e.content))

How do you programmatically get a list of Google Forms (with ids) using Google Forms API?

I would like to know if it is possible to get the list of a Google Drive user's Forms (not the Docs, Spreadsheets, ...) using the Forms Service or the Google Drive API.
The reason why I am not sure is because there is no indication on how to do this on the Forms Service page, and on the Drive API's page the indications are very general. They don't take into account the fact that I will be using a OAuth2 token with a 'forms' scope and not a 'drive' scope.
/* List all Google Forms in your Google Drive */
function getGoogleFormsList() {
var files = DriveApp.getFilesByType(MimeType.GOOGLE_FORMS);
while (files.hasNext()) {
var file = files.next();
Logger.log("%s %s %s", file.getName(), file.getId(), file.getUrl());
}
}
Python solution:
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(
'client_secrets.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:
page_token = None
drive_service = build('drive', 'v3', credentials=creds)
while True:
response = drive_service.files().list(
# You can use MIME types to filter query results
q="mimeType='application/vnd.google-apps.form'",
spaces='drive',
fields='nextPageToken, files(id, name)',
pageToken=page_token
).execute()
for file in response.get('files', []):
# Process change
print ('Found file: %s (%s)' % (file.get('name'), file.get('id')))
page_token = response.get('nextPageToken', None)
if page_token is None:
break
except HttpError as error:
# TODO(developer) - Handle errors from drive API.
print(f'An error occurred: {error}')
if __name__ == '__main__':
main()

Resources