Builtin Prosody: new settings to choose how long the room's content is archived, and if it should be archived by default.
This commit is contained in:
parent
e260f84584
commit
5e988605ce
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
* UI/UX improvements. Now using a custom ConverseJS build.
|
* UI/UX improvements. Now using a custom ConverseJS build.
|
||||||
* Auto color detection: when using ConverseJS, the plugin tries to guess colors to apply to its theme.
|
* Auto color detection: when using ConverseJS, the plugin tries to guess colors to apply to its theme.
|
||||||
|
* Builtin Prosody: new settings to choose how long the room's content is archived, and if it should be archived by default.
|
||||||
|
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
|
|
||||||
|
@ -208,6 +208,8 @@ function register ({ registerHook, registerSettingsScript, peertubeHelpers }: Re
|
|||||||
case 'chat-type-help-builtin-prosody':
|
case 'chat-type-help-builtin-prosody':
|
||||||
case 'prosody-list-rooms':
|
case 'prosody-list-rooms':
|
||||||
case 'prosody-advanced':
|
case 'prosody-advanced':
|
||||||
|
case 'prosody-muc-log-by-default':
|
||||||
|
case 'prosody-muc-expiration':
|
||||||
case 'prosody-c2s':
|
case 'prosody-c2s':
|
||||||
return options.formValues['chat-type'] !== ('builtin-prosody' as ChatType)
|
return options.formValues['chat-type'] !== ('builtin-prosody' as ChatType)
|
||||||
case 'prosody-c2s-port':
|
case 'prosody-c2s-port':
|
||||||
|
@ -36,6 +36,20 @@ export async function diagProsody (test: string, options: RegisterServerOptions)
|
|||||||
|
|
||||||
result.messages.push(`Prosody rooms will be grouped by '${wantedConfig.roomType}'.`)
|
result.messages.push(`Prosody rooms will be grouped by '${wantedConfig.roomType}'.`)
|
||||||
|
|
||||||
|
if (wantedConfig.logByDefault) {
|
||||||
|
result.messages.push('By default, room content will be archived.')
|
||||||
|
} else {
|
||||||
|
result.messages.push('By default, room content will not be archived.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('error' in wantedConfig.logExpiration) {
|
||||||
|
result.messages.push({
|
||||||
|
level: 'error',
|
||||||
|
message: 'Errors: Room logs expiration value is not valid. Using the default value.'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
result.messages.push(`Room content will be saved for '${wantedConfig.logExpiration.value}'`)
|
||||||
|
|
||||||
await fs.promises.access(filePath, fs.constants.R_OK) // throw an error if file does not exist.
|
await fs.promises.access(filePath, fs.constants.R_OK) // throw an error if file does not exist.
|
||||||
result.messages.push(`The prosody configuration file (${filePath}) exists`)
|
result.messages.push(`The prosody configuration file (${filePath}) exists`)
|
||||||
const actualContent = await fs.promises.readFile(filePath, {
|
const actualContent = await fs.promises.readFile(filePath, {
|
||||||
|
@ -2,7 +2,7 @@ import * as fs from 'fs'
|
|||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import { getBaseRouterRoute } from '../helpers'
|
import { getBaseRouterRoute } from '../helpers'
|
||||||
import { ProsodyFilePaths } from './config/paths'
|
import { ProsodyFilePaths } from './config/paths'
|
||||||
import { ProsodyConfigContent } from './config/content'
|
import { ConfigLogExpiration, ProsodyConfigContent } from './config/content'
|
||||||
import { getProsodyDomain } from './config/domain'
|
import { getProsodyDomain } from './config/domain'
|
||||||
import { getAPIKey } from '../apikey'
|
import { getAPIKey } from '../apikey'
|
||||||
import type { ProsodyLogLevel } from './config/content'
|
import type { ProsodyLogLevel } from './config/content'
|
||||||
@ -70,6 +70,8 @@ interface ProsodyConfig {
|
|||||||
port: string
|
port: string
|
||||||
baseApiUrl: string
|
baseApiUrl: string
|
||||||
roomType: 'video' | 'channel'
|
roomType: 'video' | 'channel'
|
||||||
|
logByDefault: boolean
|
||||||
|
logExpiration: ConfigLogExpiration
|
||||||
}
|
}
|
||||||
async function getProsodyConfig (options: RegisterServerOptions): Promise<ProsodyConfig> {
|
async function getProsodyConfig (options: RegisterServerOptions): Promise<ProsodyConfig> {
|
||||||
const logger = options.peertubeHelpers.logger
|
const logger = options.peertubeHelpers.logger
|
||||||
@ -79,6 +81,9 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise<Prosod
|
|||||||
if (!/^\d+$/.test(port)) {
|
if (!/^\d+$/.test(port)) {
|
||||||
throw new Error('Invalid port')
|
throw new Error('Invalid port')
|
||||||
}
|
}
|
||||||
|
const logByDefault = (await options.settingsManager.getSetting('prosody-muc-log-by-default') as boolean) ?? true
|
||||||
|
const logExpirationSetting =
|
||||||
|
(await options.settingsManager.getSetting('prosody-muc-expiration') as string) ?? DEFAULTLOGEXPIRATION
|
||||||
const enableC2s = (await options.settingsManager.getSetting('prosody-c2s') as boolean) || false
|
const enableC2s = (await options.settingsManager.getSetting('prosody-c2s') as boolean) || false
|
||||||
const prosodyDomain = await getProsodyDomain(options)
|
const prosodyDomain = await getProsodyDomain(options)
|
||||||
const paths = await getProsodyFilePaths(options)
|
const paths = await getProsodyFilePaths(options)
|
||||||
@ -111,8 +116,8 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise<Prosod
|
|||||||
config.useC2S(c2sPort)
|
config.useC2S(c2sPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add a settings so that admin can choose? (on/off and duration)
|
const logExpiration = readLogExpiration(options, logExpirationSetting)
|
||||||
config.useMam('1w') // Remove archived messages after 1 week
|
config.useMam(logByDefault, logExpiration)
|
||||||
// TODO: add a settings to choose?
|
// TODO: add a settings to choose?
|
||||||
config.useDefaultPersistent()
|
config.useDefaultPersistent()
|
||||||
|
|
||||||
@ -142,7 +147,9 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise<Prosod
|
|||||||
port,
|
port,
|
||||||
baseApiUrl,
|
baseApiUrl,
|
||||||
host: prosodyDomain,
|
host: prosodyDomain,
|
||||||
roomType
|
roomType,
|
||||||
|
logByDefault,
|
||||||
|
logExpiration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +171,57 @@ async function writeProsodyConfig (options: RegisterServerOptions): Promise<Pros
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULTLOGEXPIRATION = '1w'
|
||||||
|
const DEFAULTLOGEXPIRATIONTYPE = 'period'
|
||||||
|
function readLogExpiration (options: RegisterServerOptions, logExpiration: string): ConfigLogExpiration {
|
||||||
|
const logger = options.peertubeHelpers.logger
|
||||||
|
logExpiration = logExpiration?.trim()
|
||||||
|
if (logExpiration === 'never') {
|
||||||
|
return {
|
||||||
|
value: 'never',
|
||||||
|
type: 'never'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (/^\d+$/.test(logExpiration)) {
|
||||||
|
if (logExpiration === '0') {
|
||||||
|
logger.error('Invalid prosody-muc-expiration value, cannot be 0.')
|
||||||
|
return {
|
||||||
|
value: DEFAULTLOGEXPIRATION,
|
||||||
|
type: DEFAULTLOGEXPIRATIONTYPE,
|
||||||
|
error: '0 is not an acceptable value.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
value: logExpiration,
|
||||||
|
type: 'seconds',
|
||||||
|
seconds: parseInt(logExpiration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const matches = logExpiration.match(/^(\d+)([d|w|m|y])$/)
|
||||||
|
if (matches) {
|
||||||
|
const d = matches[1]
|
||||||
|
if (d === '0') {
|
||||||
|
logger.error(`Invalid prosody-muc-expiration value, cannot be ${logExpiration}.`)
|
||||||
|
return {
|
||||||
|
value: DEFAULTLOGEXPIRATION,
|
||||||
|
type: DEFAULTLOGEXPIRATIONTYPE,
|
||||||
|
error: '0 is not an acceptable value.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
value: logExpiration,
|
||||||
|
type: 'period'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.error(`Invalid prosody-muc-expiration value '${logExpiration}'.`)
|
||||||
|
return {
|
||||||
|
value: DEFAULTLOGEXPIRATION,
|
||||||
|
type: DEFAULTLOGEXPIRATIONTYPE,
|
||||||
|
error: `Invalid value '${logExpiration}'.`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getProsodyConfig,
|
getProsodyConfig,
|
||||||
getWorkingDir,
|
getWorkingDir,
|
||||||
|
@ -4,6 +4,27 @@ type ConfigEntryValue = boolean | number | string | ConfigEntryValue[]
|
|||||||
|
|
||||||
type ConfigEntries = Map<string, ConfigEntryValue>
|
type ConfigEntries = Map<string, ConfigEntryValue>
|
||||||
|
|
||||||
|
interface ConfigLogExpirationNever {
|
||||||
|
value: 'never'
|
||||||
|
type: 'never'
|
||||||
|
}
|
||||||
|
interface ConfigLogExpirationSeconds {
|
||||||
|
value: string
|
||||||
|
seconds: number
|
||||||
|
type: 'seconds'
|
||||||
|
}
|
||||||
|
interface ConfigLogExpirationPeriod {
|
||||||
|
value: string
|
||||||
|
type: 'period'
|
||||||
|
}
|
||||||
|
interface ConfigLogExpirationError {
|
||||||
|
value: string
|
||||||
|
error: string
|
||||||
|
type: 'period'
|
||||||
|
}
|
||||||
|
type ConfigLogExpiration =
|
||||||
|
ConfigLogExpirationNever | ConfigLogExpirationPeriod | ConfigLogExpirationSeconds | ConfigLogExpirationError
|
||||||
|
|
||||||
function writeValue (value: ConfigEntryValue): string {
|
function writeValue (value: ConfigEntryValue): string {
|
||||||
if (typeof value === 'boolean') {
|
if (typeof value === 'boolean') {
|
||||||
return value.toString() + ';\n'
|
return value.toString() + ';\n'
|
||||||
@ -218,16 +239,23 @@ class ProsodyConfigContent {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Calling this method makes Prosody use mod_muc_mam to store rooms history.
|
* Calling this method makes Prosody use mod_muc_mam to store rooms history.
|
||||||
* @param duration: how long the server must store messages. See https://prosody.im/doc/modules/mod_muc_mam
|
* @param logByDefault: if the room content should be archived by default.
|
||||||
|
* @param logExpiration: how long the server must store messages. See https://prosody.im/doc/modules/mod_muc_mam
|
||||||
*/
|
*/
|
||||||
useMam (duration: string): void {
|
useMam (logByDefault: boolean, logExpiration: ConfigLogExpiration): void {
|
||||||
this.muc.add('modules_enabled', 'muc_mam')
|
this.muc.add('modules_enabled', 'muc_mam')
|
||||||
|
|
||||||
this.muc.set('muc_log_by_default', true)
|
this.muc.set('muc_log_by_default', !!logByDefault)
|
||||||
this.muc.set('muc_log_presences', true)
|
this.muc.set('muc_log_presences', true)
|
||||||
this.muc.set('log_all_rooms', true)
|
this.muc.set('log_all_rooms', false)
|
||||||
this.muc.set('muc_log_expires_after', duration)
|
this.muc.set('muc_log_expires_after', logExpiration.value)
|
||||||
this.muc.set('muc_log_cleanup_interval', 4 * 60 * 60)
|
const defaultCleanupInterval = 4 * 60 * 60
|
||||||
|
if (logExpiration.type === 'seconds' && logExpiration.seconds && logExpiration.seconds < defaultCleanupInterval) {
|
||||||
|
// if the log expiration is less than the default cleanup interval, we have to decrease it.
|
||||||
|
this.muc.set('muc_log_cleanup_interval', logExpiration.seconds)
|
||||||
|
} else {
|
||||||
|
this.muc.set('muc_log_cleanup_interval', defaultCleanupInterval)
|
||||||
|
}
|
||||||
|
|
||||||
// We can also use mod_muc_moderation
|
// We can also use mod_muc_moderation
|
||||||
// NB: for now Prosody has a partial support of this feature with «internal» storage.
|
// NB: for now Prosody has a partial support of this feature with «internal» storage.
|
||||||
@ -287,5 +315,6 @@ class ProsodyConfigContent {
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
ProsodyLogLevel,
|
ProsodyLogLevel,
|
||||||
ProsodyConfigContent
|
ProsodyConfigContent,
|
||||||
|
ConfigLogExpiration
|
||||||
}
|
}
|
||||||
|
@ -327,6 +327,38 @@ In some rare case, Prosody can't call Peertube's API from its public URI.
|
|||||||
You can use this field to customise Peertube's URI for Prosody modules (for example with «http://localhost:9000»).`
|
You can use this field to customise Peertube's URI for Prosody modules (for example with «http://localhost:9000»).`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
registerSetting({
|
||||||
|
name: 'prosody-muc-log-by-default',
|
||||||
|
label: 'Log rooms content by default',
|
||||||
|
type: 'input-checkbox',
|
||||||
|
default: true,
|
||||||
|
private: true,
|
||||||
|
descriptionHTML:
|
||||||
|
`If checked, room contents will be saved by default.
|
||||||
|
Any user that join a room will we what was written before he joins.<br>
|
||||||
|
Please note that it is always possible to enable/disable the content
|
||||||
|
archiving for a specific room, by editing its properties.
|
||||||
|
`
|
||||||
|
})
|
||||||
|
|
||||||
|
registerSetting({
|
||||||
|
name: 'prosody-muc-expiration',
|
||||||
|
label: 'Room logs expiration',
|
||||||
|
type: 'input',
|
||||||
|
default: '1w',
|
||||||
|
private: true,
|
||||||
|
descriptionHTML:
|
||||||
|
`You can choose here how long the chatting room's content is kept by the server. The value can be:
|
||||||
|
<ul>
|
||||||
|
<li><b>60</b>: the content will be saved for 60 <b>seconds</b>. You can replace 60 by any integer value.</li>
|
||||||
|
<li><b>1d</b>: the content will be saved for 1 <b>day</b>. You can replace 1 by any integer value.</li>
|
||||||
|
<li><b>1w</b>: the content will be saved for 1 <b>week</b>. You can replace 1 by any integer value.</li>
|
||||||
|
<li><b>1m</b>: the content will be saved for 1 <b>month</b>. You can replace 1 by any integer value.</li>
|
||||||
|
<li><b>1y</b>: the content will be saved for 1 <b>year</b>. You can replace 1 by any integer value.</li>
|
||||||
|
<li><b>never</b>: the content will never expire, and will be kept forever.</li>
|
||||||
|
</ul>`
|
||||||
|
})
|
||||||
|
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: 'prosody-c2s',
|
name: 'prosody-c2s',
|
||||||
label: 'Enable client to server connections',
|
label: 'Enable client to server connections',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user