Mercurial > prosody-modules
annotate mod_mam_muc/mod_mam_muc.lua @ 1142:fabdaa0d99e3
mod_mam_muc: Stap archived messages
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Sat, 10 Aug 2013 21:17:12 +0200 |
| parents | 1091be1c3aba |
| children | 8098683b6d6f |
| rev | line source |
|---|---|
| 820 | 1 -- XEP-0313: Message Archive Management for Prosody |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
2 -- Copyright (C) 2011-2013 Kim Alvefur |
| 820 | 3 -- |
| 4 -- This file is MIT/X11 licensed. | |
| 5 | |
| 6 local xmlns_mam = "urn:xmpp:mam:tmp"; | |
| 7 local xmlns_delay = "urn:xmpp:delay"; | |
| 8 local xmlns_forward = "urn:xmpp:forward:0"; | |
| 9 | |
| 10 local st = require "util.stanza"; | |
| 11 local rsm = module:require "mod_mam/rsm"; | |
| 12 local jid_bare = require "util.jid".bare; | |
| 13 local jid_split = require "util.jid".split; | |
| 14 | |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
15 local getmetatable = getmetatable; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
16 local function is_stanza(x) |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
17 return getmetatable(x) == st.stanza_mt; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
18 end |
| 820 | 19 |
| 20 local tostring = tostring; | |
| 21 local time_now = os.time; | |
| 22 local m_min = math.min; | |
| 23 local timestamp, timestamp_parse = require "util.datetime".datetime, require "util.datetime".parse; | |
| 24 local default_max_items, max_max_items = 20, module:get_option_number("max_archive_query_results", 50); | |
| 25 | |
|
1142
fabdaa0d99e3
mod_mam_muc: Stap archived messages
Kim Alvefur <zash@zash.se>
parents:
1141
diff
changeset
|
26 local advertise_archive = module:get_option_boolean("muc_log_advertise", true); |
|
fabdaa0d99e3
mod_mam_muc: Stap archived messages
Kim Alvefur <zash@zash.se>
parents:
1141
diff
changeset
|
27 |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
28 local archive = module:open_store("archive2", "archive"); |
|
1139
b32d65e41755
mod_mam_muc: Get room objects in a less awkward fashion
Kim Alvefur <zash@zash.se>
parents:
1138
diff
changeset
|
29 local rooms = hosts[module.host].modules.muc.rooms; |
| 820 | 30 |
| 31 -- Handle archive queries | |
|
1138
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
32 module:hook("iq-get/bare/"..xmlns_mam..":query", function(event) |
| 820 | 33 local origin, stanza = event.origin, event.stanza; |
| 34 local room = jid_split(stanza.attr.to); | |
| 35 local query = stanza.tags[1]; | |
| 36 | |
|
1139
b32d65e41755
mod_mam_muc: Get room objects in a less awkward fashion
Kim Alvefur <zash@zash.se>
parents:
1138
diff
changeset
|
37 local room_obj = rooms[room]; |
| 820 | 38 if not room_obj then |
| 39 return -- FIXME not found | |
| 40 end | |
| 41 local from = jid_bare(stanza.attr.from); | |
| 42 | |
|
1140
402cb9b604eb
mod_mam_muc: Send proper error reply when one is not allowed to query archive
Kim Alvefur <zash@zash.se>
parents:
1139
diff
changeset
|
43 -- Banned or not a member of a members-only room? |
| 820 | 44 if room_obj._affiliations[from] == "outcast" |
| 45 or room_obj._data.members_only and not room_obj._affiliations[from] then | |
|
1140
402cb9b604eb
mod_mam_muc: Send proper error reply when one is not allowed to query archive
Kim Alvefur <zash@zash.se>
parents:
1139
diff
changeset
|
46 return origin.send(st.error_reply(stanza, "auth", "forbidden")) |
| 820 | 47 end |
| 48 | |
|
1138
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
49 local qid = query.attr.queryid; |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
50 |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
51 -- Search query parameters |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
52 local qstart = query:get_child_text("start"); |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
53 local qend = query:get_child_text("end"); |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
54 module:log("debug", "Archive query, id %s from %s until %s)", |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
55 tostring(qid), qstart or "the dawn of time", qend or "now"); |
| 820 | 56 |
|
1138
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
57 if qstart or qend then -- Validate timestamps |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
58 local vstart, vend = (qstart and timestamp_parse(qstart)), (qend and timestamp_parse(qend)) |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
59 if (qstart and not vstart) or (qend and not vend) then |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
60 origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid timestamp")) |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
61 return true |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
62 end |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
63 qstart, qend = vstart, vend; |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
64 end |
| 820 | 65 |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
66 -- RSM stuff |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
67 local qset = rsm.get(query); |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
68 local qmax = m_min(qset and qset.max or default_max_items, max_max_items); |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
69 local reverse = qset and qset.before or false; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
70 |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
71 local before, after = qset and qset.before, qset and qset.after; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
72 if type(before) ~= "string" then before = nil; end |
| 820 | 73 |
|
1138
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
74 -- Load all the data! |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
75 local data, err = archive:find(origin.username, { |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
76 start = qstart; ["end"] = qend; -- Time range |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
77 limit = qmax; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
78 before = before; after = after; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
79 reverse = reverse; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
80 total = true; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
81 }); |
|
1138
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
82 |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
83 if not data then |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
84 return origin.send(st.error_reply(stanza, "cancel", "internal-server-error")); |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
85 end |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
86 local count = err; |
|
1138
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
87 |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
88 -- Wrap it in stuff and deliver |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
89 local first, last; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
90 for id, item, when in data do |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
91 local fwd_st = st.message{ to = origin.full_jid } |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
92 :tag("result", { xmlns = xmlns_mam, queryid = qid, id = id }) |
|
1138
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
93 :tag("forwarded", { xmlns = xmlns_forward }) |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
94 :tag("delay", { xmlns = xmlns_delay, stamp = timestamp(when) }):up(); |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
95 |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
96 if not is_stanza(item) then |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
97 item = st.deserialize(item); |
|
1138
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
98 end |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
99 item.attr.xmlns = "jabber:client"; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
100 fwd_st:add_child(item); |
| 820 | 101 |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
102 if not first then first = id; end |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
103 last = id; |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
104 |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
105 origin.send(fwd_st); |
|
1138
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
106 end |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
107 -- That's all folks! |
|
5c97ee75cadb
mod_mam_muc: Switch to iq-get hook and drop some indentation
Kim Alvefur <zash@zash.se>
parents:
820
diff
changeset
|
108 module:log("debug", "Archive query %s completed", tostring(qid)); |
| 820 | 109 |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
110 if reverse then first, last = last, first; end |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
111 return origin.send(st.reply(stanza) |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
112 :query(xmlns_mam):add_child(rsm.generate { |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
113 first = first, last = last, count = count })); |
| 820 | 114 end); |
| 115 | |
| 116 -- Handle messages | |
| 117 local function message_handler(event) | |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
118 local stanza = event.stanza; |
| 820 | 119 local orig_type = stanza.attr.type or "normal"; |
| 120 local orig_to = stanza.attr.to; | |
| 121 local orig_from = stanza.attr.from; | |
| 122 | |
| 123 -- Only store groupchat messages | |
| 124 if not (orig_type == "groupchat" and (stanza:get_child("body") or stanza:get_child("subject"))) then | |
| 125 return; | |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
126 -- Chat states and other non-content messages, what TODO? |
| 820 | 127 end |
| 128 | |
| 129 local room = jid_split(orig_to); | |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
130 local room_obj = rooms[orig_to] |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
131 if not room_obj then return end -- No such room |
| 820 | 132 |
| 133 local nick = room_obj._jid_nick[orig_from]; | |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
134 if not nick then return end -- Message from someone not in the room? |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
135 |
| 820 | 136 stanza.attr.from = nick; |
| 137 -- And stash it | |
|
1142
fabdaa0d99e3
mod_mam_muc: Stap archived messages
Kim Alvefur <zash@zash.se>
parents:
1141
diff
changeset
|
138 local ok, id = archive:append(room, time_now(), "", stanza); |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
139 stanza.attr.from = orig_from; |
|
1142
fabdaa0d99e3
mod_mam_muc: Stap archived messages
Kim Alvefur <zash@zash.se>
parents:
1141
diff
changeset
|
140 if ok and advertise_archive then |
|
fabdaa0d99e3
mod_mam_muc: Stap archived messages
Kim Alvefur <zash@zash.se>
parents:
1141
diff
changeset
|
141 stanza:tag("archived", { xmlns = xmlns_mam, by = jid_bare(orig_to), id = id }):up(); |
|
fabdaa0d99e3
mod_mam_muc: Stap archived messages
Kim Alvefur <zash@zash.se>
parents:
1141
diff
changeset
|
142 end |
| 820 | 143 end |
| 144 | |
| 145 module:hook("message/bare", message_handler, 2); | |
| 146 | |
|
1141
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
147 -- TODO should we perhaps log presence as well? |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
148 -- And role/affiliation changes? |
|
1091be1c3aba
mod_mam_muc: Switch to new stanza storage API
Kim Alvefur <zash@zash.se>
parents:
1140
diff
changeset
|
149 |
| 820 | 150 module:add_feature(xmlns_mam); |
