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)
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'])
}
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
*/
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'
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
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
}
}
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
}
}
}
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)
}
})
+ 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 })
import './stats'
import './tracker'
import './no-client'
+import './plugins'
--- /dev/null
+/* 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 ])
+ })
+})
getUsersList,
getUsersListPaginationAndSort,
getVideoChannel,
- getVideosList,
+ getVideosList, installPlugin,
login,
makePutBodyRequest,
rateVideo,
server = await flushAndRunServer(1)
await setAccessTokensToServers([ server ])
+
+ await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-theme-background-red' })
})
describe('OAuth client', 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 () {
import './create-transcoding-job'
import './optimize-old-videos'
import './peertube'
+import './plugins'
import './reset-password'
import './update-host'
}
})
- 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`)
- it('Should add a user', async function () {
- this.timeout(60000)
+ expect(stdout).to.contain('no instance selected')
+ })
- const env = getEnvCli(server)
- await execCLI(`${env} ${cmd} auth add -u ${server.url} -U user_1 -p super_password`)
- })
+ it('Should add a user', async function () {
+ this.timeout(60000)
- it('Should default to this 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`)
+ })
- const env = getEnvCli(server)
- const stdout = await execCLI(`${env} ${cmd} --help`)
+ it('Should default to this user', async function () {
+ this.timeout(60000)
- expect(stdout).to.contain(`instance ${server.url} selected`)
- })
+ const env = getEnvCli(server)
+ const stdout = await execCLI(`${env} ${cmd} --help`)
- it('Should remember the user', async function () {
- this.timeout(60000)
+ expect(stdout).to.contain(`instance ${server.url} selected`)
+ })
- const env = getEnvCli(server)
- const stdout = await execCLI(`${env} ${cmd} auth list`)
+ it('Should remember the user', async function () {
+ this.timeout(60000)
- expect(stdout).to.contain(server.url)
+ 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)
+ describe('Video upload/import', function () {
- const env = getEnvCli(server)
+ it('Should upload a video', async function () {
+ this.timeout(60000)
- const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4')
+ const env = getEnvCli(server)
- const params = `-f ${fixture} --video-name 'test upload' --channel-name user_channel --support 'support_text'`
+ const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4')
- await execCLI(`${env} ${cmd} upload ${params}`)
- })
+ const params = `-f ${fixture} --video-name 'test upload' --channel-name user_channel --support 'support_text'`
- it('Should have the video uploaded', async function () {
- const res = await getVideosList(server.url)
+ await execCLI(`${env} ${cmd} upload ${params}`)
+ })
- expect(res.body.total).to.equal(1)
+ it('Should have the video uploaded', async function () {
+ const res = await getVideosList(server.url)
- const videos: Video[] = res.body.data
+ expect(res.body.total).to.equal(1)
- const video: VideoDetails = (await getVideo(server.url, videos[0].uuid)).body
+ const videos: Video[] = res.body.data
- expect(video.name).to.equal('test upload')
- expect(video.support).to.equal('support_text')
- expect(video.channel.name).to.equal('user_channel')
- })
+ const video: VideoDetails = (await getVideo(server.url, videos[ 0 ].uuid)).body
- it('Should import a video', async function () {
- this.timeout(60000)
+ expect(video.name).to.equal('test upload')
+ expect(video.support).to.equal('support_text')
+ expect(video.channel.name).to.equal('user_channel')
+ })
- const env = getEnvCli(server)
+ it('Should import a video', async function () {
+ this.timeout(60000)
- const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel`
+ const env = getEnvCli(server)
- await execCLI(`${env} ${cmd} import ${params}`)
- })
+ const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel`
- it('Should have imported the video', async function () {
- this.timeout(60000)
+ await execCLI(`${env} ${cmd} import ${params}`)
+ })
- await waitJobs([ server ])
+ it('Should have imported the video', async function () {
+ this.timeout(60000)
- const res = await getVideosList(server.url)
+ await waitJobs([ server ])
- expect(res.body.total).to.equal(2)
+ const res = await getVideosList(server.url)
- const videos: Video[] = res.body.data
- const video = videos.find(v => v.name === 'small video - youtube')
- expect(video).to.not.be.undefined
+ expect(res.body.total).to.equal(2)
- 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
+ const videos: Video[] = res.body.data
+ const video = videos.find(v => v.name === 'small video - youtube')
+ expect(video).to.not.be.undefined
- // So we can reimport it
- await removeVideo(server.url, userAccessToken, video.id)
- })
+ 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
- it('Should import and override some imported attributes', async function () {
- this.timeout(60000)
+ // So we can reimport it
+ await removeVideo(server.url, userAccessToken, video.id)
+ })
- const env = getEnvCli(server)
+ it('Should import and override some imported attributes', async function () {
+ this.timeout(60000)
- const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel --video-name toto --nsfw --support support`
+ const env = getEnvCli(server)
- await execCLI(`${env} ${cmd} import ${params}`)
+ const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel --video-name toto --nsfw --support support`
- await waitJobs([ server ])
+ await execCLI(`${env} ${cmd} import ${params}`)
- {
- const res = await getVideosList(server.url)
- expect(res.body.total).to.equal(2)
+ await waitJobs([ server ])
- const videos: Video[] = res.body.data
- const video = videos.find(v => v.name === 'toto')
- expect(video).to.not.be.undefined
+ {
+ const res = await getVideosList(server.url)
+ expect(res.body.total).to.equal(2)
- 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
- }
+ 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 () {
+
+ it('Should remove the auth user', async function () {
+ const env = getEnvCli(server)
+
+ await execCLI(`${env} ${cmd} auth del ${server.url}`)
+
+ 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`)
- await execCLI(`${env} ${cmd} auth del ${server.url}`)
+ expect(res).to.contain('peertube-plugin-hello-world')
+ })
- const stdout = await execCLI(`${env} ${cmd} --help`)
+ 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(stdout).to.contain('no instance selected')
+ expect(res).to.not.contain('peertube-plugin-hello-world')
+ })
})
after(async function () {
--- /dev/null
+/* 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 ])
+ })
+})
--- /dev/null
+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)
+}
--- /dev/null
+{
+ "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": []
+}
import './feeds/'
import './cli/'
import './api/'
+import './plugins/'
--- /dev/null
+/* 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 ])
+ })
+})
--- /dev/null
+/* 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 ])
+ })
+})
--- /dev/null
+export * from './action-hooks'
+export * from './filter-hooks'
.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
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,
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({
*/
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
}
}
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]
```
$ 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.
$ 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.