Creating a DfpClient with a Service Account in Python - python

I use the google DFP api to collect some statistics on ads clicked on our website. The
code is written in Python. Currently, I am trying to upgrade the code to use oAuth 2.
Since, the code runs automatically everyday without any user involvement, I created a
service account under my google project and added the account to the DoubleClick for
Publishers network of our company. Based on the sample codes on the web, I wrote this:
import httplib2
from oauth2client.client import SignedJwtAssertionCredentials
from apiclient.discovery import build
from googleads.dfp import DfpClient
GOOGLE_DFP_SCOPE="https://www.googleapis.com/auth/dfp"
API_VERSION="v201411"
KEY_FILE="*******.p12"
ACCT_EMAIL="************************#developer.gserviceaccount.com"
NETWORK_CODE="**********"
with open(KEY_FILE) as config_file:
my_private_key = config_file.read()
credentials = SignedJwtAssertionCredentials(service_account_name=ACCT_EMAIL, private_key=my_private_key,scope=GOOGLE_DFP_SCOPE)
http = httplib2.Http()
http_auth = credentials.authorize(http)
dfp_client = build(serviceName='dfp',version=API_VERSION,http=http_auth)
This code does not seem to be correct, because the network_code has not been passed
anywhere in the code. In addition, it fails with the following message:
apiclient.errors.UnknownApiNameOrVersion: name: dfp version: v201411.
Also, the line below:
dfp_client = DfpClient.LoadFromStorage()
does not work for my case, because, this is based on googleads.yaml which seems
to be formatted only for web-app accounts with client secret, not P12 private key.
Any advice? Thanks.

Apiclient.discovery uses a default route to check the services.
But I did not find a service for DoubleClick for publishers.
I use this code to use API with Oauth2. Using Flask
import json
import requests
import flask
from googleads import dfp
from googleads import oauth2
app = flask.Flask(__name__)
CLIENT_ID = ''
CLIENT_SECRET = '' # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/dfp'
REDIRECT_URI = ''
APPLICATION_NAME = 'DFP API SERVICE'
NETWORK_CODE = ''
#app.route('/')
def index():
if 'credentials' not in flask.session:
return flask.redirect(flask.url_for('oauth2callback'))
credentials = json.loads(flask.session['credentials'])
if credentials['expires_in'] <= 0:
return flask.redirect(flask.url_for('oauth2callback'))
else:
try:
refresh_token = credentials['refresh_token']
oauth2_client = oauth2.GoogleRefreshTokenClient(CLIENT_ID, CLIENT_SECRET, refresh_token)
dfp_client = dfp.DfpClient(oauth2_client, APPLICATION_NAME, NETWORK_CODE)
user_service = dfp_client.GetService('UserService', version='v201508')
user = user_service.getCurrentUser()
return flask.render_template('index.html', name=user['name'])
except:
flask.session.pop('credentials', None)
return flask.redirect(flask.url_for('oauth2callback'))
#app.route('/oauth2callback')
def oauth2callback():
if 'code' not in flask.request.args:
auth_uri = ('https://accounts.google.com/o/oauth2/auth?response_type=code'
'&access_type=offline&client_id={}&redirect_uri={}&scope={}&').format(CLIENT_ID, REDIRECT_URI, SCOPE)
return flask.redirect(auth_uri)
else:
auth_code = flask.request.args.get('code')
data = {'code': auth_code,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'authorization_code'}
r = requests.post('https://www.googleapis.com/oauth2/v3/token', data=data)
flask.session['credentials'] = r.text
return flask.redirect(flask.url_for('index'))
if __name__ == '__main__':
import uuid
app.secret_key = str(uuid.uuid4())
app.debug = False
app.run()
I hope this help you

You are correct. You have to pass the network code when you create a dfp client. And version is not necessary. Try the following code to create the client in python.
import os
from googleads import oauth2
from googleads import dfp
def get_dfp_client():
application_name = "Your application name" # from google developer console. eg: Web Client
network_code = ********
private_key_password = 'notasecret'
key_file = os.path.join('path/to/p12file')
service_account_email = '****#***.iam.gserviceaccount.com'
# create oath2 client(google login)
oauth2_client = oauth2.GoogleServiceAccountClient(
oauth2.GetAPIScope('dfp'), service_account_email, key_file)
dfp_client = dfp.DfpClient(oauth2_client, application_name, network_code)
return dfp_client
client = get_dfp_client()
Reference
Please comment if you need more clarification.
Update
googleads renamed module dfp to ad_manager, docs here – Gocht

Related

Google Shared Drive Push Notifications only Sending for Service Account Changes

I would like to get push notifications anytime a file is added to our shared drive by any user.
I have a service account authenticated with the Google Drive API calling the changes.watch() method on the shared drive, and I successfully get notifications if the shared drive name or icon changes, a file is created by the service account, or if files are modified by any user so long as the service account created the file. However, I do not get any push notifications for files created on this shared drive by other users - even though the page token increases and calling changes.list() will show me the changes that all users made on the shared drive.
I have the shared drive shared with the service account, and the service account also has domain-wide delegation for the scope https://www.googleapis.com/auth/drive and uses that scope in the API call.
Any help would be greatly appreciated as I cannot figure out what I'm lacking to get push notifications for all changes on this shared drive. Below is my code related to authenticating and subscribing to change notifications.
import urllib
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google.oauth2 import service_account
import uuid
from datetime import datetime
def get_service(api_name, api_version, scopes, key_file_location):
credentials = service_account.Credentials.from_service_account_file(
key_file_location)
scoped_credentials = credentials.with_scopes(scopes)
service = build(api_name, api_version, credentials=scoped_credentials)
return service
def get_start_page_token(service):
response = service.changes().getStartPageToken(
driveId = "REDACTED",
supportsAllDrives = True,
supportsTeamDrives = True
).execute()
startPageToken = response.get("startPageToken")
print(F'Start token: {startPageToken}')
return startPageToken
def subscribe_changes(service):
channel_id = str(uuid.uuid4())
body = {
"id": channel_id,
"type": "web_hook",
"address": "https://REDACTED"
}
response = service.changes().watch(
body=body,
pageToken = get_start_page_token(service),
includeItemsFromAllDrives = True,
supportsAllDrives = True,
supportsTeamDrives = True,
driveId = "REDACTED"
).execute()
ts = int(response['expiration'])
print("Expiration in UTC: " + datetime.utcfromtimestamp(ts / 1000).strftime('%Y-%m-%d %H:%M:%S'))
print(response)
return channel_id
# Define the auth scopes to request.
scope = 'https://www.googleapis.com/auth/drive'
key_file_location = 'credentials.json'
try:
# Authenticate and construct service.
service = get_service(
api_name='drive',
api_version='v3',
scopes=[scope],
key_file_location=key_file_location)
except HttpError as error:
print(f'An error occurred: {error}')
# subscribe to changes
channel_id = subscribe_changes(service)
print(f"Channel Id: {channel_id}")

Serialize and de-serialize oauth2client.client.OAuth2Credentials

So I have an object, which is credentials from an OAuth2 authorization for a web service. I want to save the users credentials so I can continue to use them in the future. I'm using Django.
The object is: <oauth2client.client.OAuth2Credentials object at 0x104b47310>
I'm not sure how I can stringify the credentials and then build the credentials object back from a string.
Sample code as requested:
#!/usr/bin/python
import httplib2
from apiclient import errors
from apiclient.discovery import build
from oauth2client.client import OAuth2WebServerFlow
# Copy your credentials from the console
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'
# Check https://developers.google.com/webmaster-tools/search-console-api-original/v3/ for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/webmasters.readonly'
# Redirect URI for installed apps
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
# Run through the OAuth flow and retrieve credentials
flow = OAuth2WebServerFlow(CLIENT_ID, CLIENT_SECRET, OAUTH_SCOPE, REDIRECT_URI)
authorize_url = flow.step1_get_authorize_url()
print 'Go to the following link in your browser: ' + authorize_url
code = raw_input('Enter verification code: ').strip()
credentials = flow.step2_exchange(code)
# Create an httplib2.Http object and authorize it with our credentials
http = httplib2.Http()
http = credentials.authorize(http)
webmasters_service = build('webmasters', 'v3', http=http)
# Retrieve list of properties in account
site_list = webmasters_service.sites().list().execute()
# Filter for verified websites
verified_sites_urls = [s['siteUrl'] for s in site_list['siteEntry']
if s['permissionLevel'] != 'siteUnverifiedUser'
and s['siteUrl'][:4] == 'http']
# Printing the URLs of all websites you are verified for.
for site_url in verified_sites_urls:
print site_url
# Retrieve list of sitemaps submitted
sitemaps = webmasters_service.sitemaps().list(siteUrl=site_url).execute()
if 'sitemap' in sitemaps:
sitemap_urls = [s['path'] for s in sitemaps['sitemap']]
print " " + "\n ".join(sitemap_urls)
You can use pickle module to serialize and de-serialize python objects. Here is untested code:
import pickle
# Store OAuth2Credentials to a file
with open(FILENAME, 'wb') as credentials_file:
pickle.dump(credentials, credentials_file)
# Read OAuth2Credentials from file
with open(FILENAME, 'rb') as credentials_file:
credentials = pickle.load(credentials_file)

How to use Google Blogger API with Python?

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.

Why is this mime type deemed invalid for creating a Google Doc?

I've created a "wrapper" class for the the python-quickstart code. It works fine in my class, unless I change the mime type. In their code they created a plain text document, but I'm trying to create a Google Docs file from my code. When I try to run this code, I receive an HttpError 400 stating that my mime type is invalid. What exactly am I doing wrong?
Here is my code:
import pprint
import httplib2
import googleapiclient.discovery
import googleapiclient.http
import googleapiclient.errors
import oauth2client.client
class DriveClient():
def __init__(self):
self.oauth2_scope = 'https://www.googleapis.com/auth/drive'
self.client_secrets = 'client_secrets.json'
self.mimetype = 'application/vnd.google-apps.document'
self.flow = self.set_flow()
self.drive_service = self.authorize_url()
def set_flow(self):
flow = oauth2client.client.flow_from_clientsecrets(self.client_secrets,
self.oauth2_scope)
flow.redirect_uri = oauth2client.client.OOB_CALLBACK_URN
return flow
def authorize_url(self):
authorize_url = self.flow.step1_get_authorize_url()
print('Go to the following link in your browser: ' + authorize_url)
code = input('Enter verification code: ').strip()
credentials = self.flow.step2_exchange(code)
http = httplib2.Http()
credentials.authorize(http)
drive_service = googleapiclient.discovery.build('drive', 'v2',
http=http)
return drive_service
def push_file(self, file_src, title, description=''):
media_body = googleapiclient.http.MediaFileUpload(
file_src, mimetype=self.mimetype, resumable=True)
body = {
'title': title,
'description': description
}
try:
new_file = self.drive_service.files().insert(body=body,
media_body=media_body
).execute()
pprint.pprint(new_file)
except googleapiclient.errors.HttpError as error:
print('An error occured: %s' % error)
if __name__ == '__main__':
d = DriveClient()
d.push_file('document.txt', 'mTitle', 'mDescription')
Try setting the mime type to the type of the source document, eg application/msword, application/vnd.oasis.opendocument.text , etc. Google needs to know what the format of the incoming document is, then it will choose what kind of google doc to create.

Python - oauth2 - linkedin API

I am trying to follow some companies registered on LinkedIn through python code and as per LinkedIn API documentation I need to use oauth2 - POST method to follow a company.
My queries are below:
How to specify a particular company name via python code to follow a company?
Can someone advise the python code for this?
My code is below:
oauth_token = oauth.Token(key=access_token_key, secret=access_token_secret)
oauth_consumer = oauth.Consumer(key=api_key, secret=api_secret)
signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1()
http_method = "POST"
http_handler = urllib.HTTPHandler(debuglevel=_debug)
https_handler = urllib.HTTPSHandler(debuglevel=_debug)
def linkedinreq(url, method, parameters):
req = oauth.Request.from_consumer_and_token(oauth_consumer,
token=oauth_token,
http_method=http_method,
http_url=url,
parameters=parameters)
req.sign_request(signature_method_hmac_sha1, oauth_consumer, oauth_token)
req.to_postdata()
def fetchsamples():
url = "https://api.linkedin.com/v1/people/~/following/companies"
parameters = []
response = linkedinreq(url, "POST", parameters)
fetchsamples()
The python modules python-linkedin and python-linkedin-v2 are outdated. Thus, I suggest you to use the requests_oauthlib module instead.
from requests_oauthlib import OAuth2Session
from requests_oauthlib.compliance_fixes import linkedin_compliance_fix
# In case the `redirect_url` does not implement https
import os
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
# Credentials you get from registering a new application
client_id = '<the client id you get from linkedin>'
client_secret = '<the client secret you get from linkedin>'
redirect_url = '<authorized redirect URL from LinkedIn config>'
# OAuth endpoints given in the LinkedIn API documentation (check for updates)
authorization_base_url = 'https://www.linkedin.com/oauth/v2/authorization'
token_url = 'https://www.linkedin.com/oauth/v2/accessToken'
# Authorized Redirect URL (from LinkedIn config)
linkedin = OAuth2Session(client_id, redirect_uri=redirect_url)
linkedin = linkedin_compliance_fix(linkedin)
# Redirect user to LinkedIn for authorization
authorization_url, state = linkedin.authorization_url(authorization_base_url)
print('Please go here and authorize,', authorization_url)
# Get the authorization verifier code from the callback url
redirect_response = input('Paste the full redirect URL here:')
# Fetch the access token
linkedin.fetch_token(token_url, client_secret=client_secret,
authorization_response=redirect_response)
# Fetch a protected resource, i.e. user profile
r = linkedin.get('https://api.linkedin.com/v1/people/~')
print(r.content)
Instead of reinventing the wheel, use python-linkedin wrapper.
Example code to search for the companies:
from linkedin import linkedin
CONSUMER_KEY = 'your key'
CONSUMER_SECRET = 'your secret'
USER_TOKEN = 'your token'
USER_SECRET = 'your user secret'
RETURN_URL = ''
# Instantiate the developer authentication class
authentication = linkedin.LinkedInDeveloperAuthentication(CONSUMER_KEY, CONSUMER_SECRET,
USER_TOKEN, USER_SECRET,
RETURN_URL, linkedin.PERMISSIONS.enums.values())
# Pass it in to the app...
application = linkedin.LinkedInApplication(authentication)
print application.search_company(selectors=[{'companies': ['name', 'universal-name', 'website-url']}],
params={'keywords': 'apple microsoft'})
To follow the company, use follow_company() method, see more information and examples here:
COMPANY_ID = 1035 # this you would get from the `search_company()`
application.follow_company(COMPANY_ID)

Categories

Resources