Add CLI plugins tests
This commit is contained in:
parent
32fe001389
commit
9b474844e8
22 changed files with 611 additions and 170 deletions
|
@ -4,21 +4,16 @@ import { PluginManager } from '../../server/lib/plugins/plugin-manager'
|
|||
import { isAbsolute } from 'path'
|
||||
|
||||
program
|
||||
.option('-n, --plugin-name [pluginName]', 'Plugin name to install')
|
||||
.option('-n, --npm-name [npmName]', 'Plugin to install')
|
||||
.option('-v, --plugin-version [pluginVersion]', 'Plugin version to install')
|
||||
.option('-p, --plugin-path [pluginPath]', 'Path of the plugin you want to install')
|
||||
.parse(process.argv)
|
||||
|
||||
if (!program['pluginName'] && !program['pluginPath']) {
|
||||
if (!program['npmName'] && !program['pluginPath']) {
|
||||
console.error('You need to specify a plugin name with the desired version, or a plugin path.')
|
||||
process.exit(-1)
|
||||
}
|
||||
|
||||
if (program['pluginName'] && !program['pluginVersion']) {
|
||||
console.error('You need to specify a the version of the plugin you want to install.')
|
||||
process.exit(-1)
|
||||
}
|
||||
|
||||
if (program['pluginPath'] && !isAbsolute(program['pluginPath'])) {
|
||||
console.error('Plugin path should be absolute.')
|
||||
process.exit(-1)
|
||||
|
@ -34,6 +29,6 @@ run()
|
|||
async function run () {
|
||||
await initDatabaseModels(true)
|
||||
|
||||
const toInstall = program['pluginName'] || program['pluginPath']
|
||||
const toInstall = program['npmName'] || program['pluginPath']
|
||||
await PluginManager.Instance.install(toInstall, program['pluginVersion'], !!program['pluginPath'])
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ if [ "$1" = "misc" ]; then
|
|||
mocha --timeout 5000 --exit --require ts-node/register --bail server/tests/client.ts \
|
||||
server/tests/feeds/index.ts \
|
||||
server/tests/misc-endpoints.ts \
|
||||
server/tests/helpers/index.ts
|
||||
server/tests/helpers/index.ts \
|
||||
server/tests/plugins/index.ts
|
||||
elif [ "$1" = "cli" ]; then
|
||||
npm run build:server
|
||||
CC=gcc-4.9 CXX=g++-4.9 npm run setup:cli
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
|
||||
import { createHash, HexBase64Latin1Encoding, pseudoRandomBytes } from 'crypto'
|
||||
import { isAbsolute, join } from 'path'
|
||||
import { basename, isAbsolute, join, resolve } from 'path'
|
||||
import * as pem from 'pem'
|
||||
import { URL } from 'url'
|
||||
import { truncate } from 'lodash'
|
||||
|
@ -136,16 +136,16 @@ function getAppNumber () {
|
|||
return process.env.NODE_APP_INSTANCE
|
||||
}
|
||||
|
||||
let rootPath: string
|
||||
function root () {
|
||||
if (rootPath) return rootPath
|
||||
|
||||
// We are in /helpers/utils.js
|
||||
const paths = [ __dirname, '..', '..' ]
|
||||
rootPath = join(__dirname, '..', '..')
|
||||
|
||||
// We are under /dist directory
|
||||
if (process.mainModule && process.mainModule.filename.endsWith('_mocha') === false) {
|
||||
paths.push('..')
|
||||
}
|
||||
if (basename(rootPath) === 'dist') rootPath = resolve(rootPath, '..')
|
||||
|
||||
return join.apply(null, paths)
|
||||
return rootPath
|
||||
}
|
||||
|
||||
// Thanks: https://stackoverflow.com/a/12034334
|
||||
|
|
|
@ -387,14 +387,15 @@ namespace audio {
|
|||
export namespace bitrate {
|
||||
const baseKbitrate = 384
|
||||
|
||||
const toBits = (kbits: number): number => { return kbits * 8000 }
|
||||
const toBits = (kbits: number) => kbits * 8000
|
||||
|
||||
export const aac = (bitrate: number): number => {
|
||||
switch (true) {
|
||||
case bitrate > toBits(baseKbitrate):
|
||||
return baseKbitrate
|
||||
default:
|
||||
return -1 // we interpret it as a signal to copy the audio stream as is
|
||||
case bitrate > toBits(baseKbitrate):
|
||||
return baseKbitrate
|
||||
|
||||
default:
|
||||
return -1 // we interpret it as a signal to copy the audio stream as is
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,12 +406,14 @@ namespace audio {
|
|||
made here are not made to be accurate, especially with good mp3 encoders.
|
||||
*/
|
||||
switch (true) {
|
||||
case bitrate <= toBits(192):
|
||||
return 128
|
||||
case bitrate <= toBits(384):
|
||||
return 256
|
||||
default:
|
||||
return baseKbitrate
|
||||
case bitrate <= toBits(192):
|
||||
return 128
|
||||
|
||||
case bitrate <= toBits(384):
|
||||
return 256
|
||||
|
||||
default:
|
||||
return baseKbitrate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@ import { CONFIG } from '../../initializers/config'
|
|||
import { outputJSON, pathExists } from 'fs-extra'
|
||||
import { join } from 'path'
|
||||
|
||||
async function installNpmPlugin (name: string, version?: string) {
|
||||
async function installNpmPlugin (npmName: string, version?: string) {
|
||||
// Security check
|
||||
checkNpmPluginNameOrThrow(name)
|
||||
checkNpmPluginNameOrThrow(npmName)
|
||||
if (version) checkPluginVersionOrThrow(version)
|
||||
|
||||
let toInstall = name
|
||||
let toInstall = npmName
|
||||
if (version) toInstall += `@${version}`
|
||||
|
||||
await execYarn('add ' + toInstall)
|
||||
|
|
|
@ -387,13 +387,24 @@ describe('Test users API validators', function () {
|
|||
}
|
||||
})
|
||||
|
||||
it('Should fail with an invalid theme', async function () {
|
||||
const fields = { theme: 'invalid' }
|
||||
await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should fail with an unknown theme', async function () {
|
||||
const fields = { theme: 'peertube-theme-unknown' }
|
||||
await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should succeed to change password with the correct params', async function () {
|
||||
const fields = {
|
||||
currentPassword: 'my super password',
|
||||
password: 'my super password',
|
||||
nsfwPolicy: 'blur',
|
||||
autoPlayVideo: false,
|
||||
email: 'super_email@example.com'
|
||||
email: 'super_email@example.com',
|
||||
theme: 'default'
|
||||
}
|
||||
|
||||
await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 })
|
||||
|
|
|
@ -11,3 +11,4 @@ import './reverse-proxy'
|
|||
import './stats'
|
||||
import './tracker'
|
||||
import './no-client'
|
||||
import './plugins'
|
||||
|
|
130
server/tests/api/server/plugins.ts
Normal file
130
server/tests/api/server/plugins.ts
Normal file
|
@ -0,0 +1,130 @@
|
|||
/* tslint:disable:no-unused-expression */
|
||||
|
||||
import 'mocha'
|
||||
import * as chai from 'chai'
|
||||
import { About } from '../../../../shared/models/server/about.model'
|
||||
import { CustomConfig } from '../../../../shared/models/server/custom-config.model'
|
||||
import {
|
||||
cleanupTests,
|
||||
deleteCustomConfig,
|
||||
flushAndRunServer,
|
||||
getAbout,
|
||||
getConfig,
|
||||
getCustomConfig, installPlugin,
|
||||
killallServers, parallelTests,
|
||||
registerUser,
|
||||
reRunServer, ServerInfo,
|
||||
setAccessTokensToServers,
|
||||
updateCustomConfig, uploadVideo
|
||||
} from '../../../../shared/extra-utils'
|
||||
import { ServerConfig } from '../../../../shared/models'
|
||||
import { PeerTubePlugin } from '../../../../shared/models/plugins/peertube-plugin.model'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('Test plugins', function () {
|
||||
let server = null
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000)
|
||||
|
||||
server = await flushAndRunServer(1)
|
||||
await setAccessTokensToServers([ server ])
|
||||
|
||||
{
|
||||
await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-hello-world' })
|
||||
}
|
||||
|
||||
{
|
||||
await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-background-color' })
|
||||
}
|
||||
})
|
||||
|
||||
it('Should list available plugins and themes', async function () {
|
||||
// List without filter
|
||||
// List with filter (plugin and theme)
|
||||
})
|
||||
|
||||
it('Should search available plugins', async function () {
|
||||
// Search with filter (plugin and theme)
|
||||
// Add pagination
|
||||
// Add sort
|
||||
// Add peertube engine
|
||||
})
|
||||
|
||||
it('Should have an empty global css', async function () {
|
||||
// get /global.css
|
||||
})
|
||||
|
||||
it('Should install a plugin and a theme', async function () {
|
||||
|
||||
})
|
||||
|
||||
it('Should have the correct global css', async function () {
|
||||
// get /global.css
|
||||
})
|
||||
|
||||
it('Should have the plugin loaded in the configuration', async function () {
|
||||
// Check registered themes/plugins
|
||||
})
|
||||
|
||||
it('Should update the default theme in the configuration', async function () {
|
||||
// Update config
|
||||
})
|
||||
|
||||
it('Should list plugins and themes', async function () {
|
||||
// List without filter
|
||||
// List with filter (theme/plugin)
|
||||
// List with pagination
|
||||
// List with sort
|
||||
})
|
||||
|
||||
it('Should get a plugin and a theme', async function () {
|
||||
// Get plugin
|
||||
// Get theme
|
||||
})
|
||||
|
||||
it('Should get registered settings', async function () {
|
||||
// Get plugin
|
||||
})
|
||||
|
||||
it('Should update the settings', async function () {
|
||||
// Update /settings
|
||||
|
||||
// get /plugin
|
||||
})
|
||||
|
||||
it('Should update the plugin and the theme', async function () {
|
||||
// update BDD -> 0.0.1
|
||||
// update package.json (theme + plugin)
|
||||
// list to check versions
|
||||
// update plugin + theme
|
||||
// list to check they have been updated
|
||||
// check package.json are upgraded too
|
||||
})
|
||||
|
||||
it('Should uninstall the plugin', async function () {
|
||||
// uninstall
|
||||
// list
|
||||
})
|
||||
|
||||
it('Should have an empty global css', async function () {
|
||||
// get /global.css
|
||||
})
|
||||
|
||||
it('Should list uninstalled plugins', async function () {
|
||||
// { uninstalled: true }
|
||||
})
|
||||
|
||||
it('Should uninstall the theme', async function () {
|
||||
// Uninstall
|
||||
})
|
||||
|
||||
it('Should have updated the configuration', async function () {
|
||||
// get /config (default theme + registered themes + registered plugins)
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests([ server ])
|
||||
})
|
||||
})
|
|
@ -18,7 +18,7 @@ import {
|
|||
getUsersList,
|
||||
getUsersListPaginationAndSort,
|
||||
getVideoChannel,
|
||||
getVideosList,
|
||||
getVideosList, installPlugin,
|
||||
login,
|
||||
makePutBodyRequest,
|
||||
rateVideo,
|
||||
|
@ -57,6 +57,8 @@ describe('Test users', function () {
|
|||
server = await flushAndRunServer(1)
|
||||
|
||||
await setAccessTokensToServers([ server ])
|
||||
|
||||
await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-theme-background-red' })
|
||||
})
|
||||
|
||||
describe('OAuth client', function () {
|
||||
|
@ -551,6 +553,21 @@ describe('Test users', function () {
|
|||
expect(user.account.displayName).to.equal('new display name')
|
||||
expect(user.account.description).to.equal('my super description updated')
|
||||
})
|
||||
|
||||
it('Should be able to update my theme', async function () {
|
||||
for (const theme of [ 'background-red', 'default', 'instance-default' ]) {
|
||||
await updateMyUser({
|
||||
url: server.url,
|
||||
accessToken: accessTokenUser,
|
||||
theme
|
||||
})
|
||||
|
||||
const res = await getMyUserInformation(server.url, accessTokenUser)
|
||||
const body: User = res.body
|
||||
|
||||
expect(body.theme).to.equal(theme)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('Updating another user', function () {
|
||||
|
|
|
@ -3,5 +3,6 @@ import './create-import-video-file-job'
|
|||
import './create-transcoding-job'
|
||||
import './optimize-old-videos'
|
||||
import './peertube'
|
||||
import './plugins'
|
||||
import './reset-password'
|
||||
import './update-host'
|
||||
|
|
|
@ -43,133 +43,171 @@ describe('Test CLI wrapper', function () {
|
|||
}
|
||||
})
|
||||
|
||||
it('Should display no selected instance', async function () {
|
||||
this.timeout(60000)
|
||||
describe('Authentication and instance selection', function () {
|
||||
|
||||
const env = getEnvCli(server)
|
||||
const stdout = await execCLI(`${env} ${cmd} --help`)
|
||||
it('Should display no selected instance', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
expect(stdout).to.contain('no instance selected')
|
||||
const env = getEnvCli(server)
|
||||
const stdout = await execCLI(`${env} ${cmd} --help`)
|
||||
|
||||
expect(stdout).to.contain('no instance selected')
|
||||
})
|
||||
|
||||
it('Should add a user', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
await execCLI(`${env} ${cmd} auth add -u ${server.url} -U user_1 -p super_password`)
|
||||
})
|
||||
|
||||
it('Should default to this user', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
const stdout = await execCLI(`${env} ${cmd} --help`)
|
||||
|
||||
expect(stdout).to.contain(`instance ${server.url} selected`)
|
||||
})
|
||||
|
||||
it('Should remember the user', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
const stdout = await execCLI(`${env} ${cmd} auth list`)
|
||||
|
||||
expect(stdout).to.contain(server.url)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should add a user', async function () {
|
||||
this.timeout(60000)
|
||||
describe('Video upload/import', function () {
|
||||
|
||||
const env = getEnvCli(server)
|
||||
await execCLI(`${env} ${cmd} auth add -u ${server.url} -U user_1 -p super_password`)
|
||||
})
|
||||
it('Should upload a video', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
it('Should default to this user', async function () {
|
||||
this.timeout(60000)
|
||||
const env = getEnvCli(server)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
const stdout = await execCLI(`${env} ${cmd} --help`)
|
||||
const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4')
|
||||
|
||||
expect(stdout).to.contain(`instance ${server.url} selected`)
|
||||
})
|
||||
const params = `-f ${fixture} --video-name 'test upload' --channel-name user_channel --support 'support_text'`
|
||||
|
||||
it('Should remember the user', async function () {
|
||||
this.timeout(60000)
|
||||
await execCLI(`${env} ${cmd} upload ${params}`)
|
||||
})
|
||||
|
||||
const env = getEnvCli(server)
|
||||
const stdout = await execCLI(`${env} ${cmd} auth list`)
|
||||
|
||||
expect(stdout).to.contain(server.url)
|
||||
})
|
||||
|
||||
it('Should upload a video', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
|
||||
const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4')
|
||||
|
||||
const params = `-f ${fixture} --video-name 'test upload' --channel-name user_channel --support 'support_text'`
|
||||
|
||||
await execCLI(`${env} ${cmd} upload ${params}`)
|
||||
})
|
||||
|
||||
it('Should have the video uploaded', async function () {
|
||||
const res = await getVideosList(server.url)
|
||||
|
||||
expect(res.body.total).to.equal(1)
|
||||
|
||||
const videos: Video[] = res.body.data
|
||||
|
||||
const video: VideoDetails = (await getVideo(server.url, videos[0].uuid)).body
|
||||
|
||||
expect(video.name).to.equal('test upload')
|
||||
expect(video.support).to.equal('support_text')
|
||||
expect(video.channel.name).to.equal('user_channel')
|
||||
})
|
||||
|
||||
it('Should import a video', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
|
||||
const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel`
|
||||
|
||||
await execCLI(`${env} ${cmd} import ${params}`)
|
||||
})
|
||||
|
||||
it('Should have imported the video', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
await waitJobs([ server ])
|
||||
|
||||
const res = await getVideosList(server.url)
|
||||
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const videos: Video[] = res.body.data
|
||||
const video = videos.find(v => v.name === 'small video - youtube')
|
||||
expect(video).to.not.be.undefined
|
||||
|
||||
const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body
|
||||
expect(videoDetails.channel.name).to.equal('user_channel')
|
||||
expect(videoDetails.support).to.equal('super support text')
|
||||
expect(videoDetails.nsfw).to.be.false
|
||||
|
||||
// So we can reimport it
|
||||
await removeVideo(server.url, userAccessToken, video.id)
|
||||
})
|
||||
|
||||
it('Should import and override some imported attributes', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
|
||||
const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel --video-name toto --nsfw --support support`
|
||||
|
||||
await execCLI(`${env} ${cmd} import ${params}`)
|
||||
|
||||
await waitJobs([ server ])
|
||||
|
||||
{
|
||||
it('Should have the video uploaded', async function () {
|
||||
const res = await getVideosList(server.url)
|
||||
|
||||
expect(res.body.total).to.equal(1)
|
||||
|
||||
const videos: Video[] = res.body.data
|
||||
|
||||
const video: VideoDetails = (await getVideo(server.url, videos[ 0 ].uuid)).body
|
||||
|
||||
expect(video.name).to.equal('test upload')
|
||||
expect(video.support).to.equal('support_text')
|
||||
expect(video.channel.name).to.equal('user_channel')
|
||||
})
|
||||
|
||||
it('Should import a video', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
|
||||
const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel`
|
||||
|
||||
await execCLI(`${env} ${cmd} import ${params}`)
|
||||
})
|
||||
|
||||
it('Should have imported the video', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
await waitJobs([ server ])
|
||||
|
||||
const res = await getVideosList(server.url)
|
||||
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const videos: Video[] = res.body.data
|
||||
const video = videos.find(v => v.name === 'toto')
|
||||
const video = videos.find(v => v.name === 'small video - youtube')
|
||||
expect(video).to.not.be.undefined
|
||||
|
||||
const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body
|
||||
expect(videoDetails.channel.name).to.equal('user_channel')
|
||||
expect(videoDetails.support).to.equal('support')
|
||||
expect(videoDetails.nsfw).to.be.true
|
||||
expect(videoDetails.commentsEnabled).to.be.true
|
||||
}
|
||||
expect(videoDetails.support).to.equal('super support text')
|
||||
expect(videoDetails.nsfw).to.be.false
|
||||
|
||||
// So we can reimport it
|
||||
await removeVideo(server.url, userAccessToken, video.id)
|
||||
})
|
||||
|
||||
it('Should import and override some imported attributes', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
|
||||
const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel --video-name toto --nsfw --support support`
|
||||
|
||||
await execCLI(`${env} ${cmd} import ${params}`)
|
||||
|
||||
await waitJobs([ server ])
|
||||
|
||||
{
|
||||
const res = await getVideosList(server.url)
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const videos: Video[] = res.body.data
|
||||
const video = videos.find(v => v.name === 'toto')
|
||||
expect(video).to.not.be.undefined
|
||||
|
||||
const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body
|
||||
expect(videoDetails.channel.name).to.equal('user_channel')
|
||||
expect(videoDetails.support).to.equal('support')
|
||||
expect(videoDetails.nsfw).to.be.true
|
||||
expect(videoDetails.commentsEnabled).to.be.true
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('Should remove the auth user', async function () {
|
||||
const env = getEnvCli(server)
|
||||
describe('Admin auth', function () {
|
||||
|
||||
await execCLI(`${env} ${cmd} auth del ${server.url}`)
|
||||
it('Should remove the auth user', async function () {
|
||||
const env = getEnvCli(server)
|
||||
|
||||
const stdout = await execCLI(`${env} ${cmd} --help`)
|
||||
await execCLI(`${env} ${cmd} auth del ${server.url}`)
|
||||
|
||||
expect(stdout).to.contain('no instance selected')
|
||||
const stdout = await execCLI(`${env} ${cmd} --help`)
|
||||
|
||||
expect(stdout).to.contain('no instance selected')
|
||||
})
|
||||
|
||||
it('Should add the admin user', async function () {
|
||||
const env = getEnvCli(server)
|
||||
await execCLI(`${env} ${cmd} auth add -u ${server.url} -U root -p test${server.internalServerNumber}`)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Manage plugins', function () {
|
||||
|
||||
it('Should install a plugin', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
await execCLI(`${env} ${cmd} plugins install --npm-name peertube-plugin-hello-world`)
|
||||
})
|
||||
|
||||
it('Should list installed plugins', async function () {
|
||||
const env = getEnvCli(server)
|
||||
const res = await execCLI(`${env} ${cmd} plugins list`)
|
||||
|
||||
expect(res).to.contain('peertube-plugin-hello-world')
|
||||
})
|
||||
|
||||
it('Should uninstall the plugin', async function () {
|
||||
const env = getEnvCli(server)
|
||||
const res = await execCLI(`${env} ${cmd} plugins uninstall --npm-name peertube-plugin-hello-world`)
|
||||
|
||||
expect(res).to.not.contain('peertube-plugin-hello-world')
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
|
|
87
server/tests/cli/plugins.ts
Normal file
87
server/tests/cli/plugins.ts
Normal file
|
@ -0,0 +1,87 @@
|
|||
/* tslint:disable:no-unused-expression */
|
||||
|
||||
import 'mocha'
|
||||
import {
|
||||
cleanupTests,
|
||||
execCLI,
|
||||
flushAndRunServer,
|
||||
getConfig,
|
||||
getEnvCli, killallServers,
|
||||
reRunServer,
|
||||
root,
|
||||
ServerInfo,
|
||||
setAccessTokensToServers
|
||||
} from '../../../shared/extra-utils'
|
||||
import { join } from 'path'
|
||||
import { ServerConfig } from '../../../shared/models/server'
|
||||
import { expect } from 'chai'
|
||||
|
||||
describe('Test plugin scripts', function () {
|
||||
let server: ServerInfo
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000)
|
||||
|
||||
server = await flushAndRunServer(1)
|
||||
await setAccessTokensToServers([ server ])
|
||||
})
|
||||
|
||||
it('Should install a plugin from stateless CLI', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const packagePath = join(root(), 'server', 'tests', 'fixtures', 'peertube-plugin-test')
|
||||
|
||||
const env = getEnvCli(server)
|
||||
await execCLI(`${env} npm run plugin:install -- --plugin-path ${packagePath}`)
|
||||
})
|
||||
|
||||
it('Should install a theme from stateless CLI', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
await execCLI(`${env} npm run plugin:install -- --npm-name peertube-theme-background-red`)
|
||||
})
|
||||
|
||||
it('Should have the theme and the plugin registered when we restart peertube', async function () {
|
||||
this.timeout(30000)
|
||||
|
||||
killallServers([ server ])
|
||||
await reRunServer(server)
|
||||
|
||||
const res = await getConfig(server.url)
|
||||
const config: ServerConfig = res.body
|
||||
|
||||
const plugin = config.plugin.registered
|
||||
.find(p => p.name === 'test')
|
||||
expect(plugin).to.not.be.undefined
|
||||
|
||||
const theme = config.theme.registered
|
||||
.find(t => t.name === 'background-red')
|
||||
expect(theme).to.not.be.undefined
|
||||
})
|
||||
|
||||
it('Should uninstall a plugin from stateless CLI', async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const env = getEnvCli(server)
|
||||
await execCLI(`${env} npm run plugin:uninstall -- --npm-name peertube-plugin-test`)
|
||||
})
|
||||
|
||||
it('Should have removed the plugin on another peertube restart', async function () {
|
||||
this.timeout(30000)
|
||||
|
||||
killallServers([ server ])
|
||||
await reRunServer(server)
|
||||
|
||||
const res = await getConfig(server.url)
|
||||
const config: ServerConfig = res.body
|
||||
|
||||
const plugin = config.plugin.registered
|
||||
.find(p => p.name === 'test')
|
||||
expect(plugin).to.be.undefined
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests([ server ])
|
||||
})
|
||||
})
|
39
server/tests/fixtures/peertube-plugin-test/main.js
vendored
Normal file
39
server/tests/fixtures/peertube-plugin-test/main.js
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
async function register ({ registerHook, registerSetting, settingsManager, storageManager }) {
|
||||
const defaultAdmin = 'PeerTube admin'
|
||||
|
||||
registerHook({
|
||||
target: 'action:application.listening',
|
||||
handler: () => displayHelloWorld(settingsManager, defaultAdmin)
|
||||
})
|
||||
|
||||
registerSetting({
|
||||
name: 'admin-name',
|
||||
label: 'Admin name',
|
||||
type: 'input',
|
||||
default: defaultAdmin
|
||||
})
|
||||
|
||||
const value = await storageManager.getData('toto')
|
||||
console.log(value)
|
||||
console.log(value.coucou)
|
||||
|
||||
await storageManager.storeData('toto', { coucou: 'hello' + new Date() })
|
||||
}
|
||||
|
||||
async function unregister () {
|
||||
return
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
register,
|
||||
unregister
|
||||
}
|
||||
|
||||
// ############################################################################
|
||||
|
||||
async function displayHelloWorld (settingsManager, defaultAdmin) {
|
||||
let value = await settingsManager.getSetting('admin-name')
|
||||
if (!value) value = defaultAdmin
|
||||
|
||||
console.log('hello world ' + value)
|
||||
}
|
19
server/tests/fixtures/peertube-plugin-test/package.json
vendored
Normal file
19
server/tests/fixtures/peertube-plugin-test/package.json
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "peertube-plugin-test",
|
||||
"version": "0.0.1",
|
||||
"description": "Plugin test",
|
||||
"engine": {
|
||||
"peertube": ">=1.3.0"
|
||||
},
|
||||
"keywords": [
|
||||
"peertube",
|
||||
"plugin"
|
||||
],
|
||||
"homepage": "https://github.com/Chocobozzz/PeerTube",
|
||||
"author": "Chocobozzz",
|
||||
"bugs": "https://github.com/Chocobozzz/PeerTube/issues",
|
||||
"library": "./main.js",
|
||||
"staticDirs": {},
|
||||
"css": [],
|
||||
"clientScripts": []
|
||||
}
|
|
@ -3,3 +3,4 @@ import './client'
|
|||
import './feeds/'
|
||||
import './cli/'
|
||||
import './api/'
|
||||
import './plugins/'
|
||||
|
|
27
server/tests/plugins/action-hooks.ts
Normal file
27
server/tests/plugins/action-hooks.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* tslint:disable:no-unused-expression */
|
||||
|
||||
import * as chai from 'chai'
|
||||
import 'mocha'
|
||||
import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
|
||||
import { setAccessTokensToServers } from '../../../shared/extra-utils'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('Test plugin filter hooks', function () {
|
||||
let server: ServerInfo
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000)
|
||||
server = await flushAndRunServer(1)
|
||||
|
||||
await setAccessTokensToServers([ server ])
|
||||
})
|
||||
|
||||
it('Should execute ', async function () {
|
||||
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests([ server ])
|
||||
})
|
||||
})
|
27
server/tests/plugins/filter-hooks.ts
Normal file
27
server/tests/plugins/filter-hooks.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* tslint:disable:no-unused-expression */
|
||||
|
||||
import * as chai from 'chai'
|
||||
import 'mocha'
|
||||
import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
|
||||
import { setAccessTokensToServers } from '../../../shared/extra-utils'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('Test plugin filter hooks', function () {
|
||||
let server: ServerInfo
|
||||
|
||||
before(async function () {
|
||||
this.timeout(30000)
|
||||
server = await flushAndRunServer(1)
|
||||
|
||||
await setAccessTokensToServers([ server ])
|
||||
})
|
||||
|
||||
it('Should execute ', async function () {
|
||||
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests([ server ])
|
||||
})
|
||||
})
|
2
server/tests/plugins/index.ts
Normal file
2
server/tests/plugins/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export * from './action-hooks'
|
||||
export * from './filter-hooks'
|
|
@ -18,7 +18,7 @@ program
|
|||
.command('get-access-token', 'get a peertube access token', { noHelp: true }).alias('token')
|
||||
.command('watch', 'watch a video in the terminal ✩°。⋆').alias('w')
|
||||
.command('repl', 'initiate a REPL to access internals')
|
||||
.command('plugins [action]', 'manage plugins on a local instance').alias('p')
|
||||
.command('plugins [action]', 'manage instance plugins/themes').alias('p')
|
||||
|
||||
/* Not Yet Implemented */
|
||||
program
|
||||
|
|
|
@ -6,6 +6,7 @@ import { UserRegister } from '../../models/users/user-register.model'
|
|||
import { UserRole } from '../../models/users/user-role'
|
||||
import { ServerInfo } from '../server/servers'
|
||||
import { userLogin } from './login'
|
||||
import { UserUpdateMe } from '../../models/users'
|
||||
|
||||
type CreateUserArgs = { url: string,
|
||||
accessToken: string,
|
||||
|
@ -224,19 +225,21 @@ function updateMyUser (options: {
|
|||
displayName?: string
|
||||
description?: string
|
||||
videosHistoryEnabled?: boolean
|
||||
theme?: string
|
||||
}) {
|
||||
const path = '/api/v1/users/me'
|
||||
|
||||
const toSend = {}
|
||||
if (options.currentPassword !== undefined && options.currentPassword !== null) toSend['currentPassword'] = options.currentPassword
|
||||
if (options.newPassword !== undefined && options.newPassword !== null) toSend['password'] = options.newPassword
|
||||
if (options.nsfwPolicy !== undefined && options.nsfwPolicy !== null) toSend['nsfwPolicy'] = options.nsfwPolicy
|
||||
if (options.autoPlayVideo !== undefined && options.autoPlayVideo !== null) toSend['autoPlayVideo'] = options.autoPlayVideo
|
||||
if (options.email !== undefined && options.email !== null) toSend['email'] = options.email
|
||||
if (options.description !== undefined && options.description !== null) toSend['description'] = options.description
|
||||
if (options.displayName !== undefined && options.displayName !== null) toSend['displayName'] = options.displayName
|
||||
const toSend: UserUpdateMe = {}
|
||||
if (options.currentPassword !== undefined && options.currentPassword !== null) toSend.currentPassword = options.currentPassword
|
||||
if (options.newPassword !== undefined && options.newPassword !== null) toSend.password = options.newPassword
|
||||
if (options.nsfwPolicy !== undefined && options.nsfwPolicy !== null) toSend.nsfwPolicy = options.nsfwPolicy
|
||||
if (options.autoPlayVideo !== undefined && options.autoPlayVideo !== null) toSend.autoPlayVideo = options.autoPlayVideo
|
||||
if (options.email !== undefined && options.email !== null) toSend.email = options.email
|
||||
if (options.description !== undefined && options.description !== null) toSend.description = options.description
|
||||
if (options.displayName !== undefined && options.displayName !== null) toSend.displayName = options.displayName
|
||||
if (options.theme !== undefined && options.theme !== null) toSend.theme = options.theme
|
||||
if (options.videosHistoryEnabled !== undefined && options.videosHistoryEnabled !== null) {
|
||||
toSend['videosHistoryEnabled'] = options.videosHistoryEnabled
|
||||
toSend.videosHistoryEnabled = options.videosHistoryEnabled
|
||||
}
|
||||
|
||||
return makePutBodyRequest({
|
||||
|
|
|
@ -18,30 +18,35 @@ export enum VideoResolution {
|
|||
*/
|
||||
function getBaseBitrate (resolution: VideoResolution) {
|
||||
switch (resolution) {
|
||||
case VideoResolution.H_240P:
|
||||
// quality according to Google Live Encoder: 300 - 700 Kbps
|
||||
// Quality according to YouTube Video Info: 186 Kbps
|
||||
return 250 * 1000
|
||||
case VideoResolution.H_360P:
|
||||
// quality according to Google Live Encoder: 400 - 1,000 Kbps
|
||||
// Quality according to YouTube Video Info: 480 Kbps
|
||||
return 500 * 1000
|
||||
case VideoResolution.H_480P:
|
||||
// quality according to Google Live Encoder: 500 - 2,000 Kbps
|
||||
// Quality according to YouTube Video Info: 879 Kbps
|
||||
return 900 * 1000
|
||||
case VideoResolution.H_720P:
|
||||
// quality according to Google Live Encoder: 1,500 - 4,000 Kbps
|
||||
// Quality according to YouTube Video Info: 1752 Kbps
|
||||
return 1750 * 1000
|
||||
case VideoResolution.H_1080P:
|
||||
// quality according to Google Live Encoder: 3000 - 6000 Kbps
|
||||
// Quality according to YouTube Video Info: 3277 Kbps
|
||||
return 3300 * 1000
|
||||
case VideoResolution.H_4K: // fallthrough
|
||||
default:
|
||||
// quality according to Google Live Encoder: 13000 - 34000 Kbps
|
||||
return 15000 * 1000
|
||||
case VideoResolution.H_240P:
|
||||
// quality according to Google Live Encoder: 300 - 700 Kbps
|
||||
// Quality according to YouTube Video Info: 186 Kbps
|
||||
return 250 * 1000
|
||||
|
||||
case VideoResolution.H_360P:
|
||||
// quality according to Google Live Encoder: 400 - 1,000 Kbps
|
||||
// Quality according to YouTube Video Info: 480 Kbps
|
||||
return 500 * 1000
|
||||
|
||||
case VideoResolution.H_480P:
|
||||
// quality according to Google Live Encoder: 500 - 2,000 Kbps
|
||||
// Quality according to YouTube Video Info: 879 Kbps
|
||||
return 900 * 1000
|
||||
|
||||
case VideoResolution.H_720P:
|
||||
// quality according to Google Live Encoder: 1,500 - 4,000 Kbps
|
||||
// Quality according to YouTube Video Info: 1752 Kbps
|
||||
return 1750 * 1000
|
||||
|
||||
case VideoResolution.H_1080P:
|
||||
// quality according to Google Live Encoder: 3000 - 6000 Kbps
|
||||
// Quality according to YouTube Video Info: 3277 Kbps
|
||||
return 3300 * 1000
|
||||
|
||||
case VideoResolution.H_4K: // fallthrough
|
||||
default:
|
||||
// quality according to Google Live Encoder: 13000 - 34000 Kbps
|
||||
return 15000 * 1000
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ You can access it as `peertube` via an alias in your `.bashrc` like `alias peert
|
|||
import-videos|import import a video from a streaming platform
|
||||
watch|w watch a video in the terminal ✩°。⋆
|
||||
repl initiate a REPL to access internals
|
||||
plugins|p [action] manag instance plugins
|
||||
help [cmd] display help for [cmd]
|
||||
```
|
||||
|
||||
|
@ -102,6 +103,15 @@ And now that your video is online, you can watch it from the confort of your ter
|
|||
$ peertube watch https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10
|
||||
```
|
||||
|
||||
To list, install, uninstall dynamically plugins/themes of an instance:
|
||||
|
||||
```bash
|
||||
$ peertube plugins list
|
||||
$ peertube plugins install --path /local/plugin/path
|
||||
$ peertube plugins install --npm-name peertube-plugin-myplugin
|
||||
$ peertube plugins uninstall --npm-name peertube-plugin-myplugin
|
||||
```
|
||||
|
||||
#### peertube-import-videos.js
|
||||
|
||||
You can use this script to import videos from all [supported sites of youtube-dl](https://rg3.github.io/youtube-dl/supportedsites.html) into PeerTube.
|
||||
|
@ -233,6 +243,30 @@ To reset a user password from CLI, run:
|
|||
$ sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run reset-password -- -u target_username
|
||||
```
|
||||
|
||||
|
||||
### plugin install/uninstall
|
||||
|
||||
The difference with `peertube plugins` CLI is that these scripts can be used even if PeerTube is not running.
|
||||
If PeerTube is running, you need to restart it for the changes to take effect (whereas with `peertube plugins` CLI, plugins/themes are dynamically loaded on the server).
|
||||
|
||||
To install a plugin or a theme from the disk:
|
||||
|
||||
```
|
||||
$ sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run npm run plugin:install -- --plugin-path /local/plugin/path
|
||||
```
|
||||
|
||||
From NPM:
|
||||
|
||||
```
|
||||
$ sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run npm run plugin:install -- --npm-name peertube-plugin-myplugin
|
||||
```
|
||||
|
||||
To uninstall a plugin or a theme:
|
||||
|
||||
```
|
||||
$ sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run npm run plugin:uninstall -- --npm-name peertube-plugin-myplugin
|
||||
```
|
||||
|
||||
### REPL ([Read Eval Print Loop](https://nodejs.org/docs/latest-v8.x/api/repl.html))
|
||||
|
||||
If you want to interact with the application libraries and objects even when PeerTube is not running, there is a REPL for that.
|
||||
|
|
Loading…
Reference in a new issue