plugins/mod_muc.lua

changeset 668
50072761e02d
parent 666
27f76695f43b
child 671
c7519f0c9a2c
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

mercurial