From c55e3d7227fe1453869e309025996b9d75256d5d Mon Sep 17 00:00:00 2001
From: Chocobozzz <me@florianbigard.com>
Date: Fri, 17 Dec 2021 11:58:15 +0100
Subject: Move test functions outside extra-utils

---
 shared/server-commands/index.ts                    |   1 -
 shared/server-commands/logs/logs-command.ts        |   3 +-
 shared/server-commands/miscs/checks.ts             |  58 --
 shared/server-commands/miscs/generate.ts           |  75 --
 shared/server-commands/miscs/index.ts              |   3 -
 shared/server-commands/miscs/sql-command.ts        |   2 +-
 shared/server-commands/miscs/tests.ts              | 101 ---
 shared/server-commands/mock-servers/index.ts       |   5 -
 shared/server-commands/mock-servers/mock-429.ts    |  33 -
 shared/server-commands/mock-servers/mock-email.ts  |  63 --
 .../mock-servers/mock-instances-index.ts           |  46 --
 .../mock-servers/mock-joinpeertube-versions.ts     |  34 -
 .../mock-servers/mock-object-storage.ts            |  41 --
 .../mock-servers/mock-plugin-blocklist.ts          |  36 -
 shared/server-commands/mock-servers/mock-proxy.ts  |  25 -
 shared/server-commands/mock-servers/utils.ts       |  33 -
 .../server-commands/requests/check-api-params.ts   |  48 --
 shared/server-commands/requests/index.ts           |   2 -
 shared/server-commands/requests/requests.ts        |   2 +-
 shared/server-commands/server/config-command.ts    |   5 +-
 shared/server-commands/server/directories.ts       |  34 -
 shared/server-commands/server/index.ts             |   3 -
 shared/server-commands/server/jobs-command.ts      |   3 +-
 shared/server-commands/server/jobs.ts              |   2 +-
 shared/server-commands/server/plugins.ts           |  18 -
 shared/server-commands/server/server.ts            |   8 +-
 shared/server-commands/server/servers-command.ts   |   4 +-
 shared/server-commands/server/servers.ts           |   2 +-
 shared/server-commands/server/tracker.ts           |  27 -
 shared/server-commands/shared/abstract-command.ts  |   2 +-
 shared/server-commands/users/accounts-command.ts   |   4 +-
 shared/server-commands/users/actors.ts             |  73 --
 shared/server-commands/users/index.ts              |   2 -
 .../server-commands/users/notifications-command.ts |   3 +-
 shared/server-commands/users/notifications.ts      | 795 ---------------------
 shared/server-commands/users/users-command.ts      |   2 +-
 shared/server-commands/videos/blacklist-command.ts |   3 +-
 shared/server-commands/videos/captions-command.ts  |   2 +-
 shared/server-commands/videos/captions.ts          |  21 -
 shared/server-commands/videos/channels-command.ts  |  12 +-
 shared/server-commands/videos/index.ts             |   4 -
 shared/server-commands/videos/live-command.ts      |   2 +-
 shared/server-commands/videos/live.ts              |  41 +-
 shared/server-commands/videos/playlists.ts         |  25 -
 .../server-commands/videos/streaming-playlists.ts  |  77 --
 shared/server-commands/videos/videos-command.ts    |   4 +-
 shared/server-commands/videos/videos.ts            | 104 ---
 47 files changed, 33 insertions(+), 1860 deletions(-)
 delete mode 100644 shared/server-commands/miscs/checks.ts
 delete mode 100644 shared/server-commands/miscs/generate.ts
 delete mode 100644 shared/server-commands/miscs/tests.ts
 delete mode 100644 shared/server-commands/mock-servers/index.ts
 delete mode 100644 shared/server-commands/mock-servers/mock-429.ts
 delete mode 100644 shared/server-commands/mock-servers/mock-email.ts
 delete mode 100644 shared/server-commands/mock-servers/mock-instances-index.ts
 delete mode 100644 shared/server-commands/mock-servers/mock-joinpeertube-versions.ts
 delete mode 100644 shared/server-commands/mock-servers/mock-object-storage.ts
 delete mode 100644 shared/server-commands/mock-servers/mock-plugin-blocklist.ts
 delete mode 100644 shared/server-commands/mock-servers/mock-proxy.ts
 delete mode 100644 shared/server-commands/mock-servers/utils.ts
 delete mode 100644 shared/server-commands/requests/check-api-params.ts
 delete mode 100644 shared/server-commands/server/directories.ts
 delete mode 100644 shared/server-commands/server/plugins.ts
 delete mode 100644 shared/server-commands/server/tracker.ts
 delete mode 100644 shared/server-commands/users/actors.ts
 delete mode 100644 shared/server-commands/users/notifications.ts
 delete mode 100644 shared/server-commands/videos/captions.ts
 delete mode 100644 shared/server-commands/videos/playlists.ts
 delete mode 100644 shared/server-commands/videos/streaming-playlists.ts
 delete mode 100644 shared/server-commands/videos/videos.ts

(limited to 'shared/server-commands')

diff --git a/shared/server-commands/index.ts b/shared/server-commands/index.ts
index 4b3636d06..c24ebb2df 100644
--- a/shared/server-commands/index.ts
+++ b/shared/server-commands/index.ts
@@ -4,7 +4,6 @@ export * from './custom-pages'
 export * from './feeds'
 export * from './logs'
 export * from './miscs'
-export * from './mock-servers'
 export * from './moderation'
 export * from './overviews'
 export * from './requests'
diff --git a/shared/server-commands/logs/logs-command.ts b/shared/server-commands/logs/logs-command.ts
index 7b5c66c0c..8f63383ea 100644
--- a/shared/server-commands/logs/logs-command.ts
+++ b/shared/server-commands/logs/logs-command.ts
@@ -1,5 +1,4 @@
-import { HttpStatusCode } from '@shared/models'
-import { LogLevel } from '../../models/server/log-level.type'
+import { HttpStatusCode, LogLevel } from '@shared/models'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
 export class LogsCommand extends AbstractCommand {
diff --git a/shared/server-commands/miscs/checks.ts b/shared/server-commands/miscs/checks.ts
deleted file mode 100644
index 589928997..000000000
--- a/shared/server-commands/miscs/checks.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
-
-import { expect } from 'chai'
-import { pathExists, readFile } from 'fs-extra'
-import { join } from 'path'
-import { root } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import { makeGetRequest } from '../requests'
-import { PeerTubeServer } from '../server'
-
-// Default interval -> 5 minutes
-function dateIsValid (dateString: string, interval = 300000) {
-  const dateToCheck = new Date(dateString)
-  const now = new Date()
-
-  return Math.abs(now.getTime() - dateToCheck.getTime()) <= interval
-}
-
-function expectStartWith (str: string, start: string) {
-  expect(str.startsWith(start), `${str} does not start with ${start}`).to.be.true
-}
-
-async function expectLogDoesNotContain (server: PeerTubeServer, str: string) {
-  const content = await server.servers.getLogContent()
-
-  expect(content.toString()).to.not.contain(str)
-}
-
-async function testImage (url: string, imageName: string, imagePath: string, extension = '.jpg') {
-  const res = await makeGetRequest({
-    url,
-    path: imagePath,
-    expectedStatus: HttpStatusCode.OK_200
-  })
-
-  const body = res.body
-
-  const data = await readFile(join(root(), 'server', 'tests', 'fixtures', imageName + extension))
-  const minLength = body.length - ((30 * body.length) / 100)
-  const maxLength = body.length + ((30 * body.length) / 100)
-
-  expect(data.length).to.be.above(minLength, 'the generated image is way smaller than the recorded fixture')
-  expect(data.length).to.be.below(maxLength, 'the generated image is way larger than the recorded fixture')
-}
-
-async function testFileExistsOrNot (server: PeerTubeServer, directory: string, filePath: string, exist: boolean) {
-  const base = server.servers.buildDirectory(directory)
-
-  expect(await pathExists(join(base, filePath))).to.equal(exist)
-}
-
-export {
-  dateIsValid,
-  testImage,
-  expectLogDoesNotContain,
-  testFileExistsOrNot,
-  expectStartWith
-}
diff --git a/shared/server-commands/miscs/generate.ts b/shared/server-commands/miscs/generate.ts
deleted file mode 100644
index 93673a063..000000000
--- a/shared/server-commands/miscs/generate.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { expect } from 'chai'
-import ffmpeg from 'fluent-ffmpeg'
-import { ensureDir, pathExists } from 'fs-extra'
-import { dirname } from 'path'
-import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '@shared/extra-utils/ffprobe'
-import { getMaxBitrate } from '@shared/core-utils'
-import { buildAbsoluteFixturePath } from './tests'
-
-async function ensureHasTooBigBitrate (fixturePath: string) {
-  const bitrate = await getVideoFileBitrate(fixturePath)
-  const dataResolution = await getVideoFileResolution(fixturePath)
-  const fps = await getVideoFileFPS(fixturePath)
-
-  const maxBitrate = getMaxBitrate({ ...dataResolution, fps })
-  expect(bitrate).to.be.above(maxBitrate)
-}
-
-async function generateHighBitrateVideo () {
-  const tempFixturePath = buildAbsoluteFixturePath('video_high_bitrate_1080p.mp4', true)
-
-  await ensureDir(dirname(tempFixturePath))
-
-  const exists = await pathExists(tempFixturePath)
-  if (!exists) {
-    console.log('Generating high bitrate video.')
-
-    // Generate a random, high bitrate video on the fly, so we don't have to include
-    // a large file in the repo. The video needs to have a certain minimum length so
-    // that FFmpeg properly applies bitrate limits.
-    // https://stackoverflow.com/a/15795112
-    return new Promise<string>((res, rej) => {
-      ffmpeg()
-        .outputOptions([ '-f rawvideo', '-video_size 1920x1080', '-i /dev/urandom' ])
-        .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
-        .outputOptions([ '-maxrate 10M', '-bufsize 10M' ])
-        .output(tempFixturePath)
-        .on('error', rej)
-        .on('end', () => res(tempFixturePath))
-        .run()
-    })
-  }
-
-  await ensureHasTooBigBitrate(tempFixturePath)
-
-  return tempFixturePath
-}
-
-async function generateVideoWithFramerate (fps = 60) {
-  const tempFixturePath = buildAbsoluteFixturePath(`video_${fps}fps.mp4`, true)
-
-  await ensureDir(dirname(tempFixturePath))
-
-  const exists = await pathExists(tempFixturePath)
-  if (!exists) {
-    console.log('Generating video with framerate %d.', fps)
-
-    return new Promise<string>((res, rej) => {
-      ffmpeg()
-        .outputOptions([ '-f rawvideo', '-video_size 1280x720', '-i /dev/urandom' ])
-        .outputOptions([ '-ac 2', '-f s16le', '-i /dev/urandom', '-t 10' ])
-        .outputOptions([ `-r ${fps}` ])
-        .output(tempFixturePath)
-        .on('error', rej)
-        .on('end', () => res(tempFixturePath))
-        .run()
-    })
-  }
-
-  return tempFixturePath
-}
-
-export {
-  generateHighBitrateVideo,
-  generateVideoWithFramerate
-}
diff --git a/shared/server-commands/miscs/index.ts b/shared/server-commands/miscs/index.ts
index 4474661de..a1d14e998 100644
--- a/shared/server-commands/miscs/index.ts
+++ b/shared/server-commands/miscs/index.ts
@@ -1,5 +1,2 @@
-export * from './checks'
-export * from './generate'
 export * from './sql-command'
-export * from './tests'
 export * from './webtorrent'
diff --git a/shared/server-commands/miscs/sql-command.ts b/shared/server-commands/miscs/sql-command.ts
index bedb3349b..09a99f834 100644
--- a/shared/server-commands/miscs/sql-command.ts
+++ b/shared/server-commands/miscs/sql-command.ts
@@ -1,5 +1,5 @@
 import { QueryTypes, Sequelize } from 'sequelize'
-import { AbstractCommand } from '../shared/abstract-command'
+import { AbstractCommand } from '../shared'
 
 export class SQLCommand extends AbstractCommand {
   private sequelize: Sequelize
diff --git a/shared/server-commands/miscs/tests.ts b/shared/server-commands/miscs/tests.ts
deleted file mode 100644
index 658fe5fd3..000000000
--- a/shared/server-commands/miscs/tests.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import { stat } from 'fs-extra'
-import { basename, isAbsolute, join, resolve } from 'path'
-
-const FIXTURE_URLS = {
-  peertube_long: 'https://peertube2.cpy.re/videos/watch/122d093a-1ede-43bd-bd34-59d2931ffc5e',
-  peertube_short: 'https://peertube2.cpy.re/w/3fbif9S3WmtTP8gGsC5HBd',
-
-  youtube: 'https://www.youtube.com/watch?v=msX3jv1XdvM',
-
-  /**
-   * The video is used to check format-selection correctness wrt. HDR,
-   * which brings its own set of oddities outside of a MediaSource.
-   *
-   * The video needs to have the following format_ids:
-   * (which you can check by using `youtube-dl <url> -F`):
-   * - (webm vp9)
-   * - (mp4 avc1)
-   * - (webm vp9.2 HDR)
-   */
-  youtubeHDR: 'https://www.youtube.com/watch?v=RQgnBB9z_N4',
-
-  // eslint-disable-next-line max-len
-  magnet: 'magnet:?xs=https%3A%2F%2Fpeertube2.cpy.re%2Flazy-static%2Ftorrents%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.torrent&xt=urn:btih:0f498834733e8057ed5c6f2ee2b4efd8d84a76ee&dn=super+peertube2+video&tr=https%3A%2F%2Fpeertube2.cpy.re%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube2.cpy.re%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube2.cpy.re%2Fstatic%2Fwebseed%2Fb209ca00-c8bb-4b2b-b421-1ede169f3dbc-720.mp4',
-
-  badVideo: 'https://download.cpy.re/peertube/bad_video.mp4',
-  goodVideo: 'https://download.cpy.re/peertube/good_video.mp4',
-  goodVideo720: 'https://download.cpy.re/peertube/good_video_720.mp4',
-
-  file4K: 'https://download.cpy.re/peertube/4k_file.txt'
-}
-
-function parallelTests () {
-  return process.env.MOCHA_PARALLEL === 'true'
-}
-
-function isGithubCI () {
-  return !!process.env.GITHUB_WORKSPACE
-}
-
-function areHttpImportTestsDisabled () {
-  const disabled = process.env.DISABLE_HTTP_IMPORT_TESTS === 'true'
-
-  if (disabled) console.log('DISABLE_HTTP_IMPORT_TESTS env set to "true" so import tests are disabled')
-
-  return disabled
-}
-
-function areObjectStorageTestsDisabled () {
-  const disabled = process.env.ENABLE_OBJECT_STORAGE_TESTS !== 'true'
-
-  if (disabled) console.log('ENABLE_OBJECT_STORAGE_TESTS env is not set to "true" so object storage tests are disabled')
-
-  return disabled
-}
-
-function buildAbsoluteFixturePath (path: string, customCIPath = false) {
-  if (isAbsolute(path)) return path
-
-  if (customCIPath && process.env.GITHUB_WORKSPACE) {
-    return join(process.env.GITHUB_WORKSPACE, 'fixtures', path)
-  }
-
-  return join(root(), 'server', 'tests', 'fixtures', path)
-}
-
-function root () {
-  // We are in /miscs
-  let root = join(__dirname, '..', '..', '..')
-
-  if (basename(root) === 'dist') root = resolve(root, '..')
-
-  return root
-}
-
-function wait (milliseconds: number) {
-  return new Promise(resolve => setTimeout(resolve, milliseconds))
-}
-
-async function getFileSize (path: string) {
-  const stats = await stat(path)
-
-  return stats.size
-}
-
-function buildRequestStub (): any {
-  return { }
-}
-
-export {
-  FIXTURE_URLS,
-
-  parallelTests,
-  isGithubCI,
-  areHttpImportTestsDisabled,
-  buildAbsoluteFixturePath,
-  getFileSize,
-  buildRequestStub,
-  areObjectStorageTestsDisabled,
-  wait,
-  root
-}
diff --git a/shared/server-commands/mock-servers/index.ts b/shared/server-commands/mock-servers/index.ts
deleted file mode 100644
index 93c00c788..000000000
--- a/shared/server-commands/mock-servers/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export * from './mock-email'
-export * from './mock-instances-index'
-export * from './mock-joinpeertube-versions'
-export * from './mock-plugin-blocklist'
-export * from './mock-object-storage'
diff --git a/shared/server-commands/mock-servers/mock-429.ts b/shared/server-commands/mock-servers/mock-429.ts
deleted file mode 100644
index 9e0d1281a..000000000
--- a/shared/server-commands/mock-servers/mock-429.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import express from 'express'
-import { Server } from 'http'
-import { getPort, randomListen, terminateServer } from './utils'
-
-export class Mock429 {
-  private server: Server
-  private responseSent = false
-
-  async initialize () {
-    const app = express()
-
-    app.get('/', (req: express.Request, res: express.Response, next: express.NextFunction) => {
-
-      if (!this.responseSent) {
-        this.responseSent = true
-
-        // Retry after 5 seconds
-        res.header('retry-after', '2')
-        return res.sendStatus(429)
-      }
-
-      return res.sendStatus(200)
-    })
-
-    this.server = await randomListen(app)
-
-    return getPort(this.server)
-  }
-
-  terminate () {
-    return terminateServer(this.server)
-  }
-}
diff --git a/shared/server-commands/mock-servers/mock-email.ts b/shared/server-commands/mock-servers/mock-email.ts
deleted file mode 100644
index f646c1621..000000000
--- a/shared/server-commands/mock-servers/mock-email.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { ChildProcess } from 'child_process'
-import MailDev from '@peertube/maildev'
-import { randomInt } from '@shared/core-utils'
-import { parallelTests } from '../miscs'
-
-class MockSmtpServer {
-
-  private static instance: MockSmtpServer
-  private started = false
-  private emailChildProcess: ChildProcess
-  private emails: object[]
-
-  private constructor () { }
-
-  collectEmails (emailsCollection: object[]) {
-    return new Promise<number>((res, rej) => {
-      const port = parallelTests() ? randomInt(1000, 2000) : 1025
-      this.emails = emailsCollection
-
-      if (this.started) {
-        return res(undefined)
-      }
-
-      const maildev = new MailDev({
-        ip: '127.0.0.1',
-        smtp: port,
-        disableWeb: true,
-        silent: true
-      })
-
-      maildev.on('new', email => {
-        this.emails.push(email)
-      })
-
-      maildev.listen(err => {
-        if (err) return rej(err)
-
-        this.started = true
-
-        return res(port)
-      })
-    })
-  }
-
-  kill () {
-    if (!this.emailChildProcess) return
-
-    process.kill(this.emailChildProcess.pid)
-
-    this.emailChildProcess = null
-    MockSmtpServer.instance = null
-  }
-
-  static get Instance () {
-    return this.instance || (this.instance = new this())
-  }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
-  MockSmtpServer
-}
diff --git a/shared/server-commands/mock-servers/mock-instances-index.ts b/shared/server-commands/mock-servers/mock-instances-index.ts
deleted file mode 100644
index 92b12d6f3..000000000
--- a/shared/server-commands/mock-servers/mock-instances-index.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import express from 'express'
-import { Server } from 'http'
-import { getPort, randomListen, terminateServer } from './utils'
-
-export class MockInstancesIndex {
-  private server: Server
-
-  private readonly indexInstances: { host: string, createdAt: string }[] = []
-
-  async initialize () {
-    const app = express()
-
-    app.use('/', (req: express.Request, res: express.Response, next: express.NextFunction) => {
-      if (process.env.DEBUG) console.log('Receiving request on mocked server %s.', req.url)
-
-      return next()
-    })
-
-    app.get('/api/v1/instances/hosts', (req: express.Request, res: express.Response) => {
-      const since = req.query.since
-
-      const filtered = this.indexInstances.filter(i => {
-        if (!since) return true
-
-        return i.createdAt > since
-      })
-
-      return res.json({
-        total: filtered.length,
-        data: filtered
-      })
-    })
-
-    this.server = await randomListen(app)
-
-    return getPort(this.server)
-  }
-
-  addInstance (host: string) {
-    this.indexInstances.push({ host, createdAt: new Date().toISOString() })
-  }
-
-  terminate () {
-    return terminateServer(this.server)
-  }
-}
diff --git a/shared/server-commands/mock-servers/mock-joinpeertube-versions.ts b/shared/server-commands/mock-servers/mock-joinpeertube-versions.ts
deleted file mode 100644
index e7906ea56..000000000
--- a/shared/server-commands/mock-servers/mock-joinpeertube-versions.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import express from 'express'
-import { Server } from 'http'
-import { getPort, randomListen } from './utils'
-
-export class MockJoinPeerTubeVersions {
-  private server: Server
-  private latestVersion: string
-
-  async initialize () {
-    const app = express()
-
-    app.use('/', (req: express.Request, res: express.Response, next: express.NextFunction) => {
-      if (process.env.DEBUG) console.log('Receiving request on mocked server %s.', req.url)
-
-      return next()
-    })
-
-    app.get('/versions.json', (req: express.Request, res: express.Response) => {
-      return res.json({
-        peertube: {
-          latestVersion: this.latestVersion
-        }
-      })
-    })
-
-    this.server = await randomListen(app)
-
-    return getPort(this.server)
-  }
-
-  setLatestVersion (latestVersion: string) {
-    this.latestVersion = latestVersion
-  }
-}
diff --git a/shared/server-commands/mock-servers/mock-object-storage.ts b/shared/server-commands/mock-servers/mock-object-storage.ts
deleted file mode 100644
index d135c2631..000000000
--- a/shared/server-commands/mock-servers/mock-object-storage.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import express from 'express'
-import got, { RequestError } from 'got'
-import { Server } from 'http'
-import { pipeline } from 'stream'
-import { ObjectStorageCommand } from '../server'
-import { getPort, randomListen, terminateServer } from './utils'
-
-export class MockObjectStorage {
-  private server: Server
-
-  async initialize () {
-    const app = express()
-
-    app.get('/:bucketName/:path(*)', (req: express.Request, res: express.Response, next: express.NextFunction) => {
-      const url = `http://${req.params.bucketName}.${ObjectStorageCommand.getEndpointHost()}/${req.params.path}`
-
-      if (process.env.DEBUG) {
-        console.log('Receiving request on mocked server %s.', req.url)
-        console.log('Proxifying request to %s', url)
-      }
-
-      return pipeline(
-        got.stream(url, { throwHttpErrors: false }),
-        res,
-        (err: RequestError) => {
-          if (!err) return
-
-          console.error('Pipeline failed.', err)
-        }
-      )
-    })
-
-    this.server = await randomListen(app)
-
-    return getPort(this.server)
-  }
-
-  terminate () {
-    return terminateServer(this.server)
-  }
-}
diff --git a/shared/server-commands/mock-servers/mock-plugin-blocklist.ts b/shared/server-commands/mock-servers/mock-plugin-blocklist.ts
deleted file mode 100644
index f8a271cba..000000000
--- a/shared/server-commands/mock-servers/mock-plugin-blocklist.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import express, { Request, Response } from 'express'
-import { Server } from 'http'
-import { getPort, randomListen, terminateServer } from './utils'
-
-type BlocklistResponse = {
-  data: {
-    value: string
-    action?: 'add' | 'remove'
-    updatedAt?: string
-  }[]
-}
-
-export class MockBlocklist {
-  private body: BlocklistResponse
-  private server: Server
-
-  async initialize () {
-    const app = express()
-
-    app.get('/blocklist', (req: Request, res: Response) => {
-      return res.json(this.body)
-    })
-
-    this.server = await randomListen(app)
-
-    return getPort(this.server)
-  }
-
-  replace (body: BlocklistResponse) {
-    this.body = body
-  }
-
-  terminate () {
-    return terminateServer(this.server)
-  }
-}
diff --git a/shared/server-commands/mock-servers/mock-proxy.ts b/shared/server-commands/mock-servers/mock-proxy.ts
deleted file mode 100644
index 75ac79055..000000000
--- a/shared/server-commands/mock-servers/mock-proxy.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-
-import { createServer, Server } from 'http'
-import proxy from 'proxy'
-import { getPort, terminateServer } from './utils'
-
-class MockProxy {
-  private server: Server
-
-  initialize () {
-    return new Promise<number>(res => {
-      this.server = proxy(createServer())
-      this.server.listen(0, () => res(getPort(this.server)))
-    })
-  }
-
-  terminate () {
-    return terminateServer(this.server)
-  }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
-  MockProxy
-}
diff --git a/shared/server-commands/mock-servers/utils.ts b/shared/server-commands/mock-servers/utils.ts
deleted file mode 100644
index 235642439..000000000
--- a/shared/server-commands/mock-servers/utils.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { Express } from 'express'
-import { Server } from 'http'
-import { AddressInfo } from 'net'
-
-function randomListen (app: Express) {
-  return new Promise<Server>(res => {
-    const server = app.listen(0, () => res(server))
-  })
-}
-
-function getPort (server: Server) {
-  const address = server.address() as AddressInfo
-
-  return address.port
-}
-
-function terminateServer (server: Server) {
-  if (!server) return Promise.resolve()
-
-  return new Promise<void>((res, rej) => {
-    server.close(err => {
-      if (err) return rej(err)
-
-      return res()
-    })
-  })
-}
-
-export {
-  randomListen,
-  getPort,
-  terminateServer
-}
diff --git a/shared/server-commands/requests/check-api-params.ts b/shared/server-commands/requests/check-api-params.ts
deleted file mode 100644
index 26ba1e913..000000000
--- a/shared/server-commands/requests/check-api-params.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { HttpStatusCode } from '@shared/models'
-import { makeGetRequest } from './requests'
-
-function checkBadStartPagination (url: string, path: string, token?: string, query = {}) {
-  return makeGetRequest({
-    url,
-    path,
-    token,
-    query: { ...query, start: 'hello' },
-    expectedStatus: HttpStatusCode.BAD_REQUEST_400
-  })
-}
-
-async function checkBadCountPagination (url: string, path: string, token?: string, query = {}) {
-  await makeGetRequest({
-    url,
-    path,
-    token,
-    query: { ...query, count: 'hello' },
-    expectedStatus: HttpStatusCode.BAD_REQUEST_400
-  })
-
-  await makeGetRequest({
-    url,
-    path,
-    token,
-    query: { ...query, count: 2000 },
-    expectedStatus: HttpStatusCode.BAD_REQUEST_400
-  })
-}
-
-function checkBadSortPagination (url: string, path: string, token?: string, query = {}) {
-  return makeGetRequest({
-    url,
-    path,
-    token,
-    query: { ...query, sort: 'hello' },
-    expectedStatus: HttpStatusCode.BAD_REQUEST_400
-  })
-}
-
-// ---------------------------------------------------------------------------
-
-export {
-  checkBadStartPagination,
-  checkBadCountPagination,
-  checkBadSortPagination
-}
diff --git a/shared/server-commands/requests/index.ts b/shared/server-commands/requests/index.ts
index 501163f92..802982301 100644
--- a/shared/server-commands/requests/index.ts
+++ b/shared/server-commands/requests/index.ts
@@ -1,3 +1 @@
-// Don't include activitypub that import stuff from server
-export * from './check-api-params'
 export * from './requests'
diff --git a/shared/server-commands/requests/requests.ts b/shared/server-commands/requests/requests.ts
index b6b9024ed..95e4fe6b1 100644
--- a/shared/server-commands/requests/requests.ts
+++ b/shared/server-commands/requests/requests.ts
@@ -3,8 +3,8 @@
 import { decode } from 'querystring'
 import request from 'supertest'
 import { URL } from 'url'
+import { buildAbsoluteFixturePath } from '@shared/core-utils'
 import { HttpStatusCode } from '@shared/models'
-import { buildAbsoluteFixturePath } from '../miscs/tests'
 
 export type CommonRequestParams = {
   url: string
diff --git a/shared/server-commands/server/config-command.ts b/shared/server-commands/server/config-command.ts
index 89ae8eb4f..797231b1d 100644
--- a/shared/server-commands/server/config-command.ts
+++ b/shared/server-commands/server/config-command.ts
@@ -1,8 +1,7 @@
 import { merge } from 'lodash'
+import { About, CustomConfig, HttpStatusCode, ServerConfig } from '@shared/models'
 import { DeepPartial } from '@shared/typescript-utils'
-import { About, HttpStatusCode, ServerConfig } from '@shared/models'
-import { CustomConfig } from '../../models/server/custom-config.model'
-import { AbstractCommand, OverrideCommandOptions } from '../shared'
+import { AbstractCommand, OverrideCommandOptions } from '../shared/abstract-command'
 
 export class ConfigCommand extends AbstractCommand {
 
diff --git a/shared/server-commands/server/directories.ts b/shared/server-commands/server/directories.ts
deleted file mode 100644
index e6f72d6fc..000000000
--- a/shared/server-commands/server/directories.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, readdir } from 'fs-extra'
-import { join } from 'path'
-import { root } from '@shared/core-utils'
-import { PeerTubeServer } from './server'
-
-async function checkTmpIsEmpty (server: PeerTubeServer) {
-  await checkDirectoryIsEmpty(server, 'tmp', [ 'plugins-global.css', 'hls', 'resumable-uploads' ])
-
-  if (await pathExists(join('test' + server.internalServerNumber, 'tmp', 'hls'))) {
-    await checkDirectoryIsEmpty(server, 'tmp/hls')
-  }
-}
-
-async function checkDirectoryIsEmpty (server: PeerTubeServer, directory: string, exceptions: string[] = []) {
-  const testDirectory = 'test' + server.internalServerNumber
-
-  const directoryPath = join(root(), testDirectory, directory)
-
-  const directoryExists = await pathExists(directoryPath)
-  expect(directoryExists).to.be.true
-
-  const files = await readdir(directoryPath)
-  const filtered = files.filter(f => exceptions.includes(f) === false)
-
-  expect(filtered).to.have.lengthOf(0)
-}
-
-export {
-  checkTmpIsEmpty,
-  checkDirectoryIsEmpty
-}
diff --git a/shared/server-commands/server/index.ts b/shared/server-commands/server/index.ts
index 76a2099da..0a4b21fc4 100644
--- a/shared/server-commands/server/index.ts
+++ b/shared/server-commands/server/index.ts
@@ -1,17 +1,14 @@
 export * from './config-command'
 export * from './contact-form-command'
 export * from './debug-command'
-export * from './directories'
 export * from './follows-command'
 export * from './follows'
 export * from './jobs'
 export * from './jobs-command'
 export * from './object-storage-command'
 export * from './plugins-command'
-export * from './plugins'
 export * from './redundancy-command'
 export * from './server'
 export * from './servers-command'
 export * from './servers'
 export * from './stats-command'
-export * from './tracker'
diff --git a/shared/server-commands/server/jobs-command.ts b/shared/server-commands/server/jobs-command.ts
index 6636e7e4d..ac62157d1 100644
--- a/shared/server-commands/server/jobs-command.ts
+++ b/shared/server-commands/server/jobs-command.ts
@@ -1,6 +1,5 @@
 import { pick } from '@shared/core-utils'
-import { HttpStatusCode } from '@shared/models'
-import { Job, JobState, JobType, ResultList } from '../../models'
+import { HttpStatusCode, Job, JobState, JobType, ResultList } from '@shared/models'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
 export class JobsCommand extends AbstractCommand {
diff --git a/shared/server-commands/server/jobs.ts b/shared/server-commands/server/jobs.ts
index 34fefd444..fc65a873b 100644
--- a/shared/server-commands/server/jobs.ts
+++ b/shared/server-commands/server/jobs.ts
@@ -1,7 +1,7 @@
 
 import { expect } from 'chai'
+import { wait } from '@shared/core-utils'
 import { JobState, JobType } from '../../models'
-import { wait } from '../miscs'
 import { PeerTubeServer } from './server'
 
 async function waitJobs (serversArg: PeerTubeServer[] | PeerTubeServer, skipDelayed = false) {
diff --git a/shared/server-commands/server/plugins.ts b/shared/server-commands/server/plugins.ts
deleted file mode 100644
index c6316898d..000000000
--- a/shared/server-commands/server/plugins.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { PeerTubeServer } from './server'
-
-async function testHelloWorldRegisteredSettings (server: PeerTubeServer) {
-  const body = await server.plugins.getRegisteredSettings({ npmName: 'peertube-plugin-hello-world' })
-
-  const registeredSettings = body.registeredSettings
-  expect(registeredSettings).to.have.length.at.least(1)
-
-  const adminNameSettings = registeredSettings.find(s => s.name === 'admin-name')
-  expect(adminNameSettings).to.not.be.undefined
-}
-
-export {
-  testHelloWorldRegisteredSettings
-}
diff --git a/shared/server-commands/server/server.ts b/shared/server-commands/server/server.ts
index 339b9cabb..617069b11 100644
--- a/shared/server-commands/server/server.ts
+++ b/shared/server-commands/server/server.ts
@@ -1,14 +1,14 @@
 import { ChildProcess, fork } from 'child_process'
 import { copy } from 'fs-extra'
 import { join } from 'path'
-import { root, randomInt } from '@shared/core-utils'
-import { Video, VideoChannel, VideoCreateResult, VideoDetails } from '../../models/videos'
+import { parallelTests, randomInt, root } from '@shared/core-utils'
+import { Video, VideoChannel, VideoCreateResult, VideoDetails } from '@shared/models'
 import { BulkCommand } from '../bulk'
 import { CLICommand } from '../cli'
 import { CustomPagesCommand } from '../custom-pages'
 import { FeedCommand } from '../feeds'
 import { LogsCommand } from '../logs'
-import { parallelTests, SQLCommand } from '../miscs'
+import { SQLCommand } from '../miscs'
 import { AbusesCommand } from '../moderation'
 import { OverviewsCommand } from '../overviews'
 import { SearchCommand } from '../search'
@@ -33,11 +33,11 @@ import { ContactFormCommand } from './contact-form-command'
 import { DebugCommand } from './debug-command'
 import { FollowsCommand } from './follows-command'
 import { JobsCommand } from './jobs-command'
+import { ObjectStorageCommand } from './object-storage-command'
 import { PluginsCommand } from './plugins-command'
 import { RedundancyCommand } from './redundancy-command'
 import { ServersCommand } from './servers-command'
 import { StatsCommand } from './stats-command'
-import { ObjectStorageCommand } from './object-storage-command'
 
 export type RunServerOptions = {
   hideLogs?: boolean
diff --git a/shared/server-commands/server/servers-command.ts b/shared/server-commands/server/servers-command.ts
index 47420c95f..c5d8d18dc 100644
--- a/shared/server-commands/server/servers-command.ts
+++ b/shared/server-commands/server/servers-command.ts
@@ -1,9 +1,9 @@
 import { exec } from 'child_process'
 import { copy, ensureDir, readFile, remove } from 'fs-extra'
 import { basename, join } from 'path'
-import { root } from '@shared/core-utils'
+import { isGithubCI, root, wait } from '@shared/core-utils'
+import { getFileSize } from '@shared/extra-utils'
 import { HttpStatusCode } from '@shared/models'
-import { getFileSize, isGithubCI, wait } from '../miscs'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
 export class ServersCommand extends AbstractCommand {
diff --git a/shared/server-commands/server/servers.ts b/shared/server-commands/server/servers.ts
index 21ab9405b..0faee3a8d 100644
--- a/shared/server-commands/server/servers.ts
+++ b/shared/server-commands/server/servers.ts
@@ -1,5 +1,5 @@
 import { ensureDir } from 'fs-extra'
-import { isGithubCI } from '../miscs'
+import { isGithubCI } from '@shared/core-utils'
 import { PeerTubeServer, RunServerOptions } from './server'
 
 async function createSingleServer (serverNumber: number, configOverride?: Object, options: RunServerOptions = {}) {
diff --git a/shared/server-commands/server/tracker.ts b/shared/server-commands/server/tracker.ts
deleted file mode 100644
index ed43a5924..000000000
--- a/shared/server-commands/server/tracker.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { expect } from 'chai'
-import { sha1 } from '@shared/core-utils/crypto'
-import { makeGetRequest } from '../requests'
-
-async function hlsInfohashExist (serverUrl: string, masterPlaylistUrl: string, fileNumber: number) {
-  const path = '/tracker/announce'
-
-  const infohash = sha1(`2${masterPlaylistUrl}+V${fileNumber}`)
-
-  // From bittorrent-tracker
-  const infohashBinary = escape(Buffer.from(infohash, 'hex').toString('binary')).replace(/[@*/+]/g, function (char) {
-    return '%' + char.charCodeAt(0).toString(16).toUpperCase()
-  })
-
-  const res = await makeGetRequest({
-    url: serverUrl,
-    path,
-    rawQuery: `peer_id=-WW0105-NkvYO/egUAr4&info_hash=${infohashBinary}&port=42100`,
-    expectedStatus: 200
-  })
-
-  expect(res.text).to.not.contain('failure')
-}
-
-export {
-  hlsInfohashExist
-}
diff --git a/shared/server-commands/shared/abstract-command.ts b/shared/server-commands/shared/abstract-command.ts
index a57c857fc..1b53a5330 100644
--- a/shared/server-commands/shared/abstract-command.ts
+++ b/shared/server-commands/shared/abstract-command.ts
@@ -1,5 +1,5 @@
 import { isAbsolute, join } from 'path'
-import { root } from '../miscs/tests'
+import { root } from '@shared/core-utils'
 import {
   makeDeleteRequest,
   makeGetRequest,
diff --git a/shared/server-commands/users/accounts-command.ts b/shared/server-commands/users/accounts-command.ts
index 98d9d5927..5844b330b 100644
--- a/shared/server-commands/users/accounts-command.ts
+++ b/shared/server-commands/users/accounts-command.ts
@@ -1,6 +1,4 @@
-import { HttpStatusCode, ResultList } from '@shared/models'
-import { Account, ActorFollow } from '../../models/actors'
-import { AccountVideoRate, VideoRateType } from '../../models/videos'
+import { Account, AccountVideoRate, ActorFollow, HttpStatusCode, ResultList, VideoRateType } from '@shared/models'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
 export class AccountsCommand extends AbstractCommand {
diff --git a/shared/server-commands/users/actors.ts b/shared/server-commands/users/actors.ts
deleted file mode 100644
index 12c3e078a..000000000
--- a/shared/server-commands/users/actors.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { pathExists, readdir } from 'fs-extra'
-import { join } from 'path'
-import { root } from '@shared/core-utils'
-import { Account, VideoChannel } from '@shared/models'
-import { PeerTubeServer } from '../server'
-
-async function expectChannelsFollows (options: {
-  server: PeerTubeServer
-  handle: string
-  followers: number
-  following: number
-}) {
-  const { server } = options
-  const { data } = await server.channels.list()
-
-  return expectActorFollow({ ...options, data })
-}
-
-async function expectAccountFollows (options: {
-  server: PeerTubeServer
-  handle: string
-  followers: number
-  following: number
-}) {
-  const { server } = options
-  const { data } = await server.accounts.list()
-
-  return expectActorFollow({ ...options, data })
-}
-
-async function checkActorFilesWereRemoved (filename: string, serverNumber: number) {
-  const testDirectory = 'test' + serverNumber
-
-  for (const directory of [ 'avatars' ]) {
-    const directoryPath = join(root(), testDirectory, directory)
-
-    const directoryExists = await pathExists(directoryPath)
-    expect(directoryExists).to.be.true
-
-    const files = await readdir(directoryPath)
-    for (const file of files) {
-      expect(file).to.not.contain(filename)
-    }
-  }
-}
-
-export {
-  expectAccountFollows,
-  expectChannelsFollows,
-  checkActorFilesWereRemoved
-}
-
-// ---------------------------------------------------------------------------
-
-function expectActorFollow (options: {
-  server: PeerTubeServer
-  data: (Account | VideoChannel)[]
-  handle: string
-  followers: number
-  following: number
-}) {
-  const { server, data, handle, followers, following } = options
-
-  const actor = data.find(a => a.name + '@' + a.host === handle)
-  const message = `${handle} on ${server.url}`
-
-  expect(actor, message).to.exist
-  expect(actor.followersCount).to.equal(followers, message)
-  expect(actor.followingCount).to.equal(following, message)
-}
diff --git a/shared/server-commands/users/index.ts b/shared/server-commands/users/index.ts
index 460a06f70..c2bc5c44f 100644
--- a/shared/server-commands/users/index.ts
+++ b/shared/server-commands/users/index.ts
@@ -1,9 +1,7 @@
 export * from './accounts-command'
-export * from './actors'
 export * from './blocklist-command'
 export * from './login'
 export * from './login-command'
-export * from './notifications'
 export * from './notifications-command'
 export * from './subscriptions-command'
 export * from './users-command'
diff --git a/shared/server-commands/users/notifications-command.ts b/shared/server-commands/users/notifications-command.ts
index 692420b8b..6bd815daa 100644
--- a/shared/server-commands/users/notifications-command.ts
+++ b/shared/server-commands/users/notifications-command.ts
@@ -1,5 +1,4 @@
-import { HttpStatusCode, ResultList } from '@shared/models'
-import { UserNotification, UserNotificationSetting } from '../../models/users'
+import { HttpStatusCode, ResultList, UserNotification, UserNotificationSetting } from '@shared/models'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
 export class NotificationsCommand extends AbstractCommand {
diff --git a/shared/server-commands/users/notifications.ts b/shared/server-commands/users/notifications.ts
deleted file mode 100644
index 07ccb0f8d..000000000
--- a/shared/server-commands/users/notifications.ts
+++ /dev/null
@@ -1,795 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
-import { inspect } from 'util'
-import { AbuseState, PluginType } from '@shared/models'
-import { UserNotification, UserNotificationSetting, UserNotificationSettingValue, UserNotificationType } from '../../models/users'
-import { MockSmtpServer } from '../mock-servers/mock-email'
-import { PeerTubeServer } from '../server'
-import { doubleFollow } from '../server/follows'
-import { createMultipleServers } from '../server/servers'
-import { setAccessTokensToServers } from './login'
-
-type CheckerBaseParams = {
-  server: PeerTubeServer
-  emails: any[]
-  socketNotifications: UserNotification[]
-  token: string
-  check?: { web: boolean, mail: boolean }
-}
-
-type CheckerType = 'presence' | 'absence'
-
-function getAllNotificationsSettings (): UserNotificationSetting {
-  return {
-    newVideoFromSubscription: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    newCommentOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    abuseAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    videoAutoBlacklistAsModerator: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    blacklistOnMyVideo: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    myVideoImportFinished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    myVideoPublished: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    commentMention: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    newFollow: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    newUserRegistration: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    newInstanceFollower: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    abuseNewMessage: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    abuseStateChange: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    autoInstanceFollowing: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    newPeerTubeVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL,
-    newPluginVersion: UserNotificationSettingValue.WEB | UserNotificationSettingValue.EMAIL
-  }
-}
-
-async function checkNewVideoFromSubscription (options: CheckerBaseParams & {
-  videoName: string
-  shortUUID: string
-  checkType: CheckerType
-}) {
-  const { videoName, shortUUID } = options
-  const notificationType = UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      checkVideo(notification.video, videoName, shortUUID)
-      checkActor(notification.video.channel)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.type !== UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION || n.video.name !== videoName
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-    return text.indexOf(shortUUID) !== -1 && text.indexOf('Your subscription') !== -1
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkVideoIsPublished (options: CheckerBaseParams & {
-  videoName: string
-  shortUUID: string
-  checkType: CheckerType
-}) {
-  const { videoName, shortUUID } = options
-  const notificationType = UserNotificationType.MY_VIDEO_PUBLISHED
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      checkVideo(notification.video, videoName, shortUUID)
-      checkActor(notification.video.channel)
-    } else {
-      expect(notification.video).to.satisfy(v => v === undefined || v.name !== videoName)
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text: string = email['text']
-    return text.includes(shortUUID) && text.includes('Your video')
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkMyVideoImportIsFinished (options: CheckerBaseParams & {
-  videoName: string
-  shortUUID: string
-  url: string
-  success: boolean
-  checkType: CheckerType
-}) {
-  const { videoName, shortUUID, url, success } = options
-
-  const notificationType = success ? UserNotificationType.MY_VIDEO_IMPORT_SUCCESS : UserNotificationType.MY_VIDEO_IMPORT_ERROR
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      expect(notification.videoImport.targetUrl).to.equal(url)
-
-      if (success) checkVideo(notification.videoImport.video, videoName, shortUUID)
-    } else {
-      expect(notification.videoImport).to.satisfy(i => i === undefined || i.targetUrl !== url)
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text: string = email['text']
-    const toFind = success ? ' finished' : ' error'
-
-    return text.includes(url) && text.includes(toFind)
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkUserRegistered (options: CheckerBaseParams & {
-  username: string
-  checkType: CheckerType
-}) {
-  const { username } = options
-  const notificationType = UserNotificationType.NEW_USER_REGISTRATION
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      checkActor(notification.account)
-      expect(notification.account.name).to.equal(username)
-    } else {
-      expect(notification).to.satisfy(n => n.type !== notificationType || n.account.name !== username)
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text: string = email['text']
-
-    return text.includes(' registered.') && text.includes(username)
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewActorFollow (options: CheckerBaseParams & {
-  followType: 'channel' | 'account'
-  followerName: string
-  followerDisplayName: string
-  followingDisplayName: string
-  checkType: CheckerType
-}) {
-  const { followType, followerName, followerDisplayName, followingDisplayName } = options
-  const notificationType = UserNotificationType.NEW_FOLLOW
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      checkActor(notification.actorFollow.follower)
-      expect(notification.actorFollow.follower.displayName).to.equal(followerDisplayName)
-      expect(notification.actorFollow.follower.name).to.equal(followerName)
-      expect(notification.actorFollow.follower.host).to.not.be.undefined
-
-      const following = notification.actorFollow.following
-      expect(following.displayName).to.equal(followingDisplayName)
-      expect(following.type).to.equal(followType)
-    } else {
-      expect(notification).to.satisfy(n => {
-        return n.type !== notificationType ||
-          (n.actorFollow.follower.name !== followerName && n.actorFollow.following !== followingDisplayName)
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text: string = email['text']
-
-    return text.includes(followType) && text.includes(followingDisplayName) && text.includes(followerDisplayName)
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewInstanceFollower (options: CheckerBaseParams & {
-  followerHost: string
-  checkType: CheckerType
-}) {
-  const { followerHost } = options
-  const notificationType = UserNotificationType.NEW_INSTANCE_FOLLOWER
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      checkActor(notification.actorFollow.follower)
-      expect(notification.actorFollow.follower.name).to.equal('peertube')
-      expect(notification.actorFollow.follower.host).to.equal(followerHost)
-
-      expect(notification.actorFollow.following.name).to.equal('peertube')
-    } else {
-      expect(notification).to.satisfy(n => {
-        return n.type !== notificationType || n.actorFollow.follower.host !== followerHost
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text: string = email['text']
-
-    return text.includes('instance has a new follower') && text.includes(followerHost)
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkAutoInstanceFollowing (options: CheckerBaseParams & {
-  followerHost: string
-  followingHost: string
-  checkType: CheckerType
-}) {
-  const { followerHost, followingHost } = options
-  const notificationType = UserNotificationType.AUTO_INSTANCE_FOLLOWING
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      const following = notification.actorFollow.following
-      checkActor(following)
-      expect(following.name).to.equal('peertube')
-      expect(following.host).to.equal(followingHost)
-
-      expect(notification.actorFollow.follower.name).to.equal('peertube')
-      expect(notification.actorFollow.follower.host).to.equal(followerHost)
-    } else {
-      expect(notification).to.satisfy(n => {
-        return n.type !== notificationType || n.actorFollow.following.host !== followingHost
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text: string = email['text']
-
-    return text.includes(' automatically followed a new instance') && text.includes(followingHost)
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkCommentMention (options: CheckerBaseParams & {
-  shortUUID: string
-  commentId: number
-  threadId: number
-  byAccountDisplayName: string
-  checkType: CheckerType
-}) {
-  const { shortUUID, commentId, threadId, byAccountDisplayName } = options
-  const notificationType = UserNotificationType.COMMENT_MENTION
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      checkComment(notification.comment, commentId, threadId)
-      checkActor(notification.comment.account)
-      expect(notification.comment.account.displayName).to.equal(byAccountDisplayName)
-
-      checkVideo(notification.comment.video, undefined, shortUUID)
-    } else {
-      expect(notification).to.satisfy(n => n.type !== notificationType || n.comment.id !== commentId)
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text: string = email['text']
-
-    return text.includes(' mentioned ') && text.includes(shortUUID) && text.includes(byAccountDisplayName)
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-let lastEmailCount = 0
-
-async function checkNewCommentOnMyVideo (options: CheckerBaseParams & {
-  shortUUID: string
-  commentId: number
-  threadId: number
-  checkType: CheckerType
-}) {
-  const { server, shortUUID, commentId, threadId, checkType, emails } = options
-  const notificationType = UserNotificationType.NEW_COMMENT_ON_MY_VIDEO
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      checkComment(notification.comment, commentId, threadId)
-      checkActor(notification.comment.account)
-      checkVideo(notification.comment.video, undefined, shortUUID)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.comment === undefined || n.comment.id !== commentId
-      })
-    }
-  }
-
-  const commentUrl = `http://localhost:${server.port}/w/${shortUUID};threadId=${threadId}`
-
-  function emailNotificationFinder (email: object) {
-    return email['text'].indexOf(commentUrl) !== -1
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-
-  if (checkType === 'presence') {
-    // We cannot detect email duplicates, so check we received another email
-    expect(emails).to.have.length.above(lastEmailCount)
-    lastEmailCount = emails.length
-  }
-}
-
-async function checkNewVideoAbuseForModerators (options: CheckerBaseParams & {
-  shortUUID: string
-  videoName: string
-  checkType: CheckerType
-}) {
-  const { shortUUID, videoName } = options
-  const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      expect(notification.abuse.id).to.be.a('number')
-      checkVideo(notification.abuse.video, videoName, shortUUID)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.abuse === undefined || n.abuse.video.shortUUID !== shortUUID
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-    return text.indexOf(shortUUID) !== -1 && text.indexOf('abuse') !== -1
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewAbuseMessage (options: CheckerBaseParams & {
-  abuseId: number
-  message: string
-  toEmail: string
-  checkType: CheckerType
-}) {
-  const { abuseId, message, toEmail } = options
-  const notificationType = UserNotificationType.ABUSE_NEW_MESSAGE
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      expect(notification.abuse.id).to.equal(abuseId)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.type !== notificationType || n.abuse === undefined || n.abuse.id !== abuseId
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-    const to = email['to'].filter(t => t.address === toEmail)
-
-    return text.indexOf(message) !== -1 && to.length !== 0
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkAbuseStateChange (options: CheckerBaseParams & {
-  abuseId: number
-  state: AbuseState
-  checkType: CheckerType
-}) {
-  const { abuseId, state } = options
-  const notificationType = UserNotificationType.ABUSE_STATE_CHANGE
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      expect(notification.abuse.id).to.equal(abuseId)
-      expect(notification.abuse.state).to.equal(state)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.abuse === undefined || n.abuse.id !== abuseId
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-
-    const contains = state === AbuseState.ACCEPTED
-      ? ' accepted'
-      : ' rejected'
-
-    return text.indexOf(contains) !== -1
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewCommentAbuseForModerators (options: CheckerBaseParams & {
-  shortUUID: string
-  videoName: string
-  checkType: CheckerType
-}) {
-  const { shortUUID, videoName } = options
-  const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      expect(notification.abuse.id).to.be.a('number')
-      checkVideo(notification.abuse.comment.video, videoName, shortUUID)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.abuse === undefined || n.abuse.comment.video.shortUUID !== shortUUID
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-    return text.indexOf(shortUUID) !== -1 && text.indexOf('abuse') !== -1
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewAccountAbuseForModerators (options: CheckerBaseParams & {
-  displayName: string
-  checkType: CheckerType
-}) {
-  const { displayName } = options
-  const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      expect(notification.abuse.id).to.be.a('number')
-      expect(notification.abuse.account.displayName).to.equal(displayName)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.abuse === undefined || n.abuse.account.displayName !== displayName
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-    return text.indexOf(displayName) !== -1 && text.indexOf('abuse') !== -1
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkVideoAutoBlacklistForModerators (options: CheckerBaseParams & {
-  shortUUID: string
-  videoName: string
-  checkType: CheckerType
-}) {
-  const { shortUUID, videoName } = options
-  const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      expect(notification.videoBlacklist.video.id).to.be.a('number')
-      checkVideo(notification.videoBlacklist.video, videoName, shortUUID)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.video === undefined || n.video.shortUUID !== shortUUID
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-    return text.indexOf(shortUUID) !== -1 && email['text'].indexOf('video-auto-blacklist/list') !== -1
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewBlacklistOnMyVideo (options: CheckerBaseParams & {
-  shortUUID: string
-  videoName: string
-  blacklistType: 'blacklist' | 'unblacklist'
-}) {
-  const { videoName, shortUUID, blacklistType } = options
-  const notificationType = blacklistType === 'blacklist'
-    ? UserNotificationType.BLACKLIST_ON_MY_VIDEO
-    : UserNotificationType.UNBLACKLIST_ON_MY_VIDEO
-
-  function notificationChecker (notification: UserNotification) {
-    expect(notification).to.not.be.undefined
-    expect(notification.type).to.equal(notificationType)
-
-    const video = blacklistType === 'blacklist' ? notification.videoBlacklist.video : notification.video
-
-    checkVideo(video, videoName, shortUUID)
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-    const blacklistText = blacklistType === 'blacklist'
-      ? 'blacklisted'
-      : 'unblacklisted'
-
-    return text.includes(shortUUID) && text.includes(blacklistText)
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder, checkType: 'presence' })
-}
-
-async function checkNewPeerTubeVersion (options: CheckerBaseParams & {
-  latestVersion: string
-  checkType: CheckerType
-}) {
-  const { latestVersion } = options
-  const notificationType = UserNotificationType.NEW_PEERTUBE_VERSION
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      expect(notification.peertube).to.exist
-      expect(notification.peertube.latestVersion).to.equal(latestVersion)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.peertube === undefined || n.peertube.latestVersion !== latestVersion
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-
-    return text.includes(latestVersion)
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function checkNewPluginVersion (options: CheckerBaseParams & {
-  pluginType: PluginType
-  pluginName: string
-  checkType: CheckerType
-}) {
-  const { pluginName, pluginType } = options
-  const notificationType = UserNotificationType.NEW_PLUGIN_VERSION
-
-  function notificationChecker (notification: UserNotification, checkType: CheckerType) {
-    if (checkType === 'presence') {
-      expect(notification).to.not.be.undefined
-      expect(notification.type).to.equal(notificationType)
-
-      expect(notification.plugin.name).to.equal(pluginName)
-      expect(notification.plugin.type).to.equal(pluginType)
-    } else {
-      expect(notification).to.satisfy((n: UserNotification) => {
-        return n === undefined || n.plugin === undefined || n.plugin.name !== pluginName
-      })
-    }
-  }
-
-  function emailNotificationFinder (email: object) {
-    const text = email['text']
-
-    return text.includes(pluginName)
-  }
-
-  await checkNotification({ ...options, notificationChecker, emailNotificationFinder })
-}
-
-async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: any = {}) {
-  const userNotifications: UserNotification[] = []
-  const adminNotifications: UserNotification[] = []
-  const adminNotificationsServer2: UserNotification[] = []
-  const emails: object[] = []
-
-  const port = await MockSmtpServer.Instance.collectEmails(emails)
-
-  const overrideConfig = {
-    smtp: {
-      hostname: 'localhost',
-      port
-    },
-    signup: {
-      limit: 20
-    }
-  }
-  const servers = await createMultipleServers(serversCount, Object.assign(overrideConfig, overrideConfigArg))
-
-  await setAccessTokensToServers(servers)
-
-  if (serversCount > 1) {
-    await doubleFollow(servers[0], servers[1])
-  }
-
-  const user = { username: 'user_1', password: 'super password' }
-  await servers[0].users.create({ ...user, videoQuota: 10 * 1000 * 1000 })
-  const userAccessToken = await servers[0].login.getAccessToken(user)
-
-  await servers[0].notifications.updateMySettings({ token: userAccessToken, settings: getAllNotificationsSettings() })
-  await servers[0].notifications.updateMySettings({ settings: getAllNotificationsSettings() })
-
-  if (serversCount > 1) {
-    await servers[1].notifications.updateMySettings({ settings: getAllNotificationsSettings() })
-  }
-
-  {
-    const socket = servers[0].socketIO.getUserNotificationSocket({ token: userAccessToken })
-    socket.on('new-notification', n => userNotifications.push(n))
-  }
-  {
-    const socket = servers[0].socketIO.getUserNotificationSocket()
-    socket.on('new-notification', n => adminNotifications.push(n))
-  }
-
-  if (serversCount > 1) {
-    const socket = servers[1].socketIO.getUserNotificationSocket()
-    socket.on('new-notification', n => adminNotificationsServer2.push(n))
-  }
-
-  const { videoChannels } = await servers[0].users.getMyInfo()
-  const channelId = videoChannels[0].id
-
-  return {
-    userNotifications,
-    adminNotifications,
-    adminNotificationsServer2,
-    userAccessToken,
-    emails,
-    servers,
-    channelId
-  }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
-  getAllNotificationsSettings,
-
-  CheckerBaseParams,
-  CheckerType,
-  checkMyVideoImportIsFinished,
-  checkUserRegistered,
-  checkAutoInstanceFollowing,
-  checkVideoIsPublished,
-  checkNewVideoFromSubscription,
-  checkNewActorFollow,
-  checkNewCommentOnMyVideo,
-  checkNewBlacklistOnMyVideo,
-  checkCommentMention,
-  checkNewVideoAbuseForModerators,
-  checkVideoAutoBlacklistForModerators,
-  checkNewAbuseMessage,
-  checkAbuseStateChange,
-  checkNewInstanceFollower,
-  prepareNotificationsTest,
-  checkNewCommentAbuseForModerators,
-  checkNewAccountAbuseForModerators,
-  checkNewPeerTubeVersion,
-  checkNewPluginVersion
-}
-
-// ---------------------------------------------------------------------------
-
-async function checkNotification (options: CheckerBaseParams & {
-  notificationChecker: (notification: UserNotification, checkType: CheckerType) => void
-  emailNotificationFinder: (email: object) => boolean
-  checkType: CheckerType
-}) {
-  const { server, token, checkType, notificationChecker, emailNotificationFinder, socketNotifications, emails } = options
-
-  const check = options.check || { web: true, mail: true }
-
-  if (check.web) {
-    const notification = await server.notifications.getLatest({ token: token })
-
-    if (notification || checkType !== 'absence') {
-      notificationChecker(notification, checkType)
-    }
-
-    const socketNotification = socketNotifications.find(n => {
-      try {
-        notificationChecker(n, 'presence')
-        return true
-      } catch {
-        return false
-      }
-    })
-
-    if (checkType === 'presence') {
-      const obj = inspect(socketNotifications, { depth: 5 })
-      expect(socketNotification, 'The socket notification is absent when it should be present. ' + obj).to.not.be.undefined
-    } else {
-      const obj = inspect(socketNotification, { depth: 5 })
-      expect(socketNotification, 'The socket notification is present when it should not be present. ' + obj).to.be.undefined
-    }
-  }
-
-  if (check.mail) {
-    // Last email
-    const email = emails
-                      .slice()
-                      .reverse()
-                      .find(e => emailNotificationFinder(e))
-
-    if (checkType === 'presence') {
-      const texts = emails.map(e => e.text)
-      expect(email, 'The email is absent when is should be present. ' + inspect(texts)).to.not.be.undefined
-    } else {
-      expect(email, 'The email is present when is should not be present. ' + inspect(email)).to.be.undefined
-    }
-  }
-}
-
-function checkVideo (video: any, videoName?: string, shortUUID?: string) {
-  if (videoName) {
-    expect(video.name).to.be.a('string')
-    expect(video.name).to.not.be.empty
-    expect(video.name).to.equal(videoName)
-  }
-
-  if (shortUUID) {
-    expect(video.shortUUID).to.be.a('string')
-    expect(video.shortUUID).to.not.be.empty
-    expect(video.shortUUID).to.equal(shortUUID)
-  }
-
-  expect(video.id).to.be.a('number')
-}
-
-function checkActor (actor: any) {
-  expect(actor.displayName).to.be.a('string')
-  expect(actor.displayName).to.not.be.empty
-  expect(actor.host).to.not.be.undefined
-}
-
-function checkComment (comment: any, commentId: number, threadId: number) {
-  expect(comment.id).to.equal(commentId)
-  expect(comment.threadId).to.equal(threadId)
-}
diff --git a/shared/server-commands/users/users-command.ts b/shared/server-commands/users/users-command.ts
index 90c5f2183..b5ae9008e 100644
--- a/shared/server-commands/users/users-command.ts
+++ b/shared/server-commands/users/users-command.ts
@@ -4,6 +4,7 @@ import {
   HttpStatusCode,
   MyUser,
   ResultList,
+  ScopedToken,
   User,
   UserAdminFlag,
   UserCreateResult,
@@ -13,7 +14,6 @@ import {
   UserVideoQuota,
   UserVideoRate
 } from '@shared/models'
-import { ScopedToken } from '@shared/models/users/user-scoped-token'
 import { unwrapBody } from '../requests'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
diff --git a/shared/server-commands/videos/blacklist-command.ts b/shared/server-commands/videos/blacklist-command.ts
index 3a2ef89ba..47e23ebc8 100644
--- a/shared/server-commands/videos/blacklist-command.ts
+++ b/shared/server-commands/videos/blacklist-command.ts
@@ -1,6 +1,5 @@
 
-import { HttpStatusCode, ResultList } from '@shared/models'
-import { VideoBlacklist, VideoBlacklistType } from '../../models/videos'
+import { HttpStatusCode, ResultList, VideoBlacklist, VideoBlacklistType } from '@shared/models'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
 export class BlacklistCommand extends AbstractCommand {
diff --git a/shared/server-commands/videos/captions-command.ts b/shared/server-commands/videos/captions-command.ts
index a65ea99e3..62bf9c5e6 100644
--- a/shared/server-commands/videos/captions-command.ts
+++ b/shared/server-commands/videos/captions-command.ts
@@ -1,5 +1,5 @@
+import { buildAbsoluteFixturePath } from '@shared/core-utils'
 import { HttpStatusCode, ResultList, VideoCaption } from '@shared/models'
-import { buildAbsoluteFixturePath } from '../miscs'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
 export class CaptionsCommand extends AbstractCommand {
diff --git a/shared/server-commands/videos/captions.ts b/shared/server-commands/videos/captions.ts
deleted file mode 100644
index 35e722408..000000000
--- a/shared/server-commands/videos/captions.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { expect } from 'chai'
-import request from 'supertest'
-import { HttpStatusCode } from '@shared/models'
-
-async function testCaptionFile (url: string, captionPath: string, toTest: RegExp | string) {
-  const res = await request(url)
-    .get(captionPath)
-    .expect(HttpStatusCode.OK_200)
-
-  if (toTest instanceof RegExp) {
-    expect(res.text).to.match(toTest)
-  } else {
-    expect(res.text).to.contain(toTest)
-  }
-}
-
-// ---------------------------------------------------------------------------
-
-export {
-  testCaptionFile
-}
diff --git a/shared/server-commands/videos/channels-command.ts b/shared/server-commands/videos/channels-command.ts
index e406e570b..8ab124658 100644
--- a/shared/server-commands/videos/channels-command.ts
+++ b/shared/server-commands/videos/channels-command.ts
@@ -1,7 +1,13 @@
 import { pick } from '@shared/core-utils'
-import { ActorFollow, HttpStatusCode, ResultList, VideoChannel, VideoChannelCreateResult } from '@shared/models'
-import { VideoChannelCreate } from '../../models/videos/channel/video-channel-create.model'
-import { VideoChannelUpdate } from '../../models/videos/channel/video-channel-update.model'
+import {
+  ActorFollow,
+  HttpStatusCode,
+  ResultList,
+  VideoChannel,
+  VideoChannelCreate,
+  VideoChannelCreateResult,
+  VideoChannelUpdate
+} from '@shared/models'
 import { unwrapBody } from '../requests'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
diff --git a/shared/server-commands/videos/index.ts b/shared/server-commands/videos/index.ts
index 26e663f46..68a188b21 100644
--- a/shared/server-commands/videos/index.ts
+++ b/shared/server-commands/videos/index.ts
@@ -1,6 +1,5 @@
 export * from './blacklist-command'
 export * from './captions-command'
-export * from './captions'
 export * from './change-ownership-command'
 export * from './channels'
 export * from './channels-command'
@@ -10,10 +9,7 @@ export * from './imports-command'
 export * from './live-command'
 export * from './live'
 export * from './playlists-command'
-export * from './playlists'
 export * from './services-command'
 export * from './streaming-playlists-command'
-export * from './streaming-playlists'
 export * from './comments-command'
 export * from './videos-command'
-export * from './videos'
diff --git a/shared/server-commands/videos/live-command.ts b/shared/server-commands/videos/live-command.ts
index 74f5d3089..f7816eca0 100644
--- a/shared/server-commands/videos/live-command.ts
+++ b/shared/server-commands/videos/live-command.ts
@@ -3,8 +3,8 @@
 import { readdir } from 'fs-extra'
 import { omit } from 'lodash'
 import { join } from 'path'
+import { wait } from '@shared/core-utils'
 import { HttpStatusCode, LiveVideo, LiveVideoCreate, LiveVideoUpdate, VideoCreateResult, VideoDetails, VideoState } from '@shared/models'
-import { wait } from '../miscs'
 import { unwrapBody } from '../requests'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 import { sendRTMPStream, testFfmpegStreamError } from './live'
diff --git a/shared/server-commands/videos/live.ts b/shared/server-commands/videos/live.ts
index d3665bc90..7a7faa911 100644
--- a/shared/server-commands/videos/live.ts
+++ b/shared/server-commands/videos/live.ts
@@ -1,10 +1,5 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
-
-import { expect } from 'chai'
 import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg'
-import { pathExists, readdir } from 'fs-extra'
-import { join } from 'path'
-import { buildAbsoluteFixturePath, wait } from '../miscs'
+import { buildAbsoluteFixturePath, wait } from '@shared/core-utils'
 import { PeerTubeServer } from '../server/server'
 
 function sendRTMPStream (options: {
@@ -95,43 +90,11 @@ async function waitUntilLiveSavedOnAllServers (servers: PeerTubeServer[], videoI
   }
 }
 
-async function checkLiveCleanupAfterSave (server: PeerTubeServer, videoUUID: string, resolutions: number[] = []) {
-  const basePath = server.servers.buildDirectory('streaming-playlists')
-  const hlsPath = join(basePath, 'hls', videoUUID)
-
-  if (resolutions.length === 0) {
-    const result = await pathExists(hlsPath)
-    expect(result).to.be.false
-
-    return
-  }
-
-  const files = await readdir(hlsPath)
-
-  // fragmented file and playlist per resolution + master playlist + segments sha256 json file
-  expect(files).to.have.lengthOf(resolutions.length * 2 + 2)
-
-  for (const resolution of resolutions) {
-    const fragmentedFile = files.find(f => f.endsWith(`-${resolution}-fragmented.mp4`))
-    expect(fragmentedFile).to.exist
-
-    const playlistFile = files.find(f => f.endsWith(`${resolution}.m3u8`))
-    expect(playlistFile).to.exist
-  }
-
-  const masterPlaylistFile = files.find(f => f.endsWith('-master.m3u8'))
-  expect(masterPlaylistFile).to.exist
-
-  const shaFile = files.find(f => f.endsWith('-segments-sha256.json'))
-  expect(shaFile).to.exist
-}
-
 export {
   sendRTMPStream,
   waitFfmpegUntilError,
   testFfmpegStreamError,
   stopFfmpeg,
   waitUntilLivePublishedOnAllServers,
-  waitUntilLiveSavedOnAllServers,
-  checkLiveCleanupAfterSave
+  waitUntilLiveSavedOnAllServers
 }
diff --git a/shared/server-commands/videos/playlists.ts b/shared/server-commands/videos/playlists.ts
deleted file mode 100644
index 3dde52bb9..000000000
--- a/shared/server-commands/videos/playlists.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { expect } from 'chai'
-import { readdir } from 'fs-extra'
-import { join } from 'path'
-import { root } from '../miscs'
-
-async function checkPlaylistFilesWereRemoved (
-  playlistUUID: string,
-  internalServerNumber: number,
-  directories = [ 'thumbnails' ]
-) {
-  const testDirectory = 'test' + internalServerNumber
-
-  for (const directory of directories) {
-    const directoryPath = join(root(), testDirectory, directory)
-
-    const files = await readdir(directoryPath)
-    for (const file of files) {
-      expect(file).to.not.contain(playlistUUID)
-    }
-  }
-}
-
-export {
-  checkPlaylistFilesWereRemoved
-}
diff --git a/shared/server-commands/videos/streaming-playlists.ts b/shared/server-commands/videos/streaming-playlists.ts
deleted file mode 100644
index 0451c0efe..000000000
--- a/shared/server-commands/videos/streaming-playlists.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import { expect } from 'chai'
-import { basename } from 'path'
-import { sha256 } from '@shared/core-utils/crypto'
-import { removeFragmentedMP4Ext } from '@shared/core-utils'
-import { HttpStatusCode, VideoStreamingPlaylist } from '@shared/models'
-import { PeerTubeServer } from '../server'
-
-async function checkSegmentHash (options: {
-  server: PeerTubeServer
-  baseUrlPlaylist: string
-  baseUrlSegment: string
-  resolution: number
-  hlsPlaylist: VideoStreamingPlaylist
-}) {
-  const { server, baseUrlPlaylist, baseUrlSegment, resolution, hlsPlaylist } = options
-  const command = server.streamingPlaylists
-
-  const file = hlsPlaylist.files.find(f => f.resolution.id === resolution)
-  const videoName = basename(file.fileUrl)
-
-  const playlist = await command.get({ url: `${baseUrlPlaylist}/${removeFragmentedMP4Ext(videoName)}.m3u8` })
-
-  const matches = /#EXT-X-BYTERANGE:(\d+)@(\d+)/.exec(playlist)
-
-  const length = parseInt(matches[1], 10)
-  const offset = parseInt(matches[2], 10)
-  const range = `${offset}-${offset + length - 1}`
-
-  const segmentBody = await command.getSegment({
-    url: `${baseUrlSegment}/${videoName}`,
-    expectedStatus: HttpStatusCode.PARTIAL_CONTENT_206,
-    range: `bytes=${range}`
-  })
-
-  const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url })
-  expect(sha256(segmentBody)).to.equal(shaBody[videoName][range])
-}
-
-async function checkLiveSegmentHash (options: {
-  server: PeerTubeServer
-  baseUrlSegment: string
-  videoUUID: string
-  segmentName: string
-  hlsPlaylist: VideoStreamingPlaylist
-}) {
-  const { server, baseUrlSegment, videoUUID, segmentName, hlsPlaylist } = options
-  const command = server.streamingPlaylists
-
-  const segmentBody = await command.getSegment({ url: `${baseUrlSegment}/${videoUUID}/${segmentName}` })
-  const shaBody = await command.getSegmentSha256({ url: hlsPlaylist.segmentsSha256Url })
-
-  expect(sha256(segmentBody)).to.equal(shaBody[segmentName])
-}
-
-async function checkResolutionsInMasterPlaylist (options: {
-  server: PeerTubeServer
-  playlistUrl: string
-  resolutions: number[]
-}) {
-  const { server, playlistUrl, resolutions } = options
-
-  const masterPlaylist = await server.streamingPlaylists.get({ url: playlistUrl })
-
-  for (const resolution of resolutions) {
-    const reg = new RegExp(
-      '#EXT-X-STREAM-INF:BANDWIDTH=\\d+,RESOLUTION=\\d+x' + resolution + ',(FRAME-RATE=\\d+,)?CODECS="avc1.64001f,mp4a.40.2"'
-    )
-
-    expect(masterPlaylist).to.match(reg)
-  }
-}
-
-export {
-  checkSegmentHash,
-  checkLiveSegmentHash,
-  checkResolutionsInMasterPlaylist
-}
diff --git a/shared/server-commands/videos/videos-command.ts b/shared/server-commands/videos/videos-command.ts
index 8ea828b40..ead57b9aa 100644
--- a/shared/server-commands/videos/videos-command.ts
+++ b/shared/server-commands/videos/videos-command.ts
@@ -5,8 +5,7 @@ import { createReadStream, stat } from 'fs-extra'
 import got, { Response as GotResponse } from 'got'
 import { omit } from 'lodash'
 import validator from 'validator'
-import { buildUUID } from '@shared/core-utils/uuid'
-import { pick } from '@shared/core-utils'
+import { buildAbsoluteFixturePath, buildUUID, pick, wait } from '@shared/core-utils'
 import {
   HttpStatusCode,
   ResultList,
@@ -20,7 +19,6 @@ import {
   VideosCommonQuery,
   VideoTranscodingCreate
 } from '@shared/models'
-import { buildAbsoluteFixturePath, wait } from '../miscs'
 import { unwrapBody } from '../requests'
 import { waitJobs } from '../server'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
diff --git a/shared/server-commands/videos/videos.ts b/shared/server-commands/videos/videos.ts
deleted file mode 100644
index 2c3464aa8..000000000
--- a/shared/server-commands/videos/videos.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
-
-import { expect } from 'chai'
-import { pathExists, readdir } from 'fs-extra'
-import { basename, join } from 'path'
-import { HttpStatusCode, VideoCaption, VideoDetails } from '@shared/models'
-import { waitJobs } from '../server'
-import { PeerTubeServer } from '../server/server'
-import { VideoEdit } from './videos-command'
-
-async function checkVideoFilesWereRemoved (options: {
-  server: PeerTubeServer
-  video: VideoDetails
-  captions?: VideoCaption[]
-  onlyVideoFiles?: boolean // default false
-}) {
-  const { video, server, captions = [], onlyVideoFiles = false } = options
-
-  const webtorrentFiles = video.files || []
-  const hlsFiles = video.streamingPlaylists[0]?.files || []
-
-  const thumbnailName = basename(video.thumbnailPath)
-  const previewName = basename(video.previewPath)
-
-  const torrentNames = webtorrentFiles.concat(hlsFiles).map(f => basename(f.torrentUrl))
-
-  const captionNames = captions.map(c => basename(c.captionPath))
-
-  const webtorrentFilenames = webtorrentFiles.map(f => basename(f.fileUrl))
-  const hlsFilenames = hlsFiles.map(f => basename(f.fileUrl))
-
-  let directories: { [ directory: string ]: string[] } = {
-    videos: webtorrentFilenames,
-    redundancy: webtorrentFilenames,
-    [join('playlists', 'hls')]: hlsFilenames,
-    [join('redundancy', 'hls')]: hlsFilenames
-  }
-
-  if (onlyVideoFiles !== true) {
-    directories = {
-      ...directories,
-
-      thumbnails: [ thumbnailName ],
-      previews: [ previewName ],
-      torrents: torrentNames,
-      captions: captionNames
-    }
-  }
-
-  for (const directory of Object.keys(directories)) {
-    const directoryPath = server.servers.buildDirectory(directory)
-
-    const directoryExists = await pathExists(directoryPath)
-    if (directoryExists === false) continue
-
-    const existingFiles = await readdir(directoryPath)
-    for (const existingFile of existingFiles) {
-      for (const shouldNotExist of directories[directory]) {
-        expect(existingFile, `File ${existingFile} should not exist in ${directoryPath}`).to.not.contain(shouldNotExist)
-      }
-    }
-  }
-}
-
-async function saveVideoInServers (servers: PeerTubeServer[], uuid: string) {
-  for (const server of servers) {
-    server.store.videoDetails = await server.videos.get({ id: uuid })
-  }
-}
-
-function checkUploadVideoParam (
-  server: PeerTubeServer,
-  token: string,
-  attributes: Partial<VideoEdit>,
-  expectedStatus = HttpStatusCode.OK_200,
-  mode: 'legacy' | 'resumable' = 'legacy'
-) {
-  return mode === 'legacy'
-    ? server.videos.buildLegacyUpload({ token, attributes, expectedStatus })
-    : server.videos.buildResumeUpload({ token, attributes, expectedStatus })
-}
-
-// serverNumber starts from 1
-async function uploadRandomVideoOnServers (
-  servers: PeerTubeServer[],
-  serverNumber: number,
-  additionalParams?: VideoEdit & { prefixName?: string }
-) {
-  const server = servers.find(s => s.serverNumber === serverNumber)
-  const res = await server.videos.randomUpload({ wait: false, additionalParams })
-
-  await waitJobs(servers)
-
-  return res
-}
-
-// ---------------------------------------------------------------------------
-
-export {
-  checkUploadVideoParam,
-  uploadRandomVideoOnServers,
-  checkVideoFilesWereRemoved,
-  saveVideoInServers
-}
-- 
cgit v1.2.3