Software / code / prosody
Comparison
plugins/mod_muc.lua @ 668:50072761e02d
mod_muc: Room subjects stored, and room persistence code in place. First user now the owner.
| author | Waqas Hussain <waqas20@gmail.com> |
|---|---|
| date | Wed, 31 Dec 2008 18:17:47 +0500 |
| parent | 666:27f76695f43b |
| child | 671:c7519f0c9a2c |
comparison
equal
deleted
inserted
replaced
| 667:4f4d94253547 | 668:50072761e02d |
|---|---|
| 8 local multitable_new = require "util.multitable".new; | 8 local multitable_new = require "util.multitable".new; |
| 9 | 9 |
| 10 local muc_domain = "conference."..module:get_host(); | 10 local muc_domain = "conference."..module:get_host(); |
| 11 local muc_name = "MUCMUCMUC!!!"; | 11 local muc_name = "MUCMUCMUC!!!"; |
| 12 | 12 |
| 13 -- room_name -> room | |
| 14 -- occupant_room_nick -> data | |
| 15 -- affiliation = ... | |
| 16 -- role | |
| 17 -- jid = occupant's real jid | |
| 13 local rooms = multitable_new(); | 18 local rooms = multitable_new(); |
| 14 local jid_nick = multitable_new(); | 19 |
| 20 local jid_nick = multitable_new(); -- real jid -> room's jid -> room nick | |
| 21 | |
| 22 -- room_name -> info | |
| 23 -- name - the room's friendly name | |
| 24 -- subject - the room's subject | |
| 25 -- non-anonymous = true|nil | |
| 26 -- persistent = true|nil | |
| 15 local rooms_info = multitable_new(); | 27 local rooms_info = multitable_new(); |
| 28 | |
| 29 local persist_list = datamanager.load(nil, muc_domain, 'room_list') or {}; | |
| 30 for room in pairs(persist_list) do | |
| 31 rooms_info:set(room, datamanager.store(room, muc_domain, 'rooms') or nil); | |
| 32 end | |
| 16 | 33 |
| 17 local component; | 34 local component; |
| 18 | 35 |
| 19 function getUsingPath(stanza, path, getText) | 36 function getUsingPath(stanza, path, getText) |
| 20 local tag = stanza; | 37 local tag = stanza; |
| 46 :tag("feature", {var="http://jabber.org/protocol/muc"}); -- TODO cache disco reply | 63 :tag("feature", {var="http://jabber.org/protocol/muc"}); -- TODO cache disco reply |
| 47 end | 64 end |
| 48 function get_room_disco_items(stanza) | 65 function get_room_disco_items(stanza) |
| 49 return st.iq({type='result', id=stanza.attr.id, from=stanza.attr.to, to=stanza.attr.from}):query("http://jabber.org/protocol/disco#items"); | 66 return st.iq({type='result', id=stanza.attr.id, from=stanza.attr.to, to=stanza.attr.from}):query("http://jabber.org/protocol/disco#items"); |
| 50 end -- TODO allow non-private rooms | 67 end -- TODO allow non-private rooms |
| 68 | |
| 69 function save_room(room) | |
| 70 local persistent = rooms_info:get(room, 'persistent'); | |
| 71 if persistent then | |
| 72 datamanager.store(room, muc_domain, 'rooms', rooms_info:get(room)); | |
| 73 end | |
| 74 if persistent ~= persist_list[room] then | |
| 75 if not persistent then | |
| 76 datamanager.store(room, muc_domain, 'rooms', nil); | |
| 77 end | |
| 78 persist_list[room] = persistent; | |
| 79 datamanager.store(nil, muc_domain, 'room_list', persist_list); | |
| 80 end | |
| 81 end | |
| 82 | |
| 83 function set_subject(current_nick, room, subject) | |
| 84 -- TODO check nick's authority | |
| 85 if subject == "" then subject = nil; end | |
| 86 rooms_info:set(room, 'subject', subject); | |
| 87 save_room(); | |
| 88 broadcast_message(current_nick, room, subject or "", nil); | |
| 89 return true; | |
| 90 end | |
| 51 | 91 |
| 52 function broadcast_presence(type, from, room, code) | 92 function broadcast_presence(type, from, room, code) |
| 53 local data = rooms:get(room, from); | 93 local data = rooms:get(room, from); |
| 54 local stanza = st.presence({type=type, from=from}) | 94 local stanza = st.presence({type=type, from=from}) |
| 55 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) | 95 :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) |
| 126 end | 166 end |
| 127 else -- enter room | 167 else -- enter room |
| 128 if rooms:get(room, to) then | 168 if rooms:get(room, to) then |
| 129 origin.send(st.error_reply(stanza, "cancel", "conflict")); | 169 origin.send(st.error_reply(stanza, "cancel", "conflict")); |
| 130 else | 170 else |
| 131 local data = {affiliation='none', role='participant', jid=from}; | 171 local data; |
| 172 if not rooms:get(room) and not rooms_info:get(room) then -- new room | |
| 173 data = {affiliation='owner', role='moderator', jid=from}; | |
| 174 end | |
| 175 if not data then -- new occupant | |
| 176 data = {affiliation='none', role='participant', jid=from}; | |
| 177 end | |
| 132 rooms:set(room, to, data); | 178 rooms:set(room, to, data); |
| 133 jid_nick:set(from, room, to); | 179 jid_nick:set(from, room, to); |
| 134 local r = rooms:get(room); | 180 local r = rooms:get(room); |
| 135 if r then | 181 if r then |
| 136 for occupant, o_data in pairs(r) do | 182 for occupant, o_data in pairs(r) do |
| 141 core_route_stanza(component, pres); | 187 core_route_stanza(component, pres); |
| 142 end | 188 end |
| 143 end | 189 end |
| 144 end | 190 end |
| 145 broadcast_presence(nil, to, room); | 191 broadcast_presence(nil, to, room); |
| 192 -- TODO send discussion history | |
| 193 if rooms_info:get(room, 'subject') then | |
| 194 broadcast_message(room, room, rooms_info:get(room, 'subject'), nil); | |
| 195 end | |
| 146 end | 196 end |
| 147 end | 197 end |
| 148 elseif type ~= 'result' then -- bad type | 198 elseif type ~= 'result' then -- bad type |
| 149 origin.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME correct error? | 199 origin.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME correct error? |
| 150 end | 200 end |
| 172 local room = jid_bare(to); | 222 local room = jid_bare(to); |
| 173 local current_nick = jid_nick:get(from, room); | 223 local current_nick = jid_nick:get(from, room); |
| 174 if not current_nick then -- not in room | 224 if not current_nick then -- not in room |
| 175 origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); | 225 origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); |
| 176 else | 226 else |
| 177 broadcast_message(current_nick, room, getText(stanza, {"subject"}), getText(stanza, {"body"})); | 227 local subject = getText(stanza, {"subject"}); |
| 228 if subject then | |
| 229 set_subject(current_nick, room, subject); | |
| 230 else | |
| 231 broadcast_message(current_nick, room, nil, getText(stanza, {"body"})); | |
| 232 -- TODO add to discussion history | |
| 233 end | |
| 178 end | 234 end |
| 179 else | 235 else |
| 180 if type == "error" or type == "result" then return; end | 236 if type == "error" or type == "result" then return; end |
| 181 origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); | 237 origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); |
| 182 end | 238 end |