]>
Commit | Line | Data |
---|---|---|
a7fea183 C |
1 | import * as program from 'commander' |
2 | import { createWriteStream } from 'fs' | |
3 | import { join } from 'path' | |
4 | import { cursorTo } from 'readline' | |
5 | import * as youtubeDL from 'youtube-dl' | |
6 | import { VideoPrivacy } from '../../shared/models/videos' | |
7 | import { unlinkPromise } from '../helpers/core-utils' | |
8 | import { getClient, getVideoCategories, login, searchVideo, uploadVideo } from '../tests/utils' | |
9 | ||
10 | program | |
11 | .option('-u, --url <url>', 'Server url') | |
12 | .option('-U, --username <username>', 'Username') | |
13 | .option('-p, --password <token>', 'Password') | |
e7872038 | 14 | .option('-y, --youtube-url <youtubeUrl>', 'Youtube URL') |
a7fea183 C |
15 | .parse(process.argv) |
16 | ||
17 | if ( | |
18 | !program['url'] || | |
19 | !program['username'] || | |
20 | !program['password'] || | |
21 | !program['youtubeUrl'] | |
22 | ) { | |
23 | throw new Error('All arguments are required.') | |
24 | } | |
25 | ||
26 | run().catch(err => console.error(err)) | |
27 | ||
28 | let accessToken: string | |
29 | ||
30 | async function run () { | |
31 | const res = await getClient(program['url']) | |
32 | const client = { | |
33 | id: res.body.client_id, | |
34 | secret: res.body.client_secret | |
35 | } | |
36 | ||
37 | const user = { | |
38 | username: program['username'], | |
39 | password: program['password'] | |
40 | } | |
41 | ||
42 | const res2 = await login(program['url'], client, user) | |
43 | accessToken = res2.body.access_token | |
44 | ||
45 | youtubeDL.getInfo(program['youtubeUrl'], [ '-j', '--flat-playlist' ], async (err, info) => { | |
46 | if (err) throw err | |
47 | ||
e7872038 C |
48 | // Normalize utf8 fields |
49 | info = info.map(i => normalizeObject(i)) | |
50 | ||
a7fea183 C |
51 | const videos = info.map(i => { |
52 | return { url: 'https://www.youtube.com/watch?v=' + i.id, name: i.title } | |
53 | }) | |
54 | ||
55 | console.log('Will download and upload %d videos.\n', videos.length) | |
56 | ||
57 | for (const video of videos) { | |
58 | await processVideo(video) | |
59 | } | |
60 | ||
61 | console.log('I\'m finished!') | |
62 | process.exit(0) | |
63 | }) | |
64 | } | |
65 | ||
e7872038 | 66 | function processVideo (video: { name: string, url: string }) { |
a7fea183 | 67 | return new Promise(async res => { |
e7872038 C |
68 | const result = await searchVideo(program['url'], video.name) |
69 | ||
70 | console.log('############################################################\n') | |
71 | ||
a7fea183 | 72 | if (result.body.total !== 0) { |
e7872038 | 73 | console.log('Video "%s" already exists, don\'t reupload it.\n', video.name) |
a7fea183 C |
74 | return res() |
75 | } | |
76 | ||
e7872038 | 77 | const path = join(__dirname, new Date().getTime() + '.mp4') |
a7fea183 | 78 | |
e7872038 | 79 | console.log('Downloading video "%s"...', video.name) |
a7fea183 | 80 | |
e7872038 C |
81 | youtubeDL.exec(video.url, [ '-f', 'bestvideo[ext=mp4]+bestaudio[ext=m4a]', '-o', path ], {}, async (err, output) => { |
82 | if (err) return console.error(err) | |
a7fea183 | 83 | |
e7872038 | 84 | console.log(output.join('\n')) |
a7fea183 | 85 | |
e7872038 C |
86 | youtubeDL.getInfo(video.url, async (err, videoInfo) => { |
87 | if (err) return console.error(err) | |
a7fea183 | 88 | |
e7872038 | 89 | await uploadVideoOnPeerTube(normalizeObject(videoInfo), path) |
a7fea183 | 90 | |
e7872038 C |
91 | return res() |
92 | }) | |
a7fea183 C |
93 | }) |
94 | }) | |
95 | } | |
96 | ||
a7fea183 C |
97 | async function uploadVideoOnPeerTube (videoInfo: any, videoPath: string) { |
98 | const category = await getCategory(videoInfo.categories) | |
99 | const licence = getLicence(videoInfo.license) | |
100 | const language = 13 | |
101 | ||
102 | const videoAttributes = { | |
103 | name: videoInfo.title, | |
104 | category, | |
105 | licence, | |
106 | language, | |
107 | nsfw: false, | |
108 | commentsEnabled: true, | |
109 | description: videoInfo.description, | |
110 | tags: videoInfo.tags.slice(0, 5), | |
111 | privacy: VideoPrivacy.PUBLIC, | |
112 | fixture: videoPath | |
113 | } | |
114 | ||
115 | console.log('\nUploading on PeerTube video "%s".', videoAttributes.name) | |
116 | await uploadVideo(program['url'], accessToken, videoAttributes) | |
117 | await unlinkPromise(videoPath) | |
118 | console.log('Uploaded video "%s"!\n', videoAttributes.name) | |
119 | } | |
120 | ||
121 | async function getCategory (categories: string[]) { | |
122 | const categoryString = categories[0] | |
123 | ||
124 | if (categoryString === 'News & Politics') return 11 | |
125 | ||
126 | const res = await getVideoCategories(program['url']) | |
127 | const categoriesServer = res.body | |
128 | ||
129 | for (const key of Object.keys(categoriesServer)) { | |
130 | const categoryServer = categoriesServer[key] | |
131 | if (categoryString.toLowerCase() === categoryServer.toLowerCase()) return parseInt(key, 10) | |
132 | } | |
133 | ||
134 | return undefined | |
135 | } | |
136 | ||
137 | function getLicence (licence: string) { | |
138 | if (licence.indexOf('Creative Commons Attribution licence') !== -1) return 1 | |
139 | ||
140 | return undefined | |
141 | } | |
e7872038 C |
142 | |
143 | function normalizeObject (obj: any) { | |
144 | const newObj: any = {} | |
145 | ||
146 | for (const key of Object.keys(obj)) { | |
147 | // Deprecated key | |
148 | if (key === 'resolution') continue | |
149 | ||
150 | const value = obj[key] | |
151 | ||
152 | if (typeof value === 'string') { | |
153 | newObj[key] = value.normalize() | |
154 | } else { | |
155 | newObj[key] = value | |
156 | } | |
157 | } | |
158 | ||
159 | return newObj | |
160 | } |