From ab3ead3a6f080e6768b898e699c8de92703d93c6 Mon Sep 17 00:00:00 2001
From: Chocobozzz <me@florianbigard.com>
Date: Thu, 9 Apr 2020 11:35:29 +0200
Subject: [PATCH] Add ability to remove a video from a plugin

---
 server/lib/plugins/hooks.ts                   |  2 +-
 server/lib/plugins/plugin-helpers.ts          | 17 ++++++++-
 .../peertube-plugin-test-four/main.js         | 18 ++++++++--
 server/tests/plugins/plugin-helpers.ts        | 36 ++++++++++++++++---
 .../plugins/register-server-option.model.ts   |  4 +++
 5 files changed, 68 insertions(+), 9 deletions(-)

diff --git a/server/lib/plugins/hooks.ts b/server/lib/plugins/hooks.ts
index bcc8c674e..aa92f03cc 100644
--- a/server/lib/plugins/hooks.ts
+++ b/server/lib/plugins/hooks.ts
@@ -25,7 +25,7 @@ const Hooks = {
   },
 
   runAction: <T, U extends ServerActionHookName>(hookName: U, params?: T) => {
-    PluginManager.Instance.runHook(hookName, params)
+    PluginManager.Instance.runHook(hookName, undefined, params)
       .catch(err => logger.error('Fatal hook error.', { err }))
   }
 }
diff --git a/server/lib/plugins/plugin-helpers.ts b/server/lib/plugins/plugin-helpers.ts
index a1493c7df..e91beffba 100644
--- a/server/lib/plugins/plugin-helpers.ts
+++ b/server/lib/plugins/plugin-helpers.ts
@@ -1,15 +1,18 @@
 import { PeerTubeHelpers } from '@server/typings/plugins'
 import { sequelizeTypescript } from '@server/initializers/database'
 import { buildLogger } from '@server/helpers/logger'
+import { VideoModel } from '@server/models/video/video'
 
 function buildPluginHelpers (npmName: string): PeerTubeHelpers {
   const logger = buildPluginLogger(npmName)
 
   const database = buildDatabaseHelpers()
+  const videos = buildVideosHelpers()
 
   return {
     logger,
-    database
+    database,
+    videos
   }
 }
 
@@ -28,3 +31,15 @@ function buildDatabaseHelpers () {
     query: sequelizeTypescript.query.bind(sequelizeTypescript)
   }
 }
+
+function buildVideosHelpers () {
+  return {
+    removeVideo: (id: number) => {
+      return sequelizeTypescript.transaction(async t => {
+        const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(id, t)
+
+        await video.destroy({ transaction: t })
+      })
+    }
+  }
+}
diff --git a/server/tests/fixtures/peertube-plugin-test-four/main.js b/server/tests/fixtures/peertube-plugin-test-four/main.js
index 9abb73646..2e81550c1 100644
--- a/server/tests/fixtures/peertube-plugin-test-four/main.js
+++ b/server/tests/fixtures/peertube-plugin-test-four/main.js
@@ -1,7 +1,10 @@
 async function register ({
-  peertubeHelpers
+  peertubeHelpers,
+  registerHook
 }) {
-  peertubeHelpers.logger.info('Hello world from plugin four')
+  const logger = peertubeHelpers.logger
+
+  logger.info('Hello world from plugin four')
 
   const username = 'root'
   const results = await peertubeHelpers.database.query(
@@ -12,7 +15,16 @@ async function register ({
     }
   )
 
-  peertubeHelpers.logger.info('root email is ' + results[0]['email'])
+  logger.info('root email is ' + results[0]['email'])
+
+  registerHook({
+    target: 'action:api.video.viewed',
+    handler: async ({ video }) => {
+      await peertubeHelpers.videos.removeVideo(video.id)
+
+      logger.info('Video deleted by plugin four.')
+    }
+  })
 }
 
 async function unregister () {
diff --git a/server/tests/plugins/plugin-helpers.ts b/server/tests/plugins/plugin-helpers.ts
index 05928273f..dfe8ebe55 100644
--- a/server/tests/plugins/plugin-helpers.ts
+++ b/server/tests/plugins/plugin-helpers.ts
@@ -1,11 +1,16 @@
 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
 
-import * as chai from 'chai'
 import 'mocha'
 import { cleanupTests, flushAndRunServer, ServerInfo, waitUntilLog } from '../../../shared/extra-utils/server/servers'
-import { getPluginTestPath, installPlugin, setAccessTokensToServers } from '../../../shared/extra-utils'
-
-const expect = chai.expect
+import {
+  checkVideoFilesWereRemoved,
+  getPluginTestPath,
+  getVideo,
+  installPlugin,
+  setAccessTokensToServers,
+  uploadVideoAndGetId,
+  viewVideo
+} from '../../../shared/extra-utils'
 
 describe('Test plugin helpers', function () {
   let server: ServerInfo
@@ -32,6 +37,29 @@ describe('Test plugin helpers', function () {
     await waitUntilLog(server, `root email is admin${server.internalServerNumber}@example.com`, 1)
   })
 
+  it('Should remove a video after a view', async function () {
+    this.timeout(20000)
+
+    const videoUUID = (await uploadVideoAndGetId({ server: server, videoName: 'video1' })).uuid
+
+    // Should not throw -> video exists
+    await getVideo(server.url, videoUUID)
+    // Should delete the video
+    await viewVideo(server.url, videoUUID)
+
+    await waitUntilLog(server, 'Video deleted by plugin four.', 1)
+
+    try {
+      // Should throw because the video should have been deleted
+      await getVideo(server.url, videoUUID)
+      throw new Error('Video exists')
+    } catch (err) {
+      if (err.message.includes('exists')) throw err
+    }
+
+    await checkVideoFilesWereRemoved(videoUUID, server.internalServerNumber)
+  })
+
   after(async function () {
     await cleanupTests([ server ])
   })
diff --git a/server/typings/plugins/register-server-option.model.ts b/server/typings/plugins/register-server-option.model.ts
index 6f2ba7cd6..fda9afb11 100644
--- a/server/typings/plugins/register-server-option.model.ts
+++ b/server/typings/plugins/register-server-option.model.ts
@@ -13,6 +13,10 @@ export type PeerTubeHelpers = {
   database: {
     query: Function
   }
+
+  videos: {
+    removeVideo: (videoId: number) => Promise<void>
+  }
 }
 
 export type RegisterServerOptions = {
-- 
2.25.1