+Wesley Chun
Developer Advocate
G Suite
Programming Google apps with the G Suite APIs
Contribute
questions at:
goo.gl/Rq6ABI
2017
Proprietary + Confidential
Google APIs client
libraries for many
languages, not just
Proprietary + Confidential
● Launched API v3 (Dec 2015)
○ v2 not deprecated (yet)
● WhatsApp integration (I/O 2016)
● Coming soon: Team Drives
(announced Sep 2016;
launched EAP: Mar 2017)
Drive
List (first 100) files in Google Drive
from __future__ import print_function
from apiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools
SCOPES = 'https://www.googleapis.com/auth/drive.readonly.metadata'
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
DRIVE = discovery.build('drive', 'v3', http=creds.authorize(Http()))
files = DRIVE.files().list().execute().get('files', [])
for f in files:
print(f['name'], f['mimeType'])
● API preview (I/O 2016)
● Launched API v1 (Nov 2016)
● Enhancements “v1.1” (Feb 2017)
Slides
Confidential & Proprietary
Confidential & Proprietary
Try our Node.js Markdown-to-Google-Slides generator:
github.com/googlesamples/md2googleslides
Replace text & images from template deck
requests = [
# (global) search-and-replace text
{'replaceAllText': {
'findText': '{{TITLE}}',
'replaceText': 'Hello World!',
}},
# replace text-based image placeholders (global)
{'replaceAllShapesWithImage': {
'imageUrl': IMG_URL, # link to product logo
'replaceMethod': 'CENTER_INSIDE',
'containsText': {'text': '{{LOGO}}'},
}},
]
SLIDES.presentations().batchUpdate(body={'requests': requests},
presentationId=DECK_ID, fields='').execute()
Proprietary + Confidential
● Launched API v4 (I/O 2016)
● Support text rotation (Mar 2017)
Sheets
Powerful API: expect UI features available programmatically
● Create new sheets within
spreadsheets
● Add data to sheets
● Create new spreadsheets
● Set frozen rows
● Text+number formatting
● Enforce cell validation
● Adjust column sizes
● Apply formulas
● Build pivot tables
● Create charts
● … and more!
BEFORE
(<= v3)
AFTER
(>= v4)
Import/Export: Customized reports, “database,” or both!
Try our Node.js customized reporting tool codelab:
g.co/codelabs/sheets
Migrate SQL data to a Sheet
# read SQL data then create new spreadsheet & add rows into it
FIELDS = ('ID', 'Customer Name', 'Product Code',
'Units Ordered', 'Unit Price', 'Status')
cxn = sqlite3.connect('db.sqlite')
cur = cxn.cursor()
rows = cur.execute('SELECT * FROM orders').fetchall()
cxn.close()
rows.insert(0, FIELDS)
DATA = {'properties': {'title': 'Customer orders'}}
SHEET_ID = SHEETS.spreadsheets().create(body=DATA,
fields='spreadsheetId').execute().get('spreadsheetId')
SHEETS.spreadsheets().values().update(spreadsheetId=SHEET_ID, range='A1',
body={'values': rows}, valueInputOption='RAW').execute()
Format cells (frozen & bold row)
requests = [
# freeze row 1
{'updateSheetProperties': {
'properties': {'gridProperties': {'frozenRowCount': 1}},
'fields': 'gridProperties.frozenRowCount',
}},
# bold row 1
{'repeatCell': {
'range': {'startRowIndex': 0, 'endRowIndex': 1},
'cell': {'userEnteredFormat': {'textFormat': {'bold': True}}},
'fields': 'userEnteredFormat.textFormat.bold',
}},
]
SHEETS.spreadsheets().batchUpdate(body={'requests': requests},
spreadsheetId=SHEET_ID, fields='').execute()
Proprietary + Confidential
● Settings endpoints launch (Jul 2016)
● New metadata scope (Nov 2016)
● Gmail add-ons (Mar 2017)
● Admin SDK Email Settings
deprecation (Jul 2017)
Gmail
Display Gmail threads (& # of messages)
# get all non-empty mail threads, display Subject & # of msgs in each
threads = GMAIL.users().threads().list(userId='me',
fields='threads').execute().get('threads', [])
for thread in threads:
tdata = GMAIL.users().threads().get(userId='me', id=thread['id'],
format='metadata', metadataHeaders=['subject'],
fields='messages/payload/headers(name,value)').execute()
if 'messages' not in tdata:
continue
msg = tdata['messages'][0]['payload'] # get 1st msg in thread
subject = ''
for header in msg['headers']: # get Subject line
if header['name'] == 'Subject':
subject = header['value']
break
if subject: # display if non-blank Subject
print('%2d message(s) in thread: %s' % (
len(tdata['messages']), subject))
Proprietary + Confidential
● Reminders on the web (Apr 2016)
● Events on Google Maps (Sep 2016)
● Find a time” on iOS (Sep 2016)
● New Calendar iOS app (Nov 2016)
Calendar
Create events in Calendar
# define event data, then create event
TIMEZONE = 'America/Los_Angeles'
EVENT = {
'summary': 'Dinner with friends',
'start': {'dateTime': '2017-06-14T19:00:00', 'timeZone': TIMEZONE},
'end': {'dateTime': '2017-06-14T22:00:00', 'timeZone': TIMEZONE},
'attendees': [
{'email': 'friend1@example.com'},
{'email': 'friend2@example.com'},
],
}
GCAL.events().insert(calendarId='primary', body=EVENT,
sendNotifications=True, fields='').execute()
Proprietary + Confidential
● Execution API allows external apps
to call Apps Script apps (Sep 2015)
● Android add-ons (Jul 2016)
● Advanced Services for Sheets &
Slides (Mar 2017)
● Quizzes in Forms support (Apr 2017)
Apps
Script
Sheets-bound “Hello World!”
Sheets-bound “Hello World!”
What can you do with this?
This… with help from Google Maps
AND this… with help from Maps and Gmail
Proprietary + Confidential
● Mobile Audit in Reports API
launched (May 2016)
● OAuth 1.0 deprecated (Oct 2016)
● New Drive metrics in Reports API
(Apr 2017)
● GData Admin Settings API
deprecated (Aug 2017)
Admin
SDK
Programmatically manage your domain
Proprietary + Confidential
● Classroom share button callbacks
(Dec 2015)
● Coursework access & improved Drive
integration (May 2016)
● Improved teachers & guardian
support (Aug 2016)
● Create+update questions,
modify+delete coursework, add Drive
items+YouTube videos (Jan 2017)
Classroom
Blog & video references
● G Suite APIs
○ Drive: goo.gl/ZIgf8k and goo.gl/EySSQV
○ Gmail: goo.gl/pFYUQ2
○ Calendar: goo.gl/KuYMiq
○ Sheets: goo.gl/N1RPwC and goo.gl/U6Oljn
○ Slides: developers.google.com/slides/videos
○ Sheets & Slides: goo.gl/Yb06ZC
● Google Apps Script
○ developers.google.com/apps-script/guides/videos
(intro, Google Maps & Gmail, YouTube, Google Forms)
Thank you!
Questions?
+Wesley Chun
google.com/+WesleyChun
@wescpy
twitter.com/wescpy
slide deck
goo.gl/Hs0IIR
Contribute
questions at:
goo.gl/Rq6ABI
CODELAB: Sat,
May 6, 10a-1230p
Great Falls room

Programming Google apps with the G Suite APIs

  • 1.
    +Wesley Chun Developer Advocate GSuite Programming Google apps with the G Suite APIs Contribute questions at: goo.gl/Rq6ABI 2017
  • 7.
    Proprietary + Confidential GoogleAPIs client libraries for many languages, not just Proprietary + Confidential ● Launched API v3 (Dec 2015) ○ v2 not deprecated (yet) ● WhatsApp integration (I/O 2016) ● Coming soon: Team Drives (announced Sep 2016; launched EAP: Mar 2017) Drive
  • 8.
    List (first 100)files in Google Drive from __future__ import print_function from apiclient import discovery from httplib2 import Http from oauth2client import file, client, tools SCOPES = 'https://www.googleapis.com/auth/drive.readonly.metadata' store = file.Storage('storage.json') creds = store.get() if not creds or creds.invalid: flow = client.flow_from_clientsecrets('client_secret.json', SCOPES) creds = tools.run_flow(flow, store) DRIVE = discovery.build('drive', 'v3', http=creds.authorize(Http())) files = DRIVE.files().list().execute().get('files', []) for f in files: print(f['name'], f['mimeType']) ● API preview (I/O 2016) ● Launched API v1 (Nov 2016) ● Enhancements “v1.1” (Feb 2017) Slides
  • 9.
    Confidential & Proprietary Confidential& Proprietary Try our Node.js Markdown-to-Google-Slides generator: github.com/googlesamples/md2googleslides
  • 10.
    Replace text &images from template deck requests = [ # (global) search-and-replace text {'replaceAllText': { 'findText': '{{TITLE}}', 'replaceText': 'Hello World!', }}, # replace text-based image placeholders (global) {'replaceAllShapesWithImage': { 'imageUrl': IMG_URL, # link to product logo 'replaceMethod': 'CENTER_INSIDE', 'containsText': {'text': '{{LOGO}}'}, }}, ] SLIDES.presentations().batchUpdate(body={'requests': requests}, presentationId=DECK_ID, fields='').execute() Proprietary + Confidential ● Launched API v4 (I/O 2016) ● Support text rotation (Mar 2017) Sheets
  • 11.
    Powerful API: expectUI features available programmatically ● Create new sheets within spreadsheets ● Add data to sheets ● Create new spreadsheets ● Set frozen rows ● Text+number formatting ● Enforce cell validation ● Adjust column sizes ● Apply formulas ● Build pivot tables ● Create charts ● … and more! BEFORE (<= v3) AFTER (>= v4) Import/Export: Customized reports, “database,” or both! Try our Node.js customized reporting tool codelab: g.co/codelabs/sheets
  • 12.
    Migrate SQL datato a Sheet # read SQL data then create new spreadsheet & add rows into it FIELDS = ('ID', 'Customer Name', 'Product Code', 'Units Ordered', 'Unit Price', 'Status') cxn = sqlite3.connect('db.sqlite') cur = cxn.cursor() rows = cur.execute('SELECT * FROM orders').fetchall() cxn.close() rows.insert(0, FIELDS) DATA = {'properties': {'title': 'Customer orders'}} SHEET_ID = SHEETS.spreadsheets().create(body=DATA, fields='spreadsheetId').execute().get('spreadsheetId') SHEETS.spreadsheets().values().update(spreadsheetId=SHEET_ID, range='A1', body={'values': rows}, valueInputOption='RAW').execute() Format cells (frozen & bold row) requests = [ # freeze row 1 {'updateSheetProperties': { 'properties': {'gridProperties': {'frozenRowCount': 1}}, 'fields': 'gridProperties.frozenRowCount', }}, # bold row 1 {'repeatCell': { 'range': {'startRowIndex': 0, 'endRowIndex': 1}, 'cell': {'userEnteredFormat': {'textFormat': {'bold': True}}}, 'fields': 'userEnteredFormat.textFormat.bold', }}, ] SHEETS.spreadsheets().batchUpdate(body={'requests': requests}, spreadsheetId=SHEET_ID, fields='').execute()
  • 13.
    Proprietary + Confidential ●Settings endpoints launch (Jul 2016) ● New metadata scope (Nov 2016) ● Gmail add-ons (Mar 2017) ● Admin SDK Email Settings deprecation (Jul 2017) Gmail Display Gmail threads (& # of messages) # get all non-empty mail threads, display Subject & # of msgs in each threads = GMAIL.users().threads().list(userId='me', fields='threads').execute().get('threads', []) for thread in threads: tdata = GMAIL.users().threads().get(userId='me', id=thread['id'], format='metadata', metadataHeaders=['subject'], fields='messages/payload/headers(name,value)').execute() if 'messages' not in tdata: continue msg = tdata['messages'][0]['payload'] # get 1st msg in thread subject = '' for header in msg['headers']: # get Subject line if header['name'] == 'Subject': subject = header['value'] break if subject: # display if non-blank Subject print('%2d message(s) in thread: %s' % ( len(tdata['messages']), subject))
  • 14.
    Proprietary + Confidential ●Reminders on the web (Apr 2016) ● Events on Google Maps (Sep 2016) ● Find a time” on iOS (Sep 2016) ● New Calendar iOS app (Nov 2016) Calendar Create events in Calendar # define event data, then create event TIMEZONE = 'America/Los_Angeles' EVENT = { 'summary': 'Dinner with friends', 'start': {'dateTime': '2017-06-14T19:00:00', 'timeZone': TIMEZONE}, 'end': {'dateTime': '2017-06-14T22:00:00', 'timeZone': TIMEZONE}, 'attendees': [ {'email': 'friend1@example.com'}, {'email': 'friend2@example.com'}, ], } GCAL.events().insert(calendarId='primary', body=EVENT, sendNotifications=True, fields='').execute()
  • 15.
    Proprietary + Confidential ●Execution API allows external apps to call Apps Script apps (Sep 2015) ● Android add-ons (Jul 2016) ● Advanced Services for Sheets & Slides (Mar 2017) ● Quizzes in Forms support (Apr 2017) Apps Script Sheets-bound “Hello World!”
  • 16.
  • 17.
    This… with helpfrom Google Maps AND this… with help from Maps and Gmail
  • 18.
    Proprietary + Confidential ●Mobile Audit in Reports API launched (May 2016) ● OAuth 1.0 deprecated (Oct 2016) ● New Drive metrics in Reports API (Apr 2017) ● GData Admin Settings API deprecated (Aug 2017) Admin SDK Programmatically manage your domain
  • 19.
    Proprietary + Confidential ●Classroom share button callbacks (Dec 2015) ● Coursework access & improved Drive integration (May 2016) ● Improved teachers & guardian support (Aug 2016) ● Create+update questions, modify+delete coursework, add Drive items+YouTube videos (Jan 2017) Classroom Blog & video references ● G Suite APIs ○ Drive: goo.gl/ZIgf8k and goo.gl/EySSQV ○ Gmail: goo.gl/pFYUQ2 ○ Calendar: goo.gl/KuYMiq ○ Sheets: goo.gl/N1RPwC and goo.gl/U6Oljn ○ Slides: developers.google.com/slides/videos ○ Sheets & Slides: goo.gl/Yb06ZC ● Google Apps Script ○ developers.google.com/apps-script/guides/videos (intro, Google Maps & Gmail, YouTube, Google Forms)
  • 20.
    Thank you! Questions? +Wesley Chun google.com/+WesleyChun @wescpy twitter.com/wescpy slidedeck goo.gl/Hs0IIR Contribute questions at: goo.gl/Rq6ABI CODELAB: Sat, May 6, 10a-1230p Great Falls room