From 9d4c60dccc8e7e777ad139a82e9f61feda9d21fc Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 11 Oct 2022 11:07:40 +0200 Subject: Add ability for plugins to register ws routes --- server/lib/plugins/plugin-helpers-builder.ts | 13 ++++++++---- server/lib/plugins/plugin-manager.ts | 31 +++++++++++++++++++++++++++- server/lib/plugins/register-helpers.ts | 21 +++++++++++++++++-- 3 files changed, 58 insertions(+), 7 deletions(-) (limited to 'server/lib/plugins') diff --git a/server/lib/plugins/plugin-helpers-builder.ts b/server/lib/plugins/plugin-helpers-builder.ts index 35945422c..7b1def6e3 100644 --- a/server/lib/plugins/plugin-helpers-builder.ts +++ b/server/lib/plugins/plugin-helpers-builder.ts @@ -1,4 +1,5 @@ import express from 'express' +import { Server } from 'http' import { join } from 'path' import { ffprobePromise } from '@server/helpers/ffmpeg/ffprobe-utils' import { buildLogger } from '@server/helpers/logger' @@ -17,12 +18,12 @@ import { MPlugin, MVideo, UserNotificationModelForApi } from '@server/types/mode import { PeerTubeHelpers } from '@server/types/plugins' import { VideoBlacklistCreate, VideoStorage } from '@shared/models' import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../blocklist' +import { PeerTubeSocket } from '../peertube-socket' import { ServerConfigManager } from '../server-config-manager' import { blacklistVideo, unblacklistVideo } from '../video-blacklist' import { VideoPathManager } from '../video-path-manager' -import { PeerTubeSocket } from '../peertube-socket' -function buildPluginHelpers (pluginModel: MPlugin, npmName: string): PeerTubeHelpers { +function buildPluginHelpers (httpServer: Server, pluginModel: MPlugin, npmName: string): PeerTubeHelpers { const logger = buildPluginLogger(npmName) const database = buildDatabaseHelpers() @@ -30,7 +31,7 @@ function buildPluginHelpers (pluginModel: MPlugin, npmName: string): PeerTubeHel const config = buildConfigHelpers() - const server = buildServerHelpers() + const server = buildServerHelpers(httpServer) const moderation = buildModerationHelpers() @@ -69,8 +70,10 @@ function buildDatabaseHelpers () { } } -function buildServerHelpers () { +function buildServerHelpers (httpServer: Server) { return { + getHTTPServer: () => httpServer, + getServerActor: () => getServerActor() } } @@ -218,6 +221,8 @@ function buildPluginRelatedHelpers (plugin: MPlugin, npmName: string) { getBaseRouterRoute: () => `/plugins/${plugin.name}/${plugin.version}/router/`, + getBaseWebSocketRoute: () => `/plugins/${plugin.name}/${plugin.version}/ws/`, + getDataDirectoryPath: () => join(CONFIG.STORAGE.PLUGINS_DIR, 'data', npmName) } } diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts index a46b97fa4..c4d9b6574 100644 --- a/server/lib/plugins/plugin-manager.ts +++ b/server/lib/plugins/plugin-manager.ts @@ -1,6 +1,7 @@ import express from 'express' import { createReadStream, createWriteStream } from 'fs' import { ensureDir, outputFile, readJSON } from 'fs-extra' +import { Server } from 'http' import { basename, join } from 'path' import { decachePlugin } from '@server/helpers/decache' import { ApplicationModel } from '@server/models/application/application' @@ -67,9 +68,37 @@ export class PluginManager implements ServerHook { private hooks: { [name: string]: HookInformationValue[] } = {} private translations: PluginLocalesTranslations = {} + private server: Server + private constructor () { } + init (server: Server) { + this.server = server + } + + registerWebSocketRouter () { + this.server.on('upgrade', (request, socket, head) => { + const url = request.url + + const matched = url.match(`/plugins/([^/]+)/([^/]+/)?ws(/.*)`) + if (!matched) return + + const npmName = PluginModel.buildNpmName(matched[1], PluginType.PLUGIN) + const subRoute = matched[3] + + const result = this.getRegisteredPluginOrTheme(npmName) + if (!result) return + + const routes = result.registerHelpers.getWebSocketRoutes() + + const wss = routes.find(r => r.route.startsWith(subRoute)) + if (!wss) return + + wss.handler(request, socket, head) + }) + } + // ###################### Getters ###################### isRegistered (npmName: string) { @@ -581,7 +610,7 @@ export class PluginManager implements ServerHook { }) } - const registerHelpers = new RegisterHelpers(npmName, plugin, onHookAdded.bind(this)) + const registerHelpers = new RegisterHelpers(npmName, plugin, this.server, onHookAdded.bind(this)) return { registerStore: registerHelpers, diff --git a/server/lib/plugins/register-helpers.ts b/server/lib/plugins/register-helpers.ts index f4d405676..1aaef3606 100644 --- a/server/lib/plugins/register-helpers.ts +++ b/server/lib/plugins/register-helpers.ts @@ -1,4 +1,5 @@ import express from 'express' +import { Server } from 'http' import { logger } from '@server/helpers/logger' import { onExternalUserAuthenticated } from '@server/lib/auth/external-auth' import { VideoConstantManagerFactory } from '@server/lib/plugins/video-constant-manager-factory' @@ -8,7 +9,8 @@ import { RegisterServerAuthExternalResult, RegisterServerAuthPassOptions, RegisterServerExternalAuthenticatedResult, - RegisterServerOptions + RegisterServerOptions, + RegisterServerWebSocketRouteOptions } from '@server/types/plugins' import { EncoderOptionsBuilder, @@ -49,12 +51,15 @@ export class RegisterHelpers { private readonly onSettingsChangeCallbacks: SettingsChangeCallback[] = [] + private readonly webSocketRoutes: RegisterServerWebSocketRouteOptions[] = [] + private readonly router: express.Router private readonly videoConstantManagerFactory: VideoConstantManagerFactory constructor ( private readonly npmName: string, private readonly plugin: PluginModel, + private readonly server: Server, private readonly onHookAdded: (options: RegisterServerHookOptions) => void ) { this.router = express.Router() @@ -66,6 +71,7 @@ export class RegisterHelpers { const registerSetting = this.buildRegisterSetting() const getRouter = this.buildGetRouter() + const registerWebSocketRoute = this.buildRegisterWebSocketRoute() const settingsManager = this.buildSettingsManager() const storageManager = this.buildStorageManager() @@ -85,13 +91,14 @@ export class RegisterHelpers { const unregisterIdAndPassAuth = this.buildUnregisterIdAndPassAuth() const unregisterExternalAuth = this.buildUnregisterExternalAuth() - const peertubeHelpers = buildPluginHelpers(this.plugin, this.npmName) + const peertubeHelpers = buildPluginHelpers(this.server, this.plugin, this.npmName) return { registerHook, registerSetting, getRouter, + registerWebSocketRoute, settingsManager, storageManager, @@ -180,10 +187,20 @@ export class RegisterHelpers { return this.onSettingsChangeCallbacks } + getWebSocketRoutes () { + return this.webSocketRoutes + } + private buildGetRouter () { return () => this.router } + private buildRegisterWebSocketRoute () { + return (options: RegisterServerWebSocketRouteOptions) => { + this.webSocketRoutes.push(options) + } + } + private buildRegisterSetting () { return (options: RegisterServerSettingOptions) => { this.settings.push(options) -- cgit v1.2.3