diff options
Diffstat (limited to 'server/lib/plugins')
-rw-r--r-- | server/lib/plugins/plugin-helpers-builder.ts | 60 | ||||
-rw-r--r-- | server/lib/plugins/plugin-manager.ts | 24 |
2 files changed, 73 insertions, 11 deletions
diff --git a/server/lib/plugins/plugin-helpers-builder.ts b/server/lib/plugins/plugin-helpers-builder.ts index e26776f45..78e4a28ad 100644 --- a/server/lib/plugins/plugin-helpers-builder.ts +++ b/server/lib/plugins/plugin-helpers-builder.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { join } from 'path' | 2 | import { join } from 'path' |
3 | import { ffprobePromise } from '@server/helpers/ffprobe-utils' | ||
3 | import { buildLogger } from '@server/helpers/logger' | 4 | import { buildLogger } from '@server/helpers/logger' |
4 | import { CONFIG } from '@server/initializers/config' | 5 | import { CONFIG } from '@server/initializers/config' |
5 | import { WEBSERVER } from '@server/initializers/constants' | 6 | import { WEBSERVER } from '@server/initializers/constants' |
@@ -9,15 +10,16 @@ import { AccountBlocklistModel } from '@server/models/account/account-blocklist' | |||
9 | import { getServerActor } from '@server/models/application/application' | 10 | import { getServerActor } from '@server/models/application/application' |
10 | import { ServerModel } from '@server/models/server/server' | 11 | import { ServerModel } from '@server/models/server/server' |
11 | import { ServerBlocklistModel } from '@server/models/server/server-blocklist' | 12 | import { ServerBlocklistModel } from '@server/models/server/server-blocklist' |
13 | import { UserModel } from '@server/models/user/user' | ||
12 | import { VideoModel } from '@server/models/video/video' | 14 | import { VideoModel } from '@server/models/video/video' |
13 | import { VideoBlacklistModel } from '@server/models/video/video-blacklist' | 15 | import { VideoBlacklistModel } from '@server/models/video/video-blacklist' |
14 | import { MPlugin } from '@server/types/models' | 16 | import { MPlugin } from '@server/types/models' |
15 | import { PeerTubeHelpers } from '@server/types/plugins' | 17 | import { PeerTubeHelpers } from '@server/types/plugins' |
16 | import { VideoBlacklistCreate } from '@shared/models' | 18 | import { VideoBlacklistCreate, VideoStorage } from '@shared/models' |
17 | import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../blocklist' | 19 | import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../blocklist' |
18 | import { ServerConfigManager } from '../server-config-manager' | 20 | import { ServerConfigManager } from '../server-config-manager' |
19 | import { blacklistVideo, unblacklistVideo } from '../video-blacklist' | 21 | import { blacklistVideo, unblacklistVideo } from '../video-blacklist' |
20 | import { UserModel } from '@server/models/user/user' | 22 | import { VideoPathManager } from '../video-path-manager' |
21 | 23 | ||
22 | function buildPluginHelpers (pluginModel: MPlugin, npmName: string): PeerTubeHelpers { | 24 | function buildPluginHelpers (pluginModel: MPlugin, npmName: string): PeerTubeHelpers { |
23 | const logger = buildPluginLogger(npmName) | 25 | const logger = buildPluginLogger(npmName) |
@@ -85,6 +87,60 @@ function buildVideosHelpers () { | |||
85 | 87 | ||
86 | await video.destroy({ transaction: t }) | 88 | await video.destroy({ transaction: t }) |
87 | }) | 89 | }) |
90 | }, | ||
91 | |||
92 | ffprobe: (path: string) => { | ||
93 | return ffprobePromise(path) | ||
94 | }, | ||
95 | |||
96 | getFiles: async (id: number | string) => { | ||
97 | const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(id) | ||
98 | if (!video) return undefined | ||
99 | |||
100 | const webtorrentVideoFiles = (video.VideoFiles || []).map(f => ({ | ||
101 | path: f.storage === VideoStorage.FILE_SYSTEM | ||
102 | ? VideoPathManager.Instance.getFSVideoFileOutputPath(video, f) | ||
103 | : null, | ||
104 | url: f.getFileUrl(video), | ||
105 | |||
106 | resolution: f.resolution, | ||
107 | size: f.size, | ||
108 | fps: f.fps | ||
109 | })) | ||
110 | |||
111 | const hls = video.getHLSPlaylist() | ||
112 | |||
113 | const hlsVideoFiles = hls | ||
114 | ? (video.getHLSPlaylist().VideoFiles || []).map(f => { | ||
115 | return { | ||
116 | path: f.storage === VideoStorage.FILE_SYSTEM | ||
117 | ? VideoPathManager.Instance.getFSVideoFileOutputPath(hls, f) | ||
118 | : null, | ||
119 | url: f.getFileUrl(video), | ||
120 | resolution: f.resolution, | ||
121 | size: f.size, | ||
122 | fps: f.fps | ||
123 | } | ||
124 | }) | ||
125 | : [] | ||
126 | |||
127 | const thumbnails = video.Thumbnails.map(t => ({ | ||
128 | type: t.type, | ||
129 | url: t.getFileUrl(video), | ||
130 | path: t.getPath() | ||
131 | })) | ||
132 | |||
133 | return { | ||
134 | webtorrent: { | ||
135 | videoFiles: webtorrentVideoFiles | ||
136 | }, | ||
137 | |||
138 | hls: { | ||
139 | videoFiles: hlsVideoFiles | ||
140 | }, | ||
141 | |||
142 | thumbnails | ||
143 | } | ||
88 | } | 144 | } |
89 | } | 145 | } |
90 | } | 146 | } |
diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts index d4d2a7edc..39e7f9a5b 100644 --- a/server/lib/plugins/plugin-manager.ts +++ b/server/lib/plugins/plugin-manager.ts | |||
@@ -1,11 +1,17 @@ | |||
1 | import decache from 'decache' | ||
2 | import express from 'express' | 1 | import express from 'express' |
3 | import { createReadStream, createWriteStream } from 'fs' | 2 | import { createReadStream, createWriteStream } from 'fs' |
4 | import { ensureDir, outputFile, readJSON } from 'fs-extra' | 3 | import { ensureDir, outputFile, readJSON } from 'fs-extra' |
5 | import { basename, join } from 'path' | 4 | import { basename, join } from 'path' |
5 | import { decachePlugin } from '@server/helpers/decache' | ||
6 | import { MOAuthTokenUser, MUser } from '@server/types/models' | 6 | import { MOAuthTokenUser, MUser } from '@server/types/models' |
7 | import { getCompleteLocale } from '@shared/core-utils' | 7 | import { getCompleteLocale } from '@shared/core-utils' |
8 | import { ClientScript, PluginPackageJson, PluginTranslation, PluginTranslationPaths, RegisterServerHookOptions } from '@shared/models' | 8 | import { |
9 | ClientScriptJSON, | ||
10 | PluginPackageJSON, | ||
11 | PluginTranslation, | ||
12 | PluginTranslationPathsJSON, | ||
13 | RegisterServerHookOptions | ||
14 | } from '@shared/models' | ||
9 | import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks' | 15 | import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks' |
10 | import { PluginType } from '../../../shared/models/plugins/plugin.type' | 16 | import { PluginType } from '../../../shared/models/plugins/plugin.type' |
11 | import { ServerHook, ServerHookName } from '../../../shared/models/plugins/server/server-hook.model' | 17 | import { ServerHook, ServerHookName } from '../../../shared/models/plugins/server/server-hook.model' |
@@ -31,7 +37,7 @@ export interface RegisteredPlugin { | |||
31 | path: string | 37 | path: string |
32 | 38 | ||
33 | staticDirs: { [name: string]: string } | 39 | staticDirs: { [name: string]: string } |
34 | clientScripts: { [name: string]: ClientScript } | 40 | clientScripts: { [name: string]: ClientScriptJSON } |
35 | 41 | ||
36 | css: string[] | 42 | css: string[] |
37 | 43 | ||
@@ -392,7 +398,7 @@ export class PluginManager implements ServerHook { | |||
392 | registerHelpers = result.registerStore | 398 | registerHelpers = result.registerStore |
393 | } | 399 | } |
394 | 400 | ||
395 | const clientScripts: { [id: string]: ClientScript } = {} | 401 | const clientScripts: { [id: string]: ClientScriptJSON } = {} |
396 | for (const c of packageJSON.clientScripts) { | 402 | for (const c of packageJSON.clientScripts) { |
397 | clientScripts[c.script] = c | 403 | clientScripts[c.script] = c |
398 | } | 404 | } |
@@ -415,12 +421,12 @@ export class PluginManager implements ServerHook { | |||
415 | await this.addTranslations(plugin, npmName, packageJSON.translations) | 421 | await this.addTranslations(plugin, npmName, packageJSON.translations) |
416 | } | 422 | } |
417 | 423 | ||
418 | private async registerPlugin (plugin: PluginModel, pluginPath: string, packageJSON: PluginPackageJson) { | 424 | private async registerPlugin (plugin: PluginModel, pluginPath: string, packageJSON: PluginPackageJSON) { |
419 | const npmName = PluginModel.buildNpmName(plugin.name, plugin.type) | 425 | const npmName = PluginModel.buildNpmName(plugin.name, plugin.type) |
420 | 426 | ||
421 | // Delete cache if needed | 427 | // Delete cache if needed |
422 | const modulePath = join(pluginPath, packageJSON.library) | 428 | const modulePath = join(pluginPath, packageJSON.library) |
423 | decache(modulePath) | 429 | decachePlugin(pluginPath, modulePath) |
424 | const library: PluginLibrary = require(modulePath) | 430 | const library: PluginLibrary = require(modulePath) |
425 | 431 | ||
426 | if (!isLibraryCodeValid(library)) { | 432 | if (!isLibraryCodeValid(library)) { |
@@ -442,7 +448,7 @@ export class PluginManager implements ServerHook { | |||
442 | 448 | ||
443 | // ###################### Translations ###################### | 449 | // ###################### Translations ###################### |
444 | 450 | ||
445 | private async addTranslations (plugin: PluginModel, npmName: string, translationPaths: PluginTranslationPaths) { | 451 | private async addTranslations (plugin: PluginModel, npmName: string, translationPaths: PluginTranslationPathsJSON) { |
446 | for (const locale of Object.keys(translationPaths)) { | 452 | for (const locale of Object.keys(translationPaths)) { |
447 | const path = translationPaths[locale] | 453 | const path = translationPaths[locale] |
448 | const json = await readJSON(join(this.getPluginPath(plugin.name, plugin.type), path)) | 454 | const json = await readJSON(join(this.getPluginPath(plugin.name, plugin.type), path)) |
@@ -513,7 +519,7 @@ export class PluginManager implements ServerHook { | |||
513 | private getPackageJSON (pluginName: string, pluginType: PluginType) { | 519 | private getPackageJSON (pluginName: string, pluginType: PluginType) { |
514 | const pluginPath = join(this.getPluginPath(pluginName, pluginType), 'package.json') | 520 | const pluginPath = join(this.getPluginPath(pluginName, pluginType), 'package.json') |
515 | 521 | ||
516 | return readJSON(pluginPath) as Promise<PluginPackageJson> | 522 | return readJSON(pluginPath) as Promise<PluginPackageJSON> |
517 | } | 523 | } |
518 | 524 | ||
519 | private getPluginPath (pluginName: string, pluginType: PluginType) { | 525 | private getPluginPath (pluginName: string, pluginType: PluginType) { |
@@ -572,7 +578,7 @@ export class PluginManager implements ServerHook { | |||
572 | } | 578 | } |
573 | } | 579 | } |
574 | 580 | ||
575 | private sanitizeAndCheckPackageJSONOrThrow (packageJSON: PluginPackageJson, pluginType: PluginType) { | 581 | private sanitizeAndCheckPackageJSONOrThrow (packageJSON: PluginPackageJSON, pluginType: PluginType) { |
576 | if (!packageJSON.staticDirs) packageJSON.staticDirs = {} | 582 | if (!packageJSON.staticDirs) packageJSON.staticDirs = {} |
577 | if (!packageJSON.css) packageJSON.css = [] | 583 | if (!packageJSON.css) packageJSON.css = [] |
578 | if (!packageJSON.clientScripts) packageJSON.clientScripts = [] | 584 | if (!packageJSON.clientScripts) packageJSON.clientScripts = [] |