Skip to content

Instantly share code, notes, and snippets.

@adamotte
Forked from jmb/README.md
Last active October 9, 2016 15:07
Show Gist options
  • Select an option

  • Save adamotte/cda7b8345ae50018c716 to your computer and use it in GitHub Desktop.

Select an option

Save adamotte/cda7b8345ae50018c716 to your computer and use it in GitHub Desktop.

Revisions

  1. Anthony Damotte revised this gist Dec 30, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,7 @@ Download the [Moment](http://moment.js.com) javascript library and add to your j

    The first time you run the script, it will prompt you to authorize access:

    The script will attempt to open to open a new window or tab in your default browser. If this fails, copy the URL from the console and manually open it in your browser.
    The script will attempt to open a new window or tab in your default browser. If this fails, copy the URL from the console and manually open it in your browser.

    If you are not already logged into your Google account, you will be prompted to log in. If you are logged into multiple Google accounts, you will be asked to select one account to use for the authorization.
    Click the Accept button.
  2. Anthony Damotte revised this gist Dec 30, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@ I use this widget to display my shift calendar - see the [screenshot below](http
    - Use this [wizard](https://console.developers.google.com/start/api?id=calendar) to create or select a project in the Google Developers Console and automatically turn on the API. Click Continue, then Go to credentials.
    - At the top of the page, select the OAuth consent screen tab. Select an Email address, enter a Product name if not already set, and click the Save button.
    - Select the Credentials tab, click the Add credentials button and select OAuth 2.0 client ID.
    - Select the application type Other, enter the name "Dashing.io.google.calendar", and click the Create button.
    - Select the application type Other, enter the name "dashing.io.google.calendar", and click the Create button.
    - Click OK to dismiss the resulting dialog.
    - Click the (Download JSON) button to the right of the client ID.
    - Move this file to ```jobs``` directory and rename it client_secret.json.
  3. Anthony Damotte revised this gist Dec 30, 2015. 2 changed files with 71 additions and 50 deletions.
    26 changes: 22 additions & 4 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,14 +1,20 @@
    ## Description

    [Dashing](http://shopify.github.com/dashing) widget to display the next and some subsequent [Google Calendar](https://www.google.com/calendar/) events using the Google Calendar API v3.
    [Dashing](http://dashing.io) widget to display the next and some subsequent [Google Calendar](https://www.google.com/calendar/) events using the Google Calendar API v3.

    I use this widget to display my shift calendar - see the [screenshot below](https://gist.github.com/jmb/33ae3a33d6e8dbffd102#file-google_calendar_widget-png)

    ## Set up
    ## Step 1: Turn on the Google Calendar API

    This widget works with API v3 and requires a service account to be set up via the [Google Developer's Console](https://console.developers.google.com/). Once a project is set up, enable the Calendar API. On the Credentials page create a new OpenID and download the p12 key file - set up the path to this file in the job file and grant the email address access to the relevant calendar.
    - Use this [wizard](https://console.developers.google.com/start/api?id=calendar) to create or select a project in the Google Developers Console and automatically turn on the API. Click Continue, then Go to credentials.
    - At the top of the page, select the OAuth consent screen tab. Select an Email address, enter a Product name if not already set, and click the Save button.
    - Select the Credentials tab, click the Add credentials button and select OAuth 2.0 client ID.
    - Select the application type Other, enter the name "Dashing.io.google.calendar", and click the Create button.
    - Click OK to dismiss the resulting dialog.
    - Click the (Download JSON) button to the right of the client ID.
    - Move this file to ```jobs``` directory and rename it client_secret.json.

    The job file defines how many events to get from the calendar and when to start the search. My version gets the next 6 events.
    ## Step 2: Install the Google Client Library

    Add to Gemfile:
    ```
    @@ -19,4 +25,16 @@ Run
    bundle install
    ```

    ## Step 3: Add Moment librairy

    Download the [Moment](http://moment.js.com) javascript library and add to your javascript assets. Add `#= require moment.js` to the application.coffee script. You can also use `moment.min.js` if you've downloaded that.

    ## Step 4: Authorize your script

    The first time you run the script, it will prompt you to authorize access:

    The script will attempt to open to open a new window or tab in your default browser. If this fails, copy the URL from the console and manually open it in your browser.

    If you are not already logged into your Google account, you will be prompted to log in. If you are logged into multiple Google accounts, you will be asked to select one account to use for the authorization.
    Click the Accept button.
    The script will proceed automatically, and you may close the window/tab.
    95 changes: 49 additions & 46 deletions google_calendar.rb
    Original file line number Diff line number Diff line change
    @@ -1,56 +1,59 @@
    # encoding: UTF-8

    require 'google/api_client'
    require 'date'
    require 'time'
    require 'digest/md5'
    require 'active_support'
    require 'active_support/all'
    require 'json'

    # Update these to match your own apps credentials
    service_account_email = '[email protected]' # Email of service account
    key_file = '/Path/to/keyfile.p12' # File containing your private key
    key_secret = 'notasecret' # Password to unlock private key
    calendarID = '[email protected]' # Calendar ID.

    # Get the Google API client
    client = Google::APIClient.new(:application_name => 'Dashing Calendar Widget',
    :application_version => '0.0.1')

    # Load your credentials for the service account
    if not key_file.nil? and File.exists? key_file
    key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, key_secret)
    else
    key = OpenSSL::PKey::RSA.new ENV['GOOGLE_SERVICE_PK'], key_secret
    require 'google/api_client/client_secrets'
    require 'google/api_client/auth/installed_app'
    require 'google/api_client/auth/storage'
    require 'google/api_client/auth/storages/file_store'
    require 'fileutils'

    APPLICATION_NAME = 'dashing.io.google.calendar'
    CLIENT_SECRETS_PATH = 'jobs/client_secret.json'
    CREDENTIALS_PATH = File.join(Dir.home, '.credentials',
    "google-calendar-dashing-job.json")
    SCOPE = 'https://www.googleapis.com/auth/calendar.readonly'

    ##
    # Ensure valid credentials, either by restoring from the saved credentials
    # files or intitiating an OAuth2 authorization request via InstalledAppFlow.
    # If authorization is required, the user's default browser will be launched
    # to approve the request.
    #
    # @return [Signet::OAuth2::Client] OAuth2 credentials
    def authorize
    FileUtils.mkdir_p(File.dirname(CREDENTIALS_PATH))

    file_store = Google::APIClient::FileStore.new(CREDENTIALS_PATH)
    storage = Google::APIClient::Storage.new(file_store)
    auth = storage.authorize

    if auth.nil? || (auth.expired? && auth.refresh_token.nil?)
    app_info = Google::APIClient::ClientSecrets.load(CLIENT_SECRETS_PATH)
    flow = Google::APIClient::InstalledAppFlow.new({
    :client_id => app_info.client_id,
    :client_secret => app_info.client_secret,
    :scope => SCOPE})
    auth = flow.authorize(storage)
    puts "Credentials saved to #{CREDENTIALS_PATH}" unless auth.nil?
    end
    auth
    end

    client.authorization = Signet::OAuth2::Client.new(
    :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
    :audience => 'https://accounts.google.com/o/oauth2/token',
    :scope => 'https://www.googleapis.com/auth/calendar.readonly',
    :issuer => service_account_email,
    :signing_key => key)
    # Initialize the API
    client = Google::APIClient.new(:application_name => APPLICATION_NAME)
    client.authorization = authorize
    calendar_api = client.discovered_api('calendar', 'v3')

    # Start the scheduler
    SCHEDULER.every '15m', :first_in => 4 do |job|

    # Request a token for our service account
    client.authorization.fetch_access_token!

    # Get the calendar API
    service = client.discovered_api('calendar','v3')

    # Start and end dates
    now = DateTime.now

    result = client.execute(:api_method => service.events.list,
    :parameters => {'calendarId' => calendarID,
    'timeMin' => now.rfc3339,
    'orderBy' => 'startTime',
    'singleEvents' => 'true',
    'maxResults' => 6}) # How many calendar items to get
    results = client.execute!(
    :api_method => calendar_api.events.list,
    :parameters => {
    :calendarId => 'primary',
    :maxResults => 3,
    :singleEvents => true,
    :orderBy => 'startTime',
    :timeMin => Time.now.iso8601 })

    send_event('google_calendar', { events: result.data })
    send_event('google_calendar', { events: results.data })

    end
  4. @jmb jmb revised this gist Feb 4, 2015. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,8 @@

    [Dashing](http://shopify.github.com/dashing) widget to display the next and some subsequent [Google Calendar](https://www.google.com/calendar/) events using the Google Calendar API v3.

    I use this widget to display my shift calendar - see the [screenshot below](https://gist.github.com/jmb/33ae3a33d6e8dbffd102#file-google_calendar_widget-png)

    ## Set up

    This widget works with API v3 and requires a service account to be set up via the [Google Developer's Console](https://console.developers.google.com/). Once a project is set up, enable the Calendar API. On the Credentials page create a new OpenID and download the p12 key file - set up the path to this file in the job file and grant the email address access to the relevant calendar.
  5. @jmb jmb revised this gist Feb 4, 2015. 1 changed file with 0 additions and 4 deletions.
    4 changes: 0 additions & 4 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -2,10 +2,6 @@

    [Dashing](http://shopify.github.com/dashing) widget to display the next and some subsequent [Google Calendar](https://www.google.com/calendar/) events using the Google Calendar API v3.

    ## Preview

    ![](https://gist.github.com/jmb/33ae3a33d6e8dbffd102/raw/40d3418fd354676a6b6bd4c0b5675164b579400e/google_calendar_widget.png)

    ## Set up

    This widget works with API v3 and requires a service account to be set up via the [Google Developer's Console](https://console.developers.google.com/). Once a project is set up, enable the Calendar API. On the Credentials page create a new OpenID and download the p12 key file - set up the path to this file in the job file and grant the email address access to the relevant calendar.
  6. @jmb jmb revised this gist Feb 4, 2015. 1 changed file with 7 additions and 1 deletion.
    8 changes: 7 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,12 @@
    ## Description

    [Dashing](http://shopify.github.com/dashing) widget to display the next and some subsequent [Google Calendar](https://www.google.com/calendar/) events.
    [Dashing](http://shopify.github.com/dashing) widget to display the next and some subsequent [Google Calendar](https://www.google.com/calendar/) events using the Google Calendar API v3.

    ## Preview

    ![](https://gist.github.com/jmb/33ae3a33d6e8dbffd102/raw/40d3418fd354676a6b6bd4c0b5675164b579400e/google_calendar_widget.png)

    ## Set up

    This widget works with API v3 and requires a service account to be set up via the [Google Developer's Console](https://console.developers.google.com/). Once a project is set up, enable the Calendar API. On the Credentials page create a new OpenID and download the p12 key file - set up the path to this file in the job file and grant the email address access to the relevant calendar.

  7. @jmb jmb revised this gist Feb 4, 2015. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -14,3 +14,5 @@ Run
    ```
    bundle install
    ```

    Download the [Moment](http://moment.js.com) javascript library and add to your javascript assets. Add `#= require moment.js` to the application.coffee script. You can also use `moment.min.js` if you've downloaded that.
  8. @jmb jmb revised this gist Feb 4, 2015. 1 changed file with 0 additions and 0 deletions.
    Binary file added google_calendar_widget.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  9. @jmb jmb revised this gist Feb 3, 2015. 1 changed file with 6 additions and 2 deletions.
    8 changes: 6 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -7,6 +7,10 @@ This widget works with API v3 and requires a service account to be set up via th
    The job file defines how many events to get from the calendar and when to start the search. My version gets the next 6 events.

    Add to Gemfile:
    `gem 'google-api-client', '>= 0.8'`
    ```
    gem 'google-api-client', '>= 0.8'
    ```
    Run
    `bundle install`
    ```
    bundle install
    ```
  10. @jmb jmb revised this gist Feb 3, 2015. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -6,3 +6,7 @@ This widget works with API v3 and requires a service account to be set up via th

    The job file defines how many events to get from the calendar and when to start the search. My version gets the next 6 events.

    Add to Gemfile:
    `gem 'google-api-client', '>= 0.8'`
    Run
    `bundle install`
  11. @jmb jmb revised this gist Feb 3, 2015. 3 changed files with 8 additions and 31 deletions.
    7 changes: 6 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,8 @@
    ## Description

    [Dashing](http://shopify.github.com/dashing) widget to display the next and some subsequent [Google Calendar](https://www.google.com/calendar/) events.
    [Dashing](http://shopify.github.com/dashing) widget to display the next and some subsequent [Google Calendar](https://www.google.com/calendar/) events.

    This widget works with API v3 and requires a service account to be set up via the [Google Developer's Console](https://console.developers.google.com/). Once a project is set up, enable the Calendar API. On the Credentials page create a new OpenID and download the p12 key file - set up the path to this file in the job file and grant the email address access to the relevant calendar.

    The job file defines how many events to get from the calendar and when to start the search. My version gets the next 6 events.

    22 changes: 2 additions & 20 deletions google_calendar.coffee
    Original file line number Diff line number Diff line change
    @@ -1,9 +1,6 @@
    class Dashing.GoogleCalendar extends Dashing.Widget
    ready: =>
    if !@pre? then @set('pre',0)

    onData: (data) =>

    onData: (data) =>
    event = rest = null
    getEvents = (first, others...) ->
    event = first
    @@ -20,24 +17,9 @@ class Dashing.GoogleCalendar extends Dashing.Widget

    next_events = []
    for next_event in rest
    #do (next_event) ->
    start = moment(next_event.start.dateTime)
    start_date = start.format('ddd Do MMM')
    start_time = start.format('HH:mm')

    next_events.push { summary: next_event.summary, start_date: start_date, start_time: start_time }
    @set('next_events', next_events)



    updateTime: =>
    if @event?
    event = @event
    diff = moment(event.when_start).diff(moment())
    if diff<0
    event.time = "Ends "+moment(event.when_end).fromNow()
    else
    event.time = moment(event.when_start).calendar()

    @unset('event')
    @set('event',event)
    @set('next_events', next_events)
    10 changes: 0 additions & 10 deletions google_calendar.scss
    Original file line number Diff line number Diff line change
    @@ -7,9 +7,6 @@ $title-color: rgba(255, 255, 255, 1);
    $subtitle-color: rgba(255, 255, 255, 0.7);
    $moreinfo-color: rgba(255, 255, 255, 0.7);

    $private-color: rgb(123, 209, 72);
    $business-color: rgb(255, 173, 70);

    // ----------------------------------------------------------------------------
    // Widget-calendar styles
    // ----------------------------------------------------------------------------
    @@ -57,10 +54,3 @@ $business-color: rgb(255, 173, 70);
    font-size: 65px;
    }
    }
    .calendar-name-private {
    background-color: $private-color;
    }

    .calendar-name-business {
    background-color: $business-color;
    }
  12. @jmb jmb created this gist Feb 3, 2015.
    3 changes: 3 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    ## Description

    [Dashing](http://shopify.github.com/dashing) widget to display the next and some subsequent [Google Calendar](https://www.google.com/calendar/) events.
    43 changes: 43 additions & 0 deletions google_calendar.coffee
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    class Dashing.GoogleCalendar extends Dashing.Widget
    ready: =>
    if !@pre? then @set('pre',0)

    onData: (data) =>

    event = rest = null
    getEvents = (first, others...) ->
    event = first
    rest = others

    getEvents data.events.items...

    start = moment(event.start.dateTime)
    end = moment(event.end.dateTime)

    @set('event',event)
    @set('event_date', start.format('dddd Do MMMM'))
    @set('event_times', start.format('HH:mm') + " - " + end.format('HH:mm'))

    next_events = []
    for next_event in rest
    #do (next_event) ->
    start = moment(next_event.start.dateTime)
    start_date = start.format('ddd Do MMM')
    start_time = start.format('HH:mm')

    next_events.push { summary: next_event.summary, start_date: start_date, start_time: start_time }
    @set('next_events', next_events)



    updateTime: =>
    if @event?
    event = @event
    diff = moment(event.when_start).diff(moment())
    if diff<0
    event.time = "Ends "+moment(event.when_end).fromNow()
    else
    event.time = moment(event.when_start).calendar()

    @unset('event')
    @set('event',event)
    15 changes: 15 additions & 0 deletions google_calendar.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,15 @@
    <h1 class="subtitle" >Next event:</h1>
    <h3 class="times" data-bind="event_date"></h3>
    <h2 class="title" data-bind="event.summary"></h2>
    <h3 class="times" data-bind="event_times"></h3>
    <h4 data-bind="next_count"></h4>

    <table class="next">
    <tr data-foreach-e='next_events'>
    <td data-bind="e.start_date"></td>
    <td data-bind="e.start_time"></td>
    <td data-bind="e.summary"></td>
    </tr>
    </table>

    <div class="updated-at" data-bind="updatedAtMessage"></div>
    56 changes: 56 additions & 0 deletions google_calendar.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,56 @@
    # encoding: UTF-8

    require 'google/api_client'
    require 'date'
    require 'time'
    require 'digest/md5'
    require 'active_support'
    require 'active_support/all'
    require 'json'

    # Update these to match your own apps credentials
    service_account_email = '[email protected]' # Email of service account
    key_file = '/Path/to/keyfile.p12' # File containing your private key
    key_secret = 'notasecret' # Password to unlock private key
    calendarID = '[email protected]' # Calendar ID.

    # Get the Google API client
    client = Google::APIClient.new(:application_name => 'Dashing Calendar Widget',
    :application_version => '0.0.1')

    # Load your credentials for the service account
    if not key_file.nil? and File.exists? key_file
    key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, key_secret)
    else
    key = OpenSSL::PKey::RSA.new ENV['GOOGLE_SERVICE_PK'], key_secret
    end

    client.authorization = Signet::OAuth2::Client.new(
    :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
    :audience => 'https://accounts.google.com/o/oauth2/token',
    :scope => 'https://www.googleapis.com/auth/calendar.readonly',
    :issuer => service_account_email,
    :signing_key => key)

    # Start the scheduler
    SCHEDULER.every '15m', :first_in => 4 do |job|

    # Request a token for our service account
    client.authorization.fetch_access_token!

    # Get the calendar API
    service = client.discovered_api('calendar','v3')

    # Start and end dates
    now = DateTime.now

    result = client.execute(:api_method => service.events.list,
    :parameters => {'calendarId' => calendarID,
    'timeMin' => now.rfc3339,
    'orderBy' => 'startTime',
    'singleEvents' => 'true',
    'maxResults' => 6}) # How many calendar items to get

    send_event('google_calendar', { events: result.data })

    end
    66 changes: 66 additions & 0 deletions google_calendar.scss
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,66 @@
    // ----------------------------------------------------------------------------
    // Sass declarations
    // ----------------------------------------------------------------------------
    $background-color: #47bbb3; //#ec663c;

    $title-color: rgba(255, 255, 255, 1);
    $subtitle-color: rgba(255, 255, 255, 0.7);
    $moreinfo-color: rgba(255, 255, 255, 0.7);

    $private-color: rgb(123, 209, 72);
    $business-color: rgb(255, 173, 70);

    // ----------------------------------------------------------------------------
    // Widget-calendar styles
    // ----------------------------------------------------------------------------
    .widget-google-calendar {

    background-color: $background-color;
    .subtitle {
    color: $subtitle-color;
    font-size: 0.75em;
    margin: 15px 0;
    }
    .title {
    color: $title-color;
    font-size: 1.4em;
    }

    .times {
    font-size: 0.9em;
    }

    .next {
    font-size: 0.75em;
    margin-top: 30px;
    .tr {
    border-bottom: 1px solid $subtitle-color;
    .td {
    text-align: left;
    }
    }
    }
    .more-info {
    color: $moreinfo-color;
    }

    .updated-at {
    color: $subtitle-color;
    bottom: 5px;
    right: 5px;
    left: auto;
    font-size: 0.5em;
    }


    &.large h3 {
    font-size: 65px;
    }
    }
    .calendar-name-private {
    background-color: $private-color;
    }

    .calendar-name-business {
    background-color: $business-color;
    }