// SPDX-FileCopyrightText: 2024 John Livingston
//
// SPDX-License-Identifier: AGPL-3.0-only
import type { RegisterServerOptions } from '@peertube/peertube-types'
import { migrateSettings } from './lib/migration/settings'
import { initSettings } from './lib/settings'
import { initCustomFields } from './lib/custom-fields'
import { initRouters } from './lib/routers/index'
import { initFederation } from './lib/federation/init'
import { initChannelConfiguration } from './lib/configuration/channel/init'
import { initRSS } from './lib/rss/init'
import { prepareProsody, ensureProsodyRunning, ensureProsodyNotRunning } from './lib/prosody/ctl'
import { unloadDebugMode } from './lib/debug'
import { loadLoc } from './lib/loc'
import { RoomChannel } from './lib/room-channel'
import { BotConfiguration } from './lib/configuration/bot'
import { BotsCtl } from './lib/bots/ctl'
import { ExternalAuthOIDC } from './lib/external-auth/oidc'
import { migrateMUCAffiliations } from './lib/prosody/migration/migrateV10'
import decache from 'decache'
// FIXME: Peertube unregister don't have any parameter.
// Using this global variable to fix this, so we can use helpers to unregister.
let OPTIONS: RegisterServerOptions | undefined
async function register (options: RegisterServerOptions): Promise {
OPTIONS = options
const logger = options.peertubeHelpers.logger
// This is a trick to check that peertube is at least in version 3.2.0
if (!options.peertubeHelpers.plugin) {
throw new Error('Your peertube version is not correct. This plugin is not compatible with Peertube < 3.2.0.')
}
// First: load languages files, so we can localize strings.
await loadLoc()
// Then load the BotConfiguration singleton
await BotConfiguration.initSingleton(options)
// Then load the RoomChannel singleton
const roomChannelSingleton = await RoomChannel.initSingleton(options)
// roomChannelNeedsDataInit: if true, means that the data file does not exist (or is invalid), so we must initiate it
const roomChannelNeedsDataInit = !await roomChannelSingleton.readData()
// BotsCtl.initSingleton() will force reload the bots conf files, so must be done before generating Prosody Conf.
await BotsCtl.initSingleton(options)
await migrateSettings(options)
await initSettings(options)
await initCustomFields(options)
await initRouters(options)
await initFederation(options)
await initChannelConfiguration(options)
await initRSS(options)
try {
await prepareProsody(options)
await ensureProsodyRunning(options)
let preBotPromise: Promise
if (roomChannelNeedsDataInit) {
logger.info('The RoomChannel singleton has not found any data, we must rebuild')
// no need to wait here, can be done without await.
preBotPromise = roomChannelSingleton.rebuildData().then(
() => { logger.info('RoomChannel singleton rebuild done') },
(reason) => { logger.error('RoomChannel singleton rebuild failed: ' + (reason as string)) }
)
} else {
preBotPromise = Promise.resolve()
}
// Don't need to wait for the bot to start.
preBotPromise.then(
async () => {
await BotsCtl.singleton().start()
},
() => {}
)
// livechat v10.0.0: we must migrate MUC affiliations (but we don't have to wait)
// we do this after the preBotPromise, just to avoid doing both at the same time.
preBotPromise.then(() => {
migrateMUCAffiliations(options).then(
() => {},
(err) => {
logger.error(err)
})
}, () => {})
} catch (error) {
options.peertubeHelpers.logger.error('Error when launching Prosody: ' + (error as string))
}
}
async function unregister (): Promise {
try {
await BotsCtl.destroySingleton()
} catch (_error) {} // BotsCtl will log errors.
if (OPTIONS) {
try {
await ensureProsodyNotRunning(OPTIONS)
} catch (error) {
OPTIONS.peertubeHelpers.logger.error('Error when trying to unload Prosody: ' + (error as string))
}
}
unloadDebugMode()
await RoomChannel.destroySingleton()
await BotConfiguration.destroySingleton()
await ExternalAuthOIDC.destroySingletons()
const module = __filename
OPTIONS?.peertubeHelpers.logger.info(`Unloading module ${module}...`)
// Peertube calls decache(plugin) on register, not unregister.
// Will do here, to release memory.
decache(module)
OPTIONS?.peertubeHelpers.logger.info(`Successfully unloaded the module ${module}`)
OPTIONS = undefined
}
module.exports = {
register,
unregister
}