#!/usr/bin/env ruby # # Copyright (c) 2013 Rui Paulo # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS O R # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. require 'rubygems' require 'open-uri' require 'nokogiri' require 'tzinfo' require 'ri_cal' debug = true require 'awesome_print' if debug timetable = "http://2013.asiabsdcon.org/timetable.html" if debug doc = Nokogiri::HTML(File.open("test.html")) else doc = Nokogiri::HTML(open(timetable)) end days = [] rooms = [] # Find all the days doc.xpath("//h2").each do |h2| day = h2.text.match("(\\(.*\\))") if day != nil days.push(day.to_s[/[^()]+/]) end end ap days if debug # Find all the rooms doc.xpath("//div/table/thead/tr/th").each do |th| room = th.text if room.match("Room") and rooms.index(room) == nil rooms.push(room) end end ap rooms if debug # Find all the events events = [] currentday = 0 doc.xpath("//div/table").each do |table| # XXX fix entries that span multiple rows table.xpath("tbody/tr").each do |tr| time = tr.at("th").text.split("-") tstart = DateTime.parse(days[currentday] + " " + time[0]) tend = DateTime.parse(days[currentday] + " " + time[1]) tstart.set_tzid("Asia/Tokyo") tend.set_tzid("Asia/Tokyo") currentroom = 0 tr.xpath("td").each do |td| event = {} if td.text == "-" or td.text == "Lunch" or td.text == "Break" next end anchor = td.search("a").first if anchor == nil event[:title] = td.text else event[:title] = anchor.text event[:url] = timetable + anchor.attr("href") end event[:person] = td.search("i").text.split(" (eml")[0] event[:tstart] = tstart event[:tend] = tend event[:room] = rooms[currentroom] events.push(event) currentroom += 1 end end currentday += 1 end ap events if debug # Build the Calendar file ics = RiCal.Calendar do |cal| events.each do |event| cal.event do |calevent| summary = event[:title] if event[:person] summary += " - " + event[:person] end calevent.summary = summary calevent.dtstart = event[:tstart] calevent.dtend = event[:tend] calevent.location = event[:room] if event[:url] calevent.url = event[:url] end end end end print ics