bvv2cal
author Timm S. Mueller <tmueller@schulze-mueller.de>
Fri, 12 Nov 2010 10:56:02 +0100
changeset 2 f4034a59feaa
parent 1 522bf1c3dd7c
permissions -rwxr-xr-x
Dates in daylight saving time were still incorrect, fixed
tmueller@0
     1
#!/usr/bin/env lua
tmueller@0
     2
--
tmueller@0
     3
--	$ bvvcal [bezirksname] [startdatum] [enddatum]
tmueller@0
     4
--
tmueller@0
     5
--	bezirksname : Default "friedrichshain-kreuzberg"
tmueller@1
     6
--	startdatum : in deutscher Notation (z.B. 31.12.2010), Default: heute
tmueller@0
     7
--	enddatum : Default: startdatum
tmueller@0
     8
--
tmueller@0
     9
--	Konvertiert den Berliner BVV-Sitzungskalender 
tmueller@0
    10
--	ins iCalendar 2.0 (vCal) Format
tmueller@0
    11
--
tmueller@0
    12
--	Benötigt: 
tmueller@0
    13
--	- htmltidy : http://tidy.sourceforge.net/
tmueller@0
    14
--	- wget : http://www.gnu.org/software/wget/
tmueller@0
    15
--	- Lua 5.1.x : http://www.lua.org/
tmueller@0
    16
--	- LuaExpat : http://www.keplerproject.org/luaexpat/
tmueller@0
    17
--
tmueller@1
    18
--	Revisionen:
tmueller@1
    19
--	- 0.2 : Uhrzeiten waren lokal, nicht GMT. Korrigiert.
tmueller@1
    20
--	- 0.1 : initial release
tmueller@1
    21
--
tmueller@1
    22
--	Autor: Timm S. Müller <timm-pirat@schulze-mueller.de>
tmueller@1
    23
--
tmueller@0
    24
tmueller@0
    25
local lxp = require "lxp"
tmueller@0
    26
tmueller@0
    27
local district = arg[1] or "friedrichshain-kreuzberg"
tmueller@0
    28
local startdate = arg[2] or os.date("%d.%m.%Y")
tmueller@0
    29
local enddate = arg[3] or startdate
tmueller@0
    30
local uid_uri = district .. ".bvv.berlin.piratenpartei.de"
tmueller@0
    31
tmueller@0
    32
----- --- --- -- - -  -   -    -
tmueller@0
    33
tmueller@1
    34
--	Encoding ist laut RFC 2445 UTF-8, dies ist ein Zugeständnis
tmueller@1
    35
--	an Kalendertools, die das nicht mitbekommen haben:
tmueller@1
    36
tmueller@1
    37
local umlconv = { 
tmueller@1
    38
	["ä"] = "ae", ["Ä"] = "Ae", 
tmueller@1
    39
	["ö"] = "oe", ["Ö"] = "Oe",
tmueller@1
    40
	["ü"] = "ue", ["Ü"] = "Ue",
tmueller@1
    41
	["ß"] = "ss"
tmueller@1
    42
}
tmueller@1
    43
tmueller@2
    44
local function local2gmt(y, m, d, hour, min)
tmueller@2
    45
	return os.date("%s", os.time { day=d, month=m, year=y, hour=hour, min=min })
tmueller@2
    46
end
tmueller@2
    47
tmueller@2
    48
tmueller@0
    49
local state = "waitcontent"
tmueller@0
    50
local record, cell, result = { }, { }, { }
tmueller@0
    51
local lnr = 1
tmueller@0
    52
local parser = lxp.new {
tmueller@0
    53
	StartElement = function(parser, tagname, attr)
tmueller@0
    54
		if state == "waitcontent" then
tmueller@0
    55
			if tagname == "div" and attr.id == "allrisContent" then
tmueller@0
    56
				state = "waittab"
tmueller@0
    57
			end
tmueller@0
    58
		elseif state == "waittab" then
tmueller@0
    59
			if tagname == "table" and attr.class == "tl1" then
tmueller@0
    60
				state = "waitrow"
tmueller@0
    61
			end
tmueller@0
    62
		elseif state == "waitrow" then
tmueller@0
    63
			if tagname == "tr" then
tmueller@0
    64
				state = "waitcell"
tmueller@0
    65
			end
tmueller@0
    66
		end
tmueller@0
    67
	end,
tmueller@0
    68
	EndElement = function(parser, tagname)
tmueller@0
    69
		if state == "waitrow" or state == "waittable" then
tmueller@0
    70
			if tagname == "table" then
tmueller@0
    71
				state = "end"
tmueller@0
    72
			end
tmueller@0
    73
		elseif state == "waitcell" then
tmueller@0
    74
			if tagname == "tr" then
tmueller@0
    75
				local day = table.remove(record, 1)
tmueller@0
    76
				local sdate = table.remove(record, 1)
tmueller@0
    77
				local d, m, y = (sdate or ""):match("^%s*(%d+)%.(%d+)%.(%d+)")
tmueller@0
    78
				local time = table.remove(record, 1)
tmueller@0
    79
				if d and m and y and time then
tmueller@0
    80
					local sH, sM, eH, eM = time:match("^%s*(%d+):(%d+)%s*%-%s*(%d+):(%d+)")
tmueller@0
    81
					if not sH then
tmueller@0
    82
						sH, sM = time:match("^%s*(%d+):(%d+)")
tmueller@0
    83
					end
tmueller@0
    84
					if sH then
tmueller@1
    85
						-- convert dates to GMT
tmueller@2
    86
						local startdate = local2gmt(y, m, d, sH, sM)
tmueller@2
    87
						local enddate = eH and local2gmt(y, m, d, eH, eM)
tmueller@0
    88
						local what = table.concat(record, " "):match("^%s*(.-)%s*$")
tmueller@1
    89
						what = what:gsub("([\128-\255].)", umlconv)
tmueller@1
    90
						table.insert(result, { startdate, enddate, what })
tmueller@0
    91
					end
tmueller@0
    92
				end
tmueller@0
    93
				state = "waitrow"
tmueller@0
    94
				record = { }
tmueller@0
    95
			elseif tagname == "td" then
tmueller@0
    96
				table.insert(record, table.concat(cell))
tmueller@0
    97
				cell = { }
tmueller@0
    98
			end
tmueller@0
    99
		end
tmueller@0
   100
	end,
tmueller@0
   101
	CharacterData = function(parser, s)
tmueller@0
   102
		if state == "waitcell" then
tmueller@0
   103
			table.insert(cell, s)
tmueller@0
   104
		end
tmueller@0
   105
	end
tmueller@0
   106
}
tmueller@0
   107
tmueller@0
   108
parser:setencoding("ISO-8859-1")
tmueller@0
   109
tmueller@0
   110
----- --- --- -- - -  -   -    -
tmueller@0
   111
tmueller@0
   112
local cmd = ("wget --quiet --post-data 'kaldatvon=%s&kaldatbis=%s' 'http://www.berlin.de/ba-%s/bvv-online/si010.asp' -O - | tidy -latin1 -asxml -i -w 0 2>/dev/null -q"):format(startdate, enddate, district)
tmueller@0
   113
-- print(cmd)
tmueller@0
   114
local f = io.popen(cmd)
tmueller@0
   115
for line in f:lines() do
tmueller@0
   116
-- 	print(lnr .. " : " .. line)
tmueller@0
   117
	parser:parse(line)
tmueller@0
   118
	lnr = lnr + 1
tmueller@0
   119
end
tmueller@0
   120
tmueller@0
   121
----- --- --- -- - -  -   -    -
tmueller@0
   122
tmueller@0
   123
print "BEGIN:VCALENDAR"
tmueller@0
   124
print "PRODID:BVV2CAL"
tmueller@0
   125
print "VERSION:2.0"
tmueller@0
   126
print ""
tmueller@0
   127
for i = 1, #result do
tmueller@0
   128
	local r = result[i]
tmueller@0
   129
	print "BEGIN:VEVENT"
tmueller@2
   130
	local startdate = os.date("!%Y%m%dT%H%M", r[1])
tmueller@1
   131
	print("UID:" .. startdate .. "." .. uid_uri)
tmueller@1
   132
	print("SUMMARY:" .. r[3])
tmueller@1
   133
	print("DTSTART:" .. startdate .. "00Z")
tmueller@1
   134
	if r[2] then
tmueller@2
   135
		local enddate = r[2] and os.date("!%Y%m%dT%H%M", r[2])
tmueller@1
   136
		print("DTEND:" .. enddate .. "00Z")
tmueller@0
   137
	end
tmueller@0
   138
	print "END:VEVENT"
tmueller@0
   139
	print ""
tmueller@0
   140
end
tmueller@0
   141
print "END:VCALENDAR"