Fix #87: updating chat room title when video/channel title is changed:
* renaming module list_rooms to manage_rooms * added some API to update room info * when a video or a channel is updated, sending an API call to update the room
This commit is contained in:
parent
2115b352a4
commit
4dd4f18965
@ -2,6 +2,7 @@
|
||||
|
||||
## ??? (Not Released Yet)
|
||||
|
||||
* Fix #87: updating chat room title when video/channel title is changed.
|
||||
* Updating xmppjs-chat-box version.
|
||||
|
||||
## 8.3.2
|
||||
|
@ -1,5 +1,5 @@
|
||||
# mod_http_peertubelivechat_list_rooms
|
||||
# mod_http_peertubelivechat_manage_rooms
|
||||
|
||||
This module is a custom module that allows Peertube server to list chat rooms.
|
||||
This module is a custom module that allows Peertube server to list chat rooms, and update some meta data.
|
||||
|
||||
This module is part of peertube-plugin-livechat, and is under the same LICENSE.
|
@ -1,15 +1,17 @@
|
||||
local json = require "util.json";
|
||||
local jid_split = require"util.jid".split;
|
||||
local array = require "util.array";
|
||||
local st = require "util.stanza";
|
||||
|
||||
local mod_muc = module:depends"muc";
|
||||
local all_rooms = rawget(mod_muc, "all_rooms")
|
||||
local all_rooms = rawget(mod_muc, "all_rooms");
|
||||
local get_room_from_jid = rawget(mod_muc, "get_room_from_jid");
|
||||
|
||||
module:depends"http";
|
||||
|
||||
function check_auth(routes)
|
||||
local function check_request_auth(event)
|
||||
local apikey = module:get_option_string("peertubelivechat_list_rooms_apikey", "")
|
||||
local apikey = module:get_option_string("peertubelivechat_manage_rooms_apikey", "")
|
||||
if apikey == "" then
|
||||
return false, 500;
|
||||
end
|
||||
@ -55,8 +57,51 @@ local function list_rooms(event)
|
||||
return json.encode_array(rooms_json);
|
||||
end
|
||||
|
||||
local function update_room(event)
|
||||
local request, response = event.request, event.response;
|
||||
event.response.headers["Content-Type"] = "application/json";
|
||||
|
||||
local config = json.decode(request.body);
|
||||
if not config.jid then
|
||||
return json.encode({
|
||||
result = "failed";
|
||||
});
|
||||
end
|
||||
|
||||
local room = get_room_from_jid(config.jid);
|
||||
if not room then
|
||||
return json.encode({
|
||||
result = "failed";
|
||||
});
|
||||
end
|
||||
|
||||
local must104 = false;
|
||||
|
||||
if type(config.name) == "string" then
|
||||
if room:get_name() ~= config.name then
|
||||
room:set_name(config.name);
|
||||
must104 = true;
|
||||
end
|
||||
end
|
||||
|
||||
if must104 then
|
||||
-- we must broadcast a status 104 message, so that clients can update room info
|
||||
local msg = st.message({type='groupchat', from=room.jid})
|
||||
:tag('x', {xmlns='http://jabber.org/protocol/muc#user'})
|
||||
msg:tag("status", {code = '104';}):up();
|
||||
msg:up();
|
||||
room:broadcast_message(msg);
|
||||
end
|
||||
|
||||
return json.encode({
|
||||
result = "ok";
|
||||
changed = must104;
|
||||
});
|
||||
end
|
||||
|
||||
module:provides("http", {
|
||||
route = check_auth {
|
||||
["GET /list-rooms"] = list_rooms;
|
||||
["POST /update-room"] = update_room;
|
||||
};
|
||||
});
|
@ -2,6 +2,8 @@ import type { RegisterServerOptions, MVideoFullLight, VideoChannel } from '@peer
|
||||
import { RoomChannel } from '../../room-channel'
|
||||
import { fillVideoCustomFields } from '../../custom-fields'
|
||||
import { videoHasWebchat } from '../../../../shared/lib/video'
|
||||
import { updateProsodyRoom } from '../../prosody/api/manage-rooms'
|
||||
import { getChannelInfosById } from '../../database/channel'
|
||||
|
||||
/**
|
||||
* Register stuffs related to channel configuration
|
||||
@ -98,11 +100,48 @@ async function initChannelConfiguration (options: RegisterServerOptions): Promis
|
||||
|
||||
logger.debug(`Ensuring a room-channel link between room ${roomLocalPart} and channel ${video.channelId}`)
|
||||
RoomChannel.singleton().link(video.channelId, roomLocalPart)
|
||||
|
||||
if (settings['prosody-room-type'] === 'video') {
|
||||
// Also updating chatroom meta data.
|
||||
// FIXME: this piece of code should not be in this file (nothing to do with initChannelConfiguration,
|
||||
// but will be more efficient to add here, as we already tested hasChat).
|
||||
// Note: no need to await here, would only degrade performances.
|
||||
updateProsodyRoom(options, video.channelId, video.uuid, {
|
||||
name: video.name
|
||||
}).then(
|
||||
() => {},
|
||||
(err) => logger.error(err)
|
||||
)
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
registerHook({
|
||||
target: 'action:api.video-channel.updated',
|
||||
handler: async (params: { videoChannel: VideoChannel }) => {
|
||||
const channel = await getChannelInfosById(options, params.videoChannel.id, true)
|
||||
if (!channel) { return }
|
||||
|
||||
// FIXME: this piece of code should not be in this file (nothing to do with initChannelConfiguration,
|
||||
// but for now i keep it close to the similar code on video.updated hook).
|
||||
const settings = await options.settingsManager.getSettings([
|
||||
'prosody-room-type'
|
||||
])
|
||||
if (settings['prosody-room-type'] === 'channel') {
|
||||
const jid = 'channel.' + channel.id.toString()
|
||||
// Note: no need to await here, would only degrade performances.
|
||||
updateProsodyRoom(options, channel.id, jid, {
|
||||
name: channel.displayName
|
||||
}).then(
|
||||
() => {},
|
||||
(err) => logger.error(err)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
|
@ -1,41 +0,0 @@
|
||||
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
|
||||
}
|
110
server/lib/prosody/api/manage-rooms.ts
Normal file
110
server/lib/prosody/api/manage-rooms.ts
Normal file
@ -0,0 +1,110 @@
|
||||
import type { RegisterServerOptions } from '@peertube/peertube-types'
|
||||
import { getCurrentProsody } from './host'
|
||||
import { getAPIKey } from '../../apikey'
|
||||
import { getProsodyDomain } from '../config/domain'
|
||||
const got = require('got')
|
||||
|
||||
interface ProsodyRoomDesc {
|
||||
jid: string
|
||||
localpart: string
|
||||
name: string
|
||||
lang: string
|
||||
description: string
|
||||
lasttimestamp?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists existing chatrooms.
|
||||
* @param options Peertube server options
|
||||
* @returns List of chat rooms on the Prosody server
|
||||
*/
|
||||
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_manage_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
|
||||
}
|
||||
|
||||
/**
|
||||
* Update room metadata on the Prosody server.
|
||||
* Uses an API provided by mod_http_peertubelivechat_manage_rooms.
|
||||
*
|
||||
* Note: could be called without verifying that the room exists.
|
||||
* On the Prosody side, non existing rooms will be ignored.
|
||||
* @param options Peertube server options
|
||||
* @param channelId associated channelId
|
||||
* @param jid Room JID (can be only the local part, or the local + domain)
|
||||
* @param data Data to update
|
||||
* @returns true if success
|
||||
*/
|
||||
async function updateProsodyRoom (
|
||||
options: RegisterServerOptions,
|
||||
channelId: number | string,
|
||||
jid: string,
|
||||
data: {
|
||||
name: string
|
||||
}
|
||||
): Promise<boolean> {
|
||||
const logger = options.peertubeHelpers.logger
|
||||
|
||||
const currentProsody = getCurrentProsody()
|
||||
if (!currentProsody) {
|
||||
throw new Error('It seems that prosody is not binded... Cant update room.')
|
||||
}
|
||||
|
||||
if (!jid.includes('@')) {
|
||||
jid = jid + '@room.' + await getProsodyDomain(options)
|
||||
}
|
||||
|
||||
logger.debug('Calling update room for ' + jid)
|
||||
|
||||
// Requesting on localhost, because currentProsody.host does not always resolves correctly (docker use case, ...)
|
||||
const apiUrl = `http://localhost:${currentProsody.port}/peertubelivechat_manage_rooms/update-room`
|
||||
const apiData = {
|
||||
jid,
|
||||
name: data.name
|
||||
}
|
||||
try {
|
||||
logger.debug('Calling update room API on url: ' + apiUrl + ', with data: ' + JSON.stringify(apiData))
|
||||
const result = await got(apiUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
authorization: 'Bearer ' + await getAPIKey(options),
|
||||
host: currentProsody.host
|
||||
},
|
||||
json: apiData,
|
||||
responseType: 'json',
|
||||
resolveBodyOnly: true
|
||||
})
|
||||
|
||||
logger.debug('Update room API response: ' + JSON.stringify(result))
|
||||
} catch (err) {
|
||||
// We consider it is not very bad if the metadata are not correctly updated.
|
||||
// Nothing too important.
|
||||
logger.error(`Failed to update room: ' ${err as string}`)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export {
|
||||
listProsodyRooms,
|
||||
updateProsodyRoom
|
||||
}
|
@ -313,7 +313,7 @@ async function getProsodyConfig (options: RegisterServerOptionsV5): Promise<Pros
|
||||
// TODO: add a settings to choose?
|
||||
config.useDefaultPersistent()
|
||||
|
||||
config.useListRoomsApi(apikey)
|
||||
config.useManageRoomsApi(apikey)
|
||||
config.usePeertubeVCards(basePeertubeUrl)
|
||||
config.useAnonymousRandomVCards(paths.avatars, paths.avatarsFiles)
|
||||
|
||||
|
@ -415,9 +415,9 @@ class ProsodyConfigContent {
|
||||
this.muc.set('muc_room_default_persistent', true)
|
||||
}
|
||||
|
||||
useListRoomsApi (apikey: string): void {
|
||||
this.muc.add('modules_enabled', 'http_peertubelivechat_list_rooms')
|
||||
this.muc.set('peertubelivechat_list_rooms_apikey', apikey)
|
||||
useManageRoomsApi (apikey: string): void {
|
||||
this.muc.add('modules_enabled', 'http_peertubelivechat_manage_rooms')
|
||||
this.muc.set('peertubelivechat_manage_rooms_apikey', apikey)
|
||||
}
|
||||
|
||||
useTestModule (prosodyApikey: string, apiurl: string): void {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { RegisterServerOptions } from '@peertube/peertube-types'
|
||||
import type { RoomConf } from 'xmppjs-chat-bot'
|
||||
import { getProsodyDomain } from '../prosody/config/domain'
|
||||
import { listProsodyRooms } from '../prosody/api/list-rooms'
|
||||
import { listProsodyRooms } from '../prosody/api/manage-rooms'
|
||||
import { getChannelInfosById } from '../database/channel'
|
||||
import { ChannelConfigurationOptions } from '../../../shared/lib/types'
|
||||
import {
|
||||
|
@ -9,7 +9,7 @@ import { fetchMissingRemoteServerInfos } from '../federation/fetch-infos'
|
||||
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 { listProsodyRooms } from '../prosody/api/manage-rooms'
|
||||
import * as path from 'path'
|
||||
|
||||
const fs = require('fs').promises
|
||||
|
Loading…
x
Reference in New Issue
Block a user