Skip to content

Instantly share code, notes, and snippets.

@jsyeo
Forked from jmb/README.md
Last active February 28, 2021 18:32
Show Gist options
  • Save jsyeo/39d3fde3afbffdd31093 to your computer and use it in GitHub Desktop.
Save jsyeo/39d3fde3afbffdd31093 to your computer and use it in GitHub Desktop.

Description

This is a fork of jmb's awesome widget that grabs the events with a private address instead of going through the tiresome process of Google's OAuth authentication.

Dashing widget to display the next and some subsequent Google Calendar events using the Google Calendar's private urls.

See the screenshot below

Installation

dashing install 39d3fde3afbffdd31093

Set up

Grab the private address of your calendar by going to your calendar's settings and look for the ICal button.

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.

Install Dependencies

  1. icalendar gem
  2. Moment.js

Stick gem 'icalendar' into your Gemfile and run bundle install.

Download the Moment javascript library and add to your javascript assets. Then lastly, make sure you have this at the top of assets/javascripts/application.coffee.

#= require moment.js`

Credits

Thanks @jmb!

class Dashing.GoogleCalendar extends Dashing.Widget
onData: (data) =>
event = rest = null
getEvents = (first, others...) ->
event = first
rest = others
getEvents data.events...
start = moment(event.start)
end = moment(event.end)
@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
start = moment(next_event.start)
start_date = start.format('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)
<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>
require 'icalendar'
ical_url = 'https://www.google.com/calendar/ical/xxxxxxxx%40group.calendar.google.com/private-xxxxx/basic.ics'
uri = URI ical_url
SCHEDULER.every '15s', :first_in => 4 do |job|
result = Net::HTTP.get uri
calendars = Icalendar.parse(result)
calendar = calendars.first
events = calendar.events.map do |event|
{
start: event.dtstart,
end: event.dtend,
summary: event.summary
}
end.select { |event| event[:start] > DateTime.now }
events = events.sort { |a, b| a[:start] <=> b[:start] }
events = events[0..5]
send_event('google_calendar', { events: events })
end
// ----------------------------------------------------------------------------
// 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);
// ----------------------------------------------------------------------------
// 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;
}
}
@samw78
Copy link

samw78 commented Jun 8, 2015

Hey I am getting an EOFError after result = Net::HTTP.get uri in job script.

I was able to download using https://github.com/typhoeus/typhoeus in irb, as per a stackoverflow post. I guess that confirms the ical url ok?

scheduler caught exception:
end of file reached
/usr/lib/ruby/1.9.1/net/protocol.rb:141:in `read_nonblock'
/usr/lib/ruby/1.9.1/net/protocol.rb:141:in `rbuf_fill'
/usr/lib/ruby/1.9.1/net/protocol.rb:122:in `readuntil'
/usr/lib/ruby/1.9.1/net/protocol.rb:132:in `readline'
/usr/lib/ruby/1.9.1/net/http.rb:2563:in `read_status_line'
/usr/lib/ruby/1.9.1/net/http.rb:2552:in `read_new'
/usr/lib/ruby/1.9.1/net/http.rb:1320:in `block in transport_request'
/usr/lib/ruby/1.9.1/net/http.rb:1317:in `catch'
/usr/lib/ruby/1.9.1/net/http.rb:1317:in `transport_request'
/usr/lib/ruby/1.9.1/net/http.rb:1294:in `request'
/usr/lib/ruby/1.9.1/net/http.rb:1196:in `request_get'
/usr/lib/ruby/1.9.1/net/http.rb:455:in `block in get_response'
/usr/lib/ruby/1.9.1/net/http.rb:746:in `start'
/usr/lib/ruby/1.9.1/net/http.rb:454:in `get_response'
/usr/lib/ruby/1.9.1/net/http.rb:431:in `get'
/home/sam/mydash/jobs/google_calendar.rb:7:in `block in <top (required)>'
irb(main):007:0*   result = Typhoeus.get uri
=> #<Typhoeus::Response:.........<snip>
irb(main):008:0> calendars = Icalendar.parse(result)
=> []
irb(main):009:0> calendars = Icalendar.parse(Typhoeus.get uri)
=> []

Any ideas?

Cheers.

@jvl88
Copy link

jvl88 commented Jun 11, 2015

I have the exact same issue.. Hopefully you'll be able to help us out.

Copy link

ghost commented Jun 26, 2015

FWIW, I'm experiencing the same issue. On my dev machine (OS X) no problems, on production (Ubuntu server 14.04LTS) I get this EOF. Are there are any general pointers out there I can follow? Not even starting to be ok at Ruby...

@twpark
Copy link

twpark commented Jul 1, 2015

Guys, I was struggling against this EOF issue and found a hint. There may be a bug or limited support for 'https' depending on the version of Ruby (mine is 1.9.1). You need to specify whether this is https request.

so I changed the source code like this. you may find the part to replace. It works for me. I did not have any time to push the revision, so jsyeo may want to fix this.

(original codelet)
result = Net::HTTP.get uri

(to be replaced like this)
parsed_url = URI.parse(ical_url)
http = Net::HTTP.new(parsed_url.host, parsed_url.port)
http.use_ssl = (parsed_url.scheme == "https")
req = Net::HTTP::Get.new(parsed_url.request_uri)
result = http.request(req).body

@twpark
Copy link

twpark commented Jul 1, 2015

Also it does not support recurring events correctly, as icalendar doesn't. For example, if a recurring event has been set before the current time, it does not correctly display its future events.

Perhaps we need to break recurring events down into single instances, but icalendar does not seem to support it (as far as my understandings).. So IMO so far google api v3 (like jmb's original one) seems the most preferable and accurate one.

@jvl88
Copy link

jvl88 commented Jul 24, 2015

Thanks a lot twpark!

@jvl88
Copy link

jvl88 commented Jul 24, 2015

It worked for a couple of hours.
Now the calendar Items still appear but the time and date are displayed as "invalid date"

Any clues?

@timdonovanuk
Copy link

Install doesnt work:

C:\Work\dashing\sweet_dashboard_project>dashing install 39d3fde3afbffdd31093
C:/Ruby22-x64/lib/ruby/2.2.0/net/http.rb:923:in connect': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (Open SSL::SSL::SSLError) from C:/Ruby22-x64/lib/ruby/2.2.0/net/http.rb:923:inblock in connect'
from C:/Ruby22-x64/lib/ruby/2.2.0/timeout.rb:74:in timeout' from C:/Ruby22-x64/lib/ruby/2.2.0/net/http.rb:923:inconnect'
from C:/Ruby22-x64/lib/ruby/2.2.0/net/http.rb:863:in `do_start'

@timdonovanuk
Copy link

Also an example of how to actually use this would be nice...

@notmyrealcode
Copy link

Any ideas on this issue?

scheduler caught exception:
undefined method events' for nil:NilClass /home/ubuntu/user/jobs/google_calendar.rb:17:inblock in <top (required)>'
/var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:230:in call' /var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:230:intrigger_block'
/var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:204:in block in trigger' /var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/scheduler.rb:430:incall'
/var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/scheduler.rb:430:in `block in trigger_job'

@sebstr1
Copy link

sebstr1 commented Feb 11, 2016

It is working as it should except that I have special letters in my language but it is just these 3 chars: å ä ö. These 3 are very common Swedish letters. So whenever there is an event containing one of those letters the widget breaks and displays nothing with the following error from logs:

scheduler caught exception:

"\xC3" from ASCII-8BIT to UTF-8
/home/pi/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/dashing-1.3.4/lib/dashing/app.rb:129:in `to_json'
/home/pi/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/dashing-1.3.4/lib/dashing/app.rb:129:in `send_event'
/opt/dashboard/jobs/google_calendar.rb:28:in `block in <top (required)>'
/home/pi/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:232:in `call'
/home/pi/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:232:in `trigger_block'
/home/pi/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:206:in `block in trigger'
/home/pi/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/scheduler.rb:431:in `call'
/home/pi/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/scheduler.rb:431:in `block in trigger_job'

If I remove the event with one of those letters, error goes away. I've been trying to fix this for the past 2 hours with zero success. Help anyone?

Best case: The widget displays the text with the special chars (å ä ö) Worst case: The ö is converted to o and å ä to a

@kvarnstj
Copy link

Hi!
Any fix for the problem WorldEd1t described for the scandinavian characters? I'm facing the same issue.

@fesaje
Copy link

fesaje commented Apr 6, 2016

For the problem with rare characters you can change (considering @twpark modification):

(original codelet)
result = Net::HTTP.get uri

(to be replaced like this)
parsed_url = URI.parse(ical_url)
http = Net::HTTP.new(parsed_url.host, parsed_url.port)
http.use_ssl = (parsed_url.scheme == "https")
req = Net::HTTP::Get.new(parsed_url.request_uri)
result = http.request(req).body.force_encoding('UTF-8')

@faxesystem
Copy link

Hi,

I have the problem that the calendar events are displayd two hours behind the actual time. So the event is set for 11:30 in the calendar but display to happen at 9:30 in the widget. The systems timezone is set correctly and also the clock widget of dashing is showing the correct time. Even the "Last updated" in the widget is showing the correct current time. Any ideas?

@cefimadmin
Copy link

Hi,
Could we connect more than one agenda ?
Thank you

Copy link

ghost commented Jan 31, 2017

Hi, the widget show only the upcoming events, not the current one running. Any way to get a list of events including the current event ?

@Smittey
Copy link

Smittey commented Mar 22, 2017

@twpark A somewhat delayed response, and hopefully you've found a solution by now, but in case others find the same issue I fixed this by changing the following:

   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)
      
    if event.start.dateTime == undefined
      start = moment(event.start.date)
      end = moment(event.end.date)

    @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   
      
      start = moment(next_event.start.dateTime)

      if next_event.start.dateTime == undefined
        start = moment(next_event.start.date)
          
      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)

Basically it boils down to recurring events having a differently named tag than normal events ('date' instead of 'dateTime')

@hornoo
Copy link

hornoo commented Apr 6, 2017

@Smittey with your fix for recurring events did you have some changes in the jobs file to go along with the updated coffee script?

@schuhri
Copy link

schuhri commented May 7, 2017

Hi All,
I am just new at dashing and ran into this problem after I installed this google calendar app:

pi@dashpi:~/dashboard/sweet_dashboard_project $ dashing start
bundler: failed to load command: thin (/usr/local/bin/thin)
LoadError: cannot load such file -- icalendar
/var/lib/gems/2.1.0/gems/backports-3.8.0/lib/backports/std_lib.rb:9:in require' /var/lib/gems/2.1.0/gems/backports-3.8.0/lib/backports/std_lib.rb:9:in require_with_backports'
/home/pi/dashboard/sweet_dashboard_project/jobs/google_calendar.rb:1:in <top (required)>' /var/lib/gems/2.1.0/gems/backports-3.8.0/lib/backports/std_lib.rb:9:in require'
/var/lib/gems/2.1.0/gems/backports-3.8.0/lib/backports/std_lib.rb:9:in require_with_backports' /var/lib/gems/2.1.0/gems/dashing-1.3.7/lib/dashing/app.rb:171:in block in require_glob'
/var/lib/gems/2.1.0/gems/dashing-1.3.7/lib/dashing/app.rb:170:in each' /var/lib/gems/2.1.0/gems/dashing-1.3.7/lib/dashing/app.rb:170:in require_glob'
/var/lib/gems/2.1.0/gems/dashing-1.3.7/lib/dashing/app.rb:181:in <top (required)>' /var/lib/gems/2.1.0/gems/dashing-1.3.7/lib/dashing.rb:3:in require'
/var/lib/gems/2.1.0/gems/dashing-1.3.7/lib/dashing.rb:3:in <top (required)>' config.ru:1:in require'
config.ru:1:in block in <main>' /var/lib/gems/2.1.0/gems/rack-1.5.5/lib/rack/builder.rb:55:in instance_eval'
/var/lib/gems/2.1.0/gems/rack-1.5.5/lib/rack/builder.rb:55:in initialize' config.ru:1:in new'
config.ru:1:in <main>' /var/lib/gems/2.1.0/gems/thin-1.6.4/lib/rack/adapter/loader.rb:33:in eval'
/var/lib/gems/2.1.0/gems/thin-1.6.4/lib/rack/adapter/loader.rb:33:in load' /var/lib/gems/2.1.0/gems/thin-1.6.4/lib/thin/controllers/controller.rb:182:in load_rackup_config'
/var/lib/gems/2.1.0/gems/thin-1.6.4/lib/thin/controllers/controller.rb:72:in start' /var/lib/gems/2.1.0/gems/thin-1.6.4/lib/thin/runner.rb:200:in run_command'
/var/lib/gems/2.1.0/gems/thin-1.6.4/lib/thin/runner.rb:156:in run!' /var/lib/gems/2.1.0/gems/thin-1.6.4/bin/thin:6:in <top (required)>'
/usr/local/bin/thin:23:in load' /usr/local/bin/thin:23:in <top (required)>'

Anyone any idea?
Thank you

@7k50
Copy link

7k50 commented Jul 15, 2017

@notmyrealcode: I seem to be having a similar issue:

scheduler caught exception:
undefined method `events' for nil:NilClass
/Users/me/Smashing/test01/jobs/google_calendar.rb:11:in `block in <top (required)>'
/usr/local/lib/ruby/gems/2.4.0/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:230:in `trigger_block'
/usr/local/lib/ruby/gems/2.4.0/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:204:in `block in trigger'
/usr/local/lib/ruby/gems/2.4.0/gems/rufus-scheduler-2.0.24/lib/rufus/sc/scheduler.rb:430:in `block in trigger_job'

BTW: I also need to use Scandinavian letters, but I don't have any of them in the daily calendar events I'm currently testing. Are they retrieved from future (non-intraday) events?

@manifolded
Copy link

I get this error, repeating.
**** DEPRECATION WARNING ****
Icalendar.parse will be removed. Please switch to Icalendar::Calendar.parse.

@borisv1979
Copy link

@manifolded:
Just edit file google_calendar.rb and replace line (if you are using Icalendar version 2.0 and above):

calendars = Icalendar.parse(result)

WITH

calendars = Icalendar::Calendar.parse(result)

@Burrro
Copy link

Burrro commented Feb 21, 2018

Hello there,
Is there a way to get the data of multiple icals?
I think this widget does it, but I could not get it to work with this one here.
Is anyone able to help me? :)

@Dr-Bone
Copy link

Dr-Bone commented Jul 6, 2019

Hi There
Could somebody please help me with that? When I try to load this widget I get:
69970458660820 rufus-scheduler intercepted an error:
69970458660820 job:
69970458660820 Rufus::Scheduler::EveryJob "15s" {:first_in=>4}
69970458660820 error:
69970458660820 69970458660820
69970458660820 ArgumentError
69970458660820 comparison of Time with DateTime failed
69970458660820 /usr/lib/ruby/2.5.0/delegate.rb:83:in >' 69970458660820 /usr/lib/ruby/2.5.0/delegate.rb:83:in method_missing'
69970458660820 /root/sweet_dashboard_project/jobs/google_calendar.rb:17:in block (2 levels) in <top (required)>' 69970458660820 /root/sweet_dashboard_project/jobs/google_calendar.rb:17:in select'
69970458660820 /root/sweet_dashboard_project/jobs/google_calendar.rb:17:in `block in <top (required)>'
69970458660820 ...........

@mostofthetime
Copy link

@Dr-Bone: Add

require 'date'

at top of the google_calendar.rb

@louismillette
Copy link

I had the same issue. Managed to hack around it by casting the event date to a string, then converting to a DateTime. In google_calendar.rb:
replace
end.select { |event| event[:start] > DateTime.now }
with
end.select { |event| DateTime.parse(event[:start].to_s) > DateTime.now }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment