]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Introduce generic video constant manager for plugins 4251/head
authorlutangar <johan.dufour@gmail.com>
Tue, 29 Jun 2021 14:02:05 +0000 (16:02 +0200)
committerlutangar <johan.dufour@gmail.com>
Fri, 16 Jul 2021 15:49:40 +0000 (17:49 +0200)
Allow a plugin developer to get back constants values,
and reset constants deletions or additions.

12 files changed:
server/lib/plugins/register-helpers.ts
server/lib/plugins/video-constant-manager-factory.ts [new file with mode: 0644]
server/tests/fixtures/peertube-plugin-test-video-constants/main.js
server/tests/lib/plugins/video-constant-registry-factory.test.ts [new file with mode: 0644]
server/tests/plugins/video-constants.ts
shared/models/plugins/server/managers/plugin-playlist-privacy-manager.model.ts
shared/models/plugins/server/managers/plugin-video-category-manager.model.ts
shared/models/plugins/server/managers/plugin-video-language-manager.model.ts
shared/models/plugins/server/managers/plugin-video-licence-manager.model.ts
shared/models/plugins/server/managers/plugin-video-privacy-manager.model.ts
shared/models/plugins/server/plugin-constant-manager.model.ts [new file with mode: 0644]
support/doc/plugins/guide.md

index 09275f9ba8ea6e59a268bc9b2a5243931e8f980b..af533effd8100700098235afd48c5f11304d9dbd 100644 (file)
@@ -1,13 +1,7 @@
 import * as express from 'express'
 import { logger } from '@server/helpers/logger'
-import {
-  VIDEO_CATEGORIES,
-  VIDEO_LANGUAGES,
-  VIDEO_LICENCES,
-  VIDEO_PLAYLIST_PRIVACIES,
-  VIDEO_PRIVACIES
-} from '@server/initializers/constants'
 import { onExternalUserAuthenticated } from '@server/lib/auth/external-auth'
+import { VideoConstantManagerFactory } from '@server/lib/plugins/video-constant-manager-factory'
 import { PluginModel } from '@server/models/server/plugin'
 import {
   RegisterServerAuthExternalOptions,
@@ -18,41 +12,18 @@ import {
 } from '@server/types/plugins'
 import {
   EncoderOptionsBuilder,
-  PluginPlaylistPrivacyManager,
   PluginSettingsManager,
   PluginStorageManager,
-  PluginVideoCategoryManager,
-  PluginVideoLanguageManager,
-  PluginVideoLicenceManager,
-  PluginVideoPrivacyManager,
   RegisterServerHookOptions,
   RegisterServerSettingOptions,
-  serverHookObject
+  serverHookObject,
+  VideoPlaylistPrivacy,
+  VideoPrivacy
 } from '@shared/models'
 import { VideoTranscodingProfilesManager } from '../transcoding/video-transcoding-profiles'
 import { buildPluginHelpers } from './plugin-helpers-builder'
 
-type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy'
-type VideoConstant = { [key in number | string]: string }
-
-type UpdatedVideoConstant = {
-  [name in AlterableVideoConstant]: {
-    [ npmName: string]: {
-      added: { key: number | string, label: string }[]
-      deleted: { key: number | string, label: string }[]
-    }
-  }
-}
-
 export class RegisterHelpers {
-  private readonly updatedVideoConstants: UpdatedVideoConstant = {
-    playlistPrivacy: { },
-    privacy: { },
-    language: { },
-    licence: { },
-    category: { }
-  }
-
   private readonly transcodingProfiles: {
     [ npmName: string ]: {
       type: 'vod' | 'live'
@@ -78,6 +49,7 @@ export class RegisterHelpers {
   private readonly onSettingsChangeCallbacks: ((settings: any) => Promise<any>)[] = []
 
   private readonly router: express.Router
+  private readonly videoConstantManagerFactory: VideoConstantManagerFactory
 
   constructor (
     private readonly npmName: string,
@@ -85,6 +57,7 @@ export class RegisterHelpers {
     private readonly onHookAdded: (options: RegisterServerHookOptions) => void
   ) {
     this.router = express.Router()
+    this.videoConstantManagerFactory = new VideoConstantManagerFactory(this.npmName)
   }
 
   buildRegisterHelpers (): RegisterServerOptions {
@@ -96,13 +69,13 @@ export class RegisterHelpers {
     const settingsManager = this.buildSettingsManager()
     const storageManager = this.buildStorageManager()
 
-    const videoLanguageManager = this.buildVideoLanguageManager()
+    const videoLanguageManager = this.videoConstantManagerFactory.createVideoConstantManager<string>('language')
 
-    const videoLicenceManager = this.buildVideoLicenceManager()
-    const videoCategoryManager = this.buildVideoCategoryManager()
+    const videoLicenceManager = this.videoConstantManagerFactory.createVideoConstantManager<number>('licence')
+    const videoCategoryManager = this.videoConstantManagerFactory.createVideoConstantManager<number>('category')
 
-    const videoPrivacyManager = this.buildVideoPrivacyManager()
-    const playlistPrivacyManager = this.buildPlaylistPrivacyManager()
+    const videoPrivacyManager = this.videoConstantManagerFactory.createVideoConstantManager<VideoPrivacy>('privacy')
+    const playlistPrivacyManager = this.videoConstantManagerFactory.createVideoConstantManager<VideoPlaylistPrivacy>('playlistPrivacy')
 
     const transcodingManager = this.buildTranscodingManager()
 
@@ -122,12 +95,38 @@ export class RegisterHelpers {
       settingsManager,
       storageManager,
 
-      videoLanguageManager,
-      videoCategoryManager,
-      videoLicenceManager,
+      videoLanguageManager: {
+        ...videoLanguageManager,
+        /** @deprecated use `addConstant` instead **/
+        addLanguage: videoLanguageManager.addConstant,
+        /** @deprecated use `deleteConstant` instead **/
+        deleteLanguage: videoLanguageManager.deleteConstant
+      },
+      videoCategoryManager: {
+        ...videoCategoryManager,
+        /** @deprecated use `addConstant` instead **/
+        addCategory: videoCategoryManager.addConstant,
+        /** @deprecated use `deleteConstant` instead **/
+        deleteCategory: videoCategoryManager.deleteConstant
+      },
+      videoLicenceManager: {
+        ...videoLicenceManager,
+        /** @deprecated use `addConstant` instead **/
+        addLicence: videoLicenceManager.addConstant,
+        /** @deprecated use `deleteConstant` instead **/
+        deleteLicence: videoLicenceManager.deleteConstant
+      },
 
-      videoPrivacyManager,
-      playlistPrivacyManager,
+      videoPrivacyManager: {
+        ...videoPrivacyManager,
+        /** @deprecated use `deleteConstant` instead **/
+        deletePrivacy: videoPrivacyManager.deleteConstant
+      },
+      playlistPrivacyManager: {
+        ...playlistPrivacyManager,
+        /** @deprecated use `deleteConstant` instead **/
+        deletePlaylistPrivacy: playlistPrivacyManager.deleteConstant
+      },
 
       transcodingManager,
 
@@ -141,29 +140,7 @@ export class RegisterHelpers {
   }
 
   reinitVideoConstants (npmName: string) {
-    const hash = {
-      language: VIDEO_LANGUAGES,
-      licence: VIDEO_LICENCES,
-      category: VIDEO_CATEGORIES,
-      privacy: VIDEO_PRIVACIES,
-      playlistPrivacy: VIDEO_PLAYLIST_PRIVACIES
-    }
-    const types: AlterableVideoConstant[] = [ 'language', 'licence', 'category', 'privacy', 'playlistPrivacy' ]
-
-    for (const type of types) {
-      const updatedConstants = this.updatedVideoConstants[type][npmName]
-      if (!updatedConstants) continue
-
-      for (const added of updatedConstants.added) {
-        delete hash[type][added.key]
-      }
-
-      for (const deleted of updatedConstants.deleted) {
-        hash[type][deleted.key] = deleted.label
-      }
-
-      delete this.updatedVideoConstants[type][npmName]
-    }
+    this.videoConstantManagerFactory.resetVideoConstants(npmName)
   }
 
   reinitTranscodingProfilesAndEncoders (npmName: string) {
@@ -291,119 +268,6 @@ export class RegisterHelpers {
     }
   }
 
-  private buildVideoLanguageManager (): PluginVideoLanguageManager {
-    return {
-      addLanguage: (key: string, label: string) => {
-        return this.addConstant({ npmName: this.npmName, type: 'language', obj: VIDEO_LANGUAGES, key, label })
-      },
-
-      deleteLanguage: (key: string) => {
-        return this.deleteConstant({ npmName: this.npmName, type: 'language', obj: VIDEO_LANGUAGES, key })
-      }
-    }
-  }
-
-  private buildVideoCategoryManager (): PluginVideoCategoryManager {
-    return {
-      addCategory: (key: number, label: string) => {
-        return this.addConstant({ npmName: this.npmName, type: 'category', obj: VIDEO_CATEGORIES, key, label })
-      },
-
-      deleteCategory: (key: number) => {
-        return this.deleteConstant({ npmName: this.npmName, type: 'category', obj: VIDEO_CATEGORIES, key })
-      }
-    }
-  }
-
-  private buildVideoPrivacyManager (): PluginVideoPrivacyManager {
-    return {
-      deletePrivacy: (key: number) => {
-        return this.deleteConstant({ npmName: this.npmName, type: 'privacy', obj: VIDEO_PRIVACIES, key })
-      }
-    }
-  }
-
-  private buildPlaylistPrivacyManager (): PluginPlaylistPrivacyManager {
-    return {
-      deletePlaylistPrivacy: (key: number) => {
-        return this.deleteConstant({ npmName: this.npmName, type: 'playlistPrivacy', obj: VIDEO_PLAYLIST_PRIVACIES, key })
-      }
-    }
-  }
-
-  private buildVideoLicenceManager (): PluginVideoLicenceManager {
-    return {
-      addLicence: (key: number, label: string) => {
-        return this.addConstant({ npmName: this.npmName, type: 'licence', obj: VIDEO_LICENCES, key, label })
-      },
-
-      deleteLicence: (key: number) => {
-        return this.deleteConstant({ npmName: this.npmName, type: 'licence', obj: VIDEO_LICENCES, key })
-      }
-    }
-  }
-
-  private addConstant<T extends string | number> (parameters: {
-    npmName: string
-    type: AlterableVideoConstant
-    obj: VideoConstant
-    key: T
-    label: string
-  }) {
-    const { npmName, type, obj, key, label } = parameters
-
-    if (obj[key]) {
-      logger.warn('Cannot add %s %s by plugin %s: key already exists.', type, npmName, key)
-      return false
-    }
-
-    if (!this.updatedVideoConstants[type][npmName]) {
-      this.updatedVideoConstants[type][npmName] = {
-        added: [],
-        deleted: []
-      }
-    }
-
-    this.updatedVideoConstants[type][npmName].added.push({ key, label })
-    obj[key] = label
-
-    return true
-  }
-
-  private deleteConstant<T extends string | number> (parameters: {
-    npmName: string
-    type: AlterableVideoConstant
-    obj: VideoConstant
-    key: T
-  }) {
-    const { npmName, type, obj, key } = parameters
-
-    if (!obj[key]) {
-      logger.warn('Cannot delete %s by plugin %s: key %s does not exist.', type, npmName, key)
-      return false
-    }
-
-    if (!this.updatedVideoConstants[type][npmName]) {
-      this.updatedVideoConstants[type][npmName] = {
-        added: [],
-        deleted: []
-      }
-    }
-
-    const updatedConstants = this.updatedVideoConstants[type][npmName]
-
-    const alreadyAdded = updatedConstants.added.find(a => a.key === key)
-    if (alreadyAdded) {
-      updatedConstants.added.filter(a => a.key !== key)
-    } else if (obj[key]) {
-      updatedConstants.deleted.push({ key, label: obj[key] })
-    }
-
-    delete obj[key]
-
-    return true
-  }
-
   private buildTranscodingManager () {
     const self = this
 
diff --git a/server/lib/plugins/video-constant-manager-factory.ts b/server/lib/plugins/video-constant-manager-factory.ts
new file mode 100644 (file)
index 0000000..f04dde2
--- /dev/null
@@ -0,0 +1,139 @@
+import { logger } from '@server/helpers/logger'
+import {
+  VIDEO_CATEGORIES,
+  VIDEO_LANGUAGES,
+  VIDEO_LICENCES,
+  VIDEO_PLAYLIST_PRIVACIES,
+  VIDEO_PRIVACIES
+} from '@server/initializers/constants'
+import { ConstantManager } from '@shared/models/plugins/server/plugin-constant-manager.model'
+
+type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy'
+type VideoConstant = Record<number | string, string>
+
+type UpdatedVideoConstant = {
+  [name in AlterableVideoConstant]: {
+    [ npmName: string]: {
+      added: VideoConstant[]
+      deleted: VideoConstant[]
+    }
+  }
+}
+
+const constantsHash: { [key in AlterableVideoConstant]: VideoConstant } = {
+  language: VIDEO_LANGUAGES,
+  licence: VIDEO_LICENCES,
+  category: VIDEO_CATEGORIES,
+  privacy: VIDEO_PRIVACIES,
+  playlistPrivacy: VIDEO_PLAYLIST_PRIVACIES
+}
+
+export class VideoConstantManagerFactory {
+  private readonly updatedVideoConstants: UpdatedVideoConstant = {
+    playlistPrivacy: { },
+    privacy: { },
+    language: { },
+    licence: { },
+    category: { }
+  }
+
+  constructor (
+    private readonly npmName: string
+  ) {}
+
+  public resetVideoConstants (npmName: string) {
+    const types: AlterableVideoConstant[] = [ 'language', 'licence', 'category', 'privacy', 'playlistPrivacy' ]
+    for (const type of types) {
+      this.resetConstants({ npmName, type })
+    }
+  }
+
+  private resetConstants (parameters: { npmName: string, type: AlterableVideoConstant }) {
+    const { npmName, type } = parameters
+    const updatedConstants = this.updatedVideoConstants[type][npmName]
+
+    if (!updatedConstants) return
+
+    for (const added of updatedConstants.added) {
+      delete constantsHash[type][added.key]
+    }
+
+    for (const deleted of updatedConstants.deleted) {
+      constantsHash[type][deleted.key] = deleted.label
+    }
+
+    delete this.updatedVideoConstants[type][npmName]
+  }
+
+  public createVideoConstantManager<K extends number | string>(type: AlterableVideoConstant): ConstantManager<K> {
+    const { npmName } = this
+    return {
+      addConstant: (key: K, label: string) => this.addConstant({ npmName, type, key, label }),
+      deleteConstant: (key: K) => this.deleteConstant({ npmName, type, key }),
+      getConstantValue: (key: K) => constantsHash[type][key],
+      getConstants: () => constantsHash[type] as Record<K, string>,
+      resetConstants: () => this.resetConstants({ npmName, type })
+    }
+  }
+
+  private addConstant<T extends string | number> (parameters: {
+    npmName: string
+    type: AlterableVideoConstant
+    key: T
+    label: string
+  }) {
+    const { npmName, type, key, label } = parameters
+    const obj = constantsHash[type]
+
+    if (obj[key]) {
+      logger.warn('Cannot add %s %s by plugin %s: key already exists.', type, npmName, key)
+      return false
+    }
+
+    if (!this.updatedVideoConstants[type][npmName]) {
+      this.updatedVideoConstants[type][npmName] = {
+        added: [],
+        deleted: []
+      }
+    }
+
+    this.updatedVideoConstants[type][npmName].added.push({ key: key, label } as VideoConstant)
+    obj[key] = label
+
+    return true
+  }
+
+  private deleteConstant<T extends string | number> (parameters: {
+    npmName: string
+    type: AlterableVideoConstant
+    key: T
+  }) {
+    const { npmName, type, key } = parameters
+    const obj = constantsHash[type]
+
+    if (!obj[key]) {
+      logger.warn('Cannot delete %s by plugin %s: key %s does not exist.', type, npmName, key)
+      return false
+    }
+
+    if (!this.updatedVideoConstants[type][npmName]) {
+      this.updatedVideoConstants[type][npmName] = {
+        added: [],
+        deleted: []
+      }
+    }
+
+    const updatedConstants = this.updatedVideoConstants[type][npmName]
+
+    const alreadyAdded = updatedConstants.added.find(a => a.key === key)
+    if (alreadyAdded) {
+      updatedConstants.added.filter(a => a.key !== key)
+    } else if (obj[key]) {
+      updatedConstants.deleted.push({ key, label: obj[key] } as VideoConstant)
+    }
+
+    delete obj[key]
+
+    return true
+  }
+}
index 3e650e0a12c542588781695af6f98919ecf7dcea..f44704a4489fd994a81752d8319743f1043080ec 100644 (file)
@@ -1,46 +1,44 @@
 async function register ({
-  registerHook,
-  registerSetting,
-  settingsManager,
-  storageManager,
   videoCategoryManager,
   videoLicenceManager,
   videoLanguageManager,
   videoPrivacyManager,
-  playlistPrivacyManager
+  playlistPrivacyManager,
+  getRouter
 }) {
-  videoLanguageManager.addLanguage('al_bhed', 'Al Bhed')
-  videoLanguageManager.addLanguage('al_bhed2', 'Al Bhed 2')
-  videoLanguageManager.addLanguage('al_bhed3', 'Al Bhed 3')
-  videoLanguageManager.deleteLanguage('en')
-  videoLanguageManager.deleteLanguage('fr')
-  videoLanguageManager.deleteLanguage('al_bhed3')
+  videoLanguageManager.addConstant('al_bhed', 'Al Bhed')
+  videoLanguageManager.addConstant('al_bhed2', 'Al Bhed 2')
+  videoLanguageManager.addConstant('al_bhed3', 'Al Bhed 3')
+  videoLanguageManager.deleteConstant('en')
+  videoLanguageManager.deleteConstant('fr')
+  videoLanguageManager.deleteConstant('al_bhed3')
 
-  videoCategoryManager.addCategory(42, 'Best category')
-  videoCategoryManager.addCategory(43, 'High best category')
-  videoCategoryManager.deleteCategory(1) // Music
-  videoCategoryManager.deleteCategory(2) // Films
+  videoCategoryManager.addConstant(42, 'Best category')
+  videoCategoryManager.addConstant(43, 'High best category')
+  videoCategoryManager.deleteConstant(1) // Music
+  videoCategoryManager.deleteConstant(2) // Films
 
-  videoLicenceManager.addLicence(42, 'Best licence')
-  videoLicenceManager.addLicence(43, 'High best licence')
-  videoLicenceManager.deleteLicence(1) // Attribution
-  videoLicenceManager.deleteLicence(7) // Public domain
+  videoLicenceManager.addConstant(42, 'Best licence')
+  videoLicenceManager.addConstant(43, 'High best licence')
+  videoLicenceManager.deleteConstant(1) // Attribution
+  videoLicenceManager.deleteConstant(7) // Public domain
 
-  videoPrivacyManager.deletePrivacy(2)
-  playlistPrivacyManager.deletePlaylistPrivacy(3)
-}
+  videoPrivacyManager.deleteConstant(2)
+  playlistPrivacyManager.deleteConstant(3)
+
+  {
+    const router = getRouter()
+    router.get('/reset-categories', (req, res) => {
+      videoCategoryManager.resetConstants()
 
-async function unregister () {
-  return
+      res.sendStatus(204)
+    })
+  }
 }
 
+async function unregister () {}
+
 module.exports = {
   register,
   unregister
 }
-
-// ############################################################################
-
-function addToCount (obj) {
-  return Object.assign({}, obj, { count: obj.count + 1 })
-}
diff --git a/server/tests/lib/plugins/video-constant-registry-factory.test.ts b/server/tests/lib/plugins/video-constant-registry-factory.test.ts
new file mode 100644 (file)
index 0000000..e26b286
--- /dev/null
@@ -0,0 +1,155 @@
+/* eslint-disable @typescript-eslint/no-unused-expressions */
+import 'mocha'
+import { expect } from 'chai'
+import { VideoConstantManagerFactory } from '@server/lib/plugins/video-constant-manager-factory'
+import {
+  VIDEO_CATEGORIES,
+  VIDEO_LANGUAGES,
+  VIDEO_LICENCES,
+  VIDEO_PLAYLIST_PRIVACIES,
+  VIDEO_PRIVACIES
+} from '@server/initializers/constants'
+import {
+  VideoPlaylistPrivacy,
+  VideoPrivacy
+} from '@shared/models'
+
+describe('VideoConstantManagerFactory', function () {
+  const factory = new VideoConstantManagerFactory('peertube-plugin-constants')
+
+  afterEach(() => {
+    factory.resetVideoConstants('peertube-plugin-constants')
+  })
+
+  describe('VideoCategoryManager', () => {
+    const videoCategoryManager = factory.createVideoConstantManager<number>('category')
+
+    it('Should be able to list all video category constants', () => {
+      const constants = videoCategoryManager.getConstants()
+      expect(constants).to.deep.equal(VIDEO_CATEGORIES)
+    })
+
+    it('Should be able to delete a video category constant', () => {
+      const successfullyDeleted = videoCategoryManager.deleteConstant(1)
+      expect(successfullyDeleted).to.be.true
+      expect(videoCategoryManager.getConstantValue(1)).to.be.undefined
+    })
+
+    it('Should be able to add a video category constant', () => {
+      const successfullyAdded = videoCategoryManager.addConstant(42, 'The meaning of life')
+      expect(successfullyAdded).to.be.true
+      expect(videoCategoryManager.getConstantValue(42)).to.equal('The meaning of life')
+    })
+
+    it('Should be able to reset video category constants', () => {
+      videoCategoryManager.deleteConstant(1)
+      videoCategoryManager.resetConstants()
+      expect(videoCategoryManager.getConstantValue(1)).not.be.undefined
+    })
+  })
+
+  describe('VideoLicenceManager', () => {
+    const videoLicenceManager = factory.createVideoConstantManager<number>('licence')
+    it('Should be able to list all video licence constants', () => {
+      const constants = videoLicenceManager.getConstants()
+      expect(constants).to.deep.equal(VIDEO_LICENCES)
+    })
+
+    it('Should be able to delete a video licence constant', () => {
+      const successfullyDeleted = videoLicenceManager.deleteConstant(1)
+      expect(successfullyDeleted).to.be.true
+      expect(videoLicenceManager.getConstantValue(1)).to.be.undefined
+    })
+
+    it('Should be able to add a video licence constant', () => {
+      const successfullyAdded = videoLicenceManager.addConstant(42, 'European Union Public Licence')
+      expect(successfullyAdded).to.be.true
+      expect(videoLicenceManager.getConstantValue(42)).to.equal('European Union Public Licence')
+    })
+
+    it('Should be able to reset video licence constants', () => {
+      videoLicenceManager.deleteConstant(1)
+      videoLicenceManager.resetConstants()
+      expect(videoLicenceManager.getConstantValue(1)).not.be.undefined
+    })
+  })
+
+  describe('PlaylistPrivacyManager', () => {
+    const playlistPrivacyManager = factory.createVideoConstantManager<VideoPlaylistPrivacy>('playlistPrivacy')
+    it('Should be able to list all video playlist privacy constants', () => {
+      const constants = playlistPrivacyManager.getConstants()
+      expect(constants).to.deep.equal(VIDEO_PLAYLIST_PRIVACIES)
+    })
+
+    it('Should be able to delete a video playlist privacy constant', () => {
+      const successfullyDeleted = playlistPrivacyManager.deleteConstant(1)
+      expect(successfullyDeleted).to.be.true
+      expect(playlistPrivacyManager.getConstantValue(1)).to.be.undefined
+    })
+
+    it('Should be able to add a video playlist privacy constant', () => {
+      const successfullyAdded = playlistPrivacyManager.addConstant(42, 'Friends only')
+      expect(successfullyAdded).to.be.true
+      expect(playlistPrivacyManager.getConstantValue(42)).to.equal('Friends only')
+    })
+
+    it('Should be able to reset video playlist privacy constants', () => {
+      playlistPrivacyManager.deleteConstant(1)
+      playlistPrivacyManager.resetConstants()
+      expect(playlistPrivacyManager.getConstantValue(1)).not.be.undefined
+    })
+  })
+
+  describe('VideoPrivacyManager', () => {
+    const videoPrivacyManager = factory.createVideoConstantManager<VideoPrivacy>('privacy')
+    it('Should be able to list all video privacy constants', () => {
+      const constants = videoPrivacyManager.getConstants()
+      expect(constants).to.deep.equal(VIDEO_PRIVACIES)
+    })
+
+    it('Should be able to delete a video privacy constant', () => {
+      const successfullyDeleted = videoPrivacyManager.deleteConstant(1)
+      expect(successfullyDeleted).to.be.true
+      expect(videoPrivacyManager.getConstantValue(1)).to.be.undefined
+    })
+
+    it('Should be able to add a video privacy constant', () => {
+      const successfullyAdded = videoPrivacyManager.addConstant(42, 'Friends only')
+      expect(successfullyAdded).to.be.true
+      expect(videoPrivacyManager.getConstantValue(42)).to.equal('Friends only')
+    })
+
+    it('Should be able to reset video privacy constants', () => {
+      videoPrivacyManager.deleteConstant(1)
+      videoPrivacyManager.resetConstants()
+      expect(videoPrivacyManager.getConstantValue(1)).not.be.undefined
+    })
+  })
+
+  describe('VideoLanguageManager', () => {
+    const videoLanguageManager = factory.createVideoConstantManager<string>('language')
+    it('Should be able to list all video language constants', () => {
+      const constants = videoLanguageManager.getConstants()
+      expect(constants).to.deep.equal(VIDEO_LANGUAGES)
+    })
+
+    it('Should be able to add a video language constant', () => {
+      const successfullyAdded = videoLanguageManager.addConstant('fr', 'Fr occitan')
+      expect(successfullyAdded).to.be.true
+      expect(videoLanguageManager.getConstantValue('fr')).to.equal('Fr occitan')
+    })
+
+    it('Should be able to delete a video language constant', () => {
+      videoLanguageManager.addConstant('fr', 'Fr occitan')
+      const successfullyDeleted = videoLanguageManager.deleteConstant('fr')
+      expect(successfullyDeleted).to.be.true
+      expect(videoLanguageManager.getConstantValue('fr')).to.be.undefined
+    })
+
+    it('Should be able to reset video language constants', () => {
+      videoLanguageManager.addConstant('fr', 'Fr occitan')
+      videoLanguageManager.resetConstants()
+      expect(videoLanguageManager.getConstantValue('fr')).to.be.undefined
+    })
+  })
+})
index eb014c596deb492c975541281d28cee114e33558..7b1312f88fb6c845acf63412b159d5bc5747b6a0 100644 (file)
@@ -9,8 +9,11 @@ import {
   getVideo,
   getVideoCategories,
   getVideoLanguages,
-  getVideoLicences, getVideoPlaylistPrivacies, getVideoPrivacies,
+  getVideoLicences,
+  getVideoPlaylistPrivacies,
+  getVideoPrivacies,
   installPlugin,
+  makeGetRequest,
   setAccessTokensToServers,
   uninstallPlugin,
   uploadVideo
@@ -173,6 +176,38 @@ describe('Test plugin altering video constants', function () {
     }
   })
 
+  it('Should be able to reset categories', async function () {
+    await installPlugin({
+      url: server.url,
+      accessToken: server.accessToken,
+      path: getPluginTestPath('-video-constants')
+    })
+
+    let { body: categories } = await getVideoCategories(server.url)
+
+    expect(categories[1]).to.not.exist
+    expect(categories[2]).to.not.exist
+
+    expect(categories[42]).to.exist
+    expect(categories[43]).to.exist
+
+    await makeGetRequest({
+      url: server.url,
+      token: server.accessToken,
+      path: '/plugins/test-video-constants/router/reset-categories',
+      statusCodeExpected: HttpStatusCode.NO_CONTENT_204
+    })
+
+    const { body } = await getVideoCategories(server.url)
+    categories = body
+
+    expect(categories[1]).to.exist
+    expect(categories[2]).to.exist
+
+    expect(categories[42]).to.not.exist
+    expect(categories[43]).to.not.exist
+  })
+
   after(async function () {
     await cleanupTests([ server ])
   })
index 4703c0a8bb11d3a971df126cf3d12369015b83c8..5b3b37752b28c6df98945ace15ea7878f1f448e9 100644 (file)
@@ -1,8 +1,12 @@
 import { VideoPlaylistPrivacy } from '../../../videos/playlist/video-playlist-privacy.model'
+import { ConstantManager } from '@shared/models/plugins/server/plugin-constant-manager.model'
 
-export interface PluginPlaylistPrivacyManager {
-  // PUBLIC = 1,
-  // UNLISTED = 2,
-  // PRIVATE = 3
+export interface PluginPlaylistPrivacyManager extends ConstantManager<VideoPlaylistPrivacy> {
+  /**
+   * PUBLIC = 1,
+   * UNLISTED = 2,
+   * PRIVATE = 3
+   * @deprecated use `deleteConstant` instead
+   */
   deletePlaylistPrivacy: (privacyKey: VideoPlaylistPrivacy) => boolean
 }
index 201bfa979b9fd4d1a3c0a99da6924c6f0d5a73e1..069ad14764a5e2fb18d773f42f293a0501e7e519 100644 (file)
@@ -1,5 +1,13 @@
-export interface PluginVideoCategoryManager {
+import { ConstantManager } from '@shared/models/plugins/server/plugin-constant-manager.model'
+
+export interface PluginVideoCategoryManager extends ConstantManager<number> {
+  /**
+   * @deprecated use `addConstant` instead
+   */
   addCategory: (categoryKey: number, categoryLabel: string) => boolean
 
+  /**
+   * @deprecated use `deleteConstant` instead
+   */
   deleteCategory: (categoryKey: number) => boolean
 }
index 3fd577a79e807a71e8da9a190463e393bdc2bc45..969c6c670f2a7e186cdddd0c5aaf51fa7fe6d5a3 100644 (file)
@@ -1,5 +1,13 @@
-export interface PluginVideoLanguageManager {
+import { ConstantManager } from '@shared/models/plugins/server/plugin-constant-manager.model'
+
+export interface PluginVideoLanguageManager extends ConstantManager<string> {
+  /**
+   * @deprecated use `addConstant` instead
+   */
   addLanguage: (languageKey: string, languageLabel: string) => boolean
 
+  /**
+   * @deprecated use `deleteConstant` instead
+   */
   deleteLanguage: (languageKey: string) => boolean
 }
index 82a634d3a9b55c748aac96a1cc177674657bd744..900a49661e4cbd010f808865d24daf35c048286b 100644 (file)
@@ -1,5 +1,13 @@
-export interface PluginVideoLicenceManager {
+import { ConstantManager } from '@shared/models/plugins/server/plugin-constant-manager.model'
+
+export interface PluginVideoLicenceManager extends ConstantManager<number> {
+  /**
+   * @deprecated use `addLicence` instead
+   */
   addLicence: (licenceKey: number, licenceLabel: string) => boolean
 
+  /**
+   * @deprecated use `deleteLicence` instead
+   */
   deleteLicence: (licenceKey: number) => boolean
 }
index 7717115e3e24ed52751819145f29fb0a0a363f70..e26e48a53becf08a240494c3aa8e5e12e628ff96 100644 (file)
@@ -1,9 +1,13 @@
 import { VideoPrivacy } from '../../../videos/video-privacy.enum'
+import { ConstantManager } from '@shared/models/plugins/server/plugin-constant-manager.model'
 
-export interface PluginVideoPrivacyManager {
-  // PUBLIC = 1
-  // UNLISTED = 2
-  // PRIVATE = 3
-  // INTERNAL = 4
+export interface PluginVideoPrivacyManager extends ConstantManager<VideoPrivacy> {
+  /**
+   * PUBLIC = 1,
+   * UNLISTED = 2,
+   * PRIVATE = 3
+   * INTERNAL = 4
+   * @deprecated use `deleteConstant` instead
+   */
   deletePrivacy: (privacyKey: VideoPrivacy) => boolean
 }
diff --git a/shared/models/plugins/server/plugin-constant-manager.model.ts b/shared/models/plugins/server/plugin-constant-manager.model.ts
new file mode 100644 (file)
index 0000000..4de3ce3
--- /dev/null
@@ -0,0 +1,7 @@
+export interface ConstantManager <K extends string | number> {
+  addConstant: (key: K, label: string) => boolean
+  deleteConstant: (key: K) => boolean
+  getConstantValue: (key: K) => string
+  getConstants: () => Record<K, string>
+  resetConstants: () => void
+}
index 568c0662f8bd3eb00b27f3737c068218e291d4e2..85aaf9f02ffe3300a0d2bb42bb9b25abe0a8e3a2 100644 (file)
@@ -234,21 +234,29 @@ function register ({
 
 #### Update video constants
 
-You can add/delete video categories, licences or languages using the appropriate managers:
+You can add/delete video categories, licences or languages using the appropriate constant managers:
 
 ```js
-function register (...) {
-  videoLanguageManager.addLanguage('al_bhed', 'Al Bhed')
-  videoLanguageManager.deleteLanguage('fr')
+function register ({ 
+  videoLanguageManager, 
+  videoCategoryManager, 
+  videoLicenceManager, 
+  videoPrivacyManager, 
+  playlistPrivacyManager 
+}) {
+  videoLanguageManager.addConstant('al_bhed', 'Al Bhed')
+  videoLanguageManager.deleteConstant('fr')
 
-  videoCategoryManager.addCategory(42, 'Best category')
-  videoCategoryManager.deleteCategory(1) // Music
+  videoCategoryManager.addConstant(42, 'Best category')
+  videoCategoryManager.deleteConstant(1) // Music
+  videoCategoryManager.resetConstants() // Reset to initial categories
+  videoCategoryManager.getConstants() // Retrieve all category constants
 
-  videoLicenceManager.addLicence(42, 'Best licence')
-  videoLicenceManager.deleteLicence(7) // Public domain
+  videoLicenceManager.addConstant(42, 'Best licence')
+  videoLicenceManager.deleteConstant(7) // Public domain
 
-  videoPrivacyManager.deletePrivacy(2) // Remove Unlisted video privacy
-  playlistPrivacyManager.deletePlaylistPrivacy(3) // Remove Private video playlist privacy
+  videoPrivacyManager.deleteConstant(2) // Remove Unlisted video privacy
+  playlistPrivacyManager.deleteConstant(3) // Remove Private video playlist privacy
 }
 ```