#!/usr/bin/env ruby # -*- ruby -*- # # Looks up google calendars and prints today's schedule out in # text mode. You can also list the names of the calendars in ~/.ical. # These values can be the names of calendars or the actual urls. # # Examples: # # ./today http://www.google.com/calendar/ical/s69iupuak9ll5d3tvct0io4pic%40group.calendar.google.com/public/basic.ics # ./today s69iupuak9ll5d3tvct0io4pic@group.calendar.google.com # # Requires HTTParty. To install # # % sudo gem install httparty # require 'rubygems' require 'httparty' require 'cgi' class CalendarEvent def initialize(dtstart,dtend,summary) @dtstart = dtstart @dtend = dtend @summary = summary @start_hours = @dtstart / 100 @start_mins = @dtstart % 100 @end_hours = @dtend / 100 @end_mins = @dtend % 100 end # Returns 'true' if this event's range contains time. # 'time' is an integer between 0 and 2359 def in_range(time) if @dtstart != @dtend return @dtstart-@start_mins <= time && time < @dtend else return @dtstart-@start_mins <= time && time <= @dtend end end def to_s time_str = sprintf "%02d:%02d - %02d:%02d", @start_hours, @start_mins, @end_hours, @end_mins return @summary + " (" + time_str + ")" end end class GoogleCalendar include HTTParty # cal_name is either a google calendar name or URL def self.find_calendar(cal_name) if /^http:\/\// !~ cal_name url = 'http://www.google.com/calendar/ical/' + CGI.escape(cal_name) + '/public/basic.ics' else url = cal_name end get url end end # Main entry def main(argv) # Maybe look in ~/.ical for names on single lines if argv.empty? fname = ENV['HOME'] + '/.ical' if File.exist? fname IO.foreach fname do |line| argv.push line.strip end end end # Look up all the calendar names summarys2events = {} argv.map { |arg| summarys2events.update lookup(arg.downcase) } print_events summarys2events.values end # Looks up the google calendar with name 'cal_name' and prints to # stdout. Returns a map from summaries to events def lookup(cal_name) ical = GoogleCalendar.find_calendar cal_name now = Time.now.strftime "%Y%m%d" start_token = 'DTSTART:' + now + 'T' end_token = 'DTEND:' + now + 'T' result = {} dtstart = -1 dtend = -1 summary = nil ical.each "\n" do |line| line = line.strip icolon = line.index ':' next if icolon == -1 if /^#{start_token}/ =~ line dtstart = line[start_token.length..start_token.length+3].to_i elsif /^#{end_token}/ =~ line dtend = line[end_token.length..end_token.length+3].to_i elsif /^BEGIN:VEVENT/ =~ line dtstart = -1 dtend = -1 summary = nil elsif /^SUMMARY:.*/ =~ line summary = line[icolon+1..-1] elsif /^END:VEVENT/ =~ line if summary and dtstart > 0 and dtend > 0 result.store summary, CalendarEvent.new(dtstart, dtend, summary) end end end return result end # Prints an array of events def print_events(events) (0..23).each do |hour| time = hour*100 printf "%02d:00 ", hour printed_one = false events.each do |evt| if evt.in_range time print "\n " if printed_one print evt printed_one = true end end print "\n" end end # Main main ARGV