aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-06-13 13:53:28 +0200
committerChocobozzz <me@florianbigard.com>2019-06-13 13:53:28 +0200
commit1205823fece15f249e0dbad42e096cf9b81c3ba5 (patch)
treec1291b443aa530cc37cd9389620186ec2043e441
parent1a12f66d631d28a5a58ebbcd274426f2e6e5d203 (diff)
downloadPeerTube-1205823fece15f249e0dbad42e096cf9b81c3ba5.tar.gz
PeerTube-1205823fece15f249e0dbad42e096cf9b81c3ba5.tar.zst
PeerTube-1205823fece15f249e0dbad42e096cf9b81c3ba5.zip
Add ability to override CLI import attributes
-rw-r--r--server/tests/cli/peertube.ts64
-rw-r--r--server/tools/cli.ts69
-rw-r--r--server/tools/peertube-import-videos.ts38
-rw-r--r--server/tools/peertube-upload.ts52
4 files changed, 151 insertions, 72 deletions
diff --git a/server/tests/cli/peertube.ts b/server/tests/cli/peertube.ts
index 6e7bf0843..0a8a98334 100644
--- a/server/tests/cli/peertube.ts
+++ b/server/tests/cli/peertube.ts
@@ -10,18 +10,20 @@ import {
10 execCLI, 10 execCLI,
11 flushAndRunServer, 11 flushAndRunServer,
12 getEnvCli, 12 getEnvCli,
13 getMyUserInformation, 13 getVideo,
14 getVideosList, 14 getVideosList,
15 getVideosListWithToken, removeVideo,
15 ServerInfo, 16 ServerInfo,
16 setAccessTokensToServers, 17 setAccessTokensToServers,
17 userLogin, waitJobs 18 userLogin,
19 waitJobs
18} from '../../../shared/extra-utils' 20} from '../../../shared/extra-utils'
19import { User, Video } from '../../../shared' 21import { Video, VideoDetails } from '../../../shared'
20import { getYoutubeVideoUrl } from '../../../shared/extra-utils/videos/video-imports' 22import { getYoutubeVideoUrl } from '../../../shared/extra-utils/videos/video-imports'
21 23
22describe('Test CLI wrapper', function () { 24describe('Test CLI wrapper', function () {
23 let server: ServerInfo 25 let server: ServerInfo
24 let channelId: number 26 let userAccessToken: string
25 27
26 const cmd = 'node ./dist/server/tools/peertube.js' 28 const cmd = 'node ./dist/server/tools/peertube.js'
27 29
@@ -33,11 +35,11 @@ describe('Test CLI wrapper', function () {
33 35
34 await createUser({ url: server.url, accessToken: server.accessToken, username: 'user_1', password: 'super_password' }) 36 await createUser({ url: server.url, accessToken: server.accessToken, username: 'user_1', password: 'super_password' })
35 37
36 const userAccessToken = await userLogin(server, { username: 'user_1', password: 'super_password' }) 38 userAccessToken = await userLogin(server, { username: 'user_1', password: 'super_password' })
37 39
38 { 40 {
39 const res = await addVideoChannel(server.url, userAccessToken, { name: 'user_channel', displayName: 'User channel' }) 41 const args = { name: 'user_channel', displayName: 'User channel', support: 'super support text' }
40 channelId = res.body.videoChannel.id 42 await addVideoChannel(server.url, userAccessToken, args)
41 } 43 }
42 }) 44 })
43 45
@@ -82,7 +84,7 @@ describe('Test CLI wrapper', function () {
82 84
83 const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4') 85 const fixture = buildAbsoluteFixturePath('60fps_720p_small.mp4')
84 86
85 const params = `-f ${fixture} --video-name 'test upload' --channel-id ${channelId}` 87 const params = `-f ${fixture} --video-name 'test upload' --channel-name user_channel --support 'support_text'`
86 88
87 await execCLI(`${env} ${cmd} upload ${params}`) 89 await execCLI(`${env} ${cmd} upload ${params}`)
88 }) 90 })
@@ -93,8 +95,12 @@ describe('Test CLI wrapper', function () {
93 expect(res.body.total).to.equal(1) 95 expect(res.body.total).to.equal(1)
94 96
95 const videos: Video[] = res.body.data 97 const videos: Video[] = res.body.data
96 expect(videos[0].name).to.equal('test upload') 98
97 expect(videos[0].channel.name).to.equal('user_channel') 99 const video: VideoDetails = (await getVideo(server.url, videos[0].uuid)).body
100
101 expect(video.name).to.equal('test upload')
102 expect(video.support).to.equal('support_text')
103 expect(video.channel.name).to.equal('user_channel')
98 }) 104 })
99 105
100 it('Should import a video', async function () { 106 it('Should import a video', async function () {
@@ -102,7 +108,7 @@ describe('Test CLI wrapper', function () {
102 108
103 const env = getEnvCli(server) 109 const env = getEnvCli(server)
104 110
105 const params = `--target-url ${getYoutubeVideoUrl()} --channel-id ${channelId}` 111 const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel`
106 112
107 await execCLI(`${env} ${cmd} import ${params}`) 113 await execCLI(`${env} ${cmd} import ${params}`)
108 }) 114 })
@@ -118,9 +124,41 @@ describe('Test CLI wrapper', function () {
118 124
119 const videos: Video[] = res.body.data 125 const videos: Video[] = res.body.data
120 const video = videos.find(v => v.name === 'small video - youtube') 126 const video = videos.find(v => v.name === 'small video - youtube')
121
122 expect(video).to.not.be.undefined 127 expect(video).to.not.be.undefined
123 expect(video.channel.name).to.equal('user_channel') 128
129 const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body
130 expect(videoDetails.channel.name).to.equal('user_channel')
131 expect(videoDetails.support).to.equal('super support text')
132 expect(videoDetails.nsfw).to.be.false
133
134 // So we can reimport it
135 await removeVideo(server.url, userAccessToken, video.id)
136 })
137
138 it('Should import and override some imported attributes', async function () {
139 this.timeout(60000)
140
141 const env = getEnvCli(server)
142
143 const params = `--target-url ${getYoutubeVideoUrl()} --channel-name user_channel --video-name toto --nsfw --support support`
144
145 await execCLI(`${env} ${cmd} import ${params}`)
146
147 await waitJobs([ server ])
148
149 {
150 const res = await getVideosList(server.url)
151 expect(res.body.total).to.equal(2)
152
153 const videos: Video[] = res.body.data
154 const video = videos.find(v => v.name === 'toto')
155 expect(video).to.not.be.undefined
156
157 const videoDetails: VideoDetails = (await getVideo(server.url, video.id)).body
158 expect(videoDetails.channel.name).to.equal('user_channel')
159 expect(videoDetails.support).to.equal('support')
160 expect(videoDetails.nsfw).to.be.true
161 }
124 }) 162 })
125 163
126 it('Should remove the auth user', async function () { 164 it('Should remove the auth user', async function () {
diff --git a/server/tools/cli.ts b/server/tools/cli.ts
index 6be558d7b..4aa3d9ce8 100644
--- a/server/tools/cli.ts
+++ b/server/tools/cli.ts
@@ -1,7 +1,9 @@
1import { Netrc } from 'netrc-parser' 1import { Netrc } from 'netrc-parser'
2import { isTestInstance, getAppNumber } from '../helpers/core-utils' 2import { getAppNumber, isTestInstance } from '../helpers/core-utils'
3import { join } from 'path' 3import { join } from 'path'
4import { root } from '../../shared/extra-utils' 4import { getVideoChannel, root } from '../../shared/extra-utils'
5import { Command } from 'commander'
6import { VideoChannel, VideoPrivacy } from '../../shared/models/videos'
5 7
6let configName = 'PeerTube/CLI' 8let configName = 'PeerTube/CLI'
7if (isTestInstance()) configName += `-${getAppNumber()}` 9if (isTestInstance()) configName += `-${getAppNumber()}`
@@ -94,6 +96,64 @@ function getRemoteObjectOrDie (program: any, settings: Settings, netrc: Netrc) {
94 } 96 }
95} 97}
96 98
99function buildCommonVideoOptions (command: Command) {
100 function list (val) {
101 return val.split(',')
102 }
103
104 return command
105 .option('-n, --video-name <name>', 'Video name')
106 .option('-c, --category <category_number>', 'Category number')
107 .option('-l, --licence <licence_number>', 'Licence number')
108 .option('-L, --language <language_code>', 'Language ISO 639 code (fr or en...)')
109 .option('-t, --tags <tags>', 'Video tags', list)
110 .option('-N, --nsfw', 'Video is Not Safe For Work')
111 .option('-d, --video-description <description>', 'Video description')
112 .option('-P, --privacy <privacy_number>', 'Privacy')
113 .option('-C, --channel-name <channel_name>', 'Channel name')
114 .option('-m, --comments-enabled', 'Enable comments')
115 .option('-s, --support <support>', 'Video support text')
116 .option('-w, --wait-transcoding', 'Wait transcoding before publishing the video')
117}
118
119async function buildVideoAttributesFromCommander (url: string, command: Command, defaultAttributes: any) {
120 const booleanAttributes: { [id: string]: boolean } = {}
121
122 for (const key of [ 'nsfw', 'commentsEnabled', 'downloadEnabled', 'waitTranscoding' ]) {
123 if (command[ key ] !== undefined) {
124 booleanAttributes[key] = command[ key ]
125 } else if (defaultAttributes[key] !== undefined) {
126 booleanAttributes[key] = defaultAttributes[key]
127 } else {
128 booleanAttributes[key] = false
129 }
130 }
131
132 const videoAttributes = {
133 name: command[ 'videoName' ] || defaultAttributes.name,
134 category: command[ 'category' ] || defaultAttributes.category || undefined,
135 licence: command[ 'licence' ] || defaultAttributes.licence || undefined,
136 language: command[ 'language' ] || defaultAttributes.language || undefined,
137 privacy: command[ 'privacy' ] || defaultAttributes.privacy || VideoPrivacy.PUBLIC,
138 support: command[ 'support' ] || defaultAttributes.support || undefined
139 }
140
141 Object.assign(videoAttributes, booleanAttributes)
142
143 if (command[ 'channelName' ]) {
144 const res = await getVideoChannel(url, command['channelName'])
145 const videoChannel: VideoChannel = res.body
146
147 Object.assign(videoAttributes, { channelId: videoChannel.id })
148
149 if (!videoAttributes.support && videoChannel.support) {
150 Object.assign(videoAttributes, { support: videoChannel.support })
151 }
152 }
153
154 return videoAttributes
155}
156
97// --------------------------------------------------------------------------- 157// ---------------------------------------------------------------------------
98 158
99export { 159export {
@@ -103,5 +163,8 @@ export {
103 getNetrc, 163 getNetrc,
104 getRemoteObjectOrDie, 164 getRemoteObjectOrDie,
105 writeSettings, 165 writeSettings,
106 deleteSettings 166 deleteSettings,
167
168 buildCommonVideoOptions,
169 buildVideoAttributesFromCommander
107} 170}
diff --git a/server/tools/peertube-import-videos.ts b/server/tools/peertube-import-videos.ts
index f9cd3106a..d7bb00e02 100644
--- a/server/tools/peertube-import-videos.ts
+++ b/server/tools/peertube-import-videos.ts
@@ -3,7 +3,6 @@ require('tls').DEFAULT_ECDH_CURVE = 'auto'
3 3
4import * as program from 'commander' 4import * as program from 'commander'
5import { join } from 'path' 5import { join } from 'path'
6import { VideoPrivacy } from '../../shared/models/videos'
7import { doRequestAndSaveToFile } from '../helpers/requests' 6import { doRequestAndSaveToFile } from '../helpers/requests'
8import { CONSTRAINTS_FIELDS } from '../initializers/constants' 7import { CONSTRAINTS_FIELDS } from '../initializers/constants'
9import { getClient, getVideoCategories, login, searchVideoWithSort, uploadVideo } from '../../shared/extra-utils/index' 8import { getClient, getVideoCategories, login, searchVideoWithSort, uploadVideo } from '../../shared/extra-utils/index'
@@ -12,7 +11,7 @@ import * as prompt from 'prompt'
12import { remove } from 'fs-extra' 11import { remove } from 'fs-extra'
13import { sha256 } from '../helpers/core-utils' 12import { sha256 } from '../helpers/core-utils'
14import { buildOriginallyPublishedAt, safeGetYoutubeDL } from '../helpers/youtube-dl' 13import { buildOriginallyPublishedAt, safeGetYoutubeDL } from '../helpers/youtube-dl'
15import { getNetrc, getRemoteObjectOrDie, getSettings } from './cli' 14import { buildCommonVideoOptions, buildVideoAttributesFromCommander, getNetrc, getRemoteObjectOrDie, getSettings } from './cli'
16 15
17type UserInfo = { 16type UserInfo = {
18 username: string 17 username: string
@@ -24,14 +23,16 @@ const processOptions = {
24 maxBuffer: Infinity 23 maxBuffer: Infinity
25} 24}
26 25
27program 26let command = program
28 .name('import-videos') 27 .name('import-videos')
28
29command = buildCommonVideoOptions(command)
30
31command
29 .option('-u, --url <url>', 'Server url') 32 .option('-u, --url <url>', 'Server url')
30 .option('-U, --username <username>', 'Username') 33 .option('-U, --username <username>', 'Username')
31 .option('-p, --password <token>', 'Password') 34 .option('-p, --password <token>', 'Password')
32 .option('-t, --target-url <targetUrl>', 'Video target URL') 35 .option('-t, --target-url <targetUrl>', 'Video target URL')
33 .option('-C, --channel-id <channel_id>', 'Channel ID')
34 .option('-l, --language <languageCode>', 'Language ISO 639 code (fr or en...)')
35 .option('-v, --verbose', 'Verbose mode') 36 .option('-v, --verbose', 'Verbose mode')
36 .parse(process.argv) 37 .parse(process.argv)
37 38
@@ -179,7 +180,7 @@ async function uploadVideoOnPeerTube (parameters: {
179 180
180 const originallyPublishedAt = buildOriginallyPublishedAt(videoInfo) 181 const originallyPublishedAt = buildOriginallyPublishedAt(videoInfo)
181 182
182 const videoAttributes = { 183 const defaultAttributes = {
183 name: truncate(videoInfo.title, { 184 name: truncate(videoInfo.title, {
184 'length': CONSTRAINTS_FIELDS.VIDEOS.NAME.max, 185 'length': CONSTRAINTS_FIELDS.VIDEOS.NAME.max,
185 'separator': /,? +/, 186 'separator': /,? +/,
@@ -187,24 +188,19 @@ async function uploadVideoOnPeerTube (parameters: {
187 }), 188 }),
188 category, 189 category,
189 licence, 190 licence,
190 language: program[ 'language' ],
191 nsfw: isNSFW(videoInfo), 191 nsfw: isNSFW(videoInfo),
192 waitTranscoding: true, 192 description: videoInfo.description,
193 commentsEnabled: true, 193 tags
194 downloadEnabled: true,
195 description: videoInfo.description || undefined,
196 support: undefined,
197 tags,
198 privacy: VideoPrivacy.PUBLIC,
199 fixture: videoPath,
200 thumbnailfile,
201 previewfile: thumbnailfile,
202 originallyPublishedAt: originallyPublishedAt ? originallyPublishedAt.toISOString() : null
203 } 194 }
204 195
205 if (program[ 'channelId' ]) { 196 const videoAttributes = await buildVideoAttributesFromCommander(url, program, defaultAttributes)
206 Object.assign(videoAttributes, { channelId: program['channelId'] }) 197
207 } 198 Object.assign(videoAttributes, {
199 originallyPublishedAt: originallyPublishedAt ? originallyPublishedAt.toISOString() : null,
200 thumbnailfile,
201 previewfile: thumbnailfile,
202 fixture: videoPath
203 })
208 204
209 console.log('\nUploading on PeerTube video "%s".', videoAttributes.name) 205 console.log('\nUploading on PeerTube video "%s".', videoAttributes.name)
210 206
diff --git a/server/tools/peertube-upload.ts b/server/tools/peertube-upload.ts
index 1da52da31..c00205e8f 100644
--- a/server/tools/peertube-upload.ts
+++ b/server/tools/peertube-upload.ts
@@ -3,24 +3,18 @@ import { access, constants } from 'fs-extra'
3import { isAbsolute } from 'path' 3import { isAbsolute } from 'path'
4import { getClient, login } from '../../shared/extra-utils' 4import { getClient, login } from '../../shared/extra-utils'
5import { uploadVideo } from '../../shared/extra-utils/' 5import { uploadVideo } from '../../shared/extra-utils/'
6import { VideoPrivacy } from '../../shared/models/videos' 6import { buildCommonVideoOptions, buildVideoAttributesFromCommander, getNetrc, getRemoteObjectOrDie, getSettings } from './cli'
7import { getNetrc, getRemoteObjectOrDie, getSettings } from './cli'
8 7
9program 8let command = program
10 .name('upload') 9 .name('upload')
10
11command = buildCommonVideoOptions(command)
12
13command
14
11 .option('-u, --url <url>', 'Server url') 15 .option('-u, --url <url>', 'Server url')
12 .option('-U, --username <username>', 'Username') 16 .option('-U, --username <username>', 'Username')
13 .option('-p, --password <token>', 'Password') 17 .option('-p, --password <token>', 'Password')
14 .option('-n, --video-name <name>', 'Video name')
15 .option('-P, --privacy <privacy_number>', 'Privacy')
16 .option('-N, --nsfw', 'Video is Not Safe For Work')
17 .option('-c, --category <category_number>', 'Category number')
18 .option('-C, --channel-id <channel_id>', 'Channel ID')
19 .option('-m, --comments-enabled', 'Enable comments')
20 .option('-l, --licence <licence_number>', 'Licence number')
21 .option('-L, --language <language_code>', 'Language ISO 639 code (fr or en...)')
22 .option('-d, --video-description <description>', 'Video description')
23 .option('-t, --tags <tags>', 'Video tags', list)
24 .option('-b, --thumbnail <thumbnailPath>', 'Thumbnail path') 18 .option('-b, --thumbnail <thumbnailPath>', 'Thumbnail path')
25 .option('-v, --preview <previewPath>', 'Preview path') 19 .option('-v, --preview <previewPath>', 'Preview path')
26 .option('-f, --file <file>', 'Video absolute file path') 20 .option('-f, --file <file>', 'Video absolute file path')
@@ -30,10 +24,9 @@ Promise.all([ getSettings(), getNetrc() ])
30 .then(([ settings, netrc ]) => { 24 .then(([ settings, netrc ]) => {
31 const { url, username, password } = getRemoteObjectOrDie(program, settings, netrc) 25 const { url, username, password } = getRemoteObjectOrDie(program, settings, netrc)
32 26
33 if (!program[ 'videoName' ] || !program[ 'file' ] || !program[ 'channelId' ]) { 27 if (!program[ 'videoName' ] || !program[ 'file' ]) {
34 if (!program[ 'videoName' ]) console.error('--video-name is required.') 28 if (!program[ 'videoName' ]) console.error('--video-name is required.')
35 if (!program[ 'file' ]) console.error('--file is required.') 29 if (!program[ 'file' ]) console.error('--file is required.')
36 if (!program[ 'channelId' ]) console.error('--channel-id is required.')
37 30
38 process.exit(-1) 31 process.exit(-1)
39 } 32 }
@@ -70,24 +63,17 @@ async function run (url: string, username: string, password: string) {
70 63
71 console.log('Uploading %s video...', program[ 'videoName' ]) 64 console.log('Uploading %s video...', program[ 'videoName' ])
72 65
73 const videoAttributes = { 66 const defaultAttributes = {
74 name: program[ 'videoName' ], 67 tags: command[ 'tags' ],
75 category: program[ 'category' ] || undefined, 68 description: command[ 'videoDescription' ]
76 channelId: program[ 'channelId' ], 69 }
77 licence: program[ 'licence' ] || undefined, 70 const videoAttributes = await buildVideoAttributesFromCommander(url, program, defaultAttributes)
78 language: program[ 'language' ] || undefined, 71
79 nsfw: program[ 'nsfw' ] !== undefined ? program[ 'nsfw' ] : false, 72 Object.assign(videoAttributes, {
80 description: program[ 'videoDescription' ] || undefined,
81 tags: program[ 'tags' ] || [],
82 commentsEnabled: program[ 'commentsEnabled' ] !== undefined ? program[ 'commentsEnabled' ] : true,
83 downloadEnabled: program[ 'downloadEnabled' ] !== undefined ? program[ 'downloadEnabled' ] : true,
84 fixture: program[ 'file' ], 73 fixture: program[ 'file' ],
85 thumbnailfile: program[ 'thumbnail' ], 74 thumbnailfile: program[ 'thumbnail' ],
86 previewfile: program[ 'preview' ], 75 previewfile: program[ 'preview' ]
87 waitTranscoding: true, 76 })
88 privacy: program[ 'privacy' ] || VideoPrivacy.PUBLIC,
89 support: undefined
90 }
91 77
92 try { 78 try {
93 await uploadVideo(url, accessToken, videoAttributes) 79 await uploadVideo(url, accessToken, videoAttributes)
@@ -100,7 +86,3 @@ async function run (url: string, username: string, password: string) {
100} 86}
101 87
102// ---------------------------------------------------------------------------- 88// ----------------------------------------------------------------------------
103
104function list (val) {
105 return val.split(',')
106}