# HG changeset patch # User Matthew Wild # Date 1688689544 -3600 # Node ID 30b9f78b50587d415c1ec9acd2e7533447f0e619 # Parent 5b316088bef54d49c5b49e2713b898a17a744ced mod_muc_members_json: New module to import MUC membership from a JSON URL diff -r 5b316088bef5 -r 30b9f78b5058 mod_muc_members_json/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_muc_members_json/README.md Fri Jul 07 01:25:44 2023 +0100 @@ -0,0 +1,81 @@ +--- +labels: +- 'Stage-Beta' +summary: 'Import MUC membership info from a JSON file' +... + +Introduction +============ + +This module allows you to import MUC membership information from an external +URL in JSON format. + +Details +======= + +If you have an organization or community and lots of members and/or channels, +it can be frustrating to manage MUC affiliations manually. This module will +fetch a JSON file from a configured URL, and use that to automatically set the +MUC affiliations. + +It also supports hats/badges. + +Configuration +============= + +Add the module to the MUC host (not the global modules\_enabled): + + Component "conference.example.com" "muc" + modules_enabled = { "muc_members_json" } + +You can define (globally or per-MUC component) the following options: + + Name Description + --------------------- -------------------------------------------------- + muc_members_json_url The URL to the JSON file describing memberships + muc_members_json_mucs The MUCs to manage, and their associated configuration + +The `muc_members_json_mucs` setting determines which rooms will be managed by +the plugin, and how to map roles to hats (if desired). + +``` +muc_members_json_mucs = { + myroom = { + member_hat = { + id = "urn:uuid:6a1b143a-1c5c-11ee-80aa-4ff1ce4867dc"; + title = "Cool Member"; + }; + }; +} +``` + +JSON format +=========== + +``` +{ + "members": [ + { + "jids": ["user@example.com"] + }, + { + "jids": ["user2@example.com"] + }, + { + "jids": ["user3@example.com"], + roles: ["janitor"] + } + ] +} +``` + +Each member must have a `jids` field, and optionally a `roles` field. + +Compatibility +============= + + ------- ------------------ + trunk Works + 0.12 Works + ------- ------------------ + diff -r 5b316088bef5 -r 30b9f78b5058 mod_muc_members_json/mod_muc_members_json.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_muc_members_json/mod_muc_members_json.lua Fri Jul 07 01:25:44 2023 +0100 @@ -0,0 +1,91 @@ +local http = require "net.http"; +local json = require "util.json"; + +local json_url = assert(module:get_option_string("muc_members_json_url"), "muc_members_json_url required"); +local managed_mucs = module:get_option("muc_members_json_mucs"); + +local mod_muc = module:depends("muc"); + +--[[ +{ + xsf = { + team_hats = { + board = { + id = "xmpp:xmpp.org/hats/board"; + title = "Board"; + }; + }; + member_hat = { + id = "xmpp:xmpp.org/hats/member"; + title = "XSF member"; + }; + }; + iteam = { + team_hats = { + iteam = { + id = "xmpp:xmpp.org/hats/iteam"; + title = "Infra team"; + }; + }; + }; +} +--]] + +local function get_hats(member_info, muc_config) + local hats = {}; + if muc_config.member_hat then + hats[muc_config.member_hat.id] = { + title = muc_config.member_hat.title; + }; + end + if muc_config.team_hats and member_info.roles then + for _, role in ipairs(member_info.roles) do + local hat = muc_config.team_hats[role]; + if hat then + hats[hat.id] = { + title = hat.title; + }; + end + end + end + return hats; +end + +function module.load() + http.request(json_url) + :next(function (result) + return json.decode(result.body); + end) + :next(function (data) + module:log("debug", "DATA: %s", require "util.serialization".serialize(data, "debug")); + + for name, muc_config in pairs(managed_mucs) do + local muc_jid = name.."@"..module.host; + local muc = mod_muc.get_room_from_jid(muc_jid); + module:log("warn", "%s -> %s -> %s", name, muc_jid, muc); + if muc then + local jids = {}; + for _, member_info in ipairs(data.members) do + for _, member_jid in ipairs(member_info.jids) do + jids[member_jid] = true; + local affiliation = muc:get_affiliation(member_jid); + if not affiliation then + muc:set_affiliation(true, member_jid, "member", "imported membership"); + muc:set_affiliation_data(member_jid, "source", module.name); + end + muc:set_affiliation_data(member_jid, "hats", get_hats(member_info, muc_config)); + end + end + -- Remove affiliation from folk who weren't in the source data but previously were + for jid, aff, data in muc:each_affiliation() do + if not jids[jid] and data.source == module.name then + muc:set_affiliation(true, jid, "none", "imported membership lost"); + end + end + end + end + + end):catch(function (err) + module:log("error", "FAILED: %s", err); + end); +end