Diff

mod_adhoc_groups/mod_adhoc_groups.lua @ 2848:232da6b1d2c1

mod_adhoc_groups: Allow users to create and join roster groups
author Kim Alvefur <zash@zash.se>
date Tue, 21 Nov 2017 16:58:50 +0100
parent 2847:907a15c9d621
child 2870:d8325dfb6a13
line wrap: on
line diff
--- a/mod_adhoc_groups/mod_adhoc_groups.lua	Tue Nov 21 15:01:18 2017 +0100
+++ b/mod_adhoc_groups/mod_adhoc_groups.lua	Tue Nov 21 16:58:50 2017 +0100
@@ -1,7 +1,17 @@
 local rostermanager = require"core.rostermanager";
 local jid_join = require"util.jid".join;
+local jid_split = require"util.jid".split;
 local host = module.host;
-local sessions = prosody.hosts[host].sessions;
+local st = require "util.stanza";
+
+local groups = module:open_store("groups");
+local memberships = module:open_store("groups", "map");
+
+module:depends("adhoc");
+
+local adhoclib = module:require "adhoc";
+local dataform = require"util.dataforms";
+local adhoc_inital_data = require "util.adhoc".new_initial_data_form;
 
 -- Make a *one-way* subscription. User will see when contact is online,
 -- contact will not see when user is online.
@@ -20,23 +30,121 @@
 	-- Push updates to both rosters
 	rostermanager.roster_push(user, host, contact_jid);
 	rostermanager.roster_push(contact, host, user_jid);
+
+	module:send(st.presence({ type = "probe", from = user_jid, to = contact_jid }));
+end
+
+local create_form = dataform.new {
+	title = "Create a new group";
+	{
+		type = "hidden";
+		name = "FORM_TYPE";
+		value = "xmpp:zash.se/adhoc_groups#new";
+	};
+	{
+		type = "text-single";
+		name = "group";
+		label = "Name of group";
+		required = true;
+	};
+};
+
+local join_form = dataform.new {
+	title = "Pick the group to join";
+	{
+		type = "hidden";
+		name = "FORM_TYPE";
+		value = "xmpp:zash.se/adhoc_groups#join";
+	};
+	{
+		type = "list-single";
+		name = "group";
+		label = "Available groups";
+		required = true;
+	};
+};
+
+local function _(f)
+	return function (fields, form_err, data)
+		local ok, message = f(fields, form_err, data);
+		if ok then
+			return { status = "completed", info = message };
+		else
+			return { status = "completed", error = { message = message} };
+		end
+	end
 end
 
+module:add_item("adhoc",
+	adhoclib.new("Create group",
+		"xmpp:zash.se/adhoc_groups#new",
+		adhoc_inital_data(create_form,
+			function ()
+				return {};
+			end,
+			_(function (fields, form_err, data)
+				local user = jid_split(data.from);
+				if form_err then
+					return false, "Problem in submitted form";
+				end
 
-module:hook("resource-bind", function(event)
-	local session = event.session;
-	local user = session.username;
-	local user_jid = jid_join(user, host);
-	for contact in pairs(sessions) do
-		if contact ~= user then
-			local contact_jid = jid_join(contact, host);
-			if not rostermanager.is_contact_subscribed(user, host, contact_jid) then
-				subscribe(contact, user);
-			end
-			if not rostermanager.is_contact_subscribed(contact, host, user_jid) then
-				subscribe(user, contact);
-			end
-		end
-	end
-end);
+				local group, err = groups:get(fields.group);
+				if group then
+					if err then
+						return false, "An error occured on the server. Please try again later.";
+					else
+						return false, "That group already exists";
+					end
+				end
+
+				if not groups:set(fields.group, { [user] = true }) then
+					return false, "An error occured while creating the group";
+				end
+
+				return true, ("The %s group has been created"):format(fields.group);
+			end)), "local_user")); -- Maybe admins only?
 
+module:add_item("adhoc",
+	adhoclib.new("Join group",
+		"xmpp:zash.se/adhoc_groups#join",
+		adhoc_inital_data(join_form,
+			function ()
+				local group_list = {};
+				for group in groups:users() do
+					table.insert(group_list, group);
+					module:log("debug", "Group: %q", group);
+				end
+				table.sort(group_list);
+				return { group = group_list };
+			end,
+			_(function (fields, form_err, data)
+				local user = jid_split(data.from);
+				if form_err then
+					return false, "Problem in submitted form";
+				end
+
+				local group, err = groups:get(fields.group);
+				if not group then
+					if err then
+						return false, "An error occured on the server. Please try again later.";
+					else
+						return false, "No such group";
+					end
+				end
+				if group[data.from] then
+					return false, "You are already in this group.";
+				end
+
+				if not memberships:set(fields.group, user, true) then
+					return false, "An error occured while adding you to the group";
+				end
+
+				for member in pairs(group) do
+					if member ~= user then
+						subscribe(user, member);
+						subscribe(member, user);
+					end
+				end
+
+				return true, ("Welcome to the %s group"):format(fields.group);
+			end)), "local_user"));