diff options
-rwxr-xr-x | scripts/plugin/install.ts | 11 | ||||
-rwxr-xr-x | scripts/travis.sh | 3 | ||||
-rw-r--r-- | server/helpers/core-utils.ts | 14 | ||||
-rw-r--r-- | server/helpers/ffmpeg-utils.ts | 25 | ||||
-rw-r--r-- | server/lib/plugins/yarn.ts | 6 | ||||
-rw-r--r-- | server/tests/api/check-params/users.ts | 13 | ||||
-rw-r--r-- | server/tests/api/server/index.ts | 1 | ||||
-rw-r--r-- | server/tests/api/server/plugins.ts | 130 | ||||
-rw-r--r-- | server/tests/api/users/users.ts | 19 | ||||
-rw-r--r-- | server/tests/cli/index.ts | 1 | ||||
-rw-r--r-- | server/tests/cli/peertube.ts | 202 | ||||
-rw-r--r-- | server/tests/cli/plugins.ts | 87 | ||||
-rw-r--r-- | server/tests/fixtures/peertube-plugin-test/main.js | 39 | ||||
-rw-r--r-- | server/tests/fixtures/peertube-plugin-test/package.json | 19 | ||||
-rw-r--r-- | server/tests/index.ts | 1 | ||||
-rw-r--r-- | server/tests/plugins/action-hooks.ts | 27 | ||||
-rw-r--r-- | server/tests/plugins/filter-hooks.ts | 27 | ||||
-rw-r--r-- | server/tests/plugins/index.ts | 2 | ||||
-rw-r--r-- | server/tools/peertube.ts | 2 | ||||
-rw-r--r-- | shared/extra-utils/users/users.ts | 21 | ||||
-rw-r--r-- | shared/models/videos/video-resolution.enum.ts | 53 | ||||
-rw-r--r-- | support/doc/tools.md | 34 |
22 files changed, 589 insertions, 148 deletions
diff --git a/scripts/plugin/install.ts b/scripts/plugin/install.ts index 1725cbeb6..5d7fe4ba0 100755 --- a/scripts/plugin/install.ts +++ b/scripts/plugin/install.ts | |||
@@ -4,21 +4,16 @@ import { PluginManager } from '../../server/lib/plugins/plugin-manager' | |||
4 | import { isAbsolute } from 'path' | 4 | import { isAbsolute } from 'path' |
5 | 5 | ||
6 | program | 6 | program |
7 | .option('-n, --plugin-name [pluginName]', 'Plugin name to install') | 7 | .option('-n, --npm-name [npmName]', 'Plugin to install') |
8 | .option('-v, --plugin-version [pluginVersion]', 'Plugin version to install') | 8 | .option('-v, --plugin-version [pluginVersion]', 'Plugin version to install') |
9 | .option('-p, --plugin-path [pluginPath]', 'Path of the plugin you want to install') | 9 | .option('-p, --plugin-path [pluginPath]', 'Path of the plugin you want to install') |
10 | .parse(process.argv) | 10 | .parse(process.argv) |
11 | 11 | ||
12 | if (!program['pluginName'] && !program['pluginPath']) { | 12 | if (!program['npmName'] && !program['pluginPath']) { |
13 | console.error('You need to specify a plugin name with the desired version, or a plugin path.') | 13 | console.error('You need to specify a plugin name with the desired version, or a plugin path.') |
14 | process.exit(-1) | 14 | process.exit(-1) |
15 | } | 15 | } |
16 | 16 | ||
17 | if (program['pluginName'] && !program['pluginVersion']) { | ||
18 | console.error('You need to specify a the version of the plugin you want to install.') | ||
19 | process.exit(-1) | ||
20 | } | ||
21 | |||
22 | if (program['pluginPath'] && !isAbsolute(program['pluginPath'])) { | 17 | if (program['pluginPath'] && !isAbsolute(program['pluginPath'])) { |
23 | console.error('Plugin path should be absolute.') | 18 | console.error('Plugin path should be absolute.') |
24 | process.exit(-1) | 19 | process.exit(-1) |
@@ -34,6 +29,6 @@ run() | |||
34 | async function run () { | 29 | async function run () { |
35 | await initDatabaseModels(true) | 30 | await initDatabaseModels(true) |
36 | 31 | ||
37 | const toInstall = program['pluginName'] || program['pluginPath'] | 32 | const toInstall = program['npmName'] || program['pluginPath'] |
38 | await PluginManager.Instance.install(toInstall, program['pluginVersion'], !!program['pluginPath']) | 33 | await PluginManager.Instance.install(toInstall, program['pluginVersion'], !!program['pluginPath']) |
39 | } | 34 | } |
diff --git a/scripts/travis.sh b/scripts/travis.sh index 664d9fd6c..42e2329c6 100755 --- a/scripts/travis.sh +++ b/scripts/travis.sh | |||
@@ -14,7 +14,8 @@ if [ "$1" = "misc" ]; then | |||
14 | mocha --timeout 5000 --exit --require ts-node/register --bail server/tests/client.ts \ | 14 | mocha --timeout 5000 --exit --require ts-node/register --bail server/tests/client.ts \ |
15 | server/tests/feeds/index.ts \ | 15 | server/tests/feeds/index.ts \ |
16 | server/tests/misc-endpoints.ts \ | 16 | server/tests/misc-endpoints.ts \ |
17 | server/tests/helpers/index.ts | 17 | server/tests/helpers/index.ts \ |
18 | server/tests/plugins/index.ts | ||
18 | elif [ "$1" = "cli" ]; then | 19 | elif [ "$1" = "cli" ]; then |
19 | npm run build:server | 20 | npm run build:server |
20 | CC=gcc-4.9 CXX=g++-4.9 npm run setup:cli | 21 | CC=gcc-4.9 CXX=g++-4.9 npm run setup:cli |
diff --git a/server/helpers/core-utils.ts b/server/helpers/core-utils.ts index 38b6f63f8..9ff67c43a 100644 --- a/server/helpers/core-utils.ts +++ b/server/helpers/core-utils.ts | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | import { createHash, HexBase64Latin1Encoding, pseudoRandomBytes } from 'crypto' | 6 | import { createHash, HexBase64Latin1Encoding, pseudoRandomBytes } from 'crypto' |
7 | import { isAbsolute, join } from 'path' | 7 | import { basename, isAbsolute, join, resolve } from 'path' |
8 | import * as pem from 'pem' | 8 | import * as pem from 'pem' |
9 | import { URL } from 'url' | 9 | import { URL } from 'url' |
10 | import { truncate } from 'lodash' | 10 | import { truncate } from 'lodash' |
@@ -136,16 +136,16 @@ function getAppNumber () { | |||
136 | return process.env.NODE_APP_INSTANCE | 136 | return process.env.NODE_APP_INSTANCE |
137 | } | 137 | } |
138 | 138 | ||
139 | let rootPath: string | ||
139 | function root () { | 140 | function root () { |
141 | if (rootPath) return rootPath | ||
142 | |||
140 | // We are in /helpers/utils.js | 143 | // We are in /helpers/utils.js |
141 | const paths = [ __dirname, '..', '..' ] | 144 | rootPath = join(__dirname, '..', '..') |
142 | 145 | ||
143 | // We are under /dist directory | 146 | if (basename(rootPath) === 'dist') rootPath = resolve(rootPath, '..') |
144 | if (process.mainModule && process.mainModule.filename.endsWith('_mocha') === false) { | ||
145 | paths.push('..') | ||
146 | } | ||
147 | 147 | ||
148 | return join.apply(null, paths) | 148 | return rootPath |
149 | } | 149 | } |
150 | 150 | ||
151 | // Thanks: https://stackoverflow.com/a/12034334 | 151 | // Thanks: https://stackoverflow.com/a/12034334 |
diff --git a/server/helpers/ffmpeg-utils.ts b/server/helpers/ffmpeg-utils.ts index 8041e7b3b..914ecc51a 100644 --- a/server/helpers/ffmpeg-utils.ts +++ b/server/helpers/ffmpeg-utils.ts | |||
@@ -387,14 +387,15 @@ namespace audio { | |||
387 | export namespace bitrate { | 387 | export namespace bitrate { |
388 | const baseKbitrate = 384 | 388 | const baseKbitrate = 384 |
389 | 389 | ||
390 | const toBits = (kbits: number): number => { return kbits * 8000 } | 390 | const toBits = (kbits: number) => kbits * 8000 |
391 | 391 | ||
392 | export const aac = (bitrate: number): number => { | 392 | export const aac = (bitrate: number): number => { |
393 | switch (true) { | 393 | switch (true) { |
394 | case bitrate > toBits(baseKbitrate): | 394 | case bitrate > toBits(baseKbitrate): |
395 | return baseKbitrate | 395 | return baseKbitrate |
396 | default: | 396 | |
397 | return -1 // we interpret it as a signal to copy the audio stream as is | 397 | default: |
398 | return -1 // we interpret it as a signal to copy the audio stream as is | ||
398 | } | 399 | } |
399 | } | 400 | } |
400 | 401 | ||
@@ -405,12 +406,14 @@ namespace audio { | |||
405 | made here are not made to be accurate, especially with good mp3 encoders. | 406 | made here are not made to be accurate, especially with good mp3 encoders. |
406 | */ | 407 | */ |
407 | switch (true) { | 408 | switch (true) { |
408 | case bitrate <= toBits(192): | 409 | case bitrate <= toBits(192): |
409 | return 128 | 410 | return 128 |
410 | case bitrate <= toBits(384): | 411 | |
411 | return 256 | 412 | case bitrate <= toBits(384): |
412 | default: | 413 | return 256 |
413 | return baseKbitrate | 414 | |
415 | default: | ||
416 | return baseKbitrate | ||
414 | } | 417 | } |
415 | } | 418 | } |
416 | } | 419 | } |
diff --git a/server/lib/plugins/yarn.ts b/server/lib/plugins/yarn.ts index 5fe1c5046..74c67653c 100644 --- a/server/lib/plugins/yarn.ts +++ b/server/lib/plugins/yarn.ts | |||
@@ -5,12 +5,12 @@ import { CONFIG } from '../../initializers/config' | |||
5 | import { outputJSON, pathExists } from 'fs-extra' | 5 | import { outputJSON, pathExists } from 'fs-extra' |
6 | import { join } from 'path' | 6 | import { join } from 'path' |
7 | 7 | ||
8 | async function installNpmPlugin (name: string, version?: string) { | 8 | async function installNpmPlugin (npmName: string, version?: string) { |
9 | // Security check | 9 | // Security check |
10 | checkNpmPluginNameOrThrow(name) | 10 | checkNpmPluginNameOrThrow(npmName) |
11 | if (version) checkPluginVersionOrThrow(version) | 11 | if (version) checkPluginVersionOrThrow(version) |
12 | 12 | ||
13 | let toInstall = name | 13 | let toInstall = npmName |
14 | if (version) toInstall += `@${version}` | 14 | if (version) toInstall += `@${version}` |
15 | 15 | ||
16 | await execYarn('add ' + toInstall) | 16 | await execYarn('add ' + toInstall) |
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts index 5d62fe2b3..5b788e328 100644 --- a/server/tests/api/check-params/users.ts +++ b/server/tests/api/check-params/users.ts | |||
@@ -387,13 +387,24 @@ describe('Test users API validators', function () { | |||
387 | } | 387 | } |
388 | }) | 388 | }) |
389 | 389 | ||
390 | it('Should fail with an invalid theme', async function () { | ||
391 | const fields = { theme: 'invalid' } | ||
392 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) | ||
393 | }) | ||
394 | |||
395 | it('Should fail with an unknown theme', async function () { | ||
396 | const fields = { theme: 'peertube-theme-unknown' } | ||
397 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields }) | ||
398 | }) | ||
399 | |||
390 | it('Should succeed to change password with the correct params', async function () { | 400 | it('Should succeed to change password with the correct params', async function () { |
391 | const fields = { | 401 | const fields = { |
392 | currentPassword: 'my super password', | 402 | currentPassword: 'my super password', |
393 | password: 'my super password', | 403 | password: 'my super password', |
394 | nsfwPolicy: 'blur', | 404 | nsfwPolicy: 'blur', |
395 | autoPlayVideo: false, | 405 | autoPlayVideo: false, |
396 | email: 'super_email@example.com' | 406 | email: 'super_email@example.com', |
407 | theme: 'default' | ||
397 | } | 408 | } |
398 | 409 | ||
399 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 }) | 410 | await makePutBodyRequest({ url: server.url, path: path + 'me', token: userAccessToken, fields, statusCodeExpected: 204 }) |
diff --git a/server/tests/api/server/index.ts b/server/tests/api/server/index.ts index 94c15e0d0..3daeeb49a 100644 --- a/server/tests/api/server/index.ts +++ b/server/tests/api/server/index.ts | |||
@@ -11,3 +11,4 @@ import './reverse-proxy' | |||
11 | import './stats' | 11 | import './stats' |
12 | import './tracker' | 12 | import './tracker' |
13 | import './no-client' | 13 | import './no-client' |
14 | import './plugins' | ||
diff --git a/server/tests/api/server/plugins.ts b/server/tests/api/server/plugins.ts new file mode 100644 index 000000000..9a623c553 --- /dev/null +++ b/server/tests/api/server/plugins.ts | |||
@@ -0,0 +1,130 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import * as chai from 'chai' | ||
5 | import { About } from '../../../../shared/models/server/about.model' | ||
6 | import { CustomConfig } from '../../../../shared/models/server/custom-config.model' | ||
7 | import { | ||
8 | cleanupTests, | ||
9 | deleteCustomConfig, | ||
10 | flushAndRunServer, | ||
11 | getAbout, | ||
12 | getConfig, | ||
13 | getCustomConfig, installPlugin, | ||
14 | killallServers, parallelTests, | ||
15 | registerUser, | ||
16 | reRunServer, ServerInfo, | ||
17 | setAccessTokensToServers, | ||
18 | updateCustomConfig, uploadVideo | ||
19 | } from '../../../../shared/extra-utils' | ||
20 | import { ServerConfig } from '../../../../shared/models' | ||
21 | import { PeerTubePlugin } from '../../../../shared/models/plugins/peertube-plugin.model' | ||
22 | |||
23 | const expect = chai.expect | ||
24 | |||
25 | describe('Test plugins', function () { | ||
26 | let server = null | ||
27 | |||
28 | before(async function () { | ||
29 | this.timeout(30000) | ||
30 | |||
31 | server = await flushAndRunServer(1) | ||
32 | await setAccessTokensToServers([ server ]) | ||
33 | |||
34 | { | ||
35 | await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-hello-world' }) | ||
36 | } | ||
37 | |||
38 | { | ||
39 | await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-plugin-background-color' }) | ||
40 | } | ||
41 | }) | ||
42 | |||
43 | it('Should list available plugins and themes', async function () { | ||
44 | // List without filter | ||
45 | // List with filter (plugin and theme) | ||
46 | }) | ||
47 | |||
48 | it('Should search available plugins', async function () { | ||
49 | // Search with filter (plugin and theme) | ||
50 | // Add pagination | ||
51 | // Add sort | ||
52 | // Add peertube engine | ||
53 | }) | ||
54 | |||
55 | it('Should have an empty global css', async function () { | ||
56 | // get /global.css | ||
57 | }) | ||
58 | |||
59 | it('Should install a plugin and a theme', async function () { | ||
60 | |||
61 | }) | ||
62 | |||
63 | it('Should have the correct global css', async function () { | ||
64 | // get /global.css | ||
65 | }) | ||
66 | |||
67 | it('Should have the plugin loaded in the configuration', async function () { | ||
68 | // Check registered themes/plugins | ||
69 | }) | ||
70 | |||
71 | it('Should update the default theme in the configuration', async function () { | ||
72 | // Update config | ||
73 | }) | ||
74 | |||
75 | it('Should list plugins and themes', async function () { | ||
76 | // List without filter | ||
77 | // List with filter (theme/plugin) | ||
78 | // List with pagination | ||
79 | // List with sort | ||
80 | }) | ||
81 | |||
82 | it('Should get a plugin and a theme', async function () { | ||
83 | // Get plugin | ||
84 | // Get theme | ||
85 | }) | ||
86 | |||
87 | it('Should get registered settings', async function () { | ||
88 | // Get plugin | ||
89 | }) | ||
90 | |||
91 | it('Should update the settings', async function () { | ||
92 | // Update /settings | ||
93 | |||
94 | // get /plugin | ||
95 | }) | ||
96 | |||
97 | it('Should update the plugin and the theme', async function () { | ||
98 | // update BDD -> 0.0.1 | ||
99 | // update package.json (theme + plugin) | ||
100 | // list to check versions | ||
101 | // update plugin + theme | ||
102 | // list to check they have been updated | ||
103 | // check package.json are upgraded too | ||
104 | }) | ||
105 | |||
106 | it('Should uninstall the plugin', async function () { | ||
107 | // uninstall | ||
108 | // list | ||
109 | }) | ||
110 | |||
111 | it('Should have an empty global css', async function () { | ||
112 | // get /global.css | ||
113 | }) | ||
114 | |||
115 | it('Should list uninstalled plugins', async function () { | ||
116 | // { uninstalled: true } | ||
117 | }) | ||
118 | |||
119 | it('Should uninstall the theme', async function () { | ||
120 | // Uninstall | ||
121 | }) | ||
122 | |||
123 | it('Should have updated the configuration', async function () { | ||
124 | // get /config (default theme + registered themes + registered plugins) | ||
125 | }) | ||
126 | |||
127 | after(async function () { | ||
128 | await cleanupTests([ server ]) | ||
129 | }) | ||
130 | }) | ||
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts index 6fc2a070f..3a3fabb4c 100644 --- a/server/tests/api/users/users.ts +++ b/server/tests/api/users/users.ts | |||
@@ -18,7 +18,7 @@ import { | |||
18 | getUsersList, | 18 | getUsersList, |
19 | getUsersListPaginationAndSort, | 19 | getUsersListPaginationAndSort, |
20 | getVideoChannel, | 20 | getVideoChannel, |
21 | getVideosList, | 21 | getVideosList, installPlugin, |
22 | login, | 22 | login, |
23 | makePutBodyRequest, | 23 | makePutBodyRequest, |
24 | rateVideo, | 24 | rateVideo, |
@@ -57,6 +57,8 @@ describe('Test users', function () { | |||
57 | server = await flushAndRunServer(1) | 57 | server = await flushAndRunServer(1) |
58 | 58 | ||
59 | await setAccessTokensToServers([ server ]) | 59 | await setAccessTokensToServers([ server ]) |
60 | |||
61 | await installPlugin({ url: server.url, accessToken: server.accessToken, npmName: 'peertube-theme-background-red' }) | ||
60 | }) | 62 | }) |
61 | 63 | ||
62 | describe('OAuth client', function () { | 64 | describe('OAuth client', function () { |
@@ -551,6 +553,21 @@ describe('Test users', function () { | |||
551 | expect(user.account.displayName).to.equal('new display name') | 553 | expect(user.account.displayName).to.equal('new display name') |
552 | expect(user.account.description).to.equal('my super description updated') | 554 | expect(user.account.description).to.equal('my super description updated') |
553 | }) | 555 | }) |
556 | |||
557 | it('Should be able to update my theme', async function () { | ||
558 | for (const theme of [ 'background-red', 'default', 'instance-default' ]) { | ||
559 | await updateMyUser({ | ||
560 | url: server.url, | ||
561 | accessToken: accessTokenUser, | ||
562 | theme | ||
563 | }) | ||
564 | |||
565 | const res = await getMyUserInformation(server.url, accessTokenUser) | ||
566 | const body: User = res.body | ||
567 | |||
568 | expect(body.theme).to.equal(theme) | ||
569 | } | ||
570 | }) | ||
554 | }) | 571 | }) |
555 | 572 | ||
556 | describe('Updating another user', function () { | 573 | describe('Updating another user', function () { |
diff --git a/server/tests/cli/index.ts b/server/tests/cli/index.ts index c6b7ec078..5af286fe2 100644 --- a/server/tests/cli/index.ts +++ b/server/tests/cli/index.ts | |||
@@ -3,5 +3,6 @@ import './create-import-video-file-job' | |||
3 | import './create-transcoding-job' | 3 | import './create-transcoding-job' |
4 | import './optimize-old-videos' | 4 | import './optimize-old-videos' |
5 | import './peertube' | 5 | import './peertube' |
6 | import './plugins' | ||
6 | import './reset-password' | 7 | import './reset-password' |
7 | import './update-host' | 8 | import './update-host' |
diff --git a/server/tests/cli/peertube.ts b/server/tests/cli/peertube.ts index d73e27564..b8c0b1f79 100644 --- a/server/tests/cli/peertube.ts +++ b/server/tests/cli/peertube.ts | |||
@@ -43,133 +43,171 @@ describe('Test CLI wrapper', function () { | |||
43 | } | 43 | } |
44 | }) | 44 | }) |
45 | 45 | ||
46 | it('Should display no selected instance', async function () { | 46 | describe('Authentication and instance selection', function () { |
47 | this.timeout(60000) | ||
48 | 47 | ||
49 | const env = getEnvCli(server) | 48 | it('Should display no selected instance', async function () { |
50 | const stdout = await execCLI(`${env} ${cmd} --help`) | 49 | this.timeout(60000) |
51 | 50 | ||
52 | expect(stdout).to.contain('no instance selected') | 51 | const env = getEnvCli(server) |
53 | }) | 52 | const stdout = await execCLI(`${env} ${cmd} --help`) |
54 | 53 | ||
55 | it('Should add a user', async function () { | 54 | expect(stdout).to.contain('no instance selected') |
56 | this.timeout(60000) | 55 | }) |
57 | 56 | ||
58 | const env = getEnvCli(server) | 57 | it('Should add a user', async function () { |
59 | await execCLI(`${env} ${cmd} auth add -u ${server.url} -U user_1 -p super_password`) | 58 | this.timeout(60000) |
60 | }) | ||
61 | 59 | ||
62 | it('Should default to this user', async function () { | 60 | const env = getEnvCli(server) |
63 | this.timeout(60000) | 61 | await execCLI(`${env} ${cmd} auth add -u ${server.url} -U user_1 -p super_password`) |
62 | }) | ||
64 | 63 | ||
65 | const env = getEnvCli(server) | 64 | it('Should default to this user', async function () { |
66 | const stdout = await execCLI(`${env} ${cmd} --help`) | 65 | this.timeout(60000) |
67 | 66 | ||
68 | expect(stdout).to.contain(`instance ${server.url} selected`) | 67 | const env = getEnvCli(server) |
69 | }) | 68 | const stdout = await execCLI(`${env} ${cmd} --help`) |
70 | 69 | ||
71 | it('Should remember the user', async function () { | 70 | expect(stdout).to.contain(`instance ${server.url} selected`) |
72 | this.timeout(60000) | 71 | }) |
73 | 72 | ||
74 | const env = getEnvCli(server) | 73 | it('Should remember the user', async function () { |
75 | const stdout = await execCLI(`${env} ${cmd} auth list`) | 74 | this.timeout(60000) |
76 | 75 | ||
77 | expect(stdout).to.contain(server.url) | 76 | const env = getEnvCli(server) |
77 | const stdout = await execCLI(`${env} ${cmd} auth list`) | ||
78 | |||
79 | expect(stdout).to.contain(server.url) | ||
80 | }) | ||
78 | }) | 81 | }) |
79 | 82 | ||
80 | it('Should upload a video', async function () { | 83 | describe('Video upload/import', function () { |
81 | this.timeout(60000) | ||
82 | 84 | ||
83 | const env = getEnvCli(server) | 85 | it('Should upload a video', async function () { |
86 | this.timeout(60000) | ||
84 | 87 | ||
85 | const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4') | 88 | const env = getEnvCli(server) |
86 | 89 | ||
87 | const params = `-f ${fixture} --video-name 'test upload' --channel-name user_channel --support 'support_text'` | 90 | const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4') |
88 | 91 | ||
89 | await execCLI(`${env} ${cmd} upload ${params}`) | 92 | const params = `-f ${fixture} --video-name 'test upload' --channel-name user_channel --support 'support_text'` |
90 | }) | ||
91 | 93 | ||
92 | it('Should have the video uploaded', async function () { | 94 | await execCLI(`${env} ${cmd} upload ${params}`) |
93 | const res = await getVideosList(server.url) | 95 | }) |
94 | 96 | ||
95 | expect(res.body.total).to.equal(1) | 97 | it('Should have the video uploaded', async function () { |
98 | const res = await getVideosList(server.url) | ||
96 | 99 | ||
97 | const videos: Video[] = res.body.data | 100 | expect(res.body.total).to.equal(1) |
98 | 101 | ||
99 | const video: VideoDetails = (await getVideo(server.url, videos[0].uuid)).body | 102 | const videos: Video[] = res.body.data |
100 | 103 | ||
101 | expect(video.name).to.equal('test upload') | 104 | const video: VideoDetails = (await getVideo(server.url, videos[ 0 ].uuid)).body |
102 | expect(video.support).to.equal('support_text') | ||
103 | expect(video.channel.name).to.equal('user_channel') | ||
104 | }) | ||
105 | 105 | ||
106 | it('Should import a video', async function () { | 106 | expect(video.name).to.equal('test upload') |
107 | this.timeout(60000) | 107 | expect(video.support).to.equal('support_text') |
108 | expect(video.channel.name).to.equal('user_channel') | ||
109 | }) | ||
108 | 110 | ||
109 | const env = getEnvCli(server) | 111 | it('Should import a video', async function () { |
112 | this.timeout(60000) | ||
110 | 113 | ||
111 | const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel` | 114 | const env = getEnvCli(server) |
112 | 115 | ||
113 | await execCLI(`${env} ${cmd} import ${params}`) | 116 | const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel` |
114 | }) | ||
115 | 117 | ||
116 | it('Should have imported the video', async function () { | 118 | await execCLI(`${env} ${cmd} import ${params}`) |
117 | this.timeout(60000) | 119 | }) |
118 | 120 | ||
119 | await waitJobs([ server ]) | 121 | it('Should have imported the video', async function () { |
122 | this.timeout(60000) | ||
120 | 123 | ||
121 | const res = await getVideosList(server.url) | 124 | await waitJobs([ server ]) |
122 | 125 | ||
123 | expect(res.body.total).to.equal(2) | 126 | const res = await getVideosList(server.url) |
124 | 127 | ||
125 | const videos: Video[] = res.body.data | 128 | expect(res.body.total).to.equal(2) |
126 | const video = videos.find(v => v.name === 'small video - youtube') | ||
127 | expect(video).to.not.be.undefined | ||
128 | 129 | ||
129 | const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body | 130 | const videos: Video[] = res.body.data |
130 | expect(videoDetails.channel.name).to.equal('user_channel') | 131 | const video = videos.find(v => v.name === 'small video - youtube') |
131 | expect(videoDetails.support).to.equal('super support text') | 132 | expect(video).to.not.be.undefined |
132 | expect(videoDetails.nsfw).to.be.false | ||
133 | 133 | ||
134 | // So we can reimport it | 134 | const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body |
135 | await removeVideo(server.url, userAccessToken, video.id) | 135 | expect(videoDetails.channel.name).to.equal('user_channel') |
136 | }) | 136 | expect(videoDetails.support).to.equal('super support text') |
137 | expect(videoDetails.nsfw).to.be.false | ||
137 | 138 | ||
138 | it('Should import and override some imported attributes', async function () { | 139 | // So we can reimport it |
139 | this.timeout(60000) | 140 | await removeVideo(server.url, userAccessToken, video.id) |
141 | }) | ||
140 | 142 | ||
141 | const env = getEnvCli(server) | 143 | it('Should import and override some imported attributes', async function () { |
144 | this.timeout(60000) | ||
142 | 145 | ||
143 | const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel --video-name toto --nsfw --support support` | 146 | const env = getEnvCli(server) |
144 | 147 | ||
145 | await execCLI(`${env} ${cmd} import ${params}`) | 148 | const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel --video-name toto --nsfw --support support` |
146 | 149 | ||
147 | await waitJobs([ server ]) | 150 | await execCLI(`${env} ${cmd} import ${params}`) |
148 | 151 | ||
149 | { | 152 | await waitJobs([ server ]) |
150 | const res = await getVideosList(server.url) | ||
151 | expect(res.body.total).to.equal(2) | ||
152 | 153 | ||
153 | const videos: Video[] = res.body.data | 154 | { |
154 | const video = videos.find(v => v.name === 'toto') | 155 | const res = await getVideosList(server.url) |
155 | expect(video).to.not.be.undefined | 156 | expect(res.body.total).to.equal(2) |
156 | 157 | ||
157 | const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body | 158 | const videos: Video[] = res.body.data |
158 | expect(videoDetails.channel.name).to.equal('user_channel') | 159 | const video = videos.find(v => v.name === 'toto') |
159 | expect(videoDetails.support).to.equal('support') | 160 | expect(video).to.not.be.undefined |
160 | expect(videoDetails.nsfw).to.be.true | 161 | |
161 | expect(videoDetails.commentsEnabled).to.be.true | 162 | const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body |
162 | } | 163 | expect(videoDetails.channel.name).to.equal('user_channel') |
164 | expect(videoDetails.support).to.equal('support') | ||
165 | expect(videoDetails.nsfw).to.be.true | ||
166 | expect(videoDetails.commentsEnabled).to.be.true | ||
167 | } | ||
168 | }) | ||
163 | }) | 169 | }) |
164 | 170 | ||
165 | it('Should remove the auth user', async function () { | 171 | describe('Admin auth', function () { |
166 | const env = getEnvCli(server) | 172 | |
173 | it('Should remove the auth user', async function () { | ||
174 | const env = getEnvCli(server) | ||
175 | |||
176 | await execCLI(`${env} ${cmd} auth del ${server.url}`) | ||
177 | |||
178 | const stdout = await execCLI(`${env} ${cmd} --help`) | ||
179 | |||
180 | expect(stdout).to.contain('no instance selected') | ||
181 | }) | ||
182 | |||
183 | it('Should add the admin user', async function () { | ||
184 | const env = getEnvCli(server) | ||
185 | await execCLI(`${env} ${cmd} auth add -u ${server.url} -U root -p test${server.internalServerNumber}`) | ||
186 | }) | ||
187 | }) | ||
188 | |||
189 | describe('Manage plugins', function () { | ||
190 | |||
191 | it('Should install a plugin', async function () { | ||
192 | this.timeout(60000) | ||
193 | |||
194 | const env = getEnvCli(server) | ||
195 | await execCLI(`${env} ${cmd} plugins install --npm-name peertube-plugin-hello-world`) | ||
196 | }) | ||
197 | |||
198 | it('Should list installed plugins', async function () { | ||
199 | const env = getEnvCli(server) | ||
200 | const res = await execCLI(`${env} ${cmd} plugins list`) | ||
167 | 201 | ||
168 | await execCLI(`${env} ${cmd} auth del ${server.url}`) | 202 | expect(res).to.contain('peertube-plugin-hello-world') |
203 | }) | ||
169 | 204 | ||
170 | const stdout = await execCLI(`${env} ${cmd} --help`) | 205 | it('Should uninstall the plugin', async function () { |
206 | const env = getEnvCli(server) | ||
207 | const res = await execCLI(`${env} ${cmd} plugins uninstall --npm-name peertube-plugin-hello-world`) | ||
171 | 208 | ||
172 | expect(stdout).to.contain('no instance selected') | 209 | expect(res).to.not.contain('peertube-plugin-hello-world') |
210 | }) | ||
173 | }) | 211 | }) |
174 | 212 | ||
175 | after(async function () { | 213 | after(async function () { |
diff --git a/server/tests/cli/plugins.ts b/server/tests/cli/plugins.ts new file mode 100644 index 000000000..d7bf8a690 --- /dev/null +++ b/server/tests/cli/plugins.ts | |||
@@ -0,0 +1,87 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import { | ||
5 | cleanupTests, | ||
6 | execCLI, | ||
7 | flushAndRunServer, | ||
8 | getConfig, | ||
9 | getEnvCli, killallServers, | ||
10 | reRunServer, | ||
11 | root, | ||
12 | ServerInfo, | ||
13 | setAccessTokensToServers | ||
14 | } from '../../../shared/extra-utils' | ||
15 | import { join } from 'path' | ||
16 | import { ServerConfig } from '../../../shared/models/server' | ||
17 | import { expect } from 'chai' | ||
18 | |||
19 | describe('Test plugin scripts', function () { | ||
20 | let server: ServerInfo | ||
21 | |||
22 | before(async function () { | ||
23 | this.timeout(30000) | ||
24 | |||
25 | server = await flushAndRunServer(1) | ||
26 | await setAccessTokensToServers([ server ]) | ||
27 | }) | ||
28 | |||
29 | it('Should install a plugin from stateless CLI', async function () { | ||
30 | this.timeout(60000) | ||
31 | |||
32 | const packagePath = join(root(), 'server', 'tests', 'fixtures', 'peertube-plugin-test') | ||
33 | |||
34 | const env = getEnvCli(server) | ||
35 | await execCLI(`${env} npm run plugin:install -- --plugin-path ${packagePath}`) | ||
36 | }) | ||
37 | |||
38 | it('Should install a theme from stateless CLI', async function () { | ||
39 | this.timeout(60000) | ||
40 | |||
41 | const env = getEnvCli(server) | ||
42 | await execCLI(`${env} npm run plugin:install -- --npm-name peertube-theme-background-red`) | ||
43 | }) | ||
44 | |||
45 | it('Should have the theme and the plugin registered when we restart peertube', async function () { | ||
46 | this.timeout(30000) | ||
47 | |||
48 | killallServers([ server ]) | ||
49 | await reRunServer(server) | ||
50 | |||
51 | const res = await getConfig(server.url) | ||
52 | const config: ServerConfig = res.body | ||
53 | |||
54 | const plugin = config.plugin.registered | ||
55 | .find(p => p.name === 'test') | ||
56 | expect(plugin).to.not.be.undefined | ||
57 | |||
58 | const theme = config.theme.registered | ||
59 | .find(t => t.name === 'background-red') | ||
60 | expect(theme).to.not.be.undefined | ||
61 | }) | ||
62 | |||
63 | it('Should uninstall a plugin from stateless CLI', async function () { | ||
64 | this.timeout(60000) | ||
65 | |||
66 | const env = getEnvCli(server) | ||
67 | await execCLI(`${env} npm run plugin:uninstall -- --npm-name peertube-plugin-test`) | ||
68 | }) | ||
69 | |||
70 | it('Should have removed the plugin on another peertube restart', async function () { | ||
71 | this.timeout(30000) | ||
72 | |||
73 | killallServers([ server ]) | ||
74 | await reRunServer(server) | ||
75 | |||
76 | const res = await getConfig(server.url) | ||
77 | const config: ServerConfig = res.body | ||
78 | |||
79 | const plugin = config.plugin.registered | ||
80 | .find(p => p.name === 'test') | ||
81 | expect(plugin).to.be.undefined | ||
82 | }) | ||
83 | |||
84 | after(async function () { | ||
85 | await cleanupTests([ server ]) | ||
86 | }) | ||
87 | }) | ||
diff --git a/server/tests/fixtures/peertube-plugin-test/main.js b/server/tests/fixtures/peertube-plugin-test/main.js new file mode 100644 index 000000000..fae0ef948 --- /dev/null +++ b/server/tests/fixtures/peertube-plugin-test/main.js | |||
@@ -0,0 +1,39 @@ | |||
1 | async function register ({ registerHook, registerSetting, settingsManager, storageManager }) { | ||
2 | const defaultAdmin = 'PeerTube admin' | ||
3 | |||
4 | registerHook({ | ||
5 | target: 'action:application.listening', | ||
6 | handler: () => displayHelloWorld(settingsManager, defaultAdmin) | ||
7 | }) | ||
8 | |||
9 | registerSetting({ | ||
10 | name: 'admin-name', | ||
11 | label: 'Admin name', | ||
12 | type: 'input', | ||
13 | default: defaultAdmin | ||
14 | }) | ||
15 | |||
16 | const value = await storageManager.getData('toto') | ||
17 | console.log(value) | ||
18 | console.log(value.coucou) | ||
19 | |||
20 | await storageManager.storeData('toto', { coucou: 'hello' + new Date() }) | ||
21 | } | ||
22 | |||
23 | async function unregister () { | ||
24 | return | ||
25 | } | ||
26 | |||
27 | module.exports = { | ||
28 | register, | ||
29 | unregister | ||
30 | } | ||
31 | |||
32 | // ############################################################################ | ||
33 | |||
34 | async function displayHelloWorld (settingsManager, defaultAdmin) { | ||
35 | let value = await settingsManager.getSetting('admin-name') | ||
36 | if (!value) value = defaultAdmin | ||
37 | |||
38 | console.log('hello world ' + value) | ||
39 | } | ||
diff --git a/server/tests/fixtures/peertube-plugin-test/package.json b/server/tests/fixtures/peertube-plugin-test/package.json new file mode 100644 index 000000000..9d6fe5c90 --- /dev/null +++ b/server/tests/fixtures/peertube-plugin-test/package.json | |||
@@ -0,0 +1,19 @@ | |||
1 | { | ||
2 | "name": "peertube-plugin-test", | ||
3 | "version": "0.0.1", | ||
4 | "description": "Plugin test", | ||
5 | "engine": { | ||
6 | "peertube": ">=1.3.0" | ||
7 | }, | ||
8 | "keywords": [ | ||
9 | "peertube", | ||
10 | "plugin" | ||
11 | ], | ||
12 | "homepage": "https://github.com/Chocobozzz/PeerTube", | ||
13 | "author": "Chocobozzz", | ||
14 | "bugs": "https://github.com/Chocobozzz/PeerTube/issues", | ||
15 | "library": "./main.js", | ||
16 | "staticDirs": {}, | ||
17 | "css": [], | ||
18 | "clientScripts": [] | ||
19 | } | ||
diff --git a/server/tests/index.ts b/server/tests/index.ts index ed16d65dd..8bddcfc7c 100644 --- a/server/tests/index.ts +++ b/server/tests/index.ts | |||
@@ -3,3 +3,4 @@ import './client' | |||
3 | import './feeds/' | 3 | import './feeds/' |
4 | import './cli/' | 4 | import './cli/' |
5 | import './api/' | 5 | import './api/' |
6 | import './plugins/' | ||
diff --git a/server/tests/plugins/action-hooks.ts b/server/tests/plugins/action-hooks.ts new file mode 100644 index 000000000..8abab98c2 --- /dev/null +++ b/server/tests/plugins/action-hooks.ts | |||
@@ -0,0 +1,27 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers' | ||
6 | import { setAccessTokensToServers } from '../../../shared/extra-utils' | ||
7 | |||
8 | const expect = chai.expect | ||
9 | |||
10 | describe('Test plugin filter hooks', function () { | ||
11 | let server: ServerInfo | ||
12 | |||
13 | before(async function () { | ||
14 | this.timeout(30000) | ||
15 | server = await flushAndRunServer(1) | ||
16 | |||
17 | await setAccessTokensToServers([ server ]) | ||
18 | }) | ||
19 | |||
20 | it('Should execute ', async function () { | ||
21 | |||
22 | }) | ||
23 | |||
24 | after(async function () { | ||
25 | await cleanupTests([ server ]) | ||
26 | }) | ||
27 | }) | ||
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts new file mode 100644 index 000000000..8abab98c2 --- /dev/null +++ b/server/tests/plugins/filter-hooks.ts | |||
@@ -0,0 +1,27 @@ | |||
1 | /* tslint:disable:no-unused-expression */ | ||
2 | |||
3 | import * as chai from 'chai' | ||
4 | import 'mocha' | ||
5 | import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers' | ||
6 | import { setAccessTokensToServers } from '../../../shared/extra-utils' | ||
7 | |||
8 | const expect = chai.expect | ||
9 | |||
10 | describe('Test plugin filter hooks', function () { | ||
11 | let server: ServerInfo | ||
12 | |||
13 | before(async function () { | ||
14 | this.timeout(30000) | ||
15 | server = await flushAndRunServer(1) | ||
16 | |||
17 | await setAccessTokensToServers([ server ]) | ||
18 | }) | ||
19 | |||
20 | it('Should execute ', async function () { | ||
21 | |||
22 | }) | ||
23 | |||
24 | after(async function () { | ||
25 | await cleanupTests([ server ]) | ||
26 | }) | ||
27 | }) | ||
diff --git a/server/tests/plugins/index.ts b/server/tests/plugins/index.ts new file mode 100644 index 000000000..b640ecc9e --- /dev/null +++ b/server/tests/plugins/index.ts | |||
@@ -0,0 +1,2 @@ | |||
1 | export * from './action-hooks' | ||
2 | export * from './filter-hooks' | ||
diff --git a/server/tools/peertube.ts b/server/tools/peertube.ts index e79a7e041..ddfe5b771 100644 --- a/server/tools/peertube.ts +++ b/server/tools/peertube.ts | |||
@@ -18,7 +18,7 @@ program | |||
18 | .command('get-access-token', 'get a peertube access token', { noHelp: true }).alias('token') | 18 | .command('get-access-token', 'get a peertube access token', { noHelp: true }).alias('token') |
19 | .command('watch', 'watch a video in the terminal ✩°。⋆').alias('w') | 19 | .command('watch', 'watch a video in the terminal ✩°。⋆').alias('w') |
20 | .command('repl', 'initiate a REPL to access internals') | 20 | .command('repl', 'initiate a REPL to access internals') |
21 | .command('plugins [action]', 'manage plugins on a local instance').alias('p') | 21 | .command('plugins [action]', 'manage instance plugins/themes').alias('p') |
22 | 22 | ||
23 | /* Not Yet Implemented */ | 23 | /* Not Yet Implemented */ |
24 | program | 24 | program |
diff --git a/shared/extra-utils/users/users.ts b/shared/extra-utils/users/users.ts index 5fa8cde0c..30ed1bf4a 100644 --- a/shared/extra-utils/users/users.ts +++ b/shared/extra-utils/users/users.ts | |||
@@ -6,6 +6,7 @@ import { UserRegister } from '../../models/users/user-register.model' | |||
6 | import { UserRole } from '../../models/users/user-role' | 6 | import { UserRole } from '../../models/users/user-role' |
7 | import { ServerInfo } from '../server/servers' | 7 | import { ServerInfo } from '../server/servers' |
8 | import { userLogin } from './login' | 8 | import { userLogin } from './login' |
9 | import { UserUpdateMe } from '../../models/users' | ||
9 | 10 | ||
10 | type CreateUserArgs = { url: string, | 11 | type CreateUserArgs = { url: string, |
11 | accessToken: string, | 12 | accessToken: string, |
@@ -224,19 +225,21 @@ function updateMyUser (options: { | |||
224 | displayName?: string | 225 | displayName?: string |
225 | description?: string | 226 | description?: string |
226 | videosHistoryEnabled?: boolean | 227 | videosHistoryEnabled?: boolean |
228 | theme?: string | ||
227 | }) { | 229 | }) { |
228 | const path = '/api/v1/users/me' | 230 | const path = '/api/v1/users/me' |
229 | 231 | ||
230 | const toSend = {} | 232 | const toSend: UserUpdateMe = {} |
231 | if (options.currentPassword !== undefined && options.currentPassword !== null) toSend['currentPassword'] = options.currentPassword | 233 | if (options.currentPassword !== undefined && options.currentPassword !== null) toSend.currentPassword = options.currentPassword |
232 | if (options.newPassword !== undefined && options.newPassword !== null) toSend['password'] = options.newPassword | 234 | if (options.newPassword !== undefined && options.newPassword !== null) toSend.password = options.newPassword |
233 | if (options.nsfwPolicy !== undefined && options.nsfwPolicy !== null) toSend['nsfwPolicy'] = options.nsfwPolicy | 235 | if (options.nsfwPolicy !== undefined && options.nsfwPolicy !== null) toSend.nsfwPolicy = options.nsfwPolicy |
234 | if (options.autoPlayVideo !== undefined && options.autoPlayVideo !== null) toSend['autoPlayVideo'] = options.autoPlayVideo | 236 | if (options.autoPlayVideo !== undefined && options.autoPlayVideo !== null) toSend.autoPlayVideo = options.autoPlayVideo |
235 | if (options.email !== undefined && options.email !== null) toSend['email'] = options.email | 237 | if (options.email !== undefined && options.email !== null) toSend.email = options.email |
236 | if (options.description !== undefined && options.description !== null) toSend['description'] = options.description | 238 | if (options.description !== undefined && options.description !== null) toSend.description = options.description |
237 | if (options.displayName !== undefined && options.displayName !== null) toSend['displayName'] = options.displayName | 239 | if (options.displayName !== undefined && options.displayName !== null) toSend.displayName = options.displayName |
240 | if (options.theme !== undefined && options.theme !== null) toSend.theme = options.theme | ||
238 | if (options.videosHistoryEnabled !== undefined && options.videosHistoryEnabled !== null) { | 241 | if (options.videosHistoryEnabled !== undefined && options.videosHistoryEnabled !== null) { |
239 | toSend['videosHistoryEnabled'] = options.videosHistoryEnabled | 242 | toSend.videosHistoryEnabled = options.videosHistoryEnabled |
240 | } | 243 | } |
241 | 244 | ||
242 | return makePutBodyRequest({ | 245 | return makePutBodyRequest({ |
diff --git a/shared/models/videos/video-resolution.enum.ts b/shared/models/videos/video-resolution.enum.ts index 51efa2e8b..fa26fc3cc 100644 --- a/shared/models/videos/video-resolution.enum.ts +++ b/shared/models/videos/video-resolution.enum.ts | |||
@@ -18,30 +18,35 @@ export enum VideoResolution { | |||
18 | */ | 18 | */ |
19 | function getBaseBitrate (resolution: VideoResolution) { | 19 | function getBaseBitrate (resolution: VideoResolution) { |
20 | switch (resolution) { | 20 | switch (resolution) { |
21 | case VideoResolution.H_240P: | 21 | case VideoResolution.H_240P: |
22 | // quality according to Google Live Encoder: 300 - 700 Kbps | 22 | // quality according to Google Live Encoder: 300 - 700 Kbps |
23 | // Quality according to YouTube Video Info: 186 Kbps | 23 | // Quality according to YouTube Video Info: 186 Kbps |
24 | return 250 * 1000 | 24 | return 250 * 1000 |
25 | case VideoResolution.H_360P: | 25 | |
26 | // quality according to Google Live Encoder: 400 - 1,000 Kbps | 26 | case VideoResolution.H_360P: |
27 | // Quality according to YouTube Video Info: 480 Kbps | 27 | // quality according to Google Live Encoder: 400 - 1,000 Kbps |
28 | return 500 * 1000 | 28 | // Quality according to YouTube Video Info: 480 Kbps |
29 | case VideoResolution.H_480P: | 29 | return 500 * 1000 |
30 | // quality according to Google Live Encoder: 500 - 2,000 Kbps | 30 | |
31 | // Quality according to YouTube Video Info: 879 Kbps | 31 | case VideoResolution.H_480P: |
32 | return 900 * 1000 | 32 | // quality according to Google Live Encoder: 500 - 2,000 Kbps |
33 | case VideoResolution.H_720P: | 33 | // Quality according to YouTube Video Info: 879 Kbps |
34 | // quality according to Google Live Encoder: 1,500 - 4,000 Kbps | 34 | return 900 * 1000 |
35 | // Quality according to YouTube Video Info: 1752 Kbps | 35 | |
36 | return 1750 * 1000 | 36 | case VideoResolution.H_720P: |
37 | case VideoResolution.H_1080P: | 37 | // quality according to Google Live Encoder: 1,500 - 4,000 Kbps |
38 | // quality according to Google Live Encoder: 3000 - 6000 Kbps | 38 | // Quality according to YouTube Video Info: 1752 Kbps |
39 | // Quality according to YouTube Video Info: 3277 Kbps | 39 | return 1750 * 1000 |
40 | return 3300 * 1000 | 40 | |
41 | case VideoResolution.H_4K: // fallthrough | 41 | case VideoResolution.H_1080P: |
42 | default: | 42 | // quality according to Google Live Encoder: 3000 - 6000 Kbps |
43 | // quality according to Google Live Encoder: 13000 - 34000 Kbps | 43 | // Quality according to YouTube Video Info: 3277 Kbps |
44 | return 15000 * 1000 | 44 | return 3300 * 1000 |
45 | |||
46 | case VideoResolution.H_4K: // fallthrough | ||
47 | default: | ||
48 | // quality according to Google Live Encoder: 13000 - 34000 Kbps | ||
49 | return 15000 * 1000 | ||
45 | } | 50 | } |
46 | } | 51 | } |
47 | 52 | ||
diff --git a/support/doc/tools.md b/support/doc/tools.md index ba6e2b12d..f0d3b15b2 100644 --- a/support/doc/tools.md +++ b/support/doc/tools.md | |||
@@ -75,6 +75,7 @@ You can access it as `peertube` via an alias in your `.bashrc` like `alias peert | |||
75 | import-videos|import import a video from a streaming platform | 75 | import-videos|import import a video from a streaming platform |
76 | watch|w watch a video in the terminal ✩°。⋆ | 76 | watch|w watch a video in the terminal ✩°。⋆ |
77 | repl initiate a REPL to access internals | 77 | repl initiate a REPL to access internals |
78 | plugins|p [action] manag instance plugins | ||
78 | help [cmd] display help for [cmd] | 79 | help [cmd] display help for [cmd] |
79 | ``` | 80 | ``` |
80 | 81 | ||
@@ -102,6 +103,15 @@ And now that your video is online, you can watch it from the confort of your ter | |||
102 | $ peertube watch https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10 | 103 | $ peertube watch https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10 |
103 | ``` | 104 | ``` |
104 | 105 | ||
106 | To list, install, uninstall dynamically plugins/themes of an instance: | ||
107 | |||
108 | ```bash | ||
109 | $ peertube plugins list | ||
110 | $ peertube plugins install --path /local/plugin/path | ||
111 | $ peertube plugins install --npm-name peertube-plugin-myplugin | ||
112 | $ peertube plugins uninstall --npm-name peertube-plugin-myplugin | ||
113 | ``` | ||
114 | |||
105 | #### peertube-import-videos.js | 115 | #### peertube-import-videos.js |
106 | 116 | ||
107 | 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. | 117 | 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: | |||
233 | $ sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run reset-password -- -u target_username | 243 | $ sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run reset-password -- -u target_username |
234 | ``` | 244 | ``` |
235 | 245 | ||
246 | |||
247 | ### plugin install/uninstall | ||
248 | |||
249 | The difference with `peertube plugins` CLI is that these scripts can be used even if PeerTube is not running. | ||
250 | 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). | ||
251 | |||
252 | To install a plugin or a theme from the disk: | ||
253 | |||
254 | ``` | ||
255 | $ sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run npm run plugin:install -- --plugin-path /local/plugin/path | ||
256 | ``` | ||
257 | |||
258 | From NPM: | ||
259 | |||
260 | ``` | ||
261 | $ sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run npm run plugin:install -- --npm-name peertube-plugin-myplugin | ||
262 | ``` | ||
263 | |||
264 | To uninstall a plugin or a theme: | ||
265 | |||
266 | ``` | ||
267 | $ sudo -u peertube NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run npm run plugin:uninstall -- --npm-name peertube-plugin-myplugin | ||
268 | ``` | ||
269 | |||
236 | ### REPL ([Read Eval Print Loop](https://nodejs.org/docs/latest-v8.x/api/repl.html)) | 270 | ### REPL ([Read Eval Print Loop](https://nodejs.org/docs/latest-v8.x/api/repl.html)) |
237 | 271 | ||
238 | If you want to interact with the application libraries and objects even when PeerTube is not running, there is a REPL for that. | 272 | If you want to interact with the application libraries and objects even when PeerTube is not running, there is a REPL for that. |