Terms&Conditions (#18) WIP:

* channel terms
This commit is contained in:
John Livingston 2024-06-25 11:28:46 +02:00
parent b110456029
commit a06ef00e2a
No known key found for this signature in database
GPG Key ID: B17B5640CE66CDBC
9 changed files with 101 additions and 42 deletions

View File

@ -14,6 +14,9 @@ local get_room_from_jid = rawget(mod_muc, "get_room_from_jid");
module:depends"http";
local mod_muc_peertubelivechat_terms = module:depends"muc_peertubelivechat_terms";
local set_muc_terms = rawget(mod_muc_peertubelivechat_terms, "set_muc_terms");
function check_auth(routes)
local function check_request_auth(event)
local apikey = module:get_option_string("peertubelivechat_manage_rooms_apikey", "")
@ -94,6 +97,12 @@ local function update_room(event)
must104 = true;
end
end
if (type(config.livechat_muc_terms) == "string") then
-- to easily detect if the value is given or not, we consider that the caller passes "" when terms must be deleted.
if set_muc_terms then
set_muc_terms(room, config.livechat_muc_terms or nil);
end
end
if type(config.removeAffiliationsFor) == "table" then
-- array of jids
for _, jid in ipairs(config.removeAffiliationsFor) do

View File

@ -121,6 +121,11 @@ local function apply_config(room, settings)
if (type(config.mute_anonymous) == "boolean") then
room._data.x_peertubelivechat_mute_anonymous = config.mute_anonymous;
end
if (type(config.livechat_muc_terms) == "string") then
-- we don't need to use set_muc_terms here, as this is called for a newly created room
-- (and thus we don't need to broadcast changes)
room._data.livechat_muc_terms = config.livechat_muc_terms;
end
elseif config ~= nil then
module:log("error", "Invalid config returned from API for %s: %q", room.jid, config);
return nil, "format", { field = "config" };

View File

@ -29,6 +29,6 @@ The nickname that will be used by service messages.
This module reserves the nickname, so than nobody can use it in MUC rooms
(we don't want any user to spoof this nickname).
### muc_terms
### muc_terms_global
The global terms.

View File

@ -7,30 +7,71 @@
-- Please see the Peertube livechat plugin copyright information.
-- https://livingston.frama.io/peertube-plugin-livechat/credits/
--
-- Exposed functions:
-- get_muc_terms
-- set_muc_terms
local jid_escape = require "util.jid".escape;
local jid_resource = require "util.jid".resource;
local st = require "util.stanza";
local id = require "util.id";
local service_nickname = module:get_option_string("muc_terms_service_nickname", "Service");
local global_terms = module:get_option_string("muc_terms", "");
local global_terms = module:get_option_string("muc_terms_global", "");
local function create_terms_message(room, type, terms)
local from = room.jid .. '/' .. jid_escape(service_nickname);
module:log("debug", "Creating %s terms message from %s (room %s)", type, from, room);
local msg = st.message({
type = "groupchat",
from = from,
id = id.medium()
}, terms)
:tag('x-livechat-terms', { type = type }):up(); -- adding a custom tag to specify that it is a "terms" message, so that frontend can display it with a special template.
return msg;
end
-- MUC Getter/Setter
function get_muc_terms(room)
return room._data.livechat_muc_terms or nil;
end
function set_muc_terms(room, terms)
terms = terms or nil;
if get_muc_terms(room) == terms then return false; end
room._data.livechat_muc_terms = terms;
if terms ~= nil then
-- we must send new terms to all occupants.
local msg = create_terms_message(room, "muc", terms);
module:log("debug", "Broadcasting terms message to room %s", room);
room:broadcast_message(msg);
end
return true;
end
-- send the terms when joining:
function send_terms(event)
local function send_terms(event)
local origin = event.origin;
local room = event.room;
local occupant = event.occupant;
if global_terms then
module:log("debug", "Sending global terms to %s", occupant.jid);
local msg = create_terms_message(room, "global", global_terms);
msg.attr.to = occupant.jid;
origin.send(msg);
end
local muc_terms = get_muc_terms(room);
if muc_terms then
local from = room.jid .. '/' .. jid_escape(service_nickname);
module:log("debug", "Sending global terms to %s from %s (room %s)", occupant.jid, from, room);
local message = st.message({
type = "groupchat",
to = occupant.jid,
from = from,
id = id.medium()
}, global_terms)
:tag('x-livechat-terms', { type = "global" }):up(); -- adding a custom tag to specify that it is a "terms" message, so that frontend can display it with a special template.
origin.send(message);
module:log("debug", "Sending muc terms to %s", occupant.jid);
local msg = create_terms_message(room, "muc", muc_terms);
msg.attr.to = occupant.jid;
origin.send(msg);
end
end
-- Note: we could do that on muc-occupant-joined or muc-occupant-session-new.
@ -39,7 +80,7 @@ end
module:hook("muc-occupant-session-new", send_terms);
-- reserve the service_nickname:
function enforce_nick_policy(event)
local function enforce_nick_policy(event)
local origin, stanza = event.origin, event.stanza;
local requested_nick = jid_resource(stanza.attr.to);
local room = event.room;

View File

@ -119,6 +119,7 @@ async function initChannelConfiguration (options: RegisterServerOptions): Promis
// FIXME: this piece of code should not be in this file (nothing to do with initChannelConfiguration,
// but will be more efficient to add here, as we already tested hasChat).
// Note: no need to await here, would only degrade performances.
// FIXME: should also update livechat_muc_terms if channel has changed.
updateProsodyRoom(options, video.uuid, {
name: video.name
}).then(

View File

@ -64,6 +64,7 @@ async function updateProsodyRoom (
data: {
name?: string
slow_mode_duration?: number
livechat_muc_terms?: string
addAffiliations?: Affiliations
removeAffiliationsFor?: string[]
}
@ -92,6 +93,9 @@ async function updateProsodyRoom (
if (('slow_mode_duration' in data) && data.slow_mode_duration !== undefined) {
apiData.slow_mode_duration = data.slow_mode_duration
}
if ('livechat_muc_terms' in data) {
apiData.livechat_muc_terms = data.livechat_muc_terms ?? ''
}
if (('addAffiliations' in data) && data.addAffiliations !== undefined) {
apiData.addAffiliations = data.addAffiliations
}

View File

@ -246,7 +246,7 @@ class ProsodyConfigContent {
this.muc.add('modules_enabled', 'muc_peertubelivechat_terms')
this.muc.set('muc_terms_service_nickname', 'Peertube')
if (chatTerms) {
this.muc.set('muc_terms', new ConfigEntryValueMultiLineString(chatTerms))
this.muc.set('muc_terms_global', new ConfigEntryValueMultiLineString(chatTerms))
}
}

View File

@ -5,7 +5,7 @@
import type { RegisterServerOptions } from '@peertube/peertube-types'
import type { RoomConf } from 'xmppjs-chat-bot'
import { getProsodyDomain } from '../prosody/config/domain'
import { listProsodyRooms } from '../prosody/api/manage-rooms'
import { listProsodyRooms, updateProsodyRoom } from '../prosody/api/manage-rooms'
import { getChannelInfosById } from '../database/channel'
import { ChannelConfigurationOptions } from '../../../shared/lib/types'
import {
@ -292,10 +292,7 @@ class RoomChannel {
this.logger.info('Syncing...')
this.isWriting = true
// Note 2024-05-15: slow_mode_duration becomes a default value.
// We dont need prosodyRoomUpdates anymore. but keeping the code commented,
// if we want to enable again a similar sync.
// const prosodyRoomUpdates = new Map<string, Parameters<typeof updateProsodyRoom>[2]>()
const prosodyRoomUpdates = new Map<string, Parameters<typeof updateProsodyRoom>[2]>()
try {
const data = this._serializeData() // must be atomic
@ -355,12 +352,12 @@ class RoomChannel {
await BotConfiguration.singleton().updateRoom(roomJID, botConf)
// // Now we also must update some room metadata (slow mode duration, ...)
// // This can be done without waiting for the API call to finish, but we don't want to send thousands of
// // API calls at the same time. So storing data in a map, and we well launch it sequentially at the end
// prosodyRoomUpdates.set(roomJID, {
// slow_mode_duration: channelConfigurationOptions.slowMode.duration
// })
// Now we also must update some room metadata on Prosody side (livechat_muc_terms, ...)
// This can be done without waiting for the API call to finish, but we don't want to send thousands of
// API calls at the same time. So storing data in a map, and we well launch it sequentially at the end
prosodyRoomUpdates.set(roomJID, {
livechat_muc_terms: channelConfigurationOptions.terms
})
this.roomConfToUpdate.delete(roomJID)
}
@ -374,22 +371,22 @@ class RoomChannel {
this.isWriting = false
}
// if (prosodyRoomUpdates.size) {
// // Here we don't have to wait.
// // If it fails (for example because we are turning off prosody), it is not a big deal.
// // Does not worth the cost to wait.
// // eslint-disable-next-line @typescript-eslint/no-misused-promises
// setTimeout(async () => {
// this.logger.info('Syncing done, but still some data to send to Prosody')
// for (const [roomJID, data] of prosodyRoomUpdates.entries()) {
// try {
// await updateProsodyRoom(this.options, roomJID, data)
// } catch (err) {
// this.logger.error(`Failed updating prosody room info: "${err as string}".`)
// }
// }
// }, 0)
// }
if (prosodyRoomUpdates.size) {
// Here we don't have to wait.
// If it fails (for example because we are turning off prosody), it is not a big deal.
// Does not worth the cost to wait.
// eslint-disable-next-line @typescript-eslint/no-misused-promises
setTimeout(async () => {
this.logger.info('Syncing done, but still some data to send to Prosody')
for (const [roomJID, data] of prosodyRoomUpdates.entries()) {
try {
await updateProsodyRoom(this.options, roomJID, data)
} catch (err) {
this.logger.error(`Failed updating prosody room info: "${err as string}".`)
}
}
}, 0)
}
}
/**

View File

@ -37,6 +37,7 @@ interface RoomDefaults {
// Following fields are specific to livechat (for now), and requires a customized version for mod_muc_http_defaults.
slow_mode_duration?: number
mute_anonymous?: boolean
livechat_muc_terms?: string
}
affiliations?: Affiliations
}
@ -50,7 +51,8 @@ async function _getChannelSpecificOptions (
return {
slow_mode_duration: channelOptions.slowMode.duration,
mute_anonymous: channelOptions.mute.anonymous
mute_anonymous: channelOptions.mute.anonymous,
livechat_muc_terms: channelOptions.terms
}
}