# HG changeset patch # User Marco Cirillo # Date 1320190862 0 # Node ID 4f9224369e690ef6b4a8278da3426f5d164a73f8 # Parent ff03a325aa41a44fae98065b0cc5bb3ae00d9af9 mod_ircd: merged in various changes including -- code to propagate aff/role changes as modes, topic hooks/command, scarecrow motd banner, default port. diff -r ff03a325aa41 -r 4f9224369e69 mod_ircd/mod_ircd.in.lua --- a/mod_ircd/mod_ircd.in.lua Tue Nov 01 19:46:07 2011 +0100 +++ b/mod_ircd/mod_ircd.in.lua Tue Nov 01 23:41:02 2011 +0000 @@ -129,16 +129,32 @@ local channel, _, nick = jid.split(room); return "#"..channel, nick; end -local rolemap = { - moderator = "@", - participant = "+", +local role_map = { + moderator = "@", + participant = "", + visitor = "", + none = "" +} +local aff_map = { + owner = "~", + administrator = "&", + member = "+", + none = "" } -local modemap = { - moderator = "o", - participant = "v", +local role_modemap = { + moderator = "o", + participant = "", + visitor = "", + none = "" +} +local aff_modemap = { + owner = "q", + administrator = "a", + member = "v", + none = "" } -local irc_listener = { default_port = 6667, default_mode = "*l" }; +local irc_listener = { default_port = 7000, default_mode = "*l" }; local sessions = {}; local jids = {}; @@ -231,15 +247,28 @@ end local full_jid = jid.join(nick, component_jid, "ircd"); jids[full_jid] = session; + jids[full_jid]["ar_last"] = {}; nicks[nick] = session; session.nick = nick; session.full_jid = full_jid; session.type = "c2s"; - session.send{from = muc_server, "001", nick, "Welcome to IRC gateway to XMPP!"}; - session.send{from = muc_server, "002", nick, module.host.." running Prosody "..prosody.version}; + + session.send{from = muc_server, "001", nick, "Welcome in the IRC to MUC XMPP Gateway, "..nick}; + session.send{from = muc_server, "002", nick, "Your host is "..muc_server.." running Prosody "..prosody.version}; session.send{from = muc_server, "003", nick, os.date(nil, prosody.start_time)} - session.send{from = muc_server, "004", table.concat({muc_server, "alpha", "i", "ov"}, " ")}; - session.send{from = nick, "MODE", nick, "+i"}; -- why + session.send{from = muc_server, "004", table.concat({muc_server, "alpha", "i", "aoqv"}, " ")}; + session.send{from = muc_server, "375", nick, "- "..muc_server.." Message of the day -"}; + session.send{from = muc_server, "372", nick, "-"}; + session.send{from = muc_server, "372", nick, "- Please be warned that this is only a partial irc implementation,"}; + session.send{from = muc_server, "372", nick, "- it's made to facilitate users transiting away from irc to XMPP."}; + session.send{from = muc_server, "372", nick, "-"}; + session.send{from = muc_server, "372", nick, "- Prosody is _NOT_ an IRC Server and it never will."}; + session.send{from = muc_server, "372", nick, "- We also would like to remind you that this plugin is provided as is,"}; + session.send{from = muc_server, "372", nick, "- it's still an Alpha and it's still a work in progress, use it at your sole"}; + session.send{from = muc_server, "372", nick, "- risk as there's a not so little chance something will break."}; + + session.send{from = nick, "MODE", nick, "+i"}; -- why -> Invisible mode setting, + -- enforce by default on most servers (since the source host doesn't show it's sensible to have it "set") end function commands.USER(session, params) @@ -247,21 +276,38 @@ -- Empty command for now end +local function mode_map(am, rm, nicks) + local rnick; + local c_modes; + c_modes = aff_modemap[am]..role_modemap[rm] + rnick = string.rep(nicks.." ", c_modes:len()) + if c_modes == "" then return nil, nil end + return c_modes, rnick +end + function commands.JOIN(session, args) local channel = args[1]; if not channel then return end local room_jid = irc2muc(channel); print(session.full_jid); + if not jids[session.full_jid].ar_last[room_jid] then jids[session.full_jid].ar_last[room_jid] = {}; end local room, err = c:join_room(room_jid, session.nick, { source = session.full_jid } ); if not room then - return ":"..session.host.." ERR :Could not join room: "..err + return ":"..muc_server.." ERR :Could not join room: "..err end session.rooms[channel] = room; room.channel = channel; room.session = session; session.send{from=session.nick, "JOIN", channel}; - session.send{from=muc_server, 332, session.nick, channel ,"Connection in progress..."}; - + if room.subject then + session.send{from=muc_server, 332, session.nick, channel ,room.subject}; + end + commands.NAMES(session, channel); + + room:hook("subject-changed", function(changed) + session.send((":%s TOPIC %s :%s"):format(changed.by, channel, changed.to or "")); + end); + room:hook("message", function(event) if not event.body then return end local nick, body = event.nick, event.body; @@ -274,52 +320,92 @@ --FIXME PM's probably won't work end end); + + room:hook("presence", function(ar) + local c_modes; + local rnick; + if ar.nick and not jids[session.full_jid].ar_last[ar.room_jid][ar.nick] then jids[session.full_jid].ar_last[ar.room_jid][ar.nick] = {} end + local x_ar = ar.stanza:get_child("x", "http://jabber.org/protocol/muc#user") + if x_ar then + local xar_item = x_ar:get_child("item") + if xar_item and xar_item.attr and ar.stanza.attr.type ~= "unavailable" then + if xar_item.attr.affiliation and xar_item.attr.role then + if not jids[session.full_jid].ar_last[ar.room_jid][ar.nick]["affiliation"] and + not jids[session.full_jid].ar_last[ar.room_jid][ar.nick]["role"] then + jids[session.full_jid].ar_last[ar.room_jid][ar.nick]["affiliation"] = xar_item.attr.affiliation + jids[session.full_jid].ar_last[ar.room_jid][ar.nick]["role"] = xar_item.attr.role + c_modes, rnick = mode_map(xar_item.attr.affiliation, xar_item.attr.role, ar.nick); + if c_modes and rnick then session.send((":%s MODE %s +%s"):format(muc_server, channel, c_modes.." "..rnick)); end + else + c_modes, rnick = mode_map(jids[session.full_jid].ar_last[ar.room_jid][ar.nick]["affiliation"], jids[session.full_jid].ar_last[ar.room_jid][ar.nick]["role"], ar.nick); + if c_modes and rnick then session.send((":%s MODE %s -%s"):format(muc_server, channel, c_modes.." "..rnick)); end + jids[session.full_jid].ar_last[ar.room_jid][ar.nick]["affiliation"] = xar_item.attr.affiliation + jids[session.full_jid].ar_last[ar.room_jid][ar.nick]["role"] = xar_item.attr.role + c_modes, rnick = mode_map(xar_item.attr.affiliation, xar_item.attr.role, ar.nick); + if c_modes and rnick then session.send((":%s MODE %s +%s"):format(muc_server, channel, c_modes.." "..rnick)); end + end + end + end + end + end, -1); end c:hook("groupchat/joined", function(room) local session = room.session or jids[room.opts.source]; - local channel = room.channel; + local channel = "#"..room.jid:match("^(.*)@"); session.send{from=session.nick.."!"..session.nick, "JOIN", channel}; - session.send((":%s!%s JOIN %s :"):format(session.nick, session.nick, channel)); if room.topic then session.send{from=muc_server, 332, room.topic}; end commands.NAMES(session, channel) - if session.nick.role then - session.send{from=muc_server, "MODE", channel, session.nick, modemap[session.nick.role], session.nick} - end room:hook("occupant-joined", function(nick) session.send{from=nick.nick.."!"..nick.nick, "JOIN", channel}; - if nick.role and modemap[nick.role] then - session.send{from=nick.nick.."!"..nick.nick, "MODE", channel, modemap[nick.role], nick.nick}; - end end); room:hook("occupant-left", function(nick) - session.send{from=nick.nick.."!"..nick.nick, "PART", room.channel}; + jids[session.full_jid].ar_last[nick.room_jid][nick.nick] = nil; + session.send{from=nick.nick.."!"..nick.nick, "PART", channel}; end); end); function commands.NAMES(session, channel) local nicks = { }; local room = session.rooms[channel]; + local symbols_map = { + owner = "~", + administrator = "&", + moderator = "@", + member = "+" + } + if not room then return end -- TODO Break this out into commands.NAMES for nick, n in pairs(room.occupants) do - if n.role and rolemap[n.role] then - nick = rolemap[n.role] .. nick; + if n.affiliation == "owner" and n.role == "moderator" then + nick = symbols_map[n.affiliation]..nick; + elseif n.affiliation == "administrator" and n.role == "moderator" then + nick = symbols_map[n.affiliation]..nick; + elseif n.affiliation == "member" and n.role == "moderator" then + nick = symbols_map[n.role]..nick; + elseif n.affiliation == "member" and n.role == "partecipant" then + nick = symbols_map[n.affiliation]..nick; + elseif n.affiliation == "none" and n.role == "moderator" then + nick = symbols_map[n.role]..nick; end table.insert(nicks, nick); end nicks = table.concat(nicks, " "); - session.send((":%s 353 %s = %s :%s"):format(session.host, session.nick, channel, nicks)); - session.send((":%s 366 %s %s :End of /NAMES list."):format(session.host, session.nick, channel)); - session.send(":"..session.host.." 353 "..session.nick.." = "..channel.." :"..nicks); + session.send((":%s 353 %s = %s :%s"):format(muc_server, session.nick, channel, nicks)); + session.send((":%s 366 %s %s :End of /NAMES list."):format(muc_server, session.nick, channel)); + session.send(":"..muc_server.." 353 "..session.nick.." = "..channel.." :"..nicks); end function commands.PART(session, args) local channel, part_message = unpack(args); + local room = channel and nodeprep(channel:match("^#(%w+)")) or nil; + if not room then return end channel = channel:match("^([%S]*)"); session.rooms[channel]:leave(part_message); + jids[session.full_jid].ar_last[room.."@"..muc_server] = nil; session.send(":"..session.nick.." PART :"..channel); end @@ -359,6 +445,22 @@ session.send{from=muc_server, "PONG", args[1]}; end +function commands.TOPIC(session, message) + if not message then return end + local channel, topic = message:match("^(%S+) :(.*)$"); + if not channel then + channel = message:match("^(%S+)"); + end + if not channel then return end + local room = session.rooms[channel]; + if topic then + room:set_subject(topic) + session.send((":%s TOPIC %s :%s"):format(session.nick, channel, room.subject or "")); + else + session.send((":%s TOPIC %s :%s"):format(session.nick, channel, room.subject or "")); + end +end + function commands.WHO(session, args) local channel = args[1]; if session.rooms[channel] then @@ -412,5 +514,3 @@ --print("Starting loop...") --verse.loop() - -