2021-04-12 18:52:21 +00:00
|
|
|
import * as fs from 'fs'
|
2021-04-13 15:13:41 +00:00
|
|
|
import * as path from 'path'
|
2021-06-02 10:41:28 +00:00
|
|
|
import { getBaseRouterRoute } from '../helpers'
|
2021-04-30 14:22:58 +00:00
|
|
|
import { ProsodyFilePaths } from './config/paths'
|
2021-12-01 11:57:15 +00:00
|
|
|
import { ConfigLogExpiration, ProsodyConfigContent } from './config/content'
|
2021-05-06 11:31:55 +00:00
|
|
|
import { getProsodyDomain } from './config/domain'
|
2021-12-07 09:29:20 +00:00
|
|
|
import { getAPIKey, getExternalComponentKey } from '../apikey'
|
2021-05-12 09:48:38 +00:00
|
|
|
import type { ProsodyLogLevel } from './config/content'
|
2021-12-07 09:29:20 +00:00
|
|
|
import { parseConfigDemoBotUUIDs } from './config/bots'
|
2021-04-12 18:52:21 +00:00
|
|
|
|
2021-06-02 10:41:28 +00:00
|
|
|
async function getWorkingDir (options: RegisterServerOptions): Promise<string> {
|
2021-05-11 13:37:34 +00:00
|
|
|
const peertubeHelpers = options.peertubeHelpers
|
|
|
|
const logger = peertubeHelpers.logger
|
|
|
|
logger.debug('Calling getWorkingDir')
|
|
|
|
|
2021-06-02 13:48:56 +00:00
|
|
|
if (!peertubeHelpers.plugin) {
|
|
|
|
throw new Error('Missing peertubeHelpers.plugin, have you the correct Peertube version?')
|
2021-05-11 13:37:34 +00:00
|
|
|
}
|
2021-06-02 10:41:28 +00:00
|
|
|
const dir = path.resolve(peertubeHelpers.plugin.getDataDirectoryPath(), 'prosody')
|
|
|
|
logger.debug('getWorkingDir will return the dir ' + dir)
|
|
|
|
return dir
|
2021-05-11 13:37:34 +00:00
|
|
|
}
|
|
|
|
|
2021-04-14 15:10:22 +00:00
|
|
|
/**
|
|
|
|
* Creates the working dir if needed, and returns it.
|
|
|
|
*/
|
|
|
|
async function ensureWorkingDir (options: RegisterServerOptions): Promise<string> {
|
|
|
|
const logger = options.peertubeHelpers.logger
|
|
|
|
logger.debug('Calling ensureworkingDir')
|
|
|
|
|
2021-04-16 12:26:21 +00:00
|
|
|
const paths = await getProsodyFilePaths(options)
|
|
|
|
const dir = paths.dir
|
2021-04-14 15:10:22 +00:00
|
|
|
if (!fs.existsSync(dir)) {
|
|
|
|
logger.info(`The working dir ${dir} does not exists, trying to create it`)
|
|
|
|
await fs.promises.mkdir(dir)
|
|
|
|
logger.debug(`Working dir ${dir} was created`)
|
2021-04-12 18:52:21 +00:00
|
|
|
}
|
2021-04-14 15:10:22 +00:00
|
|
|
logger.debug(`Testing write access on ${dir}`)
|
|
|
|
await fs.promises.access(dir, fs.constants.W_OK) // will throw an error if no access
|
|
|
|
logger.debug(`Write access ok on ${dir}`)
|
2021-04-16 12:26:21 +00:00
|
|
|
|
|
|
|
if (!fs.existsSync(paths.data)) {
|
|
|
|
logger.info(`The data dir ${paths.data} does not exists, trying to create it`)
|
|
|
|
await fs.promises.mkdir(paths.data)
|
|
|
|
logger.debug(`Working dir ${paths.data} was created`)
|
|
|
|
}
|
|
|
|
|
2021-04-14 15:10:22 +00:00
|
|
|
return dir
|
2021-04-12 18:52:21 +00:00
|
|
|
}
|
|
|
|
|
2021-04-13 15:13:41 +00:00
|
|
|
async function getProsodyFilePaths (options: RegisterServerOptions): Promise<ProsodyFilePaths> {
|
2021-04-14 15:10:22 +00:00
|
|
|
const logger = options.peertubeHelpers.logger
|
|
|
|
logger.debug('Calling getProsodyFilePaths')
|
|
|
|
|
2021-06-02 10:41:28 +00:00
|
|
|
const dir = await getWorkingDir(options)
|
2021-04-13 15:13:41 +00:00
|
|
|
return {
|
2021-04-14 13:26:00 +00:00
|
|
|
dir: dir,
|
2021-04-13 15:13:41 +00:00
|
|
|
pid: path.resolve(dir, 'prosody.pid'),
|
|
|
|
error: path.resolve(dir, 'prosody.err'),
|
|
|
|
log: path.resolve(dir, 'prosody.log'),
|
2021-04-16 12:26:21 +00:00
|
|
|
config: path.resolve(dir, 'prosody.cfg.lua'),
|
2021-04-29 14:50:30 +00:00
|
|
|
data: path.resolve(dir, 'data'),
|
|
|
|
modules: path.resolve(__dirname, '../../prosody-modules')
|
2021-04-13 15:13:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-07 09:29:20 +00:00
|
|
|
interface ProsodyConfigBots {
|
|
|
|
demo?: string[] // if the demo bot is activated, here are the video UUIDS where it will be.
|
|
|
|
}
|
2021-04-15 10:17:08 +00:00
|
|
|
interface ProsodyConfig {
|
|
|
|
content: string
|
|
|
|
paths: ProsodyFilePaths
|
2021-07-20 00:52:58 +00:00
|
|
|
host: string
|
2021-04-15 10:17:08 +00:00
|
|
|
port: string
|
2021-06-22 11:23:01 +00:00
|
|
|
baseApiUrl: string
|
2021-08-05 13:41:49 +00:00
|
|
|
roomType: 'video' | 'channel'
|
2021-12-01 11:57:15 +00:00
|
|
|
logByDefault: boolean
|
|
|
|
logExpiration: ConfigLogExpiration
|
2021-12-07 09:29:20 +00:00
|
|
|
bots: ProsodyConfigBots
|
2021-04-15 10:17:08 +00:00
|
|
|
}
|
|
|
|
async function getProsodyConfig (options: RegisterServerOptions): Promise<ProsodyConfig> {
|
2021-04-14 15:10:22 +00:00
|
|
|
const logger = options.peertubeHelpers.logger
|
2021-04-15 10:17:08 +00:00
|
|
|
logger.debug('Calling getProsodyConfig')
|
2021-04-14 15:10:22 +00:00
|
|
|
|
2021-12-07 09:29:20 +00:00
|
|
|
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'
|
2021-04-16 13:13:46 +00:00
|
|
|
if (!/^\d+$/.test(port)) {
|
|
|
|
throw new Error('Invalid port')
|
|
|
|
}
|
2021-12-07 09:29:20 +00:00
|
|
|
const logByDefault = (settings['prosody-muc-log-by-default'] as boolean) ?? true
|
|
|
|
const logExpirationSetting = (settings['prosody-muc-expiration'] as string) ?? DEFAULTLOGEXPIRATION
|
|
|
|
const enableC2s = (settings['prosody-c2s'] as boolean) || false
|
2021-05-06 11:31:55 +00:00
|
|
|
const prosodyDomain = await getProsodyDomain(options)
|
2021-04-13 15:13:41 +00:00
|
|
|
const paths = await getProsodyFilePaths(options)
|
2021-12-07 09:29:20 +00:00
|
|
|
const roomType = (settings['prosody-room-type']) === 'channel' ? 'channel' : 'video'
|
2021-04-12 18:52:21 +00:00
|
|
|
|
2021-05-05 15:06:19 +00:00
|
|
|
const apikey = await getAPIKey(options)
|
2021-12-07 09:29:20 +00:00
|
|
|
let baseApiUrl = settings['prosody-peertube-uri'] as string
|
2021-06-22 11:23:01 +00:00
|
|
|
if (baseApiUrl && !/^https?:\/\/[a-z0-9.-_]+(?::\d+)?$/.test(baseApiUrl)) {
|
|
|
|
throw new Error('Invalid prosody-peertube-uri')
|
|
|
|
}
|
|
|
|
if (!baseApiUrl) {
|
|
|
|
baseApiUrl = options.peertubeHelpers.config.getWebserverUrl()
|
|
|
|
}
|
|
|
|
baseApiUrl += getBaseRouterRoute(options) + 'api/'
|
|
|
|
|
2021-05-05 15:06:19 +00:00
|
|
|
const authApiUrl = baseApiUrl + 'user' // FIXME: should be protected by apikey, but mod_auth_http cant handle params
|
|
|
|
const roomApiUrl = baseApiUrl + 'room?apikey=' + apikey + '&jid={room.jid|jid_node}'
|
2021-06-22 10:57:24 +00:00
|
|
|
const testApiUrl = baseApiUrl + 'test?apikey=' + apikey
|
2021-04-12 18:52:21 +00:00
|
|
|
|
2021-05-06 11:31:55 +00:00
|
|
|
const config = new ProsodyConfigContent(paths, prosodyDomain)
|
2021-05-03 18:37:23 +00:00
|
|
|
config.useHttpAuthentication(authApiUrl)
|
2021-05-06 11:31:55 +00:00
|
|
|
config.usePeertubeBosh(prosodyDomain, port)
|
2021-04-30 14:22:58 +00:00
|
|
|
config.useMucHttpDefault(roomApiUrl)
|
2021-06-02 10:41:28 +00:00
|
|
|
|
2021-07-14 16:46:08 +00:00
|
|
|
if (enableC2s) {
|
2021-12-07 09:29:20 +00:00
|
|
|
const c2sPort = (settings['prosody-c2s-port'] as string) || '52822'
|
2021-07-14 16:46:08 +00:00
|
|
|
if (!/^\d+$/.test(c2sPort)) {
|
|
|
|
throw new Error('Invalid c2s port')
|
|
|
|
}
|
|
|
|
config.useC2S(c2sPort)
|
|
|
|
}
|
|
|
|
|
2021-12-01 11:57:15 +00:00
|
|
|
const logExpiration = readLogExpiration(options, logExpirationSetting)
|
|
|
|
config.useMam(logByDefault, logExpiration)
|
2021-06-02 10:41:28 +00:00
|
|
|
// TODO: add a settings to choose?
|
|
|
|
config.useDefaultPersistent()
|
|
|
|
|
2021-06-12 01:52:45 +00:00
|
|
|
config.useListRoomsApi(apikey)
|
|
|
|
|
2021-06-22 10:57:24 +00:00
|
|
|
config.useTestModule(apikey, testApiUrl)
|
2021-06-22 08:26:45 +00:00
|
|
|
|
2021-05-12 09:48:38 +00:00
|
|
|
let logLevel: ProsodyLogLevel | undefined
|
|
|
|
if (logger.level && (typeof logger.level === 'string')) {
|
|
|
|
if (logger.level === 'error' || logger.level === 'info' || logger.level === 'debug') {
|
|
|
|
logLevel = logger.level
|
|
|
|
} else if (logger.level === 'warn' || logger.level === 'warning') {
|
|
|
|
// Should be 'warn', but just in case... (this value was buggy with peertube <= 3.2.0-rc1)
|
|
|
|
logLevel = 'warn'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (logLevel === undefined) {
|
|
|
|
logger.info('No log level found in Peertube, will use default "info" for Prosody')
|
|
|
|
logLevel = 'info'
|
|
|
|
}
|
|
|
|
config.setLog(logLevel)
|
2021-12-07 09:29:20 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2021-04-30 14:22:58 +00:00
|
|
|
const content = config.write()
|
2021-04-29 14:50:30 +00:00
|
|
|
|
2021-04-15 10:17:08 +00:00
|
|
|
return {
|
|
|
|
content,
|
|
|
|
paths,
|
2021-06-22 11:23:01 +00:00
|
|
|
port,
|
2021-07-20 00:52:58 +00:00
|
|
|
baseApiUrl,
|
2021-08-05 13:41:49 +00:00
|
|
|
host: prosodyDomain,
|
2021-12-01 11:57:15 +00:00
|
|
|
roomType,
|
|
|
|
logByDefault,
|
2021-12-07 09:29:20 +00:00
|
|
|
logExpiration,
|
|
|
|
bots
|
2021-04-15 10:17:08 +00:00
|
|
|
}
|
2021-04-12 18:52:21 +00:00
|
|
|
}
|
|
|
|
|
2021-04-15 10:17:08 +00:00
|
|
|
async function writeProsodyConfig (options: RegisterServerOptions): Promise<ProsodyConfig> {
|
2021-04-13 15:13:41 +00:00
|
|
|
const logger = options.peertubeHelpers.logger
|
2021-04-14 15:10:22 +00:00
|
|
|
logger.debug('Calling writeProsodyConfig')
|
|
|
|
|
|
|
|
logger.debug('Ensuring that the working dir exists')
|
|
|
|
await ensureWorkingDir(options)
|
|
|
|
logger.debug('Computing the Prosody config content')
|
2021-04-15 10:17:08 +00:00
|
|
|
const config = await getProsodyConfig(options)
|
|
|
|
const content = config.content
|
|
|
|
const fileName = config.paths.config
|
2021-04-14 15:10:22 +00:00
|
|
|
|
2021-04-13 15:13:41 +00:00
|
|
|
logger.info(`Writing prosody configuration file to ${fileName}`)
|
|
|
|
await fs.promises.writeFile(fileName, content)
|
2021-04-14 15:10:22 +00:00
|
|
|
logger.debug('Prosody configuration file writen')
|
2021-04-15 10:17:08 +00:00
|
|
|
|
|
|
|
return config
|
2021-04-13 15:13:41 +00:00
|
|
|
}
|
|
|
|
|
2021-12-01 11:57:15 +00:00
|
|
|
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}'.`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-12 18:52:21 +00:00
|
|
|
export {
|
2021-04-15 10:17:08 +00:00
|
|
|
getProsodyConfig,
|
2021-04-13 15:13:41 +00:00
|
|
|
getWorkingDir,
|
2021-04-14 15:10:22 +00:00
|
|
|
ensureWorkingDir,
|
2021-04-13 15:13:41 +00:00
|
|
|
getProsodyFilePaths,
|
|
|
|
writeProsodyConfig
|
2021-04-12 18:52:21 +00:00
|
|
|
}
|