Chat Federation (and a lot more) WIP:

Note: websocket s2s is not working yet, still WIP.

New Features

* Chat Federation:
  * You can now connect to a remote chat with your local account.
  * This remote connection is done using a custom implementation of [XEP-0468: WebSocket S2S](https://xmpp.org/extensions/xep-0468.html), using some specific discovering method (so that it will work without any DNS configuration).

Minor changes and fixes

* Possibility to debug Prosody in development environments.
* Using process.spawn instead of process.exec to launch Prosody (safer, and more optimal).
* Prosody AppImage: fix path mapping: we only map necessary /etc/ subdir, so that the AppImage can access to /etc/resolv.conf, /etc/hosts, ...
* Prosody AppImage: hidden debug mode to disable lua-unbound, that seems broken in some docker dev environments.
This commit is contained in:
John Livingston
2023-05-19 12:52:52 +02:00
parent 1174f661be
commit 9a2da60b7d
27 changed files with 1592 additions and 106 deletions

View File

@ -1,5 +1,5 @@
import type { RegisterServerOptions, MVideoFullLight, MVideoAP, Video, MVideoThumbnail } from '@peertube/peertube-types'
import type { LiveChatJSONLDAttribute } from './types'
import type { LiveChatJSONLDAttribute, LiveChatJSONLDS2SLink, LiveChatJSONLDPeertubeWSS2SLink } from './types'
import { sanitizePeertubeLiveChatInfos } from './sanitize'
import { URL } from 'url'
import * as fs from 'fs'
@ -97,6 +97,60 @@ async function getVideoLiveChatInfos (
return r
}
/**
* When receiving livechat information for remote servers, we store some information
* about remote server capatibilities: has it s2s enabled? can it proxify s2s in Peertube?
* These information can then be read by Prosody module mod_s2s_peertubelivechat.
*
* We simply store the more recent informations. Indeed, it should be consistent between videos.
* @param options server optiosn
* @param liveChatInfos livechat stored data
*/
async function storeRemoteServerInfos (
options: RegisterServerOptions,
liveChatInfos: LiveChatJSONLDAttribute
): Promise<void> {
if (!liveChatInfos) { return }
const logger = options.peertubeHelpers.logger
const roomJID = liveChatInfos.jid
const host = roomJID.split('@')[1]
if (!host) {
logger.error(`Room JID seems not correct, no host: ${roomJID}`)
return
}
if (host.includes('..')) {
logger.error(`Room host seems not correct, contains ..: ${host}`)
return
}
const dir = path.resolve(
options.peertubeHelpers.plugin.getDataDirectoryPath(),
'serverInfos',
host
)
const s2sFilePath = path.resolve(dir, 's2s')
const wsS2SFilePath = path.resolve(dir, 'ws-s2s')
const s2sLink = liveChatInfos.links.find(v => v.type === 'xmpp-s2s')
if (s2sLink) {
await _store(options, s2sFilePath, {
host: (s2sLink as LiveChatJSONLDS2SLink).host,
port: (s2sLink as LiveChatJSONLDS2SLink).port
})
} else {
await _del(options, s2sFilePath)
}
const wsS2SLink = liveChatInfos.links.find(v => v.type === 'xmpp-peertube-livechat-ws-s2s')
if (wsS2SLink) {
await _store(options, wsS2SFilePath, {
url: (wsS2SLink as LiveChatJSONLDPeertubeWSS2SLink).url
})
} else {
await _del(options, wsS2SFilePath)
}
}
async function _getFilePath (
options: RegisterServerOptions,
remote: boolean,
@ -152,13 +206,22 @@ async function _del (options: RegisterServerOptions, filePath: string): Promise<
async function _store (options: RegisterServerOptions, filePath: string, content: any): Promise<void> {
const logger = options.peertubeHelpers.logger
try {
const jsonContent = JSON.stringify(content)
if (!fs.existsSync(filePath)) {
const dir = path.dirname(filePath)
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true })
}
} else {
// only write if the content is different
try {
const currentJSONContent = await fs.promises.readFile(filePath, {
encoding: 'utf-8'
})
if (currentJSONContent === jsonContent) { return }
} catch (_err) {}
}
await fs.promises.writeFile(filePath, JSON.stringify(content), {
await fs.promises.writeFile(filePath, jsonContent, {
encoding: 'utf-8'
})
} catch (err) {
@ -182,7 +245,16 @@ async function _get (options: RegisterServerOptions, filePath: string): Promise<
}
}
function getRemoteServerInfosDir (options: RegisterServerOptions): string {
return path.resolve(
options.peertubeHelpers.plugin.getDataDirectoryPath(),
'serverInfos'
)
}
export {
storeVideoLiveChatInfos,
getVideoLiveChatInfos
storeRemoteServerInfos,
getVideoLiveChatInfos,
getRemoteServerInfosDir
}