WIP: store and get relation between rooms and channels:
* rebuildData * handling video update (to check for channel changes)
This commit is contained in:
parent
ea1c008ded
commit
e4683cf282
@ -1,5 +1,7 @@
|
|||||||
import type { RegisterServerOptions, MVideoFullLight, VideoChannel } from '@peertube/peertube-types'
|
import type { RegisterServerOptions, MVideoFullLight, VideoChannel } from '@peertube/peertube-types'
|
||||||
import { RoomChannel } from '../../room-channel'
|
import { RoomChannel } from '../../room-channel'
|
||||||
|
import { fillVideoCustomFields } from '../../custom-fields'
|
||||||
|
import { videoHasWebchat } from '../../../../shared/lib/video'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register stuffs related to channel configuration
|
* Register stuffs related to channel configuration
|
||||||
@ -15,6 +17,7 @@ async function initChannelConfiguration (options: RegisterServerOptions): Promis
|
|||||||
// When a video is deleted, we can delete the channel2room and room2channel files.
|
// When a video is deleted, we can delete the channel2room and room2channel files.
|
||||||
// Note: don't need to check if there is a chat for this video, just deleting existing files...
|
// Note: don't need to check if there is a chat for this video, just deleting existing files...
|
||||||
const video = params.video
|
const video = params.video
|
||||||
|
if (video.remote) { return }
|
||||||
logger.info(`Video ${video.uuid} deleted, removing 'channel configuration' related stuff.`)
|
logger.info(`Video ${video.uuid} deleted, removing 'channel configuration' related stuff.`)
|
||||||
// Here the associated channel can be either channel.X@mucdomain or video_uuid@mucdomain.
|
// Here the associated channel can be either channel.X@mucdomain or video_uuid@mucdomain.
|
||||||
// In first case, nothing to do... in the second, we must delete.
|
// In first case, nothing to do... in the second, we must delete.
|
||||||
@ -34,6 +37,7 @@ async function initChannelConfiguration (options: RegisterServerOptions): Promis
|
|||||||
handler: async (params: { channel: VideoChannel }) => {
|
handler: async (params: { channel: VideoChannel }) => {
|
||||||
// When a video is deleted, we can delete the channel2room and room2channel files.
|
// When a video is deleted, we can delete the channel2room and room2channel files.
|
||||||
// Note: don't need to check if there is a chat for this video, just deleting existing files...
|
// Note: don't need to check if there is a chat for this video, just deleting existing files...
|
||||||
|
if (!params.channel.isLocal) { return }
|
||||||
const channelId = params.channel.id
|
const channelId = params.channel.id
|
||||||
logger.info(`Channel ${channelId} deleted, removing 'channel configuration' related stuff.`)
|
logger.info(`Channel ${channelId} deleted, removing 'channel configuration' related stuff.`)
|
||||||
// Here the associated channel can be either channel.X@mucdomain or video_uuid@mucdomain.
|
// Here the associated channel can be either channel.X@mucdomain or video_uuid@mucdomain.
|
||||||
@ -48,6 +52,52 @@ async function initChannelConfiguration (options: RegisterServerOptions): Promis
|
|||||||
// Note: we don't delete the room. So that admins can check logs afterward, if any doubts.
|
// Note: we don't delete the room. So that admins can check logs afterward, if any doubts.
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
registerHook({
|
||||||
|
target: 'action:api.video.updated',
|
||||||
|
handler: async (params: { video: MVideoFullLight }) => {
|
||||||
|
// When a video is updated, the channel could change.
|
||||||
|
// So we ensure the room-channel link is ok.
|
||||||
|
// But we can only do this if the video has a chatroom!
|
||||||
|
const video = params.video
|
||||||
|
logger.info(`Video ${video.uuid} updated, updating room-channel informations.`)
|
||||||
|
try {
|
||||||
|
if (video.remote) { return }
|
||||||
|
const settings = await options.settingsManager.getSettings([
|
||||||
|
'chat-per-live-video',
|
||||||
|
'chat-all-lives',
|
||||||
|
'chat-all-non-lives',
|
||||||
|
'chat-videos-list',
|
||||||
|
'prosody-room-type'
|
||||||
|
])
|
||||||
|
|
||||||
|
await fillVideoCustomFields(options, video)
|
||||||
|
const hasChat = await videoHasWebchat({
|
||||||
|
'chat-per-live-video': !!settings['chat-per-live-video'],
|
||||||
|
'chat-all-lives': !!settings['chat-all-lives'],
|
||||||
|
'chat-all-non-lives': !!settings['chat-all-non-lives'],
|
||||||
|
'chat-videos-list': settings['chat-videos-list'] as string
|
||||||
|
}, video)
|
||||||
|
|
||||||
|
if (!hasChat) {
|
||||||
|
logger.debug(`Video ${video.uuid} has no chat, skipping`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let roomLocalPart: string
|
||||||
|
if (settings['prosody-room-type'] === 'channel') {
|
||||||
|
roomLocalPart = 'channel.' + video.channelId.toString()
|
||||||
|
} else {
|
||||||
|
roomLocalPart = video.uuid
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Ensuring a room-channel link between room ${roomLocalPart} and channel ${video.channelId}`)
|
||||||
|
RoomChannel.singleton().link(video.channelId, roomLocalPart)
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
41
server/lib/prosody/api/host.ts
Normal file
41
server/lib/prosody/api/host.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
interface ProsodyHost {
|
||||||
|
host: string
|
||||||
|
port: string
|
||||||
|
}
|
||||||
|
|
||||||
|
let current: ProsodyHost | undefined
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When loading Prosody, keep track of the current host and port.
|
||||||
|
* @param host host
|
||||||
|
* @param port port
|
||||||
|
*/
|
||||||
|
function setCurrentProsody (host: string, port: string): void {
|
||||||
|
current = {
|
||||||
|
host,
|
||||||
|
port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When stopping Prosody, delete current host and port.
|
||||||
|
*/
|
||||||
|
function delCurrentProsody (): void {
|
||||||
|
current = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current Prosody host infos.
|
||||||
|
* @returns Prosody host info
|
||||||
|
*/
|
||||||
|
function getCurrentProsody (): ProsodyHost | null {
|
||||||
|
// cloning to avoid issues
|
||||||
|
if (!current) { return null }
|
||||||
|
return Object.assign({}, current)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
setCurrentProsody,
|
||||||
|
delCurrentProsody,
|
||||||
|
getCurrentProsody
|
||||||
|
}
|
41
server/lib/prosody/api/list-rooms.ts
Normal file
41
server/lib/prosody/api/list-rooms.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import type { RegisterServerOptions } from '@peertube/peertube-types'
|
||||||
|
import { getCurrentProsody } from './host'
|
||||||
|
import { getAPIKey } from '../../apikey'
|
||||||
|
const got = require('got')
|
||||||
|
|
||||||
|
interface ProsodyRoomDesc {
|
||||||
|
jid: string
|
||||||
|
localpart: string
|
||||||
|
name: string
|
||||||
|
lang: string
|
||||||
|
description: string
|
||||||
|
lasttimestamp?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
async function listProsodyRooms (options: RegisterServerOptions): Promise<ProsodyRoomDesc[]> {
|
||||||
|
const logger = options.peertubeHelpers.logger
|
||||||
|
|
||||||
|
const currentProsody = getCurrentProsody()
|
||||||
|
if (!currentProsody) {
|
||||||
|
throw new Error('It seems that prosody is not binded... Cant list rooms.')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requesting on localhost, because currentProsody.host does not always resolves correctly (docker use case, ...)
|
||||||
|
const apiUrl = `http://localhost:${currentProsody.port}/peertubelivechat_list_rooms/list-rooms`
|
||||||
|
logger.debug('Calling list rooms API on url: ' + apiUrl)
|
||||||
|
const rooms = await got(apiUrl, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
authorization: 'Bearer ' + await getAPIKey(options),
|
||||||
|
host: currentProsody.host
|
||||||
|
},
|
||||||
|
responseType: 'json',
|
||||||
|
resolveBodyOnly: true
|
||||||
|
})
|
||||||
|
|
||||||
|
return rooms
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
listProsodyRooms
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import type { RegisterServerOptions } from '@peertube/peertube-types'
|
import type { RegisterServerOptions } from '@peertube/peertube-types'
|
||||||
import { getProsodyDomain } from '../prosody/config/domain'
|
import { getProsodyDomain } from '../prosody/config/domain'
|
||||||
|
import { listProsodyRooms } from '../prosody/api/list-rooms'
|
||||||
|
import { getChannelInfosById } from '../database/channel'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
|
|
||||||
@ -21,6 +23,7 @@ class RoomChannel {
|
|||||||
|
|
||||||
protected room2Channel: Map<string, number> = new Map<string, number>()
|
protected room2Channel: Map<string, number> = new Map<string, number>()
|
||||||
protected channel2Rooms: Map<number, Map<string, true>> = new Map<number, Map<string, true>>()
|
protected channel2Rooms: Map<number, Map<string, true>> = new Map<number, Map<string, true>>()
|
||||||
|
protected needSync: boolean = false
|
||||||
|
|
||||||
constructor (params: {
|
constructor (params: {
|
||||||
options: RegisterServerOptions
|
options: RegisterServerOptions
|
||||||
@ -115,6 +118,7 @@ class RoomChannel {
|
|||||||
protected _readData (data: any): boolean {
|
protected _readData (data: any): boolean {
|
||||||
this.room2Channel.clear()
|
this.room2Channel.clear()
|
||||||
this.channel2Rooms.clear()
|
this.channel2Rooms.clear()
|
||||||
|
this.needSync = true
|
||||||
|
|
||||||
if (typeof data !== 'object') {
|
if (typeof data !== 'object') {
|
||||||
this.logger.error('Invalid room-channel data file content')
|
this.logger.error('Invalid room-channel data file content')
|
||||||
@ -152,9 +156,56 @@ class RoomChannel {
|
|||||||
/**
|
/**
|
||||||
* Rebuilt the data from scratch.
|
* Rebuilt the data from scratch.
|
||||||
* Can be used for the initial migration.
|
* Can be used for the initial migration.
|
||||||
|
* Can also be scheduled daily, or on an admin action (not sure it will be done, at the time of the writing).
|
||||||
*/
|
*/
|
||||||
public async rebuildData (): Promise<void> {
|
public async rebuildData (): Promise<void> {
|
||||||
this.logger.error('rebuildData Not implemented yet')
|
const data: any = {}
|
||||||
|
|
||||||
|
const rooms = await listProsodyRooms(this.options)
|
||||||
|
for (const room of rooms) {
|
||||||
|
let channelId: string | number | undefined
|
||||||
|
|
||||||
|
const matches = room.localpart.match(/^channel\.(\d+)$/)
|
||||||
|
if (matches?.[1]) {
|
||||||
|
channelId = parseInt(matches[1])
|
||||||
|
if (isNaN(channelId)) {
|
||||||
|
this.logger.error(`Invalid room JID '${room.localpart}'`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Checking that channel still exists
|
||||||
|
const channelInfos = await getChannelInfosById(this.options, channelId)
|
||||||
|
if (!channelInfos) {
|
||||||
|
this.logger.debug(
|
||||||
|
`Ignoring room ${room.localpart}, because channel ${channelId} seems to not exist anymore`
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const uuid = room.localpart
|
||||||
|
const video = await this.options.peertubeHelpers.videos.loadByIdOrUUID(uuid)
|
||||||
|
if (!video) {
|
||||||
|
this.logger.debug(
|
||||||
|
`Ignoring room ${room.localpart}, because video ${uuid} seems to not exist anymore`
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
channelId = video.channelId
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!channelId) {
|
||||||
|
this.logger.error(`Did not find channelId for ${room.localpart}`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
channelId = channelId.toString()
|
||||||
|
if (!(channelId in data)) {
|
||||||
|
this.logger.debug(`Room ${room.localpart} is associated to channel ${channelId}`)
|
||||||
|
data[channelId] = [room.localpart]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This part must be done atomicly:
|
||||||
|
this._readData(data)
|
||||||
|
|
||||||
await this.sync() // FIXME: or maybe scheduleSync ?
|
await this.sync() // FIXME: or maybe scheduleSync ?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +213,9 @@ class RoomChannel {
|
|||||||
* Syncs data to disk.
|
* Syncs data to disk.
|
||||||
*/
|
*/
|
||||||
public async sync (): Promise<void> {
|
public async sync (): Promise<void> {
|
||||||
|
if (!this.needSync) { return }
|
||||||
this.logger.error('sync Not implemented yet')
|
this.logger.error('sync Not implemented yet')
|
||||||
|
this.needSync = false // Note: must be done at the right moment
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,6 +223,7 @@ class RoomChannel {
|
|||||||
* Each times data are modified, we can schedule a sync, but we don't have to wait the file writing to be done.
|
* Each times data are modified, we can schedule a sync, but we don't have to wait the file writing to be done.
|
||||||
*/
|
*/
|
||||||
public scheduleSync (): void {
|
public scheduleSync (): void {
|
||||||
|
if (!this.needSync) { return }
|
||||||
this.logger.error('scheduleSync Not implemented yet')
|
this.logger.error('scheduleSync Not implemented yet')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,20 +249,31 @@ class RoomChannel {
|
|||||||
// First, if the room was linked to another channel, we must unlink.
|
// First, if the room was linked to another channel, we must unlink.
|
||||||
const previousChannelId = this.room2Channel.get(roomJID)
|
const previousChannelId = this.room2Channel.get(roomJID)
|
||||||
if (previousChannelId) {
|
if (previousChannelId) {
|
||||||
this.room2Channel.delete(roomJID)
|
if (this.room2Channel.delete(roomJID)) {
|
||||||
|
this.needSync = true
|
||||||
|
}
|
||||||
const previousRooms = this.channel2Rooms.get(previousChannelId)
|
const previousRooms = this.channel2Rooms.get(previousChannelId)
|
||||||
if (previousRooms) {
|
if (previousRooms) {
|
||||||
previousRooms.delete(roomJID)
|
if (previousRooms.delete(roomJID)) {
|
||||||
|
this.needSync = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.room2Channel.set(roomJID, channelId)
|
if (this.room2Channel.get(roomJID) !== channelId) {
|
||||||
|
this.room2Channel.set(roomJID, channelId)
|
||||||
|
this.needSync = true
|
||||||
|
}
|
||||||
let rooms = this.channel2Rooms.get(channelId)
|
let rooms = this.channel2Rooms.get(channelId)
|
||||||
if (!rooms) {
|
if (!rooms) {
|
||||||
rooms = new Map<string, true>()
|
rooms = new Map<string, true>()
|
||||||
this.channel2Rooms.set(channelId, rooms)
|
this.channel2Rooms.set(channelId, rooms)
|
||||||
|
this.needSync = true
|
||||||
|
}
|
||||||
|
if (!rooms.has(roomJID)) {
|
||||||
|
rooms.set(roomJID, true)
|
||||||
|
this.needSync = true
|
||||||
}
|
}
|
||||||
rooms.set(roomJID, true)
|
|
||||||
|
|
||||||
this.scheduleSync()
|
this.scheduleSync()
|
||||||
}
|
}
|
||||||
@ -228,11 +293,15 @@ class RoomChannel {
|
|||||||
if (channelId) {
|
if (channelId) {
|
||||||
const rooms = this.channel2Rooms.get(channelId)
|
const rooms = this.channel2Rooms.get(channelId)
|
||||||
if (rooms) {
|
if (rooms) {
|
||||||
rooms.delete(roomJID)
|
if (rooms.delete(roomJID)) {
|
||||||
|
this.needSync = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.room2Channel.delete(roomJID)
|
if (this.room2Channel.delete(roomJID)) {
|
||||||
|
this.needSync = true
|
||||||
|
}
|
||||||
|
|
||||||
this.scheduleSync()
|
this.scheduleSync()
|
||||||
}
|
}
|
||||||
@ -254,11 +323,14 @@ class RoomChannel {
|
|||||||
// checking the consistency... only removing if the channel is the current one
|
// checking the consistency... only removing if the channel is the current one
|
||||||
if (this.room2Channel.get(jid) === channelId) {
|
if (this.room2Channel.get(jid) === channelId) {
|
||||||
this.room2Channel.delete(jid)
|
this.room2Channel.delete(jid)
|
||||||
|
this.needSync = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.channel2Rooms.delete(channelId)
|
if (this.channel2Rooms.delete(channelId)) {
|
||||||
|
this.needSync = true
|
||||||
|
}
|
||||||
|
|
||||||
this.scheduleSync()
|
this.scheduleSync()
|
||||||
}
|
}
|
||||||
@ -287,4 +359,3 @@ export {
|
|||||||
|
|
||||||
// TODO: schedule rebuild every X hours/days
|
// TODO: schedule rebuild every X hours/days
|
||||||
// TODO: write to disk, debouncing writes
|
// TODO: write to disk, debouncing writes
|
||||||
// TODO: only write if there is data changes
|
|
||||||
|
@ -4,13 +4,13 @@ import type { ProsodyListRoomsResult, ProsodyListRoomsResultRoom } from '../../.
|
|||||||
import { createProxyServer } from 'http-proxy'
|
import { createProxyServer } from 'http-proxy'
|
||||||
import { RegisterServerOptionsV5, isUserAdmin } from '../helpers'
|
import { RegisterServerOptionsV5, isUserAdmin } from '../helpers'
|
||||||
import { asyncMiddleware } from '../middlewares/async'
|
import { asyncMiddleware } from '../middlewares/async'
|
||||||
import { getAPIKey } from '../apikey'
|
|
||||||
import { getChannelInfosById } from '../database/channel'
|
|
||||||
import { isAutoColorsAvailable, areAutoColorsValid, AutoColors } from '../../../shared/lib/autocolors'
|
import { isAutoColorsAvailable, areAutoColorsValid, AutoColors } from '../../../shared/lib/autocolors'
|
||||||
import { fetchMissingRemoteServerInfos } from '../federation/fetch-infos'
|
import { fetchMissingRemoteServerInfos } from '../federation/fetch-infos'
|
||||||
import { getConverseJSParams } from '../conversejs/params'
|
import { getConverseJSParams } from '../conversejs/params'
|
||||||
|
import { setCurrentProsody, delCurrentProsody } from '../prosody/api/host'
|
||||||
|
import { getChannelInfosById } from '../database/channel'
|
||||||
|
import { listProsodyRooms } from '../prosody/api/list-rooms'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
const got = require('got')
|
|
||||||
|
|
||||||
const fs = require('fs').promises
|
const fs = require('fs').promises
|
||||||
|
|
||||||
@ -18,7 +18,6 @@ interface ProsodyProxyInfo {
|
|||||||
host: string
|
host: string
|
||||||
port: string
|
port: string
|
||||||
}
|
}
|
||||||
let currentProsodyProxyInfo: ProsodyProxyInfo | null = null
|
|
||||||
let currentHttpBindProxy: ReturnType<typeof createProxyServer> | null = null
|
let currentHttpBindProxy: ReturnType<typeof createProxyServer> | null = null
|
||||||
let currentWebsocketProxy: ReturnType<typeof createProxyServer> | null = null
|
let currentWebsocketProxy: ReturnType<typeof createProxyServer> | null = null
|
||||||
let currentS2SWebsocketProxy: ReturnType<typeof createProxyServer> | null = null
|
let currentS2SWebsocketProxy: ReturnType<typeof createProxyServer> | null = null
|
||||||
@ -218,21 +217,8 @@ async function initWebchatRouter (options: RegisterServerOptionsV5): Promise<Rou
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentProsodyProxyInfo) {
|
const rooms = await listProsodyRooms(options)
|
||||||
throw new Error('It seems that prosody is not binded... Cant list rooms.')
|
// For the frontend, we are adding channel data if the room is channel specific
|
||||||
}
|
|
||||||
const apiUrl = `http://localhost:${currentProsodyProxyInfo.port}/peertubelivechat_list_rooms/list-rooms`
|
|
||||||
peertubeHelpers.logger.debug('Calling list rooms API on url: ' + apiUrl)
|
|
||||||
const rooms = await got(apiUrl, {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
authorization: 'Bearer ' + await getAPIKey(options),
|
|
||||||
host: currentProsodyProxyInfo.host
|
|
||||||
},
|
|
||||||
responseType: 'json',
|
|
||||||
resolveBodyOnly: true
|
|
||||||
})
|
|
||||||
|
|
||||||
if (Array.isArray(rooms)) {
|
if (Array.isArray(rooms)) {
|
||||||
for (let i = 0; i < rooms.length; i++) {
|
for (let i = 0; i < rooms.length; i++) {
|
||||||
const room: ProsodyListRoomsResultRoom = rooms[i]
|
const room: ProsodyListRoomsResultRoom = rooms[i]
|
||||||
@ -268,7 +254,7 @@ async function disableProxyRoute ({ peertubeHelpers }: RegisterServerOptions): P
|
|||||||
// But this seems to never happen, and stucked the plugin uninstallation.
|
// But this seems to never happen, and stucked the plugin uninstallation.
|
||||||
// So I don't wait.
|
// So I don't wait.
|
||||||
try {
|
try {
|
||||||
currentProsodyProxyInfo = null
|
delCurrentProsody()
|
||||||
if (currentHttpBindProxy) {
|
if (currentHttpBindProxy) {
|
||||||
peertubeHelpers.logger.info('Closing the http bind proxy...')
|
peertubeHelpers.logger.info('Closing the http bind proxy...')
|
||||||
currentHttpBindProxy.close()
|
currentHttpBindProxy.close()
|
||||||
@ -299,7 +285,7 @@ async function enableProxyRoute (
|
|||||||
logger.error(`Port '${prosodyProxyInfo.port}' is not valid. Aborting.`)
|
logger.error(`Port '${prosodyProxyInfo.port}' is not valid. Aborting.`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
currentProsodyProxyInfo = prosodyProxyInfo
|
setCurrentProsody(prosodyProxyInfo.host, prosodyProxyInfo.port)
|
||||||
|
|
||||||
logger.info('Creating a new http bind proxy')
|
logger.info('Creating a new http bind proxy')
|
||||||
currentHttpBindProxy = createProxyServer({
|
currentHttpBindProxy = createProxyServer({
|
||||||
|
@ -63,7 +63,7 @@ We won't use SQL queries, because we only want such information for video that h
|
|||||||
So we will store in the `room-channel/muc_domain.json` file (where `muc_domain` is the actual MUC domain,
|
So we will store in the `room-channel/muc_domain.json` file (where `muc_domain` is the actual MUC domain,
|
||||||
something like `room.instance.tld`) a JSON object representing these relations.
|
something like `room.instance.tld`) a JSON object representing these relations.
|
||||||
|
|
||||||
In the JSON object, keys are the channel ID, values are arrays of strings representing the rooms JIDs local part (without the MUC domain).
|
In the JSON object, keys are the channel ID (as string), values are arrays of strings representing the rooms JIDs local part (without the MUC domain).
|
||||||
|
|
||||||
When a chatroom is created, the corresponding entry will be added.
|
When a chatroom is created, the corresponding entry will be added.
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ Here is a sample file:
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
1: [
|
"1": [
|
||||||
"8df24108-6e70-4fc8-b1cc-f2db7fcdd535"
|
"8df24108-6e70-4fc8-b1cc-f2db7fcdd535"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user