# HG changeset patch # User Chris # Date 1274362421 -3600 # Node ID ae69cea97598a93339c1ca6cd9bc61179fa64a48 # Parent 22e6c003a83a890822f92f25f39a0c8955023b88 Formatting, indentation and cleanup diff -r 22e6c003a83a -r ae69cea97598 init.lua --- a/init.lua Thu May 20 14:33:09 2010 +0100 +++ b/init.lua Thu May 20 14:33:41 2010 +0100 @@ -18,41 +18,37 @@ function riddim_mt:start() self:event("started"); self.stream:hook("stanza", function (stanza) - local body = stanza:get_child("body"); - local event = { - sender = { jid = stanza.attr.from }; - body = (body and body:get_text()) or nil; - stanza = stanza; - }; - if stanza.name == "message" then - local replied; - local bot = self; - function event:reply(reply) - if replied then return false; end - replied = true; - return bot:send_message(stanza.attr.from, stanza.attr.type, reply); - end + local body = stanza:get_child("body"); + local event = { + sender = { jid = stanza.attr.from }; + body = (body and body:get_text()) or nil; + stanza = stanza; + }; + if stanza.name == "message" then + local replied; + local bot = self; + function event:reply(reply) + if replied then return false; end + replied = true; + return bot:send_message(stanza.attr.from, stanza.attr.type, reply); end - local ret; - if stanza.name == "iq" and (stanza.attr.type == "get" or stanza.attr.type == "set") then - local xmlns = stanza.tags[1] and stanza.tags[1].attr.xmlns; - if xmlns then - event.xmlns = xmlns; - print(event.stanza) - ret = self:event("iq/"..xmlns, event); - if not ret then - ret = self:event(stanza.name, event); - end - end - else - ret = self:event(stanza.name, event); + end + local ret; + if stanza.name == "iq" and (stanza.attr.type == "get" or stanza.attr.type == "set") then + local xmlns = stanza.tags[1] and stanza.tags[1].attr.xmlns; + if xmlns then + event.xmlns = xmlns; + ret = self:event("iq/"..xmlns, event); end - - if ret and type(ret) == "table" and ret.name then - self:send(ret); - end - return ret; - end, 1); + end + if not ret then + ret = self:event(stanza.name, event); + end + if ret and type(ret) == "table" and ret.name then + self:send(ret); + end + return ret; + end, 1); end function riddim_mt:send(s) @@ -128,14 +124,14 @@ b:send(presence); end); - c:hook("binding-success", function () b:start(); end) + c:hook("binding-success", function () b:start(); end); - if config.connect_host then - c.connect_host = config.connect_host - end - if config.connect_port then - c.connect_port = config.connect_port - end + if config.connect_host then + c.connect_host = config.connect_host; + end + if config.connect_port then + c.connect_port = config.connect_port; + end c:connect_client(config.jid, config.password); diff -r 22e6c003a83a -r ae69cea97598 plugins/commands.lua --- a/plugins/commands.lua Thu May 20 14:33:09 2010 +0100 +++ b/plugins/commands.lua Thu May 20 14:33:41 2010 +0100 @@ -18,13 +18,13 @@ if command then local command_event = { - command = command, - param = param, - sender = event.sender, - stanza = event.stanza, - reply = event.reply, - room = event.room, -- groupchat support - }; + command = command, + param = param, + sender = event.sender, + stanza = event.stanza, + reply = event.reply, + room = event.room, -- groupchat support + }; local ret = bot:event("commands/"..command, command_event); if type(ret) == "string" then event:reply(ret); diff -r 22e6c003a83a -r ae69cea97598 plugins/disco.lua --- a/plugins/disco.lua Thu May 20 14:33:09 2010 +0100 +++ b/plugins/disco.lua Thu May 20 14:33:41 2010 +0100 @@ -4,23 +4,23 @@ -- capabilities hash (XEP-0115). -- Fill the bot.disco.info.identities, bot.disco.info.features, and --- bot.disco.items tables with the relevant disco data. It comes pre-populated +-- bot.disco.items tables with the relevant disco data. It comes pre-populated -- to advertise support for disco#info, disco#items, and entity capabilities, -- and to identify itself as Riddim. -- If you want to advertise a node, add entries to the bot.disco.nodes table --- with the relevant data. The bot.disco.nodes table should have the same --- format as bot.disco (without the nodes element). The nodes are NOT +-- with the relevant data. The bot.disco.nodes table should have the same +-- format as bot.disco (without the nodes element). The nodes are NOT -- automatically added to the base disco items, so you will need to add them -- yourself. -- To property implement Entity Capabilities, you should make sure that you --- send a "c" element within presence stanzas that are sent. The correct "c" +-- send a "c" element within presence stanzas that are sent. The correct "c" -- element can be obtained by calling bot.caps() (or bot:caps()). -- Hubert Chathi --- This file is hereby placed in the public domain. Feel free to modify and +-- This file is hereby placed in the public domain. Feel free to modify and -- redistribute it at will local st = require "util.stanza" @@ -28,170 +28,179 @@ local sha1 = require("util.hashes").sha1 function riddim.plugins.disco(bot) - bot.disco = {} - bot.disco.info = {} - bot.disco.info.identities = { - {category = 'client', type='bot', name='Riddim'}, - } - bot.disco.info.features = { - {var = 'http://jabber.org/protocol/caps'}, - {var = 'http://jabber.org/protocol/disco#info'}, - {var = 'http://jabber.org/protocol/disco#items'}, - } - bot.disco.items = {} - bot.disco.nodes = {} + bot.disco = {} + bot.disco.info = {} + bot.disco.info.identities = { + {category = 'client', type='bot', name='Riddim'}, + } + bot.disco.info.features = { + {var = 'http://jabber.org/protocol/caps'}, + {var = 'http://jabber.org/protocol/disco#info'}, + {var = 'http://jabber.org/protocol/disco#items'}, + } + bot.disco.items = {} + bot.disco.nodes = {} + + bot.caps = {} + bot.caps.node = 'http://code.matthewwild.co.uk/riddim/' - bot.caps = {} - bot.caps.node = 'http://code.matthewwild.co.uk/riddim/' - - local function cmp_identity(item1, item2) - if item1.category < item2.category then return true; - elseif item2.category < item1.category then return false; - end - if item1.type < item2.type then return true; - elseif item2.type < item1.type then return false; - end - if (not item1['xml:lang'] and item2['xml:lang']) - or (item2['xml:lang'] and item1['xml:lang'] < item2['xml:lang']) then - return true - end - return false - end + local function cmp_identity(item1, item2) + if item1.category < item2.category then + return true; + elseif item2.category < item1.category then + return false; + end + if item1.type < item2.type then + return true; + elseif item2.type < item1.type then + return false; + end + if (not item1['xml:lang'] and item2['xml:lang']) or + (item2['xml:lang'] and item1['xml:lang'] < item2['xml:lang']) then + return true + end + return false + end - local function cmp_feature(item1, item2) - return item1.var < item2.var - end + local function cmp_feature(item1, item2) + return item1.var < item2.var + end - local function calculate_hash() - table.sort(bot.disco.info.identities, cmp_identity) - table.sort(bot.disco.info.features, cmp_feature) - local S = '' - for key,identity in pairs(bot.disco.info.identities) do - S = S .. string.format('%s/%s/%s/%s', identity.category, identity.type, - identity['xml:lang'] or '', identity.name or '') - .. '<' - end - for key,feature in pairs(bot.disco.info.features) do - S = S .. feature.var - .. '<' - end - -- FIXME: make sure S is utf8-encoded - return (b64(sha1(S))) - end + local function calculate_hash() + table.sort(bot.disco.info.identities, cmp_identity) + table.sort(bot.disco.info.features, cmp_feature) + local S = '' + for key,identity in pairs(bot.disco.info.identities) do + S = S .. string.format( + '%s/%s/%s/%s', identity.category, identity.type, + identity['xml:lang'] or '', identity.name or '' + ) .. '<' + end + for key,feature in pairs(bot.disco.info.features) do + S = S .. feature.var .. '<' + end + -- FIXME: make sure S is utf8-encoded + return (b64(sha1(S))) + end - setmetatable(bot.caps, - { - __call = function (...) -- vararg: allow calling as function or member - -- retrieve the c stanza to insert into the - -- presence stanza - local hash = calculate_hash() - return st.stanza('c', - {xmlns = 'http://jabber.org/protocol/caps', - hash = 'sha-1', - node = bot.caps.node, - ver = hash}) - end}) + setmetatable(bot.caps, { + __call = function (...) -- vararg: allow calling as function or member + -- retrieve the c stanza to insert into the + -- presence stanza + local hash = calculate_hash() + return st.stanza('c', { + xmlns = 'http://jabber.org/protocol/caps', + hash = 'sha-1', + node = bot.caps.node, + ver = hash + }) + end + }) - bot:hook("iq/http://jabber.org/protocol/disco#info", - function (event) - local stanza = event.stanza - if stanza.attr.type == 'get' then - local query = stanza:child_with_name('query') - if not query then return; end - -- figure out what identities/features to send - local identities - local features - if query.attr.node then - local hash = calculate_hash() - local node = bot.disco.nodes[query.attr.node] - if node and node.info then - identities = node.info.identities or {} - features = node.info.identities or {} - elseif query.attr.node == bot.caps.node..'#'..hash then - -- matches caps hash, so use the main info - identities = bot.disco.info.identities - features = bot.disco.info.features - else - -- unknown node: give an error - local response = st.stanza('iq', - {to = stanza.attr.from, - from = stanza.attr.to, - id = stanza.attr.id, - type = 'error'}) - response:tag('query',{xmlns = 'http://jabber.org/protocol/disco#info'}):reset() - response:tag('error',{type = 'cancel'}) - :tag('item-not-found',{xmlns = 'urn:ietf:params:xml:ns:xmpp-stanzas'}) - bot:send(response) + bot:hook("iq/http://jabber.org/protocol/disco#info", function (event) + local stanza = event.stanza + if stanza.attr.type == 'get' then + local query = stanza:child_with_name('query') + if not query then return; end + -- figure out what identities/features to send + local identities + local features + if query.attr.node then + local hash = calculate_hash() + local node = bot.disco.nodes[query.attr.node] + if node and node.info then + identities = node.info.identities or {} + features = node.info.identities or {} + elseif query.attr.node == bot.caps.node..'#'..hash then + -- matches caps hash, so use the main info + identities = bot.disco.info.identities + features = bot.disco.info.features + else + -- unknown node: give an error + local response = st.stanza('iq',{ + to = stanza.attr.from, + from = stanza.attr.to, + id = stanza.attr.id, + type = 'error' + }) + response:tag('query',{xmlns = 'http://jabber.org/protocol/disco#info'}):reset() + response:tag('error',{type = 'cancel'}):tag( + 'item-not-found',{xmlns = 'urn:ietf:params:xml:ns:xmpp-stanzas'} + ) + bot:send(response) + return true + end + else + identities = bot.disco.info.identities + features = bot.disco.info.features + end + -- construct the response + local result = st.stanza('query',{ + xmlns = 'http://jabber.org/protocol/disco#info', + node = query.attr.node + }) + for key,identity in pairs(identities) do + result:tag('identity', identity):reset() + end + for key,feature in pairs(features) do + result:tag('feature', feature):reset() + end + bot:send(st.stanza('iq',{ + to = stanza.attr.from, + from = stanza.attr.to, + id = stanza.attr.id, + type = 'result' + }):add_child(result)) return true - end - else - identities = bot.disco.info.identities - features = bot.disco.info.features - end - -- construct the response - local result = st.stanza('query', - {xmlns = 'http://jabber.org/protocol/disco#info', - node = query.attr.node}) - for key,identity in pairs(identities) do - result:tag('identity', identity):reset() - end - for key,feature in pairs(features) do - result:tag('feature', feature):reset() - end - bot:send(st.stanza('iq', - {to = stanza.attr.from, - from = stanza.attr.to, - id = stanza.attr.id, - type = 'result'}) - :add_child(result)) - return true - end - end); + end + end); - bot:hook("iq/http://jabber.org/protocol/disco#items", - function (event) - local stanza = event.stanza - if stanza.attr.type == 'get' then - local query = stanza:child_with_name('query') - if not query then return; end - -- figure out what items to send - local items - if query.attr.node then - local node = bot.disco.nodes[query.attr.node] - if node then - items = node.items or {} - else - -- unknown node: give an error - local response = st.stanza('iq', - {to = stanza.attr.from, - from = stanza.attr.to, - id = stanza.attr.id, - type = 'error'}) - response:tag('query',{xmlns = 'http://jabber.org/protocol/disco#items'}):reset() - response:tag('error',{type = 'cancel'}) - :tag('item-not-found',{xmlns = 'urn:ietf:params:xml:ns:xmpp-stanzas'}) - bot:send(response) + bot:hook("iq/http://jabber.org/protocol/disco#items", function (event) + local stanza = event.stanza + if stanza.attr.type == 'get' then + local query = stanza:child_with_name('query') + if not query then return; end + -- figure out what items to send + local items + if query.attr.node then + local node = bot.disco.nodes[query.attr.node] + if node then + items = node.items or {} + else + -- unknown node: give an error + local response = st.stanza('iq',{ + to = stanza.attr.from, + from = stanza.attr.to, + id = stanza.attr.id, + type = 'error' + }) + response:tag('query',{xmlns = 'http://jabber.org/protocol/disco#items'}):reset() + response:tag('error',{type = 'cancel'}):tag( + 'item-not-found',{xmlns = 'urn:ietf:params:xml:ns:xmpp-stanzas'} + ) + bot:send(response) + return true + end + else + items = bot.disco.items + end + -- construct the response + local result = st.stanza('query',{ + xmlns = 'http://jabber.org/protocol/disco#items', + node = query.attr.node + }) + for key,item in pairs(items) do + result:tag('item', item):reset() + end + bot:send(st.stanza('iq',{ + to = stanza.attr.from, + from = stanza.attr.to, + id = stanza.attr.id, + type = 'result' + }):add_child(result)) return true - end - else - items = bot.disco.items - end - -- construct the response - local result = st.stanza('query', - {xmlns = 'http://jabber.org/protocol/disco#items', - node = query.attr.node}) - for key,item in pairs(items) do - result:tag('item', item):reset() - end - bot:send(st.stanza('iq', - {to = stanza.attr.from, - from = stanza.attr.to, - id = stanza.attr.id, - type = 'result'}) - :add_child(result)) - return true - end - end); + end + end); end -- end of disco.lua diff -r 22e6c003a83a -r ae69cea97598 plugins/groupchat.lua --- a/plugins/groupchat.lua Thu May 20 14:33:09 2010 +0100 +++ b/plugins/groupchat.lua Thu May 20 14:33:41 2010 +0100 @@ -29,14 +29,14 @@ local body = stanza:get_child("body"); local delay = stanza:get_child("delay", xmlns_delay); local event = { - room_jid = room_jid; - room = room; - sender = room.occupants[nick]; - nick = nick; - body = (body and body:get_text()) or nil; - stanza = stanza; - delay = (delay and delay.attr.stamp); - }; + room_jid = room_jid; + room = room; + sender = room.occupants[nick]; + nick = nick; + body = (body and body:get_text()) or nil; + stanza = stanza; + delay = (delay and delay.attr.stamp); + }; if stanza.name == "message" then local replied; local r = st.reply(stanza); @@ -67,7 +67,8 @@ local room = setmetatable({ bot = bot, jid = jid, nick = nick, occupants = {}, - events = events.new() }, room_mt); + events = events.new() + }, room_mt); self.rooms[jid] = room; local occupants = room.occupants; room:hook("presence", function (presence) @@ -77,7 +78,7 @@ nick = nick; jid = presence.stanza.attr.from; presence = presence.stanza; - }; + }; if nick == room.nick then room.bot:event("groupchat/joined", room); else diff -r 22e6c003a83a -r ae69cea97598 plugins/ping.lua --- a/plugins/ping.lua Thu May 20 14:33:09 2010 +0100 +++ b/plugins/ping.lua Thu May 20 14:33:41 2010 +0100 @@ -2,17 +2,17 @@ function riddim.plugins.ping(bot) bot.stream:add_plugin("ping"); bot:hook("commands/ping", function (command) - local jid = command.param; - if jid then - bot.stream:ping(jid, function (time, jid, error) - if time then - command:reply(string.format("Pong from %s in %0.3f seconds", jid, time)); - else - command:reply("Ping failed ("..(error.condition or "unknown reason")..")"..(error.text and (": "..error.text) or "")); - end - end); - return true; - end - return "pong"; - end); + local jid = command.param; + if jid then + bot.stream:ping(jid, function (time, jid, error) + if time then + command:reply(string.format("Pong from %s in %0.3f seconds", jid, time)); + else + command:reply("Ping failed ("..(error.condition or "unknown reason")..")"..(error.text and (": "..error.text) or "")); + end + end); + return true; + end + return "pong"; + end); end diff -r 22e6c003a83a -r ae69cea97598 plugins/tell.lua --- a/plugins/tell.lua Thu May 20 14:33:09 2010 +0100 +++ b/plugins/tell.lua Thu May 20 14:33:41 2010 +0100 @@ -3,45 +3,45 @@ function riddim.plugins.tell(bot) bot:hook("commands/tell", function (command) - if command.room then - local s, e = command.param:find(" "); - local nick = command.param:sub(0, s - 1); - local msg = command.param:sub(s + 1); - local found = false; - - for tmp,_ in pairs(command.room.occupants) do - if tmp == nick then - found = true; - break; - end + if command.room then + local s, e = command.param:find(" "); + local nick = command.param:sub(0, s - 1); + local msg = command.param:sub(s + 1); + local found = false; + + for tmp,_ in pairs(command.room.occupants) do + if tmp == nick then + found = true; + break; end + end - if not found then - if(tellings[nick] == nil) then - tellings[nick] = {}; - end - tellings[nick][#tellings[nick] + 1] = {from=command.sender.nick, msg=msg}; - return "Ok! Will tell " .. nick .. " what you have said!"; + if not found then + if(tellings[nick] == nil) then + tellings[nick] = {}; + end + tellings[nick][#tellings[nick] + 1] = {from=command.sender.nick, msg=msg}; + return "Ok! Will tell " .. nick .. " what you have said!"; + else + if nick == command.sender.nick then + return "Are you going crazy!? You are " .. nick .. "!"; else - if nick == command.sender.nick then - return "Are you going crazy!? You are " .. nick .. "!"; - else - return "Aehm?! ... " .. nick .. " is currently online!"; - end + return "Aehm?! ... " .. nick .. " is currently online!"; end - else - return "Sorry, but this command only makes sense if you execute it in a groupchat."; + end + else + return "Sorry, but this command only makes sense if you execute it in a groupchat."; + end + end); + + bot:hook("groupchat/joined", function (room) + room:hook("occupant-joined", function (occupant) + if(tellings[occupant.nick] ~= nil) then + for _,msg in ipairs(tellings[occupant.nick]) do + room:send_message(occupant.nick .. ": Welcome back! " .. msg.from .. " told me, to tell you, \"" .. msg.msg .. "\"."); + end end end); - - bot:hook("groupchat/joined", function (room) - room:hook("occupant-joined", function (occupant) - if(tellings[occupant.nick] ~= nil) then - for _,msg in ipairs(tellings[occupant.nick]) do - room:send_message(occupant.nick .. ": Welcome back! " .. msg.from .. " told me, to tell you, \"" .. msg.msg .. "\"."); - end - end - end); - end); + end); end diff -r 22e6c003a83a -r ae69cea97598 plugins/version.lua --- a/plugins/version.lua Thu May 20 14:33:09 2010 +0100 +++ b/plugins/version.lua Thu May 20 14:33:41 2010 +0100 @@ -22,31 +22,30 @@ end end - bot.stream:query_version(who, - function (reply) - if not reply.error then - local saywho = (who == command.sender.jid and "You are") or (param.." is"); - command:reply(saywho.." running "..(reply.name or "something") - .." version "..(reply.version or "unknown") - .." on "..(reply.platform or "an unknown platform")); - else - local type, condition, text = reply.type, reply.condition, reply.text; - local r = "There was an error requesting "..param.."'s version"; - if condition == "service-unavailable" then - r = param.." doesn't reply to version requests"; - elseif condition == "feature-not-implemented" then - r = param.." doesn't support feature requests"; - elseif condition == "remote-server-not-found" then - r = param.." can't be reached via XMPP"; - elseif condition and not text then - r = r..": "..condition; - end - if text then - r = r .. " ("..text..")"; - end - command:reply(r); + bot.stream:query_version(who, function (reply) + if not reply.error then + local saywho = (who == command.sender.jid and "You are") or (param.." is"); + command:reply(saywho.." running "..(reply.name or "something") + .." version "..(reply.version or "unknown") + .." on "..(reply.platform or "an unknown platform")); + else + local type, condition, text = reply.type, reply.condition, reply.text; + local r = "There was an error requesting "..param.."'s version"; + if condition == "service-unavailable" then + r = param.." doesn't reply to version requests"; + elseif condition == "feature-not-implemented" then + r = param.." doesn't support feature requests"; + elseif condition == "remote-server-not-found" then + r = param.." can't be reached via XMPP"; + elseif condition and not text then + r = r..": "..condition; end - end); + if text then + r = r .. " ("..text..")"; + end + command:reply(r); + end + end); return true; end); end