mcbot/cmds/rfc.lua
author Mikael Berthe <mikael@lilotux.net>
Tue, 27 Nov 2012 16:26:04 +0100
changeset 66 d9c00a9fe9d5
parent 34 ca01a1696cff
child 67 5c756a9d7d8c
permissions -rw-r--r--
Add notices before public release

#! /usr/bin/env lua

--  This module is part of the McBot / mcabbot project
--  RFC index parser
--
-- 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.
--

-- TXT index database, retrieved from
-- <ftp://ftp.rfc-editor.org/in-notes/rfc-index.txt>
local indexfname = "/home/mikael/.mcabber/lua/mcbot/rfc-index.txt"

local urlbase = "http://tools.ietf.org/html/rfc"

local rfc = { ["desc"] = "Search RFC database" }

local rfcdb = {}

local function parse_file (fname)
    local fh = io.open(fname)

    if not fh then return nil, "Cannot open RFC database" end

    -- Skip header
    local count = 0
    for line in fh:lines() do
        count = count + 1
        if line:match("^%s+RFC INDEX%s*$") and count > 30 then
            break
        end
    end

    -- Skip 2 more lines
    fh:read("*l")
    fh:read("*l")

    local contents = fh:read("*a")
    fh:close()

    for entry in contents:gfind("(%d%d%d%d .-)\n\n") do
        entry = entry:gsub("\n     ", " ")
        local n = entry:match("^(%d%d%d%d) ")
        entry = entry:gsub("^(%d%d%d%d) ", "")

        local data = {}
        data.title = entry:match("^(.-)%. ")
        entry = entry:gsub("^(.-)%. ", "")

        data.date = entry:match("%. (.-)%. %(Format:")
        data.obsoletes = entry:match("%(Obsoletes (.-)%)")
        data.obsoleted_by = entry:match("%(Obsoleted by (.-)%)")
        data.updates = entry:match("%(Updates (.-)%)")
        data.updated_by = entry:match("%(Updated by (.-)%)")
        data.also = entry:match("%(Also (.-)%)")
        data.status = entry:match("%(Status: (.-)%)")

        if data.title then
            rfcdb[n] = data
        end
    end
    return true
end

local function rfc_lookup_string (rfcstring)
    rfcstring = rfcstring:lower()
    local r = ""
    for id, data in pairs(rfcdb) do
        if data.title:lower():find(rfcstring) then
            r = r.."RFC"..id..": "..data.title.."\n"
        end
    end
    r = r:gsub("\n$", "")
    if r ~= "" then return r; end
    return nil, "Sorry, I couldn't find any relevant RFC"
end

local function rfc_lookup_number (rfcnum)
    rfcnum = tostring(rfcnum)
    rfcnum = string.rep("0", 4 - rfcnum:len()) .. rfcnum

    local data = rfcdb[rfcnum]
    if not data then return nil, "Sorry, RFC not found" end

    local r = "RFC"..rfcnum .. " is " .. data.title .. "\n"
    if data.status then
        r = r .. "Status:\t" .. data.status:lower() .. "\n"
    end
    if data.obsoletes then
        r = r .. "Obsoletes:\t" .. data.obsoletes .. "\n"
    end
    if data.obsoleted_by then
        r = r .. "Obsoleted by:\t" .. data.obsoleted_by .. "\n"
    end
    if data.updates then
        r = r .. "Updates:\t" .. data.updates .. "\n"
    end
    if data.updated_by then
        r = r .. "Updated by:\t" .. data.updated_by .. "\n"
    end
    if data.also then
        r = r .. "Also:\t" .. data.also .. "\n"
    end
    r = r .. "URL:\t" .. urlbase..rfcnum
    return r
end

function rfc.cmd (rfcnum)
    local empty = true
    for i,v in pairs(rfcdb) do empty = false; break end
    if empty then
        local r, err = parse_file(indexfname)
        if not r then return nil, err end
    end

    if (rfcnum) then
        rfcnum = rfcnum:gsub("^RFC[%s%-]*", "")
        rfcnum = rfcnum:gsub("^rfc[%s%-]*", "")
        rfcnum = rfcnum:gsub("[!%?%s:]+$", "")
    end

    if not rfcnum or rfcnum == "" then
        return nil, "What RFC do you want?"
    end

    local n = tonumber(rfcnum)
    if not n then return rfc_lookup_string(rfcnum) end

    return rfc_lookup_number(n)
end

mcbot_register_command("rfc", rfc)