# HG changeset patch # User Matthew Wild # Date 1708728425 0 # Node ID ed82916e57966288d23d89b070b3056447111c7d # Parent 904b226fddf1d651cab45889f4c31e2210657d23 mod_server_info: Rewrite/backport from Prosody 1ce18cb3e6cc diff -r 904b226fddf1 -r ed82916e5796 mod_server_info/README.md --- a/mod_server_info/README.md Fri Feb 23 13:02:33 2024 +0000 +++ b/mod_server_info/README.md Fri Feb 23 22:47:05 2024 +0000 @@ -14,37 +14,52 @@ Everything configured here is publicly visible to other XMPP entities. +**Note:** This module was rewritten in February 2024, the configuration is not +compatible with the previous version of the module. + ## Configuration -The `server_info` option accepts a list of dataforms. A dataform is an array -of fields. A field has three required properties: +The `server_info_extensions` option accepts a list of custom fields to include +in the server info form. + +A field has three required properties: - `type` - usually `text-single` or `list-multi` -- `var` - the field name +- `var` - the field name (see below) - `value` the field value Example configuration: ``` lua server_info = { - - -- Our custom form - { - -- Conventionally XMPP dataforms have a 'FORM_TYPE' field to - -- indicate what type of form it is - { type = "hidden", var = "FORM_TYPE", value = "urn:example:foo" }; + -- Advertise that our maximum speed is 88 mph + { type = "text-single", var = "speed", value = "88" }; - -- Advertise that our maximum speed is 88 mph - { type = "text-single", var = "speed", value = "88" }; - - -- Advertise that the time is 1:20 AM and zero seconds - { type = "text-single", var = "time", value = "01:21:00" }; - }; - + -- Advertise that the time is 1:20 AM and zero seconds + { type = "text-single", var = "time", value = "01:21:00" }; } ``` +The `var` attribute is used to uniquely identify fields. Every `var` should be +registered with the XSF [form registry](https://xmpp.org/registrar/formtypes.html#http:--jabber.org-network-serverinfo), +or prefixed with a custom namespace using Clark notation, e.g. `{https://example.com}my-field-name`. This is to prevent +collisions. + +## Developers + +Developers of other modules can add fields to the form at runtime: + +```lua +module:depends("server_info"); + +module:add_item("server-info-fields", { + { type = "text-single", var = "speed", value = "88" }; + { type = "text-single", var = "time", value = "01:21:00" }; +}); +``` + +Prosody will ensure they are removed if your module is unloaded. + ## Compatibility -This module should be compatible with Prosody 0.12, and possibly earlier -versions. +This module should be compatible with Prosody 0.12 and later. diff -r 904b226fddf1 -r ed82916e5796 mod_server_info/mod_server_info.lua --- a/mod_server_info/mod_server_info.lua Fri Feb 23 13:02:33 2024 +0000 +++ b/mod_server_info/mod_server_info.lua Fri Feb 23 22:47:05 2024 +0000 @@ -1,18 +1,60 @@ --- XEP-0128: Service Discovery Extensions (manual config) --- --- Copyright (C) 2023 Matthew Wild --- --- This project is MIT/X11 licensed. Please see the --- COPYING file in the source package for more information. --- +-- mod_server_info imported from Prosody commit 1ce18cb3e6cc for the benefit +-- of 0.12 deployments. This community version of the module will not load in +-- newer Prosody versions, which include their own copy of the module. +--% conflicts: mod_server_info + +local dataforms = require "prosody.util.dataforms"; + +local server_info_config = module:get_option("server_info", {}); +local server_info_custom_fields = module:get_option_array("server_info_extensions"); -local dataforms = require "util.dataforms"; - -local config = module:get_option("server_info"); +-- Source: http://xmpp.org/registrar/formtypes.html#http:--jabber.org-network-serverinfo +local form_layout = dataforms.new({ + { var = "FORM_TYPE"; type = "hidden"; value = "http://jabber.org/network/serverinfo" }; +}); -if not config or next(config) == nil then return; end -- Nothing to do - -for _, form in ipairs(config) do - module:add_extension(dataforms.new(form):form({}, "result")); +if server_info_custom_fields then + for _, field in ipairs(server_info_custom_fields) do + table.insert(form_layout, field); + end end +local generated_form; + +function update_form() + local new_form = form_layout:form(server_info_config, "result"); + if generated_form then + module:remove_item("extension", generated_form); + end + generated_form = new_form; + module:add_item("extension", generated_form); +end + +function add_fields(event) + local fields = event.item; + for _, field in ipairs(fields) do + table.insert(form_layout, field); + end + update_form(); +end + +function remove_fields(event) + local removed_fields = event.item; + for _, removed_field in ipairs(removed_fields) do + local removed_var = removed_field.var or removed_field.name; + for i, field in ipairs(form_layout) do + local var = field.var or field.name + if var == removed_var then + table.remove(form_layout, i); + break; + end + end + end + update_form(); +end + +module:handle_items("server-info-fields", add_fields, remove_fields); + +function module.load() + update_form(); +end