Mercurial > prosody-modules
comparison mod_mam/mod_mam.lua @ 2516:248054199d0f
mod_mam: Add support for XEP-0313 v0.6
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Mon, 20 Feb 2017 01:59:33 +0100 |
| parents | 4cb549622862 |
| children | 0f44d04d0d18 |
comparison
equal
deleted
inserted
replaced
| 2515:4cb549622862 | 2516:248054199d0f |
|---|---|
| 3 -- | 3 -- |
| 4 -- This file is MIT/X11 licensed. | 4 -- This file is MIT/X11 licensed. |
| 5 | 5 |
| 6 local xmlns_mam0 = "urn:xmpp:mam:0"; | 6 local xmlns_mam0 = "urn:xmpp:mam:0"; |
| 7 local xmlns_mam1 = "urn:xmpp:mam:1"; | 7 local xmlns_mam1 = "urn:xmpp:mam:1"; |
| 8 local xmlns_mam2 = "urn:xmpp:mam:2"; | |
| 8 local xmlns_delay = "urn:xmpp:delay"; | 9 local xmlns_delay = "urn:xmpp:delay"; |
| 9 local xmlns_forward = "urn:xmpp:forward:0"; | 10 local xmlns_forward = "urn:xmpp:forward:0"; |
| 11 local xmlns_st_id = "urn:xmpp:sid:0"; | |
| 10 | 12 |
| 11 local um = require "core.usermanager"; | 13 local um = require "core.usermanager"; |
| 12 local st = require "util.stanza"; | 14 local st = require "util.stanza"; |
| 13 local rsm = module:require "rsm"; | 15 local rsm = module:require "rsm"; |
| 14 local get_prefs = module:require"mamprefs".get; | 16 local get_prefs = module:require"mamprefs".get; |
| 15 local set_prefs = module:require"mamprefs".set; | 17 local set_prefs = module:require"mamprefs".set; |
| 16 local prefs_to_stanza = module:require"mamprefsxml".tostanza; | 18 local prefs_to_stanza = module:require"mamprefsxml".tostanza; |
| 17 local prefs_from_stanza = module:require"mamprefsxml".fromstanza; | 19 local prefs_from_stanza = module:require"mamprefsxml".fromstanza; |
| 18 local jid_bare = require "util.jid".bare; | 20 local jid_bare = require "util.jid".bare; |
| 19 local jid_split = require "util.jid".split; | 21 local jid_split = require "util.jid".split; |
| 22 local jid_prepped_split = require "util.jid".prepped_split; | |
| 20 local dataform = require "util.dataforms".new; | 23 local dataform = require "util.dataforms".new; |
| 21 local host = module.host; | 24 local host = module.host; |
| 22 | 25 |
| 23 local rm_load_roster = require "core.rostermanager".load_roster; | 26 local rm_load_roster = require "core.rostermanager".load_roster; |
| 24 | 27 |
| 76 return true; | 79 return true; |
| 77 end | 80 end |
| 78 | 81 |
| 79 module:hook("iq/self/"..xmlns_mam0..":prefs", handle_prefs); | 82 module:hook("iq/self/"..xmlns_mam0..":prefs", handle_prefs); |
| 80 module:hook("iq/self/"..xmlns_mam1..":prefs", handle_prefs); | 83 module:hook("iq/self/"..xmlns_mam1..":prefs", handle_prefs); |
| 84 module:hook("iq/self/"..xmlns_mam2..":prefs", handle_prefs); | |
| 81 | 85 |
| 82 local query_form = dataform { | 86 local query_form = dataform { |
| 83 { name = "FORM_TYPE"; type = "hidden"; value = xmlns_mam0; }; | 87 { name = "FORM_TYPE"; type = "hidden"; value = xmlns_mam0; }; |
| 84 { name = "with"; type = "jid-single"; }; | 88 { name = "with"; type = "jid-single"; }; |
| 85 { name = "start"; type = "text-single" }; | 89 { name = "start"; type = "text-single" }; |
| 95 return true; | 99 return true; |
| 96 end | 100 end |
| 97 | 101 |
| 98 module:hook("iq-get/self/"..xmlns_mam0..":query", handle_get_form); | 102 module:hook("iq-get/self/"..xmlns_mam0..":query", handle_get_form); |
| 99 module:hook("iq-get/self/"..xmlns_mam1..":query", handle_get_form); | 103 module:hook("iq-get/self/"..xmlns_mam1..":query", handle_get_form); |
| 104 module:hook("iq-get/self/"..xmlns_mam2..":query", handle_get_form); | |
| 100 | 105 |
| 101 -- Handle archive queries | 106 -- Handle archive queries |
| 102 local function handle_mam_query(event) | 107 local function handle_mam_query(event) |
| 103 local origin, stanza = event.origin, event.stanza; | 108 local origin, stanza = event.origin, event.stanza; |
| 104 local xmlns_mam = stanza.tags[1].attr.xmlns; | 109 local xmlns_mam = stanza.tags[1].attr.xmlns; |
| 219 origin.send(fin); | 224 origin.send(fin); |
| 220 return true; | 225 return true; |
| 221 end | 226 end |
| 222 module:hook("iq-set/self/"..xmlns_mam0..":query", handle_mam_query); | 227 module:hook("iq-set/self/"..xmlns_mam0..":query", handle_mam_query); |
| 223 module:hook("iq-set/self/"..xmlns_mam1..":query", handle_mam_query); | 228 module:hook("iq-set/self/"..xmlns_mam1..":query", handle_mam_query); |
| 229 module:hook("iq-set/self/"..xmlns_mam2..":query", handle_mam_query); | |
| 224 | 230 |
| 225 local function has_in_roster(user, who) | 231 local function has_in_roster(user, who) |
| 226 local roster = rm_load_roster(user, host); | 232 local roster = rm_load_roster(user, host); |
| 227 module:log("debug", "%s has %s in roster? %s", user, who, roster[who] and "yes" or "no"); | 233 module:log("debug", "%s has %s in roster? %s", user, who, roster[who] and "yes" or "no"); |
| 228 return roster[who]; | 234 return roster[who]; |
| 259 local orig_type = stanza.attr.type or "normal"; | 265 local orig_type = stanza.attr.type or "normal"; |
| 260 local orig_from = stanza.attr.from; | 266 local orig_from = stanza.attr.from; |
| 261 local orig_to = stanza.attr.to or orig_from; | 267 local orig_to = stanza.attr.to or orig_from; |
| 262 -- Stanza without 'to' are treated as if it was to their own bare jid | 268 -- Stanza without 'to' are treated as if it was to their own bare jid |
| 263 | 269 |
| 270 -- Whos storage do we put it in? | |
| 271 local store_user = c2s and origin.username or jid_split(orig_to); | |
| 272 -- And who are they chatting with? | |
| 273 local with = jid_bare(c2s and orig_to or orig_from); | |
| 274 | |
| 275 -- Filter out <stanza-id> that claim to be from us | |
| 276 stanza:maptags(function (tag) | |
| 277 if tag.name == "stanza-id" and tag.attr.xmlns == xmlns_st_id then | |
| 278 local by_user, by_host, res = jid_prepped_split(tag.attr.by); | |
| 279 if not res and by_host == module.host and by_user == store_user then | |
| 280 return nil; | |
| 281 end | |
| 282 end | |
| 283 return tag; | |
| 284 end); | |
| 285 | |
| 264 -- We store chat messages or normal messages that have a body | 286 -- We store chat messages or normal messages that have a body |
| 265 if not(orig_type == "chat" or (orig_type == "normal" and stanza:get_child("body")) ) then | 287 if not(orig_type == "chat" or (orig_type == "normal" and stanza:get_child("body")) ) then |
| 266 log("debug", "Not archiving stanza: %s (type)", stanza:top_tag()); | 288 log("debug", "Not archiving stanza: %s (type)", stanza:top_tag()); |
| 267 return; | 289 return; |
| 268 end | 290 end |
| 274 log("debug", "Not archiving stanza: %s (hint)", stanza:top_tag()); | 296 log("debug", "Not archiving stanza: %s (hint)", stanza:top_tag()); |
| 275 return; | 297 return; |
| 276 end | 298 end |
| 277 end | 299 end |
| 278 | 300 |
| 279 -- Whos storage do we put it in? | |
| 280 local store_user = c2s and origin.username or jid_split(orig_to); | |
| 281 -- And who are they chatting with? | |
| 282 local with = jid_bare(c2s and orig_to or orig_from); | |
| 283 | |
| 284 -- Check with the users preferences | 301 -- Check with the users preferences |
| 285 if shall_store(store_user, with) then | 302 if shall_store(store_user, with) then |
| 286 log("debug", "Archiving stanza: %s", stanza:top_tag()); | 303 log("debug", "Archiving stanza: %s", stanza:top_tag()); |
| 287 | 304 |
| 288 -- And stash it | 305 -- And stash it |
| 289 local ok = archive:append(store_user, nil, stanza, time_now(), with); | 306 local ok = archive:append(store_user, nil, stanza, time_now(), with); |
| 290 if ok then | 307 if ok then |
| 291 local id = ok; | 308 local id = ok; |
| 309 stanza:tag("stanza-id", { xmlns = xmlns_st_id, by = store_user.."@"..host, id = id }):up(); | |
| 292 if cleanup then cleanup[store_user] = true; end | 310 if cleanup then cleanup[store_user] = true; end |
| 293 module:fire_event("archive-message-added", { origin = origin, stanza = stanza, for_user = store_user, id = id }); | 311 module:fire_event("archive-message-added", { origin = origin, stanza = stanza, for_user = store_user, id = id }); |
| 294 end | 312 end |
| 295 else | 313 else |
| 296 log("debug", "Not archiving stanza: %s (prefs)", stanza:top_tag()); | 314 log("debug", "Not archiving stanza: %s (prefs)", stanza:top_tag()); |
| 298 end | 316 end |
| 299 | 317 |
| 300 local function c2s_message_handler(event) | 318 local function c2s_message_handler(event) |
| 301 return message_handler(event, true); | 319 return message_handler(event, true); |
| 302 end | 320 end |
| 321 | |
| 322 local function strip_stanza_id(event) | |
| 323 local strip_by = jid_bare(event.origin.full_jid); | |
| 324 event.stanza:maptags(function(tag) | |
| 325 if not ( tag.attr.xmlns == xmlns_st_id and tag.attr.by == strip_by ) then | |
| 326 return tag; | |
| 327 end | |
| 328 end); | |
| 329 end | |
| 330 | |
| 331 module:hook("pre-message/bare", strip_stanza_id, 0.01); | |
| 332 module:hook("pre-message/full", strip_stanza_id, 0.01); | |
| 303 | 333 |
| 304 local cleanup_after = module:get_option_string("archive_expires_after", "1w"); | 334 local cleanup_after = module:get_option_string("archive_expires_after", "1w"); |
| 305 local cleanup_interval = module:get_option_number("archive_cleanup_interval", 4 * 60 * 60); | 335 local cleanup_interval = module:get_option_number("archive_cleanup_interval", 4 * 60 * 60); |
| 306 if cleanup_after ~= "never" then | 336 if cleanup_after ~= "never" then |
| 307 local day = 86400; | 337 local day = 86400; |
| 364 module:add_feature(xmlns_mam0); -- COMPAT with XEP-0313 v 0.1 | 394 module:add_feature(xmlns_mam0); -- COMPAT with XEP-0313 v 0.1 |
| 365 | 395 |
| 366 module:hook("account-disco-info", function(event) | 396 module:hook("account-disco-info", function(event) |
| 367 (event.reply or event.stanza):tag("feature", {var=xmlns_mam0}):up(); | 397 (event.reply or event.stanza):tag("feature", {var=xmlns_mam0}):up(); |
| 368 (event.reply or event.stanza):tag("feature", {var=xmlns_mam1}):up(); | 398 (event.reply or event.stanza):tag("feature", {var=xmlns_mam1}):up(); |
| 399 (event.reply or event.stanza):tag("feature", {var=xmlns_mam2}):up(); | |
| 400 (event.reply or event.stanza):tag("feature", {var=xmlns_st_id}):up(); | |
| 369 end); | 401 end); |
| 370 | 402 |
