aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tools/peertube-import-videos.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/tools/peertube-import-videos.ts')
-rw-r--r--server/tools/peertube-import-videos.ts110
1 files changed, 53 insertions, 57 deletions
diff --git a/server/tools/peertube-import-videos.ts b/server/tools/peertube-import-videos.ts
index 101a95b2a..52aae3d2c 100644
--- a/server/tools/peertube-import-videos.ts
+++ b/server/tools/peertube-import-videos.ts
@@ -8,17 +8,19 @@ import { truncate } from 'lodash'
8import { join } from 'path' 8import { join } from 'path'
9import * as prompt from 'prompt' 9import * as prompt from 'prompt'
10import { promisify } from 'util' 10import { promisify } from 'util'
11import { advancedVideosSearch, getClient, getVideoCategories, login, uploadVideo } from '../../shared/extra-utils/index' 11import { YoutubeDL } from '@server/helpers/youtube-dl'
12import { sha256 } from '../helpers/core-utils' 12import { sha256 } from '../helpers/core-utils'
13import { doRequestAndSaveToFile } from '../helpers/requests' 13import { doRequestAndSaveToFile } from '../helpers/requests'
14import { CONSTRAINTS_FIELDS } from '../initializers/constants' 14import { CONSTRAINTS_FIELDS } from '../initializers/constants'
15import { buildCommonVideoOptions, buildVideoAttributesFromCommander, getLogger, getServerCredentials } from './cli' 15import {
16import { YoutubeDL } from '@server/helpers/youtube-dl' 16 assignToken,
17 17 buildCommonVideoOptions,
18type UserInfo = { 18 buildServer,
19 username: string 19 buildVideoAttributesFromCommander,
20 password: string 20 getLogger,
21} 21 getServerCredentials
22} from './cli'
23import { PeerTubeServer } from '@shared/extra-utils'
22 24
23const processOptions = { 25const processOptions = {
24 maxBuffer: Infinity 26 maxBuffer: Infinity
@@ -62,17 +64,13 @@ getServerCredentials(command)
62 url = normalizeTargetUrl(url) 64 url = normalizeTargetUrl(url)
63 options.targetUrl = normalizeTargetUrl(options.targetUrl) 65 options.targetUrl = normalizeTargetUrl(options.targetUrl)
64 66
65 const user = { username, password } 67 run(url, username, password)
66
67 run(url, user)
68 .catch(err => exitError(err)) 68 .catch(err => exitError(err))
69 }) 69 })
70 .catch(err => console.error(err)) 70 .catch(err => console.error(err))
71 71
72async function run (url: string, user: UserInfo) { 72async function run (url: string, username: string, password: string) {
73 if (!user.password) { 73 if (!password) password = await promptPassword()
74 user.password = await promptPassword()
75 }
76 74
77 const youtubeDLBinary = await YoutubeDL.safeGetYoutubeDL() 75 const youtubeDLBinary = await YoutubeDL.safeGetYoutubeDL()
78 76
@@ -111,7 +109,8 @@ async function run (url: string, user: UserInfo) {
111 await processVideo({ 109 await processVideo({
112 cwd: options.tmpdir, 110 cwd: options.tmpdir,
113 url, 111 url,
114 user, 112 username,
113 password,
115 youtubeInfo: info 114 youtubeInfo: info
116 }) 115 })
117 } catch (err) { 116 } catch (err) {
@@ -119,17 +118,18 @@ async function run (url: string, user: UserInfo) {
119 } 118 }
120 } 119 }
121 120
122 log.info('Video/s for user %s imported: %s', user.username, options.targetUrl) 121 log.info('Video/s for user %s imported: %s', username, options.targetUrl)
123 process.exit(0) 122 process.exit(0)
124} 123}
125 124
126async function processVideo (parameters: { 125async function processVideo (parameters: {
127 cwd: string 126 cwd: string
128 url: string 127 url: string
129 user: { username: string, password: string } 128 username: string
129 password: string
130 youtubeInfo: any 130 youtubeInfo: any
131}) { 131}) {
132 const { youtubeInfo, cwd, url, user } = parameters 132 const { youtubeInfo, cwd, url, username, password } = parameters
133 const youtubeDL = new YoutubeDL('', []) 133 const youtubeDL = new YoutubeDL('', [])
134 134
135 log.debug('Fetching object.', youtubeInfo) 135 log.debug('Fetching object.', youtubeInfo)
@@ -138,22 +138,29 @@ async function processVideo (parameters: {
138 log.debug('Fetched object.', videoInfo) 138 log.debug('Fetched object.', videoInfo)
139 139
140 const originallyPublishedAt = youtubeDL.buildOriginallyPublishedAt(videoInfo) 140 const originallyPublishedAt = youtubeDL.buildOriginallyPublishedAt(videoInfo)
141
141 if (options.since && originallyPublishedAt && originallyPublishedAt.getTime() < options.since.getTime()) { 142 if (options.since && originallyPublishedAt && originallyPublishedAt.getTime() < options.since.getTime()) {
142 log.info('Video "%s" has been published before "%s", don\'t upload it.\n', 143 log.info('Video "%s" has been published before "%s", don\'t upload it.\n', videoInfo.title, formatDate(options.since))
143 videoInfo.title, formatDate(options.since))
144 return 144 return
145 } 145 }
146
146 if (options.until && originallyPublishedAt && originallyPublishedAt.getTime() > options.until.getTime()) { 147 if (options.until && originallyPublishedAt && originallyPublishedAt.getTime() > options.until.getTime()) {
147 log.info('Video "%s" has been published after "%s", don\'t upload it.\n', 148 log.info('Video "%s" has been published after "%s", don\'t upload it.\n', videoInfo.title, formatDate(options.until))
148 videoInfo.title, formatDate(options.until))
149 return 149 return
150 } 150 }
151 151
152 const result = await advancedVideosSearch(url, { search: videoInfo.title, sort: '-match', searchTarget: 'local' }) 152 const server = buildServer(url)
153 const { data } = await server.search.advancedVideoSearch({
154 search: {
155 search: videoInfo.title,
156 sort: '-match',
157 searchTarget: 'local'
158 }
159 })
153 160
154 log.info('############################################################\n') 161 log.info('############################################################\n')
155 162
156 if (result.body.data.find(v => v.name === videoInfo.title)) { 163 if (data.find(v => v.name === videoInfo.title)) {
157 log.info('Video "%s" already exists, don\'t reupload it.\n', videoInfo.title) 164 log.info('Video "%s" already exists, don\'t reupload it.\n', videoInfo.title)
158 return 165 return
159 } 166 }
@@ -172,7 +179,8 @@ async function processVideo (parameters: {
172 youtubeDL, 179 youtubeDL,
173 cwd, 180 cwd,
174 url, 181 url,
175 user, 182 username,
183 password,
176 videoInfo: normalizeObject(videoInfo), 184 videoInfo: normalizeObject(videoInfo),
177 videoPath: path 185 videoPath: path
178 }) 186 })
@@ -187,11 +195,15 @@ async function uploadVideoOnPeerTube (parameters: {
187 videoPath: string 195 videoPath: string
188 cwd: string 196 cwd: string
189 url: string 197 url: string
190 user: { username: string, password: string } 198 username: string
199 password: string
191}) { 200}) {
192 const { youtubeDL, videoInfo, videoPath, cwd, url, user } = parameters 201 const { youtubeDL, videoInfo, videoPath, cwd, url, username, password } = parameters
193 202
194 const category = await getCategory(videoInfo.categories, url) 203 const server = buildServer(url)
204 await assignToken(server, username, password)
205
206 const category = await getCategory(server, videoInfo.categories)
195 const licence = getLicence(videoInfo.license) 207 const licence = getLicence(videoInfo.license)
196 let tags = [] 208 let tags = []
197 if (Array.isArray(videoInfo.tags)) { 209 if (Array.isArray(videoInfo.tags)) {
@@ -223,28 +235,28 @@ async function uploadVideoOnPeerTube (parameters: {
223 tags 235 tags
224 } 236 }
225 237
226 const videoAttributes = await buildVideoAttributesFromCommander(url, program, defaultAttributes) 238 const baseAttributes = await buildVideoAttributesFromCommander(server, program, defaultAttributes)
239
240 const attributes = {
241 ...baseAttributes,
227 242
228 Object.assign(videoAttributes, {
229 originallyPublishedAt: originallyPublishedAt ? originallyPublishedAt.toISOString() : null, 243 originallyPublishedAt: originallyPublishedAt ? originallyPublishedAt.toISOString() : null,
230 thumbnailfile, 244 thumbnailfile,
231 previewfile: thumbnailfile, 245 previewfile: thumbnailfile,
232 fixture: videoPath 246 fixture: videoPath
233 }) 247 }
234
235 log.info('\nUploading on PeerTube video "%s".', videoAttributes.name)
236 248
237 let accessToken = await getAccessTokenOrDie(url, user) 249 log.info('\nUploading on PeerTube video "%s".', attributes.name)
238 250
239 try { 251 try {
240 await uploadVideo(url, accessToken, videoAttributes) 252 await server.videos.upload({ attributes })
241 } catch (err) { 253 } catch (err) {
242 if (err.message.indexOf('401') !== -1) { 254 if (err.message.indexOf('401') !== -1) {
243 log.info('Got 401 Unauthorized, token may have expired, renewing token and retry.') 255 log.info('Got 401 Unauthorized, token may have expired, renewing token and retry.')
244 256
245 accessToken = await getAccessTokenOrDie(url, user) 257 server.accessToken = await server.login.getAccessToken(username, password)
246 258
247 await uploadVideo(url, accessToken, videoAttributes) 259 await server.videos.upload({ attributes })
248 } else { 260 } else {
249 exitError(err.message) 261 exitError(err.message)
250 } 262 }
@@ -253,20 +265,19 @@ async function uploadVideoOnPeerTube (parameters: {
253 await remove(videoPath) 265 await remove(videoPath)
254 if (thumbnailfile) await remove(thumbnailfile) 266 if (thumbnailfile) await remove(thumbnailfile)
255 267
256 log.warn('Uploaded video "%s"!\n', videoAttributes.name) 268 log.warn('Uploaded video "%s"!\n', attributes.name)
257} 269}
258 270
259/* ---------------------------------------------------------- */ 271/* ---------------------------------------------------------- */
260 272
261async function getCategory (categories: string[], url: string) { 273async function getCategory (server: PeerTubeServer, categories: string[]) {
262 if (!categories) return undefined 274 if (!categories) return undefined
263 275
264 const categoryString = categories[0] 276 const categoryString = categories[0]
265 277
266 if (categoryString === 'News & Politics') return 11 278 if (categoryString === 'News & Politics') return 11
267 279
268 const res = await getVideoCategories(url) 280 const categoriesServer = await server.videos.getCategories()
269 const categoriesServer = res.body
270 281
271 for (const key of Object.keys(categoriesServer)) { 282 for (const key of Object.keys(categoriesServer)) {
272 const categoryServer = categoriesServer[key] 283 const categoryServer = categoriesServer[key]
@@ -362,21 +373,6 @@ async function promptPassword () {
362 }) 373 })
363} 374}
364 375
365async function getAccessTokenOrDie (url: string, user: UserInfo) {
366 const resClient = await getClient(url)
367 const client = {
368 id: resClient.body.client_id,
369 secret: resClient.body.client_secret
370 }
371
372 try {
373 const res = await login(url, client, user)
374 return res.body.access_token
375 } catch (err) {
376 exitError('Cannot authenticate. Please check your username/password.')
377 }
378}
379
380function parseDate (dateAsStr: string): Date { 376function parseDate (dateAsStr: string): Date {
381 if (!/\d{4}-\d{2}-\d{2}/.test(dateAsStr)) { 377 if (!/\d{4}-\d{2}-\d{2}/.test(dateAsStr)) {
382 exitError(`Invalid date passed: ${dateAsStr}. Expected format: YYYY-MM-DD. See help for usage.`) 378 exitError(`Invalid date passed: ${dateAsStr}. Expected format: YYYY-MM-DD. See help for usage.`)