I'm playing with the Google Mirror API and I am struggling to find a way to push a card to a specific user only.
Given the userid ( 12345677 ) when I try to post the card with the following Python code:
timeline_item = {'text': 'Test10'}
timeline_item['recipients'] = [{'id':'12345677'}]
self.mirror_service.timeline().insert(body=timeline_item).execute()
The card is visible in the timeline of all the other test users.
What am I doing wrong?
It looks like you are coding in Python and using the Google APIs Client Library for Python. To push a timeline item to a specific user id, set the user id when creating the mirror service. The Mirror API Python Quickstart has an example of how to do this in its notifications code. The recipients field has nothing to do with to whose timeline the item gets pushed.
from oauth2client.appengine import StorageByKeyName
from model import Credentials
self.mirror_service = create_service(
'mirror', 'v1',
StorageByKeyName(Credentials, MY_USER_ID, 'credentials').get())
timeline_item = {'text': 'Test10'}
self.mirror_service.timeline().insert(body=timeline_item).execute()
Code for create_service
import httplib2
from apiclient.discovery import build
from model import Credentials
def create_service(service, version, creds=None):
"""Create a Google API service.
Load an API service from a discovery document and authorize it with the
provided credentials.
Args:
service: Service name (e.g 'mirror', 'oauth2').
version: Service version (e.g 'v1').
creds: Credentials used to authorize service.
Returns:
Authorized Google API service.
"""
# Instantiate an Http instance
http = httplib2.Http()
if creds:
# Authorize the Http instance with the passed credentials
creds.authorize(http)
return build(service, version, http=http)
The recipients field doesn't specify who a timeline item should be sent to. It contains information about who has been sent the information on the card - it is intended for use by the REPLY_ALL card to be able to handle replies that should be sent to multiple people (not necessarily using Glass).
It isn't clear what language you're using, but it sounds like you are sending the item to all the authenticated users of your service.
Typically, you will specify the OAuth Token of a particular user to write to their timeline.
Related
In a django application, I try to have RW access to a google calendar which I own myself.
Tried several ways with a service account & client secrets, but all resulting in authentication errors.
The API explorer works, but it requests consent in a popup window, which is obviously not acceptable.
Documentation on google OAuth2 describes several scenarios. Probably "web server application" applies here? It says:
"The authorization sequence begins when your application redirects a
browser to a Google URL; the URL includes query parameters that
indicate the type of access being requested. Google handles the user
authentication, session selection, and user consent. The result is an
authorization code, which the application can exchange for an access
token and a refresh token."
Again, we do not want a browser redirection, we want direct access to the google calendar.
So question is: how can a django server access a google calendar, on which I have full rights, view events and add events using a simple server stored key or similar mechanism?
With help of DalmTo and this great article, I got RW access to a google calendar working from python code. I will summarize the solution here.
Here are the steps:
First of all register for a google service account: Service accounts are pre-authorized accounts that avoid you need to get consent or refresh keys every time:
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
(The part on G-suite can be ignored)
Download the service account credentials and store them safely. Your python code will need access to this file.
Go to your google calendar you want to get access to.
e.g. https://calendar.google.com/calendar/r/month
On the right side you see your calendars. Create an additional one for testing (since we'll write to it soon). Then point to this new calendar: click the 3 dots next to it and edit the sharing settings. Add the service account email address to the share under "share with specific people". (you can find the service account email address in the file downloaded previously under "client_email")
In the same screen, note the "calendar ID", you'll need it in below code.
Now you service account has the RW rights to the calendar.
Add at least one event to the calendar using the web UI (https://calendar.google.com/calendar/r/month) so we can read and change it from below code.
Then use following python code to read the calendar and change an event.
from google.oauth2 import service_account
import googleapiclient.discovery
SCOPES = ['https://www.googleapis.com/auth/calendar']
SERVICE_ACCOUNT_FILE = '<path to your service account file>'
CAL_ID = '<your calendar ID>'
credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
service = googleapiclient.discovery.build('calendar', 'v3', credentials=credentials)
events_result = service.events().list(calendarId=CAL_ID).execute()
events = events_result.get('items', [])
event_id = events[0]['id']
event = events[0]
service.events().update(calendarId=CAL_ID, eventId=event_id, body={"end":{"date":"2018-03-25"},"start":{"date":"2018-03-25"},"summary":"Kilroy was here"}).execute()
And there you go... read an event and updated the event.
I am try to access dbm api , I am authenticating the url using service account please find the sample code below
from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build
from httplib2 import Http
scopes =['https://www.googleapis.com/auth/doubleclickbidmanager']
credentials = ServiceAccountCredentials.from_json_keyfile_name(
'path/to/key/.jsonfile', scopes=scopes)
http_auth = credentials.authorize(Http())
body={}
dbm = build('doubleclickbidmanager', 'v1', http=http_auth)
print dbm
request = dbm.lineitems().downloadlineitems(body=body).execute()
print request
If I use oauth mechanism to authenticate the url the code is running properly, since I don't want user interaction, I need server to server mechanism so I used service account
Steps which I tried:
I have created the service account and downloaded the json key file and used in the code but when I try to run my code it throws the following error:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/doubleclickbidmanager/v1/lineitems/downloadlineitems?alt=json returned "You are not authorized to use DoubleClick Bid Manager API. Please contact dbm-support#google.com.">
Please help , thanks in advance.
As others have said here, you want to log in to the DBM site and add your service account as a user:
Then, per this documentation, you can set up service account credentials using your client secrets json file. If you want that service account to be able to access reports you've created in DBM under your user account (what you log in with) you need to delegate domain-wide authority:
delegated_credentials = credentials.create_delegated('user#example.org')
http_auth = delegated_credentials.authorize(Http())
dbm = build('doubleclickbidmanager', 'v1', http=http_auth)
queries = dbm.queries().listqueries().execute()['queries']
A service account isn't you its a dummy user it has its on Google drive account for example, and by default it doesn't have access to any DoubleClick Bid Manager APIs. Service accounts need to be pre authorized to be able to access private data. So for it to be able to access your double click data you are going to have to grant it access.
Normally with any other API I would say you take the service account email address and add it as a user. I don't have access to double click so I am not even sure if you can add other users manually. They don't have anything in the documentation about service accounts kind of makes me think its not supported. Let us know if you manage to get it to work.
I have a google app engine site, and what I want to do, is get access to the files on my drive and publish them. Note that, my account owns both the drive and the app engine page.
I have tried looking at the google drive api, and the problem is that I don't know where to start with the following boilerplate code located in their documentation.
If you take a look at this function:
def get_credentials(authorization_code, state):
"""Retrieve credentials using the provided authorization code.
This function exchanges the authorization code for an access token and queries
the UserInfo API to retrieve the user's e-mail address.
If a refresh token has been retrieved along with an access token, it is stored
in the application database using the user's e-mail address as key.
If no refresh token has been retrieved, the function checks in the application
database for one and returns it if found or raises a NoRefreshTokenException
with the authorization URL to redirect the user to.
Args:
authorization_code: Authorization code to use to retrieve an access token.
state: State to set to the authorization URL in case of error.
Returns:
oauth2client.client.OAuth2Credentials instance containing an access and
refresh token.
Raises:
CodeExchangeError: Could not exchange the authorization code.
NoRefreshTokenException: No refresh token could be retrieved from the
available sources.
"""
email_address = ''
try:
credentials = exchange_code(authorization_code)
user_info = get_user_info(credentials)
email_address = user_info.get('email')
user_id = user_info.get('id')
if credentials.refresh_token is not None:
store_credentials(user_id, credentials)
return credentials
else:
credentials = get_stored_credentials(user_id)
if credentials and credentials.refresh_token is not None:
return credentials
except CodeExchangeException, error:
logging.error('An error occurred during code exchange.')
# Drive apps should try to retrieve the user and credentials for the current
# session.
# If none is available, redirect the user to the authorization URL.
error.authorization_url = get_authorization_url(email_address, state)
raise error
except NoUserIdException:
logging.error('No user ID could be retrieved.')
# No refresh token has been retrieved.
authorization_url = get_authorization_url(email_address, state)
raise NoRefreshTokenException(authorization_url)
This is a part of the boilerplate code. However, where am I supposed to get authorisation_code from?
I recently had to implement something similar, and it is quite tricky to find the relevant pieces of documentation.
This is what worked for me.
One-time setup to enable Google Drive for your Google App Engine project
Go to the Google APIs Console and select your App Engine project. If you don't see your App Engine project listed, you need to enable the cloud integration in the App Engine admin tool first (Administration > Application Settings > Cloud Integration > Create project)
In Google APIs Console, now go to Services and look for the "Drive API" in that long list. Turn it on.
Go to the API Access section on Google APIs Console, and find back the "Simple API Access" API Key. (see screenshot below)
Getting and installing the Python Drive API Client
Download the Python Drive API Client: https://developers.google.com/api-client-library/python/start/installation#appengine
Documentation on this Python API: https://google-api-client-libraries.appspot.com/documentation/drive/v2/python/latest/
Using the Python Drive API Client
To create the Drive service object, I use this:
import httplib2
def createDriveService():
"""Builds and returns a Drive service object authorized with the
application's service account.
Returns:
Drive service object.
"""
from oauth2client.appengine import AppAssertionCredentials
from apiclient.discovery import build
credentials = AppAssertionCredentials(scope='https://www.googleapis.com/auth/drive')
http = httplib2.Http()
http = credentials.authorize(http)
return build('drive', 'v2', http=http, developerKey=API_KEY)
You can then use this service object to execute Google Drive API calls, for example, to create a folder:
service = createDriveService()
res = {'title': foldername,
'mimeType': "application/vnd.google-apps.folder"}
service.files().insert(body=res).execute()
Caveats
I was not able to get the Drive API to work in unittesting, nor on the dev_appserver. I always get an error that my credentials are not valid. However, it works fine on the real app engine server.
I'm looking for a good way to retrieve every emails address of my contacts from a google account for a "desktop" application in Python.
In a first time, I created an app via Google Code. I toggled Google Plus API, retrieving most of my user data, but not any of my contacts.
I started investigate, and I found a lot of stuff, but most of them was outdated.
I found a good way to retrieve my contacts, using gdata library but granting me a full read/write access on it, via https://www.google.com/m8/feeds with no feedback.
self.gd_client = gdata.contacts.client.ContactsClient(source='MyAppliName')
self.gd_client.ClientLogin(email, password, self.gd_client.source)
According to the official 'google contact api' google group, which migrated to stackoverflow, read only access is broken.
By the way, I'm not a huge fan of 'Trust my application, I use read only access, I swear."
I found the google api playground at https://developers.google.com/oauthplayground in which they use OAuth2.0 token with most of apis, including contact, toggling a webpage:
Google OAuth 2.0 Playground is requesting permission to:
Manage your contacts
According to this playground, it's possible to use OAuth2.0 with google contact api, but I have no idea how to add https:// www.google.com/m8/feeds to my scope, which doesn't appear on the list.
Is there an other way to do that ?
If this question is still open for you, here is some sample code how to use oauth2 and Google Contact API v3:
import gdata.contacts.client
from gdata.gauth import AuthSubToken
from oauth2client import tools
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
def oauth2_authorize_application(client_secret_file, scope, credential_cache_file='credentials_cache.json'):
"""
authorize an application to the requested scope by asking the user in a browser.
:param client_secret_file: json file containing the client secret for an offline application
:param scope: scope(s) to authorize the application for
:param credential_cache_file: if provided or not None, the credenials will be cached in a file.
The user does not need to be reauthenticated
:return OAuth2Credentials object
"""
FLOW = flow_from_clientsecrets(client_secret_file,
scope=scope)
storage = Storage(credential_cache_file)
credentials = storage.get()
if credentials is None or credentials.invalid:
# Run oauth2 flow with default arguments.
credentials = tools.run_flow(FLOW, storage, tools.argparser.parse_args([]))
return credentials
SCOPES = ['https://www.google.com/m8/feeds/', 'https://www.googleapis.com/auth/userinfo.email']
credentials = oauth2_authorize_application('client-secret.json', scope=SCOPES)
token_string = credentials.get_access_token().access_token
# deprecated!
# auth_token = AuthSubToken(token_string, SCOPES)
with open('client-secret.json') as f:
oauth2_client_secret = json.load(f)
auth_token = gdata.gauth.OAuth2Token(
client_id=oauth2_client_secret['web']['client_id'],
client_secret=oauth2_client_secret['web']['client_secret'],
scope=SCOPES,
user_agent='MyUserAgent/1.0',
access_token=credentials.get_access_token().access_token,
refresh_token=credentials.refresh_token)
client = gdata.contacts.client.ContactsClient(auth_token=auth_token)
query = gdata.contacts.client.ContactsQuery()
The request should look like:
https://accounts.google.com/o/oauth2/auth?
scope=https%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds&
state=<myState>&
redirect_uri=<Redirect URI>&
response_type=code&
client_id=<my Client ID>&approval_prompt=force
This will obtain read/write access to the user's contacts.
I would like to access my Google Affiliate Network product feed via the Google search API for shopping. I would like to do this from a backend Python library i'm developing. Has anyone done something like this?
I have the following:
A Google account
Enabled Search API for Shopping in the Google API Console and got
an API key (for server apps) and a client ID + client secret (for installed applications).
A GAN account and got the pid.
Several advertiser who approved me so i have products available in my product feed.
OAuth2 Python Code:
from apiclient.discovery import build
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run
from oauth2client.django_orm import Storage
from models import CredentialsModel
storage = Storage(CredentialsModel, 'name', 'GAN Reporting', 'credentials')
credentials = storage.get()
if credentials is None or credentials.invalid == True:
flow = OAuth2WebServerFlow(
client_id=MyClientID,
client_secret=MyClientSecret,
scope='https://www.googleapis.com/auth/shoppingapi',
user_agent='cleverblocks/1.0',
access_type='offline')
credentials = run(flow, storage)
http = httplib2.Http()
credentials.authorize(http)
client = build('shopping', 'v1', http=http,
developerKey=MyAPIKey)
resource = client.products()
request = resource.list(source='gan:MyGANPid', country='US')
return request.execute()
Running this i get back the following error (HttpError 412):
no advertisers are registered for the given publisher
The user I am using to authenticate is listed on the GAN->settings->users section.
I've been hacking at this from all directions to the point where I'm now starting to think this API is broken. Has anyone managed to access GAN product feed via the Search API for Shopping?
Any help is appreciated.
Finally got the above oAuth code to work.
The missing step was in the GAN console, under Subscriptions->Product Feed, to set an FTP subscription for all your advertisers. I used dummy FTP credentials.
Without this step you will get the above error.