#! /usr/bin/env lua
-- This module is part of the McBot / mcabbot project
-- Data extractor for http://www.pogdesign.co.uk/cat/
--
-- Copyright (C) 2010-2012 Mikael Berthe <mikael@lilotux.net>
--
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or (at
-- your option) any later version.
--
-- Please check the license in the COPYING file at the root of the tree.
--
require "libs.shcmd"
local tvcal = { ["desc"] = "Display TV calendar" }
local tvcaldata = {}
local tvcaldata_timestamp
-- Function from PIL
local function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end
local function parse_webpage (url)
local contents = shcmd("curl "..url)
if not contents then
return nil, "Could not fetch calendar, please try again later!"
end
-- Work around frackin ugly end of line characters... :/
local eol = "[%s"..string.char(13).."]*"
-- Regex for each day
local tabregex = '<td id="d_(%d+_%d+_%d%d%d%d)" class="t?o?day"%s*>'..
'%s*(.-)%s*</td>'
-- Regex for parsing one day
local epregex = '<p[^>]*>'..
'<a href=[^>]+>([^<]+)</a>'..eol.. -- Name
'<br /><a href=[^>]+>([^<]+)</a>'..eol.. -- Episode
'</p>'
-- loop over all days
for day, daytab in string.gmatch(contents, tabregex) do
local d, m, y = day:match("^(%d+)_(%d+)_(%d%d%d%d)$")
day = string.format("%04d-%02d-%02d", y, m, d)
local shows = {}
-- Loop over all episodes of a day
for name, ep in string.gmatch(daytab, epregex) do
name = name:gsub(""", "\""):gsub("&", "&")
name = name:gsub("<", "<"):gsub(">", ">")
name = name:gsub("'", "'")
name = name:gsub("%s*\n%s*", " ")
local obj = {
["name"] = name,
["ep"] = ep
}
table.insert(shows, obj)
end
tvcaldata[day] = shows
end
tvcaldata_timestamp = os.date("%F")
return true
end
local function tvcal_by_date (d)
if not tvcaldata[d] then
return "No episode found for this date ("..d..")"
end
local r = "Shows on " .. d .. ":\n"
for i,j in ipairs(tvcaldata[d]) do
r = r .. j.name .. " (" ..j.ep .. ")\n"
end
r = r:gsub("\n+$", "")
return r
end
local function tvcal_by_name (name, plain)
local action = plain and "contain" or "match"
local r = ""
name = name:lower()
for day, obj in pairsByKeys(tvcaldata) do
for i,j in ipairs(obj) do
if j.name:lower():find(name, 1, plain) then
r = r .. day .. "\t" .. j.name .. " (" ..j.ep .. ")\n"
end
end
end
if r == "" then
return "No episode found "..action.."ing this string"
end
r = r:gsub("\n+$", "")
return "Episodes "..action.."ing \""..name.."\":\n" .. r
end
function tvcal.cmd (arg)
if not tvcaldata_timestamp or tvcaldata_timestamp ~= os.date("%F") then
tvcaldata = {} -- Empty the previous list
local r, err = parse_webpage("http://www.pogdesign.co.uk/cat/")
if not r then return nil, err end
-- Fetch next month as well...
local m = tonumber(os.date("%m"))+1
local y = os.date("%Y")
if m > 12 then m = 1; y = y + 1; end
parse_webpage("http://www.pogdesign.co.uk/cat/"..m.."-"..y)
end
if not arg or arg == "today" then
arg = os.date("%F")
elseif arg == "tomorrow" then
arg = os.date("%F", os.date("%s")+86400)
elseif arg:match("^%+%d+$") then
local n = tonumber(arg:match("^%+(%d+)$"))
if n < 60 then
arg = os.date("%F", os.date("%s")+86400*n)
end
end
if arg:match("^%d%d%d%d%-%d%d%-%d%d$") then
return tvcal_by_date(arg)
end
-- Is it a pattern? (string surrounded by quotes)
local plain = arg:match('^"(.*)"$')
if plain then
arg = plain
plain = false
else
plain = true
end
return tvcal_by_name(arg, plain)
end
mcbot_register_command("tvcal", tvcal)