changeset 3496:262e68821f3f

mod_map: Experimental module exposing MAM summary
author Kim Alvefur <zash@zash.se>
date Mon, 25 Feb 2019 15:52:46 +0100
parents 5567098a7f91
children bc67519803f5
files mod_map/README.markdown mod_map/mod_map.lua
diffstat 2 files changed, 119 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_map/README.markdown	Mon Feb 25 15:52:46 2019 +0100
@@ -0,0 +1,52 @@
+---
+labels:
+- 'Stage-Experimental'
+summary: Prototype MAM summary
+---
+
+This is a prototype for an experimental archive summary API recently
+added in [Prosody trunk](https://hg.prosody.im/trunk/rev/2c5546cc5c70).
+
+# Protocol
+
+::: {.alert .alert-danger}
+This is not a finished protocol, but a prototype meant for testing.
+:::
+
+A basic query:
+
+``` {.xml}
+<iq id="lx7" type="get">
+  <summary xmlns="xmpp:prosody.im/mod_map"/>
+</iq>
+```
+
+Answered like:
+
+``` {.xml}
+<?xml version="1.0"?>
+<iq type="result" id="lx7">
+  <summary xmlns="xmpp:prosody.im/mod_map">
+    <item jid="juliet@capulet.lit">
+      <count>3</count>
+    </item>
+  </summary>
+</iq>
+```
+
+It can also take dataform and RSM parameters similar to a [filtered MAM
+query](https://xmpp.org/extensions/xep-0313.html#filter).
+
+E.g if the last message you received had an id `09af3-cc343-b409f` then
+the following query would tell you who sent you messages since:
+
+``` {.xml}
+<iq id="lx8" type="get">
+  <summary xmlns="xmpp:prosody.im/mod_map">
+    <set xmlns="http://jabber.org/protocol/rsm">
+      <max>10</max>
+      <after>09af3-cc343-b409f</after>
+    </set>
+  </summary>
+</iq>
+```
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_map/mod_map.lua	Mon Feb 25 15:52:46 2019 +0100
@@ -0,0 +1,67 @@
+
+local st = require "util.stanza";
+local jid_bare = require "util.jid".bare;
+local rsm = require "util.rsm";
+local dataform = require "util.dataforms".new;
+
+local archive = module:open_store("archive", "archive");
+
+local query_form = dataform {
+	{ name = "with"; type = "jid-single"; };
+	{ name = "start"; type = "text-single" };
+	{ name = "end"; type = "text-single"; };
+};
+
+if not archive.summary then
+	module:log("error", "The archive:summary() API is not supported by %s", archive._provided_by);
+	return
+end
+
+module:hook("iq-get/self/xmpp:prosody.im/mod_map:summary", function(event)
+	local origin, stanza = event.origin, event.stanza;
+
+	local query = stanza.tags[1];
+
+	-- Search query parameters
+	local qwith, qstart, qend;
+	local form = query:get_child("x", "jabber:x:data");
+	if form then
+		local err;
+		form, err = query_form:data(form);
+		if err then
+			origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err))));
+			return true;
+		end
+		qwith, qstart, qend = form["with"], form["start"], form["end"];
+		qwith = qwith and jid_bare(qwith); -- dataforms does jidprep
+	end
+
+	local qset = rsm.get(query);
+	local qmax = qset and qset.max;
+	local before, after = qset and qset.before, qset and qset.after;
+	if type(before) ~= "string" then before = nil; end
+
+	local summary = archive:summary(origin.username, {
+		start = qstart; ["end"] = qend; -- Time range
+		with = qwith;
+		limit = qmax;
+		before = before; after = after;
+	});
+	if not summary then
+		module:send(st.error_reply(stanza, "wait", "internal-server-error"));
+		return true;
+	end
+
+	local reply = st.reply(stanza);
+	reply:tag("summary", { xmlns = "xmpp:prosody.im/mod_map" });
+	for jid, count in pairs(summary) do
+		reply:tag("item", { jid = jid });
+		if type(count) == "number" then
+			reply:text_tag("count", ("%d"):format(count));
+		end
+		reply:up();
+	end
+
+	module:send(reply);
+	return true;
+end);