Prosody mode only:

Removing old modes (ConverseJS and External URI).
Work in progress.
This commit is contained in:
John Livingston 2022-10-10 18:08:20 +02:00
parent e2ec66bf37
commit 7906ddf625
No known key found for this signature in database
GPG Key ID: B17B5640CE66CDBC
20 changed files with 98 additions and 572 deletions

View File

@ -1,5 +1,30 @@
# Changelog
## 6.0.0 (Not Released Yet)
### Breaking changes
Following modes are removed:
* Connect to an existing XMPP server with ConverseJS
* Use an external web chat tool
The only remaining mode is the recommanded one: «Prosody server controlled by Peertube».
These modes were here for historical reasons (backward compatibility, etc.).
But they became difficult to maintain, and impossible to document (adding a lot of confusion).
Moreover, it seems that they weren't really used.
**Note:** If you were using one of the 2 removed modes, or if you disabled the plugin in the settings,
the server will try to use the new mode after updating the plugin.
If you don't want the chat server to be active, just uninstall the plugin
(settings won't be lost, you just have to download it again).
### New Features
*
## 5.7.1
* Adding an easy way to customize background transparency in OBS and co.

View File

@ -1,6 +1,6 @@
import type { RegisterClientOptions } from '@peertube/peertube-types/client'
import type { Video } from '@peertube/peertube-types'
import type { ChatType, ProsodyListRoomsResult } from 'shared/lib/types'
import type { ProsodyListRoomsResult } from 'shared/lib/types'
interface ActionPluginSettingsParams {
npmName: string
@ -202,56 +202,13 @@ function register ({ registerHook, registerSettingsScript, peertubeHelpers }: Re
isSettingHidden: options => {
const name = options.setting.name
switch (name) {
case 'chat-type-help-disabled':
return options.formValues['chat-type'] !== ('disabled' as ChatType)
case 'prosody-room-type':
case 'prosody-port':
case 'prosody-peertube-uri':
case 'chat-type-help-builtin-prosody':
case 'prosody-list-rooms':
case 'prosody-advanced':
case 'prosody-muc-log-by-default':
case 'prosody-muc-expiration':
case 'prosody-c2s':
case 'prosody-components':
case 'chat-share-url':
return options.formValues['chat-type'] !== ('builtin-prosody' as ChatType)
case 'prosody-c2s-port':
return !(
options.formValues['chat-type'] === ('builtin-prosody' as ChatType) &&
options.formValues['prosody-c2s'] === true
)
return options.formValues['prosody-c2s'] !== true
case 'prosody-components-port':
case 'prosody-components-list':
return !(
options.formValues['chat-type'] === ('builtin-prosody' as ChatType) &&
options.formValues['prosody-components'] === true
)
case 'chat-server':
case 'chat-room':
case 'chat-bosh-uri':
case 'chat-ws-uri':
case 'chat-type-help-builtin-converse':
return options.formValues['chat-type'] !== ('builtin-converse' as ChatType)
case 'converse-advanced':
case 'converse-theme':
return !(
options.formValues['chat-type'] === ('builtin-converse' as ChatType) ||
options.formValues['chat-type'] === ('builtin-prosody' as ChatType)
)
return options.formValues['prosody-components'] !== true
case 'converse-autocolors':
return !(
(
options.formValues['chat-type'] === ('builtin-converse' as ChatType) ||
options.formValues['chat-type'] === ('builtin-prosody' as ChatType)
) &&
options.formValues['converse-theme'] === 'peertube'
)
case 'chat-uri':
case 'chat-type-help-external-uri':
return options.formValues['chat-type'] !== ('external-uri' as ChatType)
case 'chat-style':
return options.formValues['chat-type'] === 'disabled'
return options.formValues['converse-theme'] !== 'peertube'
case 'chat-per-live-video-warning':
return !(options.formValues['chat-all-lives'] === true && options.formValues['chat-per-live-video'] === true)
}

View File

@ -253,20 +253,15 @@ function register (registerOptions: RegisterClientOptions): void {
}
let showShareUrlButton: boolean = false
if (settings['chat-type'] === 'builtin-prosody') {
// The share url functionality should be technically possible for other modes
// than builtin-prosody. But it is too difficult to maintain.
// So I choose to enable it only for builtin-prosody.
const chatShareUrl = settings['chat-share-url'] ?? ''
if (chatShareUrl === 'everyone') {
showShareUrlButton = true
} else if (chatShareUrl === 'owner') {
showShareUrlButton = guessIsMine(registerOptions, video)
} else if (chatShareUrl === 'owner+moderators') {
showShareUrlButton = guessIsMine(registerOptions, video) || guessIamIModerator(registerOptions)
}
const chatShareUrl = settings['chat-share-url'] ?? ''
if (chatShareUrl === 'everyone') {
showShareUrlButton = true
} else if (chatShareUrl === 'owner') {
showShareUrlButton = guessIsMine(registerOptions, video)
} else if (chatShareUrl === 'owner+moderators') {
showShareUrlButton = guessIsMine(registerOptions, video) || guessIamIModerator(registerOptions)
}
insertChatDom(container as HTMLElement, video, !!settings['chat-open-blank'], showShareUrlButton).then(() => {
if (settings['chat-auto-display']) {
openChat(video)

View File

@ -106,7 +106,7 @@ async function shareChatUrl (registerOptions: RegisterClientOptions, settings: a
readonlyOptions.append(transparentLabelEl)
let autoColors
if (isAutoColorsAvailable(settings['chat-type'], settings['converse-theme'])) {
if (isAutoColorsAvailable(settings['converse-theme'])) {
const label = document.createElement('label')
label.innerText = labelAutocolors
autoColors = document.createElement('input')

View File

@ -1,6 +1,5 @@
import type { RegisterClientOptions } from '@peertube/peertube-types/client'
import type { Video } from '@peertube/peertube-types'
import type { ChatType } from 'shared/lib/types'
import { AutoColors, isAutoColorsAvailable } from 'shared/lib/autocolors'
import { logger } from './logger'
import { computeAutoColors } from './colors'
@ -32,41 +31,15 @@ function getIframeUri (
logger.error('Settings are not initialized, too soon to compute the iframeUri')
return null
}
let iframeUriStr = ''
const chatType: ChatType = (settings['chat-type'] ?? 'disabled') as ChatType
if (chatType === 'builtin-prosody' || chatType === 'builtin-converse') {
// Using the builtin converseJS
iframeUriStr = getBaseRoute(registerOptions, uriOptions.permanent)
iframeUriStr += '/webchat/room/' + encodeURIComponent(video.uuid)
} else if (chatType === 'external-uri') {
iframeUriStr = settings['chat-uri'] || ''
iframeUriStr = iframeUriStr.replace(/{{VIDEO_UUID}}/g, encodeURIComponent(video.uuid))
if (iframeUriStr.includes('{{CHANNEL_ID}}')) {
if (!video.channel || !video.channel.id) {
logger.error('Missing channel info in video object.')
return null
}
iframeUriStr = iframeUriStr.replace(/{{CHANNEL_ID}}/g, encodeURIComponent(video.channel.id))
}
if (!/^https?:\/\//.test(iframeUriStr)) {
logger.error('The webchaturi must begin with https://')
return null
}
} else {
logger.error('Chat disabled.')
return null
}
if (iframeUriStr === '') {
logger.error('No iframe uri')
return null
}
let iframeUriStr = getBaseRoute(registerOptions, uriOptions.permanent)
iframeUriStr += '/webchat/room/' + encodeURIComponent(video.uuid)
const iFrameUri = new URL(iframeUriStr, window.location.origin)
if (
!uriOptions.ignoreAutoColors &&
settings['converse-autocolors'] &&
isAutoColorsAvailable(settings['chat-type'] as ChatType, settings['converse-theme'])
isAutoColorsAvailable(settings['converse-theme'])
) {
logger.info('We have to try to compute autocolors.')
try {

8
package-lock.json generated
View File

@ -5,6 +5,7 @@
"requires": true,
"packages": {
"": {
"name": "peertube-plugin-livechat",
"version": "5.7.1",
"license": "AGPL-3.0",
"dependencies": {
@ -46,6 +47,9 @@
"typescript": "^4.3.5",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12"
},
"engines": {
"npm": ">=7 <8"
}
},
"node_modules/@aws-crypto/crc32": {
@ -3712,7 +3716,6 @@
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"fsevents": "~2.3.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
@ -12189,8 +12192,7 @@
"dependencies": {
"chokidar": "^3.4.1",
"graceful-fs": "^4.1.2",
"neo-async": "^2.5.0",
"watchpack-chokidar2": "^2.0.1"
"neo-async": "^2.5.0"
},
"optionalDependencies": {
"watchpack-chokidar2": "^2.0.1"

View File

@ -1,7 +1,7 @@
{
"name": "peertube-plugin-livechat",
"description": "PeerTube plugin livechat: offers a way to embed a chat system into Peertube.",
"version": "5.7.1",
"version": "6.0.0",
"license": "AGPL-3.0",
"author": {
"name": "John Livingston",

View File

@ -1,30 +0,0 @@
import type { RegisterServerOptions } from '@peertube/peertube-types'
import { newResult, TestResult } from './utils'
import type { ChatType } from '../../../shared/lib/types'
export async function diagChatType (test: string, { settingsManager }: RegisterServerOptions): Promise<TestResult> {
const result = newResult(test)
const typeSettings = await settingsManager.getSettings([
'chat-type'
])
result.label = 'Webchat type'
const chatType: ChatType = (typeSettings['chat-type'] ?? 'disabled') as ChatType
if (chatType === 'builtin-prosody') {
result.messages.push('Using builtin Prosody')
result.ok = true
result.next = 'prosody'
} else if (chatType === 'builtin-converse') {
result.messages.push('Using builtin ConverseJS to connect to an external XMPP server')
result.ok = true
result.next = 'converse'
} else if (chatType === 'external-uri') {
result.messages.push('Using an external uri')
result.ok = true
result.next = 'use-uri'
} else if (chatType === 'disabled') {
result.messages.push('Webchat disabled')
} else {
result.messages.push('Unknown chat type value: ' + (chatType as string))
}
return result
}

View File

@ -1,77 +0,0 @@
import type { RegisterServerOptions } from '@peertube/peertube-types'
import { newResult, TestResult } from './utils'
export async function diagConverse (test: string, { settingsManager }: RegisterServerOptions): Promise<TestResult> {
const result = newResult(test)
result.label = 'Builtin ConverseJS on XMPP service'
const builtinSettings = await settingsManager.getSettings([
'chat-server',
'chat-room',
'chat-bosh-uri',
'chat-ws-uri'
])
let isBuiltinError = false
const chatServer: string = (builtinSettings['chat-server'] as string) || ''
if (chatServer === '') {
result.messages.push('Missing chat server configuration')
isBuiltinError = true
} else if (!/^([a-z0-9.]+)+[a-z0-9]+$/.test(chatServer)) {
result.messages.push(
'Invalid value for the webchat server: "' +
chatServer +
'"'
)
isBuiltinError = true
} else {
result.messages.push('Chat server is correct')
}
const chatRoom: string = (builtinSettings['chat-room'] as string) || ''
if (chatRoom === '') {
result.messages.push('Missing chat room configuration')
isBuiltinError = true
} else if (
!/^(\w|{{(VIDEO_UUID|CHANNEL_ID|CHANNEL_NAME)}})+@([a-z0-9.]+)+[a-z0-9]+$/
.test(chatRoom)
) {
result.messages.push(
'Invalid value for the webchat room: "' +
chatRoom +
'"'
)
isBuiltinError = true
} else {
result.messages.push('Chat room is correct and will be: ' + chatRoom)
}
const chatBoshUri: string = (builtinSettings['chat-bosh-uri'] as string) || ''
const chatWsUri: string = (builtinSettings['chat-ws-uri'] as string) || ''
if (chatBoshUri === '' && chatWsUri === '') {
result.messages.push('Missing BOSH or Websocket uri')
isBuiltinError = true
}
if (chatBoshUri !== '') {
if (!/^https?:\/\//.test(chatBoshUri)) {
result.messages.push('Invalid BOSH Uri, should begin with https://')
isBuiltinError = true
} else {
result.messages.push('Valid Bosh Uri')
}
}
if (chatWsUri !== '') {
if (!/^wss?:\/\//.test(chatWsUri)) {
result.messages.push('Invalid Websocket Uri, should begin with wss://')
isBuiltinError = true
} else {
result.messages.push('Valid Websocket Uri')
}
}
if (!isBuiltinError) {
result.messages.push('Builtin converse is correctly configured')
result.ok = true
}
return result
}

View File

@ -1,10 +1,7 @@
import type { RegisterServerOptions } from '@peertube/peertube-types'
import { diagBackend } from './backend'
import { diagConverse } from './converse'
import { diagChatType } from './chat-type'
import { TestResult, newResult } from './utils'
import { diagProsody } from './prosody'
import { diagUri } from './uri'
import { diagVideo } from './video'
export async function diag (test: string, options: RegisterServerOptions): Promise<TestResult> {
@ -14,14 +11,8 @@ export async function diag (test: string, options: RegisterServerOptions): Promi
result = await diagBackend(test, options)
} else if (test === 'webchat-video') {
result = await diagVideo(test, options)
} else if (test === 'webchat-type') {
result = await diagChatType(test, options)
} else if (test === 'prosody') {
result = await diagProsody(test, options)
} else if (test === 'converse') {
result = await diagConverse(test, options)
} else if (test === 'use-uri') {
result = await diagUri(test, options)
} else {
result = newResult(test)
result.messages.push('Unknown test')

View File

@ -1,17 +0,0 @@
import type { RegisterServerOptions } from '@peertube/peertube-types'
import { newResult, TestResult } from './utils'
export async function diagUri (test: string, { settingsManager }: RegisterServerOptions): Promise<TestResult> {
const result = newResult(test)
result.label = 'External Webchat using an iframe'
const settings = await settingsManager.getSettings([
'chat-uri'
])
if (/^https:\/\//.test(settings['chat-uri'] as string)) {
result.ok = true
result.messages.push('Chat url will be: ' + (settings['chat-uri'] as string))
} else {
result.messages.push('Incorrect value for the uri (it does not start with https://)')
}
return result
}

View File

@ -1,4 +1,4 @@
type nextValue = 'backend' | 'webchat-video' | 'webchat-type' | 'prosody' | 'converse' | 'use-uri'
type nextValue = 'backend' | 'webchat-video' | 'prosody'
interface MessageWithLevel {
level: 'info' | 'warning' | 'error'

View File

@ -46,7 +46,7 @@ export async function diagVideo (test: string, { settingsManager }: RegisterServ
}
if (atLeastOne) {
result.ok = true
result.next = 'webchat-type'
result.next = 'prosody'
} else {
result.ok = false
result.messages.push('Chat is activate for no video.')

View File

@ -1,87 +1,9 @@
import type { RegisterServerOptions } from '@peertube/peertube-types'
import { pluginShortName } from '../helpers'
import type { ChatType } from '../../../shared/lib/types'
async function _migrateChatTypeSetting (options: RegisterServerOptions): Promise<void> {
const peertubeHelpers = options.peertubeHelpers
const logger = peertubeHelpers.logger
// Previous to plugin v3.0.0, there was multiple checkbox and input-text for settings the plugin mode.
// With Peertube v2.3.0, we can replace all these settings with a single select.
// This function migrates old values if needed.
// NB: we cant use safely settingsManager.getSetting, because settings are not registered yet.
logger.info('Checking if we need to migrate chat-type')
if (!/^[-a-z]+$/.test(pluginShortName)) {
// to prevent sql injection... be sure there is no special char here.
throw new Error(`Wrong pluginShortName '${pluginShortName}'`)
}
const [results] = await peertubeHelpers.database.query(
'SELECT "settings" FROM "plugin"' +
' WHERE "plugin"."name" = :pluginShortName',
{
replacements: {
pluginShortName
}
}
)
if (!Array.isArray(results)) {
throw new Error('_migrateChatTypeSetting: query result is not an array.')
}
if (results.length === 0) {
logger.error('Plugin not found in database')
return
}
if (results.length > 1) {
logger.error('Multiple lines for plugin in database, dont know which one to migrate... Aborting.')
return
}
const settings = results[0].settings
if (!settings) {
logger.info('Plugin settings are empty in database, no migration needed.')
return
}
if (typeof settings !== 'object') {
logger.error('Plugin settings in database seems to be invalid json')
return
}
if ('chat-type' in settings) {
logger.info('The setting chat-type is already here, no need to migrate.')
return
}
logger.info('The setting chat-type is not here, checking if we have to migrate from previous settings...')
let chatType: ChatType | undefined
if (settings['chat-use-prosody'] === true) {
chatType = 'builtin-prosody'
} else if (settings['chat-use-builtin'] === true) {
chatType = 'builtin-converse'
} else if (((settings['chat-uri'] || '') as string) !== '') {
chatType = 'external-uri'
} else {
logger.info('It seems there was no previous active chat configuration.')
return
}
logger.info(`We have to set chat-type to value '${chatType}'.`)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
await peertubeHelpers.database.query(
'UPDATE "plugin" ' +
' SET "settings" = "settings" || :value ' +
' WHERE "name" = :pluginShortName',
{
replacements: {
pluginShortName,
value: JSON.stringify({
'chat-type': chatType
})
}
}
)
}
async function migrateSettings (options: RegisterServerOptions): Promise<void> {
const logger = options.peertubeHelpers.logger
logger.info('Checking if there is a migration script to launch...')
await _migrateChatTypeSetting(options)
// 2022-10-10: as we removed the «chat-type» settings, there is no migration needed for now.
}
export {

View File

@ -2,7 +2,6 @@ import type { RegisterServerOptions } from '@peertube/peertube-types'
import { getProsodyConfig, getProsodyFilePaths, writeProsodyConfig } from './config'
import { startProsodyLogRotate, stopProsodyLogRotate } from './logrotate'
import { changeHttpBindRoute } from '../routers/webchat'
import type { ChatType } from '../../../shared/lib/types'
import * as fs from 'fs'
import * as child_process from 'child_process'
@ -139,17 +138,10 @@ async function testProsodyCorrectlyRunning (options: RegisterServerOptions): Pro
}
async function ensureProsodyRunning (options: RegisterServerOptions): Promise<void> {
const { peertubeHelpers, settingsManager } = options
const { peertubeHelpers } = options
const logger = peertubeHelpers.logger
logger.debug('Calling ensureProsodyRunning')
logger.debug('Checking if prosody should be active')
const setting = await settingsManager.getSetting('chat-type')
if (setting !== ('builtin-prosody' as ChatType)) {
logger.info('Chat type is not set to builtin-prosody, we wont launch it')
return
}
const r = await testProsodyCorrectlyRunning(options)
if (r.ok) {
r.messages.forEach(m => logger.debug(m))

View File

@ -7,7 +7,6 @@ import { prosodyCheckUserPassword, prosodyRegisterUser, prosodyUserRegistered }
import { getUserNickname } from '../helpers'
import { Affiliations, getVideoAffiliations, getChannelAffiliations } from '../prosody/config/affiliations'
import { getProsodyDomain } from '../prosody/config/domain'
import type { ChatType } from '../../../shared/lib/types'
import { fillVideoCustomFields } from '../custom-fields'
import { getChannelInfosById } from '../database/channel'
@ -51,14 +50,8 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
logger.info(`Requesting room information for room '${jid}'.`)
const settings = await options.settingsManager.getSettings([
'chat-type',
'prosody-room-type'
])
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
logger.warn('Prosody chat is not active')
res.sendStatus(403)
return
}
// Now, we have two different room type: per video or per channel.
if (settings['prosody-room-type'] === 'channel') {
const matches = jid.match(/^channel\.(\d+)$/)
@ -106,17 +99,11 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
// check settings (chat enabled for this video?)
const settings = await options.settingsManager.getSettings([
'chat-type',
'chat-per-live-video',
'chat-all-lives',
'chat-all-non-lives',
'chat-videos-list'
])
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
logger.warn('Prosody chat is not active')
res.sendStatus(403)
return
}
if (!videoHasWebchat({
'chat-per-live-video': !!settings['chat-per-live-video'],
'chat-all-lives': !!settings['chat-all-lives'],
@ -186,14 +173,6 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
router.get('/user/check_password', asyncMiddleware(
async (req: Request, res: Response, _next: NextFunction) => {
const settings = await options.settingsManager.getSettings([
'chat-type'
])
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
logger.warn('Prosody chat is not active')
res.status(200).send('false')
return
}
const prosodyDomain = await getProsodyDomain(options)
const user = req.query.user
const server = req.query.server
@ -213,14 +192,6 @@ async function initApiRouter (options: RegisterServerOptions): Promise<Router> {
router.get('/user/user_exists', asyncMiddleware(
async (req: Request, res: Response, _next: NextFunction) => {
const settings = await options.settingsManager.getSettings([
'chat-type'
])
if (settings['chat-type'] !== ('builtin-prosody' as ChatType)) {
logger.warn('Prosody chat is not active')
res.status(200).send('false')
return
}
const prosodyDomain = await getProsodyDomain(options)
const user = req.query.user
const server = req.query.server

View File

@ -2,7 +2,7 @@ import type { RegisterServerOptions, MVideoThumbnail } from '@peertube/peertube-
import type { Router, RequestHandler, Request, Response, NextFunction } from 'express'
import type { ProxyOptions } from 'express-http-proxy'
import type {
ChatType, ProsodyListRoomsResult, ProsodyListRoomsResultRoom
ProsodyListRoomsResult, ProsodyListRoomsResultRoom
} from '../../../shared/lib/types'
import { getBaseRouterRoute, getBaseStaticRoute, isUserAdmin } from '../helpers'
import { asyncMiddleware } from '../middlewares/async'
@ -41,17 +41,11 @@ async function initWebchatRouter (options: RegisterServerOptions): Promise<Route
const roomKey = req.params.roomKey
const settings = await settingsManager.getSettings([
'chat-type', 'chat-room', 'chat-server',
'chat-bosh-uri', 'chat-ws-uri',
'prosody-room-type',
'converse-theme', 'converse-autocolors'
])
const chatType: ChatType = (settings['chat-type'] ?? 'disabled') as ChatType
let jid: string
let room: string
let boshUri: string
let wsUri: string
let authenticationUrl: string = ''
let advancedControls: boolean = false // auto join the chat in viewer mode, if not logged in
let autoViewerMode: boolean = false
@ -61,60 +55,42 @@ async function initWebchatRouter (options: RegisterServerOptions): Promise<Route
if (!/^\w+$/.test(converseJSTheme)) {
converseJSTheme = 'peertube'
}
if (chatType === 'builtin-prosody') {
const prosodyDomain = await getProsodyDomain(options)
jid = 'anon.' + prosodyDomain
if (req.query.forcetype === '1') {
// We come from the room list in the settings page.
// Here we don't read the prosody-room-type settings,
// but use the roomKey format.
// NB: there is no extra security. Any user can add this parameter.
// This is not an issue: the setting will be tested at the room creation.
// No room can be created in the wrong mode.
if (/^channel\.\d+$/.test(roomKey)) {
room = 'channel.{{CHANNEL_ID}}@room.' + prosodyDomain
} else {
room = '{{VIDEO_UUID}}@room.' + prosodyDomain
}
const prosodyDomain = await getProsodyDomain(options)
const jid = 'anon.' + prosodyDomain
if (req.query.forcetype === '1') {
// We come from the room list in the settings page.
// Here we don't read the prosody-room-type settings,
// but use the roomKey format.
// NB: there is no extra security. Any user can add this parameter.
// This is not an issue: the setting will be tested at the room creation.
// No room can be created in the wrong mode.
if (/^channel\.\d+$/.test(roomKey)) {
room = 'channel.{{CHANNEL_ID}}@room.' + prosodyDomain
} else {
if (settings['prosody-room-type'] === 'channel') {
room = 'channel.{{CHANNEL_ID}}@room.' + prosodyDomain
} else {
room = '{{VIDEO_UUID}}@room.' + prosodyDomain
}
room = '{{VIDEO_UUID}}@room.' + prosodyDomain
}
boshUri = getBaseRouterRoute(options) + 'webchat/http-bind'
wsUri = ''
authenticationUrl = options.peertubeHelpers.config.getWebserverUrl() +
getBaseRouterRoute(options) +
'api/auth'
advancedControls = true
if (req.query._readonly === 'true') {
forceReadonly = 'true'
} else if (req.query._readonly === 'noscroll') {
forceReadonly = 'noscroll'
} else {
autoViewerMode = true // auto join the chat in viewer mode, if not logged in
}
if (req.query._transparent === 'true') {
transparent = true
}
} else if (chatType === 'builtin-converse') {
if (!settings['chat-server']) {
throw new Error('Missing chat-server settings.')
}
if (!settings['chat-room']) {
throw new Error('Missing chat-room settings.')
}
if (!settings['chat-bosh-uri'] && !settings['chat-ws-uri']) {
throw new Error('Missing BOSH or Websocket uri.')
}
jid = settings['chat-server'] as string
room = settings['chat-room'] as string
boshUri = settings['chat-bosh-uri'] as string
wsUri = settings['chat-ws-uri'] as string
} else {
throw new Error('Builtin chat disabled.')
if (settings['prosody-room-type'] === 'channel') {
room = 'channel.{{CHANNEL_ID}}@room.' + prosodyDomain
} else {
room = '{{VIDEO_UUID}}@room.' + prosodyDomain
}
}
const boshUri = getBaseRouterRoute(options) + 'webchat/http-bind'
const wsUri = ''
authenticationUrl = options.peertubeHelpers.config.getWebserverUrl() +
getBaseRouterRoute(options) +
'api/auth'
advancedControls = true
if (req.query._readonly === 'true') {
forceReadonly = 'true'
} else if (req.query._readonly === 'noscroll') {
forceReadonly = 'noscroll'
} else {
autoViewerMode = true // auto join the chat in viewer mode, if not logged in
}
if (req.query._transparent === 'true') {
transparent = true
}
let video: MVideoThumbnail | undefined
@ -122,10 +98,7 @@ async function initWebchatRouter (options: RegisterServerOptions): Promise<Route
const channelMatches = roomKey.match(/^channel\.(\d+)$/)
if (channelMatches?.[1]) {
channelId = parseInt(channelMatches[1])
// Here we are on a room... must be in prosody mode.
if (chatType !== 'builtin-prosody') {
throw new Error('Cant access a chat by a channel uri if chatType!==builtin-prosody')
}
// Here we are on a channel room...
const channelInfos = await getChannelInfosById(options, channelId)
if (!channelInfos) {
throw new Error('Channel not found')
@ -168,7 +141,7 @@ async function initWebchatRouter (options: RegisterServerOptions): Promise<Route
let autocolorsStyles = ''
if (
settings['converse-autocolors'] &&
isAutoColorsAvailable(settings['chat-type'] as ChatType, settings['converse-theme'] as string)
isAutoColorsAvailable(settings['converse-theme'] as string)
) {
peertubeHelpers.logger.debug('Trying to load AutoColors...')
const autocolors: AutoColors = {
@ -249,18 +222,6 @@ async function initWebchatRouter (options: RegisterServerOptions): Promise<Route
return
}
const chatType: ChatType = await options.settingsManager.getSetting('chat-type') as ChatType
if (chatType !== 'builtin-prosody') {
const message = 'Please save the settings first.' // TODO: translate?
res.status(200)
const r: ProsodyListRoomsResult = {
ok: false,
error: message
}
res.json(r)
return
}
if (!currentProsodyHttpBindInfo) {
throw new Error('It seems that prosody is not binded... Cant list rooms.')
}

View File

@ -1,6 +1,6 @@
import type { RegisterServerOptions } from '@peertube/peertube-types'
import { ensureProsodyRunning, ensureProsodyNotRunning } from './prosody/ctl'
import type { ChatType, ConverseJSTheme } from '../../shared/lib/types'
import { ensureProsodyRunning } from './prosody/ctl'
import type { ConverseJSTheme } from '../../shared/lib/types'
function initSettings (options: RegisterServerOptions): void {
const { peertubeHelpers, registerSetting, settingsManager } = options
@ -34,78 +34,18 @@ function initSettings (options: RegisterServerOptions): void {
descriptionHTML: '<h3>Chat mode</h3>'
})
registerSetting({
name: 'chat-type',
label: 'Chat mode',
type: 'select',
default: 'disabled' as ChatType,
private: false,
options: [
{ value: 'disabled', label: 'Disabled' },
{ value: 'builtin-prosody', label: 'Prosody server controlled by Peertube (recommended)' },
{ value: 'builtin-converse', label: 'Connect to an existing XMPP server with ConverseJS' },
{ value: 'external-uri', label: 'Use an external web chat tool' }
] as Array<{value: ChatType, label: string}>,
descriptionHTML: 'Please choose the webchat mode you want to use.'
})
registerSetting({
name: 'chat-type-help-disabled',
name: 'chat-help-builtin-prosody',
type: 'html',
descriptionHTML: 'The chat is disabled.',
private: true
})
registerSetting({
name: 'chat-type-help-builtin-prosody',
type: 'html',
label: 'Prosody server controlled by Peertube (recommended)',
descriptionHTML: `With this mode, the Peertube server will control a local Prosody XMPP server.<br>
Note: you have to install the Prosody XMPP server.
label: 'Prosody server',
descriptionHTML: `This plugin uses the Prosody XMPP server to handle chat rooms.<br>
The Peertube server will control this Prosody server.<br>
Important Note: you have to install Prosody on your server.
Please read the <a
href="https://github.com/JohnXLivingston/peertube-plugin-livechat/blob/main/documentation/prosody.md"
target="_blank"
>documentation</a>.`,
private: true
})
registerSetting({
name: 'chat-type-help-builtin-converse',
type: 'html',
label: 'Connect to an existing XMPP server with ConverseJS',
descriptionHTML:
`<div class="peertube-plugin-livechat-warning"><b>
This mode is deprecated and will be removed in version 6.0.0.
More information in the
<a href="https://github.com/JohnXLivingston/peertube-plugin-livechat/blob/main/CHANGELOG.md#560" target="_blank">
CHANGELOG
</a>.
</b></div>
With this mode, you can connect to an existing XMPP server, that allow anonymous authentication and room creation.
Please read the
<a
href="https://github.com/JohnXLivingston/peertube-plugin-livechat/blob/main/documentation/conversejs.md"
target="_blank"
>documentation</a>.`,
private: true
})
registerSetting({
name: 'chat-type-help-external-uri',
type: 'html',
label: 'Use an external webchat',
descriptionHTML:
`<div class="peertube-plugin-livechat-warning"><b>
This mode is deprecated and will be removed in version 6.0.0.
More information in the
<a href="https://github.com/JohnXLivingston/peertube-plugin-livechat/blob/main/CHANGELOG.md#560" target="_blank">
CHANGELOG
</a>.
</b></div>
With this mode, you can use any external web chat that can be included in an iframe.
Please read the
<a
href="https://github.com/JohnXLivingston/peertube-plugin-livechat/blob/main/documentation/external.md"
target="_blank"
>documentation</a>.`,
private: true
})
registerSetting({
name: 'prosody-list-rooms',
@ -140,70 +80,6 @@ Change it if this port is already in use on your server.<br>
You can close this port on your firewall, it will not be accessed from the outer world.`
})
registerSetting({
name: 'chat-server',
label: 'XMPP service server',
type: 'input',
default: '',
descriptionHTML: 'Your XMPP server. Without any scheme. Example : peertube.im.your_domain.',
private: true
})
registerSetting({
name: 'chat-room',
label: 'XMPP room template',
type: 'input',
default: '',
descriptionHTML:
`Your XMPP room. You can use following placeholders to inject video metadata in the room name:
<ul>
<li>{{VIDEO_UUID}} to add the video UUID.</li>
<li>{{CHANNEL_ID}} to add the CHANNEL numerical ID.</li>
<li>{{CHANNEL_NAME}} to add the channel name (see the Peertube's documentation for possible characters).</li>
</ul>
Without any placeholder, all videos will point to the same chat room.<br>
Example: public@room.peertube.im.your_domain<br>
Example: public_{{VIDEO_UUID}}@room.peertube.im.your_domain`,
private: true
})
registerSetting({
name: 'chat-bosh-uri',
label: 'BOSH uri',
type: 'input',
default: '',
descriptionHTML:
`URI of the external BOSH server.
Please make sure it accept cross origin request from your domain.<br>
You must at least have a BOSH or a Websocket uri.`,
private: true
})
registerSetting({
name: 'chat-ws-uri',
label: 'Websocket uri',
type: 'input',
default: '',
descriptionHTML: `
URI of the external WS server.
Please make sure it accept cross origin request from your domain.<br>
You must at least have a BOSH or a Websocket uri.`,
private: true
})
registerSetting({
name: 'chat-uri',
label: 'Webchat url',
type: 'input',
default: '',
descriptionHTML:
`Put here your webchat url. An iframe will be created pointing to this url.
You can use following placeholders to inject video metadata in the url:
<ul>
<li>{{VIDEO_UUID}} to add the video UUID.</li>
<li>{{CHANNEL_ID}} to add the CHANNEL numerical ID.</li>
</ul>
Example : https://my_domain/conversejs.html?room=video_{{VIDEO_UUID}}.`,
private: false
})
// ********** Chat behaviour
registerSetting({
type: 'html',
@ -467,17 +343,9 @@ You can keep this port closed on your firewall for now, it will not be accessed
})
// ********** settings changes management
settingsManager.onSettingsChange(async (settings: any) => {
if ('chat-type' in settings) {
const chatType: ChatType = settings['chat-type'] ?? 'disabled'
if (chatType === 'builtin-prosody') {
peertubeHelpers.logger.info('Saving settings, ensuring prosody is running')
await ensureProsodyRunning(options)
} else {
peertubeHelpers.logger.info('Saving settings, ensuring prosody is not running')
await ensureProsodyNotRunning(options)
}
}
settingsManager.onSettingsChange(async (_settings: any) => {
peertubeHelpers.logger.info('Saving settings, ensuring prosody is running')
await ensureProsodyRunning(options)
})
}

View File

@ -1,4 +1,3 @@
import type { ChatType } from './types'
const validateColor = require('validate-color').default
type AutoColorValue = string
@ -19,14 +18,10 @@ interface AutoColors {
}
/**
* @param chatType value of the settings 'chat-type'
* @param theme value of the settings 'converse-theme'
* @returns true if the theme can use autocolors
*/
function isAutoColorsAvailable (chatType: ChatType, theme: string): boolean {
if (chatType !== 'builtin-prosody' && chatType !== 'builtin-converse') {
return false
}
function isAutoColorsAvailable (theme: string): boolean {
return theme === 'peertube' // currently the only theme that can handle autocolors.
}

View File

@ -1,4 +1,3 @@
type ChatType = 'disabled' | 'builtin-prosody' | 'builtin-converse' | 'external-uri'
type ConverseJSTheme = 'peertube' | 'default' | 'concord'
interface ProsodyListRoomsResultError {
@ -28,7 +27,6 @@ interface ProsodyListRoomsResultSuccess {
type ProsodyListRoomsResult = ProsodyListRoomsResultError | ProsodyListRoomsResultSuccess
export {
ChatType,
ConverseJSTheme,
ProsodyListRoomsResult,
ProsodyListRoomsResultRoom