Software /
code /
prosody-modules
Diff
mod_groups_internal/mod_groups_internal.lua @ 4383:1e7406b85add
mod_groups_internal: new module for grouping beyond mod_adhoc_groups
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 25 Jan 2021 18:43:20 +0100 |
child | 4385:dfb34cc97028 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_groups_internal/mod_groups_internal.lua Mon Jan 25 18:43:20 2021 +0100 @@ -0,0 +1,180 @@ +local rostermanager = require"core.rostermanager"; +local id = require "util.id"; +local jid = require "util.jid"; +local jid_join = jid.join; +local host = module.host; + +local group_info_store = module:open_store("group_info"); +local group_members_store = module:open_store("groups"); +local group_memberships = module:open_store("groups", "map"); + +local is_contact_subscribed = rostermanager.is_contact_subscribed; + +-- Make a *one-way* subscription. User will see when contact is online, +-- contact will not see when user is online. +local function subscribe(user, user_jid, contact, contact_jid) + -- Update user's roster to say subscription request is pending... + rostermanager.set_contact_pending_out(user, host, contact_jid); + -- Update contact's roster to say subscription request is pending... + rostermanager.set_contact_pending_in(contact, host, user_jid); + -- Update contact's roster to say subscription request approved... + rostermanager.subscribed(contact, host, user_jid); + -- Update user's roster to say subscription request approved... + rostermanager.process_inbound_subscription_approval(user, host, contact_jid); + + -- Push updates to both rosters + rostermanager.roster_push(user, host, contact_jid); + rostermanager.roster_push(contact, host, user_jid); +end + +local function user_groups(username) + return pairs(group_memberships:get_all(username) or {}); +end + +local function do_single_group_subscriptions(username, group_id) + local members = group_members_store:get(group_id); + if not members then return; end + local user_jid = jid_join(username, host); + for membername in pairs(members) do + if membername ~= username then + local member_jid = jid_join(membername, host); + if not is_contact_subscribed(username, host, member_jid) then + module:log("debug", "[group %s] Subscribing %s to %s", member_jid, user_jid); + subscribe(membername, member_jid, username, user_jid); + end + if not is_contact_subscribed(membername, host, user_jid) then + module:log("debug", "[group %s] Subscribing %s to %s", user_jid, member_jid); + subscribe(username, user_jid, membername, member_jid); + end + end + end +end + +local function do_all_group_subscriptions_by_user(username) + for group_id in user_groups(username) do + do_single_group_subscriptions(username, group_id); + end +end + +local function do_all_group_subscriptions_by_group(group_id) + for membername in pairs(get_members(group_id)) do + do_single_group_subscriptions(membername, group_id); + end +end + +module:hook("resource-bind", function(event) + module:log("debug", "Updating group subscriptions..."); + do_all_group_subscriptions_by_user(event.session.username); +end); + +local function get_group_muc(group_id) + -- Group MUC + local group_info = group_info_store:get(group_id); + if group_info and group_info.muc_jid then + local muc_jid = group_info.muc_jid; + local mod_muc = hosts[jid.host(muc_jid)].modules.muc; + if mod_muc then + local room = mod_muc.get_room_from_jid(muc_jid); + if not room then + room = mod_muc.create_room(muc_jid); + end + return room; + end + end +end + +--luacheck: ignore 131 +function create(group_info, create_muc) + if not group_info.name then + return nil, "group-name-required"; + end + local group_id = id.short(); + + if create_muc then + return nil, "not-implemented"; + end + + local ok = group_info_store:set(group_id, { + name = group_info.name; + }); + if not ok then + return nil, "internal-server-error"; + end + return group_id; +end + +function get_info(group_id) + return group_info_store:get(group_id); +end + +function set_info(group_id, info) + if not info then + return nil, "bad-request" + end + + if not info.name or #info.name == 0 then + return nil, "bad-request" + end + + local ok = group_info_store:set(group_id, info); + if not ok then + return nil, "internal-server-error"; + end + return true +end + +function get_members(group_id) + return group_members_store:get(group_id); +end + +function exists(group_id) + return not not get_info(group_id); +end + +function get_user_groups(username) + local groups = {}; + do + local group_set = group_memberships:get_all(username); + if group_set then + for group_id in pairs(group_set) do + table.insert(groups, group_id); + end + end + end + return groups; +end + +function delete(group_id) + if group_members_store:set(group_id, nil) then + return group_info_store:set(group_id, nil); + end + return nil, "internal-server-error"; +end + +function add_member(group_id, username) + local group_info = group_info_store:get(group_id); + if not group_info then + return nil, "group-not-found"; + end + if not group_memberships:set(group_id, username, {}) then + return nil, "internal-server-error"; + end + do_all_group_subscriptions_by_group(group_id); + return true; +end + +function remove_member(group_id, username) + local group_info = group_info_store:get(group_id); + if not group_info then + return nil, "group-not-found"; + end + if not group_memberships:set(group_id, username, nil) then + return nil, "internal-server-error"; + end + return true; +end + +-- Returns iterator over group ids +function groups() + return group_info_store:users(); +end