Bots settings (WIP).
This commit is contained in:
parent
7bb444af2c
commit
62456aead1
@ -211,6 +211,7 @@ function register ({ registerHook, registerSettingsScript, peertubeHelpers }: Re
|
|||||||
case 'prosody-muc-log-by-default':
|
case 'prosody-muc-log-by-default':
|
||||||
case 'prosody-muc-expiration':
|
case 'prosody-muc-expiration':
|
||||||
case 'prosody-c2s':
|
case 'prosody-c2s':
|
||||||
|
case 'prosody-component-port':
|
||||||
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':
|
||||||
return !(
|
return !(
|
||||||
|
@ -3,15 +3,28 @@ For internal API, we will generate an api Key that must be provided as
|
|||||||
GET parameter for every API call.
|
GET parameter for every API call.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
async function getAPIKey ({ storageManager }: RegisterServerOptions): Promise<string> {
|
async function _getKey ({ storageManager }: RegisterServerOptions, key: string): Promise<string> {
|
||||||
let value: string = await storageManager.getData('APIKEY')
|
let value: string = await storageManager.getData(key)
|
||||||
if (!value) {
|
if (!value) {
|
||||||
value = Math.random().toString(36).slice(2, 12)
|
value = Math.random().toString(36).slice(2, 12)
|
||||||
await storageManager.storeData('APIKEY', value)
|
await storageManager.storeData(key, value)
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
async function getAPIKey (options: RegisterServerOptions): Promise<string> {
|
||||||
getAPIKey
|
return _getKey(options, 'APIKEY')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getExternalComponentKey (options: RegisterServerOptions, componentName: string): Promise<string> {
|
||||||
|
if (!/^[A-Z]+$/.test(componentName)) {
|
||||||
|
throw new Error('Invalid component name: ' + componentName)
|
||||||
|
}
|
||||||
|
const key = 'EXTERNALCOMPONENTKEY_' + componentName
|
||||||
|
return _getKey(options, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getAPIKey,
|
||||||
|
getExternalComponentKey
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,10 @@ export async function diagProsody (test: string, options: RegisterServerOptions)
|
|||||||
}
|
}
|
||||||
result.messages.push(`Room content will be saved for '${wantedConfig.logExpiration.value}'`)
|
result.messages.push(`Room content will be saved for '${wantedConfig.logExpiration.value}'`)
|
||||||
|
|
||||||
|
if (wantedConfig.bots.demo) {
|
||||||
|
result.messages.push(`The Demo bot is active for videos: ${wantedConfig.bots.demo.join(', ')}`)
|
||||||
|
}
|
||||||
|
|
||||||
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, {
|
||||||
|
@ -4,8 +4,9 @@ import { getBaseRouterRoute } from '../helpers'
|
|||||||
import { ProsodyFilePaths } from './config/paths'
|
import { ProsodyFilePaths } from './config/paths'
|
||||||
import { ConfigLogExpiration, 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, getExternalComponentKey } from '../apikey'
|
||||||
import type { ProsodyLogLevel } from './config/content'
|
import type { ProsodyLogLevel } from './config/content'
|
||||||
|
import { parseConfigDemoBotUUIDs } from './config/bots'
|
||||||
|
|
||||||
async function getWorkingDir (options: RegisterServerOptions): Promise<string> {
|
async function getWorkingDir (options: RegisterServerOptions): Promise<string> {
|
||||||
const peertubeHelpers = options.peertubeHelpers
|
const peertubeHelpers = options.peertubeHelpers
|
||||||
@ -63,6 +64,9 @@ async function getProsodyFilePaths (options: RegisterServerOptions): Promise<Pro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ProsodyConfigBots {
|
||||||
|
demo?: string[] // if the demo bot is activated, here are the video UUIDS where it will be.
|
||||||
|
}
|
||||||
interface ProsodyConfig {
|
interface ProsodyConfig {
|
||||||
content: string
|
content: string
|
||||||
paths: ProsodyFilePaths
|
paths: ProsodyFilePaths
|
||||||
@ -72,25 +76,40 @@ interface ProsodyConfig {
|
|||||||
roomType: 'video' | 'channel'
|
roomType: 'video' | 'channel'
|
||||||
logByDefault: boolean
|
logByDefault: boolean
|
||||||
logExpiration: ConfigLogExpiration
|
logExpiration: ConfigLogExpiration
|
||||||
|
bots: ProsodyConfigBots
|
||||||
}
|
}
|
||||||
async function getProsodyConfig (options: RegisterServerOptions): Promise<ProsodyConfig> {
|
async function getProsodyConfig (options: RegisterServerOptions): Promise<ProsodyConfig> {
|
||||||
const logger = options.peertubeHelpers.logger
|
const logger = options.peertubeHelpers.logger
|
||||||
logger.debug('Calling getProsodyConfig')
|
logger.debug('Calling getProsodyConfig')
|
||||||
|
|
||||||
const port = (await options.settingsManager.getSetting('prosody-port') as string) || '52800'
|
let useExternalComponents = false
|
||||||
|
const bots: ProsodyConfigBots = {}
|
||||||
|
|
||||||
|
const settings = await options.settingsManager.getSettings([
|
||||||
|
'prosody-port',
|
||||||
|
'prosody-muc-log-by-default',
|
||||||
|
'prosody-muc-expiration',
|
||||||
|
'prosody-c2s',
|
||||||
|
'prosody-room-type',
|
||||||
|
'prosody-peertube-uri',
|
||||||
|
'prosody-c2s-port',
|
||||||
|
'prosody-component-port',
|
||||||
|
'chat-videos-list'
|
||||||
|
])
|
||||||
|
|
||||||
|
const port = (settings['prosody-port'] as string) || '52800'
|
||||||
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 logByDefault = (settings['prosody-muc-log-by-default'] as boolean) ?? true
|
||||||
const logExpirationSetting =
|
const logExpirationSetting = (settings['prosody-muc-expiration'] as string) ?? DEFAULTLOGEXPIRATION
|
||||||
(await options.settingsManager.getSetting('prosody-muc-expiration') as string) ?? DEFAULTLOGEXPIRATION
|
const enableC2s = (settings['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)
|
||||||
const roomType = (await options.settingsManager.getSetting('prosody-room-type')) === 'channel' ? 'channel' : 'video'
|
const roomType = (settings['prosody-room-type']) === 'channel' ? 'channel' : 'video'
|
||||||
|
|
||||||
const apikey = await getAPIKey(options)
|
const apikey = await getAPIKey(options)
|
||||||
let baseApiUrl = await options.settingsManager.getSetting('prosody-peertube-uri') as string
|
let baseApiUrl = settings['prosody-peertube-uri'] as string
|
||||||
if (baseApiUrl && !/^https?:\/\/[a-z0-9.-_]+(?::\d+)?$/.test(baseApiUrl)) {
|
if (baseApiUrl && !/^https?:\/\/[a-z0-9.-_]+(?::\d+)?$/.test(baseApiUrl)) {
|
||||||
throw new Error('Invalid prosody-peertube-uri')
|
throw new Error('Invalid prosody-peertube-uri')
|
||||||
}
|
}
|
||||||
@ -109,7 +128,7 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise<Prosod
|
|||||||
config.useMucHttpDefault(roomApiUrl)
|
config.useMucHttpDefault(roomApiUrl)
|
||||||
|
|
||||||
if (enableC2s) {
|
if (enableC2s) {
|
||||||
const c2sPort = (await options.settingsManager.getSetting('prosody-c2s-port') as string) || '52822'
|
const c2sPort = (settings['prosody-c2s-port'] as string) || '52822'
|
||||||
if (!/^\d+$/.test(c2sPort)) {
|
if (!/^\d+$/.test(c2sPort)) {
|
||||||
throw new Error('Invalid c2s port')
|
throw new Error('Invalid c2s port')
|
||||||
}
|
}
|
||||||
@ -139,6 +158,22 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise<Prosod
|
|||||||
logLevel = 'info'
|
logLevel = 'info'
|
||||||
}
|
}
|
||||||
config.setLog(logLevel)
|
config.setLog(logLevel)
|
||||||
|
|
||||||
|
const demoBotUUIDs = parseConfigDemoBotUUIDs((settings['chat-videos-list'] as string) || '')
|
||||||
|
if (demoBotUUIDs?.length > 0) {
|
||||||
|
useExternalComponents = true
|
||||||
|
config.useDemoBot(await getExternalComponentKey(options, 'DEMOBOT'))
|
||||||
|
bots.demo = demoBotUUIDs
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useExternalComponents) {
|
||||||
|
const externalComponentsPort = (settings['prosody-component-port'] as string) || '53470'
|
||||||
|
if (!/^\d+$/.test(externalComponentsPort)) {
|
||||||
|
throw new Error('Invalid external components port')
|
||||||
|
}
|
||||||
|
config.useExternalComponents(externalComponentsPort)
|
||||||
|
}
|
||||||
|
|
||||||
const content = config.write()
|
const content = config.write()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -149,7 +184,8 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise<Prosod
|
|||||||
host: prosodyDomain,
|
host: prosodyDomain,
|
||||||
roomType,
|
roomType,
|
||||||
logByDefault,
|
logByDefault,
|
||||||
logExpiration
|
logExpiration,
|
||||||
|
bots
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
server/lib/prosody/config/bots.ts
Normal file
19
server/lib/prosody/config/bots.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
function parseConfigDemoBotUUIDs (s: string): string[] {
|
||||||
|
if (!s) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
let a = s.split('\n')
|
||||||
|
// find lines that are like:
|
||||||
|
// 6432f147-83c7-4fa3-b3b5-e49c2590e825 #!demobot
|
||||||
|
a = a.filter(line => /#!demobot\b/.test(line))
|
||||||
|
a = a.map(line => {
|
||||||
|
return line.replace(/#.*$/, '')
|
||||||
|
.replace(/^\s+/, '')
|
||||||
|
.replace(/\s+$/, '')
|
||||||
|
})
|
||||||
|
return a.filter(line => line !== '')
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
parseConfigDemoBotUUIDs
|
||||||
|
}
|
@ -102,16 +102,19 @@ class ProsodyConfigVirtualHost extends ProsodyConfigBlock {
|
|||||||
|
|
||||||
class ProsodyConfigComponent extends ProsodyConfigBlock {
|
class ProsodyConfigComponent extends ProsodyConfigBlock {
|
||||||
name: string
|
name: string
|
||||||
type: string
|
type?: string
|
||||||
|
|
||||||
constructor (type: string, name: string) {
|
constructor (name: string, type?: string) {
|
||||||
super(' ')
|
super(' ')
|
||||||
this.type = type
|
this.type = type
|
||||||
this.name = name
|
this.name = name
|
||||||
}
|
}
|
||||||
|
|
||||||
write (): string {
|
write (): string {
|
||||||
return `Component "${this.name}" "${this.type}"\n` + super.write()
|
if (this.type !== undefined) {
|
||||||
|
return `Component "${this.name}" "${this.type}"\n` + super.write()
|
||||||
|
}
|
||||||
|
return `Component "${this.name}"\n` + super.write()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +126,7 @@ class ProsodyConfigContent {
|
|||||||
authenticated?: ProsodyConfigVirtualHost
|
authenticated?: ProsodyConfigVirtualHost
|
||||||
anon: ProsodyConfigVirtualHost
|
anon: ProsodyConfigVirtualHost
|
||||||
muc: ProsodyConfigComponent
|
muc: ProsodyConfigComponent
|
||||||
|
externalComponents: ProsodyConfigComponent[] = []
|
||||||
log: string
|
log: string
|
||||||
prosodyDomain: string
|
prosodyDomain: string
|
||||||
|
|
||||||
@ -132,7 +136,7 @@ class ProsodyConfigContent {
|
|||||||
this.log = ''
|
this.log = ''
|
||||||
this.prosodyDomain = prosodyDomain
|
this.prosodyDomain = prosodyDomain
|
||||||
this.anon = new ProsodyConfigVirtualHost('anon.' + prosodyDomain)
|
this.anon = new ProsodyConfigVirtualHost('anon.' + prosodyDomain)
|
||||||
this.muc = new ProsodyConfigComponent('muc', 'room.' + prosodyDomain)
|
this.muc = new ProsodyConfigComponent('room.' + prosodyDomain, 'muc')
|
||||||
|
|
||||||
this.global.set('daemonize', false)
|
this.global.set('daemonize', false)
|
||||||
this.global.set('allow_registration', false)
|
this.global.set('allow_registration', false)
|
||||||
@ -281,6 +285,21 @@ class ProsodyConfigContent {
|
|||||||
this.muc.set('peertubelivechat_test_peertube_api_url', apiurl)
|
this.muc.set('peertubelivechat_test_peertube_api_url', apiurl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useExternalComponents (componentsPort: string): void {
|
||||||
|
this.global.set('component_ports', [componentsPort])
|
||||||
|
this.global.set('component_interfaces', ['127.0.0.1', '::1'])
|
||||||
|
}
|
||||||
|
|
||||||
|
useDemoBot (componentSecret: string): void {
|
||||||
|
const demoBot = new ProsodyConfigComponent('demobot.' + this.prosodyDomain)
|
||||||
|
demoBot.set('component_secret', componentSecret)
|
||||||
|
|
||||||
|
// If we want the bot to be moderator, should do the trick:
|
||||||
|
// this.global.add('admins', 'demobot.' + this.prosodyDomain)
|
||||||
|
|
||||||
|
this.externalComponents.push(demoBot)
|
||||||
|
}
|
||||||
|
|
||||||
setLog (level: ProsodyLogLevel, syslog?: ProsodyLogLevel[]): void {
|
setLog (level: ProsodyLogLevel, syslog?: ProsodyLogLevel[]): void {
|
||||||
let log = ''
|
let log = ''
|
||||||
log += 'log = {\n'
|
log += 'log = {\n'
|
||||||
@ -309,6 +328,11 @@ class ProsodyConfigContent {
|
|||||||
content += '\n\n'
|
content += '\n\n'
|
||||||
content += this.muc.write()
|
content += this.muc.write()
|
||||||
content += '\n\n'
|
content += '\n\n'
|
||||||
|
this.externalComponents.forEach((externalComponent) => {
|
||||||
|
content += '\n\n'
|
||||||
|
content += externalComponent.write()
|
||||||
|
content += '\n\n'
|
||||||
|
})
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,6 +359,22 @@ archiving for a specific room, by editing its properties.
|
|||||||
</ul>`
|
</ul>`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
registerSetting({
|
||||||
|
name: 'prosody-component-port',
|
||||||
|
label: 'The port to be use for external components',
|
||||||
|
type: 'input',
|
||||||
|
default: '53470',
|
||||||
|
private: true,
|
||||||
|
descriptionHTML:
|
||||||
|
`The port that will be used for extra components used by the builtin Prosody server.<br>
|
||||||
|
This is only used when one of these special features is used:<br>
|
||||||
|
<ul>
|
||||||
|
<li>Demo bot: this is a hidden feature, for demonstration purposes. See the documentation for more information.</li>
|
||||||
|
</ul><br>
|
||||||
|
Change it if this port is already in use on your server.
|
||||||
|
`
|
||||||
|
})
|
||||||
|
|
||||||
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