Software /
code /
prosody-modules
Comparison
mod_mam_muc/mod_mam_muc.lua @ 1138:5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 10 Aug 2013 21:05:38 +0200 |
parent | 820:005037032d65 |
child | 1139:b32d65e41755 |
comparison
equal
deleted
inserted
replaced
1137:431627b07b9f | 1138:5c97ee75cadb |
---|---|
27 -- TODO Should be possible to enforce it too | 27 -- TODO Should be possible to enforce it too |
28 | 28 |
29 local archive_store = "archive2"; | 29 local archive_store = "archive2"; |
30 | 30 |
31 -- Handle archive queries | 31 -- Handle archive queries |
32 module:hook("iq/bare/"..xmlns_mam..":query", function(event) | 32 module:hook("iq-get/bare/"..xmlns_mam..":query", function(event) |
33 local origin, stanza = event.origin, event.stanza; | 33 local origin, stanza = event.origin, event.stanza; |
34 local room = jid_split(stanza.attr.to); | 34 local room = jid_split(stanza.attr.to); |
35 local query = stanza.tags[1]; | 35 local query = stanza.tags[1]; |
36 | 36 |
37 local room_obj = hosts[module.host].modules.muc.rooms[jid_bare(stanza.attr.to)]; | 37 local room_obj = hosts[module.host].modules.muc.rooms[jid_bare(stanza.attr.to)]; |
43 if room_obj._affiliations[from] == "outcast" | 43 if room_obj._affiliations[from] == "outcast" |
44 or room_obj._data.members_only and not room_obj._affiliations[from] then | 44 or room_obj._data.members_only and not room_obj._affiliations[from] then |
45 return -- FIXME unauth | 45 return -- FIXME unauth |
46 end | 46 end |
47 | 47 |
48 if stanza.attr.type == "get" then | 48 local qid = query.attr.queryid; |
49 local qid = query.attr.queryid; | 49 |
50 | 50 -- Search query parameters |
51 -- Search query parameters | 51 local qwith = query:get_child_text("with"); |
52 local qwith = query:get_child_text("with"); | 52 local qstart = query:get_child_text("start"); |
53 local qstart = query:get_child_text("start"); | 53 local qend = query:get_child_text("end"); |
54 local qend = query:get_child_text("end"); | 54 local qset = rsm.get(query); |
55 local qset = rsm.get(query); | 55 module:log("debug", "Archive query, id %s with %s from %s until %s)", |
56 module:log("debug", "Archive query, id %s with %s from %s until %s)", | 56 tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now"); |
57 tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now"); | 57 |
58 | 58 if qstart or qend then -- Validate timestamps |
59 if qstart or qend then -- Validate timestamps | 59 local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend)) |
60 local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend)) | 60 if (qstart and not vstart) or (qend and not vend) then |
61 if (qstart and not vstart) or (qend and not vend) then | 61 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid timestamp")) |
62 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid timestamp")) | 62 return true |
63 return true | 63 end |
64 qstart, qend = vstart, vend; | |
65 end | |
66 | |
67 local qres; | |
68 if qwith then -- Validate the 'with' jid | |
69 local pwith = qwith and jid_prep(qwith); | |
70 if pwith and not qwith then -- it failed prepping | |
71 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid JID")) | |
72 return true | |
73 end | |
74 local _, _, resource = jid_split(qwith); | |
75 qwith = jid_bare(pwith); | |
76 qres = resource; | |
77 end | |
78 | |
79 -- Load all the data! | |
80 local data, err = dm_list_load(room, module.host, archive_store); | |
81 if not data then | |
82 if (not err) then | |
83 module:log("debug", "The archive was empty."); | |
84 origin.send(st.reply(stanza)); | |
85 else | |
86 origin.send(st.error_reply(stanza, "cancel", "internal-server-error", "Error loading archive: "..tostring(err))); | |
87 end | |
88 return true | |
89 end | |
90 | |
91 -- RSM stuff | |
92 local qmax = m_min(qset and qset.max or default_max_items, max_max_items); | |
93 local qset_matches = not (qset and qset.after); | |
94 local first, last, index; | |
95 local n = 0; | |
96 local start = qset and qset.index or 1; | |
97 | |
98 module:log("debug", "Loaded %d items, about to filter", #data); | |
99 for i=start,#data do | |
100 local item = data[i]; | |
101 local when, nick = item.when, item.resource; | |
102 local id = item.id; | |
103 --module:log("debug", "id is %s", id); | |
104 | |
105 -- RSM pre-send-checking | |
106 if qset then | |
107 if qset.before == id then | |
108 module:log("debug", "End of matching range found"); | |
109 qset_matches = false; | |
110 break; | |
64 end | 111 end |
65 qstart, qend = vstart, vend; | 112 end |
66 end | 113 |
67 | 114 --module:log("debug", "message with %s at %s", with, when or "???"); |
68 local qres; | 115 -- Apply query filter |
69 if qwith then -- Validate the 'with' jid | 116 if (not qres or (qres == nick)) |
70 local pwith = qwith and jid_prep(qwith); | 117 and (not qstart or when >= qstart) |
71 if pwith and not qwith then -- it failed prepping | 118 and (not qend or when <= qend) |
72 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid JID")) | 119 and (not qset or qset_matches) then |
73 return true | 120 local fwd_st = st.message{ to = stanza.attr.from } |
121 :tag("result", { xmlns = xmlns_mam, queryid = qid, id = id }):up() | |
122 :tag("forwarded", { xmlns = xmlns_forward }) | |
123 :tag("delay", { xmlns = xmlns_delay, stamp = timestamp(when) }):up(); | |
124 local orig_stanza = st.deserialize(item.stanza); | |
125 orig_stanza.attr.xmlns = "jabber:client"; | |
126 fwd_st:add_child(orig_stanza); | |
127 origin.send(fwd_st); | |
128 if not first then | |
129 index = i; | |
130 first = id; | |
74 end | 131 end |
75 local _, _, resource = jid_split(qwith); | 132 last = id; |
76 qwith = jid_bare(pwith); | 133 n = n + 1; |
77 qres = resource; | 134 elseif (qend and when > qend) then |
78 end | 135 module:log("debug", "We have passed into messages more recent than requested"); |
79 | 136 break -- We have passed into messages more recent than requested |
80 -- Load all the data! | 137 end |
81 local data, err = dm_list_load(room, module.host, archive_store); | 138 |
82 if not data then | 139 -- RSM post-send-checking |
83 if (not err) then | 140 if qset then |
84 module:log("debug", "The archive was empty."); | 141 if qset.after == id then |
85 origin.send(st.reply(stanza)); | 142 module:log("debug", "Start of matching range found"); |
86 else | 143 qset_matches = true; |
87 origin.send(st.error_reply(stanza, "cancel", "internal-server-error", "Error loading archive: "..tostring(err))); | |
88 end | 144 end |
89 return true | 145 end |
90 end | 146 if n >= qmax then |
91 | 147 module:log("debug", "Max number of items matched"); |
92 -- RSM stuff | 148 break |
93 local qmax = m_min(qset and qset.max or default_max_items, max_max_items); | 149 end |
94 local qset_matches = not (qset and qset.after); | 150 end |
95 local first, last, index; | 151 -- That's all folks! |
96 local n = 0; | 152 module:log("debug", "Archive query %s completed", tostring(qid)); |
97 local start = qset and qset.index or 1; | 153 |
98 | 154 local reply = st.reply(stanza); |
99 module:log("debug", "Loaded %d items, about to filter", #data); | 155 if last then |
100 for i=start,#data do | 156 -- This is a bit redundant, isn't it? |
101 local item = data[i]; | 157 reply:query(xmlns_mam):add_child(rsm.generate{first = first, last = last, count = n}); |
102 local when, nick = item.when, item.resource; | 158 end |
103 local id = item.id; | 159 origin.send(reply); |
104 --module:log("debug", "id is %s", id); | 160 return true |
105 | |
106 -- RSM pre-send-checking | |
107 if qset then | |
108 if qset.before == id then | |
109 module:log("debug", "End of matching range found"); | |
110 qset_matches = false; | |
111 break; | |
112 end | |
113 end | |
114 | |
115 --module:log("debug", "message with %s at %s", with, when or "???"); | |
116 -- Apply query filter | |
117 if (not qres or (qres == nick)) | |
118 and (not qstart or when >= qstart) | |
119 and (not qend or when <= qend) | |
120 and (not qset or qset_matches) then | |
121 local fwd_st = st.message{ to = stanza.attr.from } | |
122 :tag("result", { xmlns = xmlns_mam, queryid = qid, id = id }):up() | |
123 :tag("forwarded", { xmlns = xmlns_forward }) | |
124 :tag("delay", { xmlns = xmlns_delay, stamp = timestamp(when) }):up(); | |
125 local orig_stanza = st.deserialize(item.stanza); | |
126 orig_stanza.attr.xmlns = "jabber:client"; | |
127 fwd_st:add_child(orig_stanza); | |
128 origin.send(fwd_st); | |
129 if not first then | |
130 index = i; | |
131 first = id; | |
132 end | |
133 last = id; | |
134 n = n + 1; | |
135 elseif (qend and when > qend) then | |
136 module:log("debug", "We have passed into messages more recent than requested"); | |
137 break -- We have passed into messages more recent than requested | |
138 end | |
139 | |
140 -- RSM post-send-checking | |
141 if qset then | |
142 if qset.after == id then | |
143 module:log("debug", "Start of matching range found"); | |
144 qset_matches = true; | |
145 end | |
146 end | |
147 if n >= qmax then | |
148 module:log("debug", "Max number of items matched"); | |
149 break | |
150 end | |
151 end | |
152 -- That's all folks! | |
153 module:log("debug", "Archive query %s completed", tostring(qid)); | |
154 | |
155 local reply = st.reply(stanza); | |
156 if last then | |
157 -- This is a bit redundant, isn't it? | |
158 reply:query(xmlns_mam):add_child(rsm.generate{first = first, last = last, count = n}); | |
159 end | |
160 origin.send(reply); | |
161 return true | |
162 end | |
163 end); | 161 end); |
164 | 162 |
165 -- Handle messages | 163 -- Handle messages |
166 local function message_handler(event) | 164 local function message_handler(event) |
167 local origin, stanza = event.origin, event.stanza; | 165 local origin, stanza = event.origin, event.stanza; |