I am trying to upload an APK to Google Play using the Developer API. I have a Python script that mostly works, but the upload keeps returning a "HttpError 403 when requesting 'APK size too big'" error. We have had no problems uploading and releasing the app manually through the web interface. Am I missing a setting somewhere?
Here is my current script:
import argparse
from googleapiclient.discovery import build
import google_auth_httplib2
import httplib2
from oauth2client import client
from google.oauth2 import service_account
from google.auth.transport.requests import Request
import sys, os, socket
def main():
pathname = os.path.dirname(sys.argv[0])
fullpath = os.path.abspath(pathname)
SCOPES = ['https://www.googleapis.com/auth/androidpublisher']
SERVICE_ACCOUNT_FILE = fullpath + '/authorization_data.json' # access keys json file
credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
credentials.refresh(Request())
print(credentials.token)
http = httplib2.Http(timeout=300)
http = google_auth_httplib2.AuthorizedHttp(credentials, http=http)
service = build('androidpublisher', 'v3', http=http)
package_name = 'com.company.app'
apk_file = 'upload/myapp.apk'
try:
print('creating edit')
edit_request = service.edits().insert(body={}, packageName=package_name)
result = edit_request.execute()
edit_id = result['id']
print('id: ' + edit_id)
print('uploading apk')
apk_response = service.edits().apks().upload(
editId=edit_id,
packageName=package_name,
media_body=apk_file
).execute()
print('Version code %d has been uploaded' % apk_response['versionCode'])
print('committing edit')
commit_request = service.edits().commit(
editId=edit_id,
packageName=package_name
).execute()
print('Edit "%s" has been committed' % commit_request['id'])
except client.AccessTokenRefreshError:
print('The credentials have been revoked or expired, please re-run the application to re-authorize')
if __name__ == '__main__':
main()
Related
I'm trying to get the video list of my youtube channel and update it as i please, i've done it with .net & it's quite easy, But in python it's kind of disturbing each time i run the script i got the message of "Please visit this URL to authorize this application" Althought i use the same credentials.json file i use it on .net.
NB: No need to mark down this question for duplicate or anything because i already check many Many of the same question here on stackover like this , this & this other forums too but none seems to provide a clear concrete solution every solution so far i've tried has the same result.
Here's the sample code i'm using :
Any help will be much appreciated.
import os
import sys
file_path = os.path.dirname(__file__)
module_path = os.path.join(file_path, "lib")
sys.path.append(module_path)
import pickle
import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors
scopes = [
"https://www.googleapis.com/auth/youtube",
"https://www.googleapis.com/auth/youtube.upload",
"https://www.googleapis.com/auth/youtubepartner",
"https://www.googleapis.com/auth/youtube.force-ssl",
]
client_secrets_file = "credentials.json"
api_service_name = "youtube"
api_version = "v3"
def main():
# Disable OAuthlib's HTTPS verification when running locally.
# *DO NOT* leave this option enabled in production.
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
# Get credentials and create an API client
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
client_secrets_file, scopes)
youtube = get_authenticated_service()
request = youtube.channels().list(
part="contentDetails",
mine=True
)
response = request.execute()
print(response)
def get_authenticated_service():
if os.path.exists("CREDENTIALS_PICKLE_FILE"):
with open("CREDENTIALS_PICKLE_FILE", 'rb') as f:
credentials = pickle.load(f)
else:
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(client_secrets_file, scopes)
credentials = flow.run_console()
with open("CREDENTIALS_PICKLE_FILE", 'wb') as f:
pickle.dump(credentials, f)
return googleapiclient.discovery.build(
api_service_name, api_version, credentials=credentials)
if __name__ == "__main__":
main()
I luckily found the solution to this problem, and here a sample working script that will list all the video you have in ur YouTube channel and will ask for authorization Code just one time.
i know it's a bit messy but it's ok
import os
import sys
file_path = os.path.dirname(__file__)
module_path = os.path.join(file_path, "lib")
sys.path.append(module_path)
import httplib2
import json
import argparse
import re
import random
from pytz import timezone
from dateutil import parser
from datetime import datetime
from googleapiclient.discovery import build
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import argparser, run_flow
random.seed()
CLIENT_SECRETS_FILE = "credentials.json"
MISSING_CLIENT_SECRETS_MESSAGE = """
WARNING: Please configure OAuth 2.0
To make this sample run you will need to populate the client_secrets.json file
found at: %swith information from the Developers Console
""" % os.path.abspath(os.path.join(os.path.dirname(__file__),CLIENT_SECRETS_FILE))
scopes = [
"https://www.googleapis.com/auth/youtube",
"https://www.googleapis.com/auth/youtube.upload",
"https://www.googleapis.com/auth/youtubepartner",
"https://www.googleapis.com/auth/youtube.force-ssl",
]
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE,message=MISSING_CLIENT_SECRETS_MESSAGE, scope=scopes)
storage = Storage("%s-oauth2.json" % sys.argv[0])
credentials = storage.get()
if credentials is None or credentials.invalid:
flags = argparser.parse_args()
credentials = run_flow(flow, storage, flags)
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
http=credentials.authorize(httplib2.Http()))
channels_response = youtube.channels().list(
mine=True,
part="contentDetails"
).execute()
for channel in channels_response["items"]:
uploads_list_id = channel["contentDetails"]["relatedPlaylists"]["uploads"]
print("Videos in list {0:s}".format(uploads_list_id),file=sys.stderr)
playlistitems_list_request = youtube.playlistItems().list(
playlistId=uploads_list_id,
part="snippet",
maxResults=50
)
playlistitems_list_response = playlistitems_list_request.execute()
for playlist_item in playlistitems_list_response["items"]:
title = playlist_item["snippet"]["title"]
video_id = playlist_item["snippet"]["resourceId"]["videoId"]
video_list_request = youtube.videos().list(
id=video_id,
part="snippet,fileDetails,statistics,status",
maxResults=50
)
video_list_response = video_list_request.execute()
for video_list_item in video_list_response["items"]:
print(title)
print (video_id)
print (video_list_item["fileDetails"]["fileName"])
print (video_list_item["statistics"]["viewCount"])
print (video_list_item["statistics"]["likeCount"])
print (video_list_item["snippet"]["description"])
print (video_list_item["snippet"]["publishedAt"])
print (video_list_item["status"]["privacyStatus"])
Buy use Google Analytics API (V4) I would like to upload file "Product Data"
This is the sample code from GA Documentation
from apiclient.http import MediaFileUpload
try:
media = MediaFileUpload('custom_data.csv',
mimetype='application/octet-stream',
resumable=False)
daily_upload = analytics.management().uploads().uploadData(
accountId='123456',
webPropertyId='UA-123456-1',
customDataSourceId='9876654321',
media_body=media).execute()
except TypeError, error:
# Handle errors in constructing a query.
print 'There was an error in constructing your query : %s' % error
except HttpError, error:
# Handle API errors.
print ('There was an API error : %s : %s' %
(error.resp.status, error.resp.reason))
This is What I ahve done, but I still have an issue regarding this part - analytics.management().uploads()
import argparse
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
import httplib2
from oauth2client import client
from oauth2client import file
from oauth2client import tools
from googleapiclient.http import MediaFileUpload
# SET VARS
CUSTOM_DATA_SOURCE_ID='_xxxxxxx'
WEB_PROPERTY_ID='UA-xxxxx-1'
ACCOUNT_ID='xxxxxx'
CSV_IMPORT_FILE_LOCATION='test_file.csv'
CREDENTIALS_KEY_FILE_LOCATION='key.json'
def get_service(api_name, api_version, scope, key_file_location):
credentials = ServiceAccountCredentials.from_json_keyfile_name(
key_file_location, scopes=scope)
http = credentials.authorize(httplib2.Http())
# Build the service object.
service = build(api_name, api_version, http=http)
return service
def uploadCSV(service):
try:
media = MediaFileUpload(CSV_IMPORT_FILE_LOCATION,
mimetype='application/octet-stream',
resumable=False)
daily_upload = service.management().uploads().uploadData(
accountId=ACCOUNT_ID,
webPropertyId=WEB_PROPERTY_ID,
customDataSourceId=CUSTOM_DATA_SOURCE_ID,
media_body=media).execute()
except TypeError, error:
# Handle errors in constructing a query.
print 'There was an error in constructing your query : %s' % error
def main():
# Define the auth scopes to request.
scope = ['https://www.googleapis.com/auth/analytics.edit','https://www.googleapis.com/auth/analytics']
# Authenticate and construct service.
service = get_service('analytics', 'v4', scope, CREDENTIALS_KEY_FILE_LOCATION)
# Upload CSV Data
uploadCSV(service)
if __name__ == '__main__':
main()
This is an error which I have received all the time:
AttributeError: 'Resource' object has no attribute 'management'
Any suggestions??
I assume that this is because I do not have these methods (management().uploads()) but this is what example from documentation says.
The current analytics api v4 only includes the reporting side of the API. To access the management endpoint you have to use v3. Try to rewrite your code using the v3 version of the API.
Here's what v3 looks like
Here's what v4 looks like
To start change this line:
service = get_service('analytics', 'v3', scope, CREDENTIALS_KEY_FILE_LOCATION)
But it might require more rewriting than this.
I have a python script to match files on google drive in specific folder. It worked fine with my GSuite account in the company. But If i want to use it at home with my simple Google Drive account it's not working. No files found:
Here is my code:
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
from apiclient.http import MediaFileUpload
from apiclient import errors
import io
from apiclient.http import MediaIoBaseDownload
from apiclient import errors
import os
import csv
try :
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
folder_id = 'XYZ00000'
SCOPES = 'https://www.googleapis.com/auth/drive.file'
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
print("Create new data storage file ...")
flow = client.flow_from_clientsecrets('client_secrets.json', SCOPES)
flow.redirect_uri = client.OOB_CALLBACK_URN
authorize_url = flow.step1_get_authorize_url()
creds = tools.run_flow(flow, store, flags) \
if flags else tools.run(flow, store)
print ("Storage")
DRIVE = build('drive', 'v2', http=creds.authorize(Http()))
def getKeywordsID():
page_token = None
while True:
response = DRIVE.files().list(q="'XYZ00000' in parents and trashed = false",
spaces='drive',
fields='nextPageToken, items(id, title)',
pageToken=page_token).execute()
for file in response.get('items', []):
if ('test.txt' == file.get('title')):
print ('test.txt on Google Drive found')
page_token = response.get('nextPageToken', None)
if page_token is None:
break;
return file_id
# Download file
file_id = getKeywordsID()
if file_id != None:
request = DRIVE.files().get_media(fileId=file_id)
fh = io.FileIO('test.txt', 'wb')
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print ("Download test.txt %d%%." % int(status.progress() * 100) )
else:
print ("File not found.")
I have no idea why it's not working. I enabled Google Drive API, created a project, added an OAuth2.0 client ID (select “Other” as option) and downloaded the json file for storage.
From the traceback posted, I can see that in the getKeywordsID function you are returning the file_id variable, which you have not initialized in the getKeywordsID function scope. Hence the UnboundLocalError: local variable 'file_id' referenced before assignment is thrown.
I'm trying to use the blog functions from Google API gdata. I tried my best following the documentation but I failed very badly. Can anybody tell me how can I use the Google blogger API? My code is pretty messed up and now I'm out of clue.
EDIT FULL WORKING CODE :) :
from oauth2client.client import OAuth2WebServerFlow
import httplib2
from apiclient.discovery import build
from oauth2client.file import Storage
#flow = OAuth2WebServerFlow(client_id='', #ID
# client_secret='', #SECRET ID
# scope='https://www.googleapis.com/auth/blogger',
# redirect_uri='urn:ietf:wg:oauth:2.0:oob')
#auth_uri = flow.step1_get_authorize_url()
# Redirect the user to auth_uri on your platform.
# Open a file
#fo = open("foo.txt", "wb")
#fo.write( auth_uri +"\n");
#fo.close()
#credentials = flow.step2_exchange( raw_input ( ) )
storage = Storage('a_credentials_file')
#storage.put(credentials)
credentials = storage.get()
http = httplib2.Http()
http = credentials.authorize(http)
service = build('blogger', 'v3', http=http)
users = service.users()
# Retrieve this user's profile information
thisuser = users.get(userId='self').execute()
print('This user\'s display name is: %s' % thisuser['displayName'])
While I was myself trying to find a solution, I found this. Then after some modifications, the code finally worked. It successfully print all details about you blog site.
from oauth2client.client import flow_from_clientsecrets
import httplib2
from apiclient.discovery import build
from oauth2client.file import Storage
import webbrowser
def get_credentials():
scope = 'https://www.googleapis.com/auth/blogger'
flow = flow_from_clientsecrets(
'client_secrets.json', scope,
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
storage = Storage('credentials.dat')
credentials = storage.get()
if not credentials or credentials.invalid:
auth_uri = flow.step1_get_authorize_url()
webbrowser.open(auth_uri)
auth_code = raw_input('Enter the auth code: ')
credentials = flow.step2_exchange(auth_code)
storage.put(credentials)
return credentials
def get_service():
"""Returns an authorised blogger api service."""
credentials = get_credentials()
http = httplib2.Http()
http = credentials.authorize(http)
service = build('blogger', 'v3', http=http)
return service
if __name__ == '__main__':
served = get_service()
blogs = served.blogs()
blog_get_obj = blogs.get(blogId='123456789123456')
details = blog_get_obj.execute()
print details
The results of print will look like:
{u'description': u'Look far and wide. There are worlds to conquer.',
u'id': u'8087466742945672359',
u'kind': u'blogger#blog',
u'locale': {u'country': u'', u'language': u'en', u'variant': u''},
u'name': u'The World Around us',
u'pages': {u'selfLink': u'https://www.googleapis.com/blogger/v3/blogs/1234567897894569/pages',
u'totalItems': 2},
u'posts': {u'selfLink': u'https://www.googleapis.com/blogger/v3/blogs/1245678992359/posts',
u'totalItems': 26},
u'published': u'2015-11-02T18:47:02+05:30',
u'selfLink': u'https://www.googleapis.com/blogger/v3/blogs/9874652945672359',
u'updated': u'2017-06-29T19:41:00+05:30',
u'url': u'http://www.safarnuma.com/'}
This is an updated and long-term stable implementation, taken from this answer and edited a bit for Blogger API v3.
All methods in the official documentation can be called on blogger_service variable of this code.
import os
import pickle
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/blogger', ]
# we check if the file to store the credentials exists
if not os.path.exists('credentials.dat'):
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
credentials = flow.run_local_server()
with open('credentials.dat', 'wb') as credentials_dat:
pickle.dump(credentials, credentials_dat)
else:
with open('credentials.dat', 'rb') as credentials_dat:
credentials = pickle.load(credentials_dat)
if credentials.expired:
credentials.refresh(Request())
blogger_service = build('blogger', 'v3', credentials=credentials)
users = blogger_service.users()
# Retrieve this user's profile information
thisuser = users.get(userId='self').execute()
print('Your display name is: %s' % thisuser['displayName'])
You can use goco
pip install goco
then use this code:
from goco import Goco
GoogleApi = Goco("path\\to\\client_secret.json", "path\\to\\credentials.storage")
MyBlog = GoogleApi.connect(scope='Blogger', service_name='blogger', version='v3')
Posts = MyBlog.posts().list(blogId='desired-blog-id').execute()
print(Posts)
you can also connect to any google service via this module.
I am trying to download a spreadsheet file from my drive to my computer.
I am able to authenticate, get list of files and even get meta-data successfully.
But when I try to download the file, I get the following error :
downloading file starts
An error occurred: <HttpError 400 when requesting https://www.googleapis.com/dri
ve/v2/files/1vJetI_p8YEYiKvPVl0LtXGS5uIAx1eRGUupsXoh7UbI?alt=media returned "The
specified file does not support the requested alternate representation.">
downloading file ends
I couldn't get any such problem or question on SO and the other methods or solutions provided on SO for downloading the spreadsheet are outdated.Those have been deprecated by Google .
Here is the code, I am using to download the file :
import httplib2
import os
from apiclient import discovery
import oauth2client
from oauth2client import client
from oauth2client import tools
from apiclient import errors
from apiclient import http
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
#SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
SCOPES = 'https://www.googleapis.com/auth/drive'
CLIENT_SECRET_FILE = 'client_secrets.json'
APPLICATION_NAME = 'Drive API Quickstart'
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,
'drive-quickstart.json')
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
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatability with Python 2.6
credentials = tools.run(flow, store)
print 'Storing credentials to ' + credential_path
return credentials
def main():
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('drive', 'v2', http=http)
file_id = '1vJetI_p8YEYiKvPVl0LtXGS5uIAx1eRGUupsXoh7UbI'
print "downloading file starts"
download_file(service, file_id)
print "downloading file ends "
def download_file(service, file_id):
local_fd = open("foo.csv", "w+")
request = service.files().get_media(fileId=file_id)
media_request = http.MediaIoBaseDownload(local_fd, request)
while True:
try:
download_progress, done = media_request.next_chunk()
except errors.HttpError, error:
print 'An error occurred: %s' % error
return
if download_progress:
print 'Download Progress: %d%%' % int(download_progress.progress() * 100)
if done:
print 'Download Complete'
return
if __name__ == '__main__':
main()
Google spreadsheets don't have media. Instead they have exportLinks. Get the file metadata, then look in the exportlinks and pick an appropriate URL.
This code worked for me. I only had to download client_secret.json from google developers dashboard and keep in the same directory as python script.
And in the list_of_lists variable I got a list with each row as list.
import gspread
import json
from oauth2client.client import SignedJwtAssertionCredentials
json_key = json.load(open('client_secret.json'))
scope = ['https://spreadsheets.google.com/feeds']
credentials = SignedJwtAssertionCredentials(json_key['client_email'], json_key['private_key'], scope)
gc = gspread.authorize(credentials)
sht1 = gc.open_by_key('<id_of_sheet>')
worksheet_list = sht1.worksheets()
worksheet = sht1.sheet1
list_of_lists = worksheet.get_all_values()
for row in list_of_lists :
print row