]>
Commit | Line | Data |
---|---|---|
1 | import CliTable3 from 'cli-table3' | |
2 | import { Command, program } from 'commander' | |
3 | import { uniq } from 'lodash' | |
4 | import { URL } from 'url' | |
5 | import validator from 'validator' | |
6 | import { HttpStatusCode, VideoRedundanciesTarget } from '@shared/models' | |
7 | import { assignToken, buildServer, getServerCredentials } from './cli' | |
8 | ||
9 | import bytes = require('bytes') | |
10 | ||
11 | program | |
12 | .name('redundancy') | |
13 | .usage('[command] [options]') | |
14 | ||
15 | program | |
16 | .command('list-remote-redundancies') | |
17 | .description('List remote redundancies on your videos') | |
18 | .option('-u, --url <url>', 'Server url') | |
19 | .option('-U, --username <username>', 'Username') | |
20 | .option('-p, --password <token>', 'Password') | |
21 | .action(() => listRedundanciesCLI('my-videos')) | |
22 | ||
23 | program | |
24 | .command('list-my-redundancies') | |
25 | .description('List your redundancies of remote videos') | |
26 | .option('-u, --url <url>', 'Server url') | |
27 | .option('-U, --username <username>', 'Username') | |
28 | .option('-p, --password <token>', 'Password') | |
29 | .action(() => listRedundanciesCLI('remote-videos')) | |
30 | ||
31 | program | |
32 | .command('add') | |
33 | .description('Duplicate a video in your redundancy system') | |
34 | .option('-u, --url <url>', 'Server url') | |
35 | .option('-U, --username <username>', 'Username') | |
36 | .option('-p, --password <token>', 'Password') | |
37 | .option('-v, --video <videoId>', 'Video id to duplicate') | |
38 | .action((options, command) => addRedundancyCLI(options, command)) | |
39 | ||
40 | program | |
41 | .command('remove') | |
42 | .description('Remove a video from your redundancies') | |
43 | .option('-u, --url <url>', 'Server url') | |
44 | .option('-U, --username <username>', 'Username') | |
45 | .option('-p, --password <token>', 'Password') | |
46 | .option('-v, --video <videoId>', 'Video id to remove from redundancies') | |
47 | .action((options, command) => removeRedundancyCLI(options, command)) | |
48 | ||
49 | if (!process.argv.slice(2).length) { | |
50 | program.outputHelp() | |
51 | } | |
52 | ||
53 | program.parse(process.argv) | |
54 | ||
55 | // ---------------------------------------------------------------------------- | |
56 | ||
57 | async function listRedundanciesCLI (target: VideoRedundanciesTarget) { | |
58 | const { url, username, password } = await getServerCredentials(program) | |
59 | const server = buildServer(url) | |
60 | await assignToken(server, username, password) | |
61 | ||
62 | const { data } = await server.redundancy.listVideos({ start: 0, count: 100, sort: 'name', target }) | |
63 | ||
64 | const table = new CliTable3({ | |
65 | head: [ 'video id', 'video name', 'video url', 'files', 'playlists', 'by instances', 'total size' ] | |
66 | }) as any | |
67 | ||
68 | for (const redundancy of data) { | |
69 | const webtorrentFiles = redundancy.redundancies.files | |
70 | const streamingPlaylists = redundancy.redundancies.streamingPlaylists | |
71 | ||
72 | let totalSize = '' | |
73 | if (target === 'remote-videos') { | |
74 | const tmp = webtorrentFiles.concat(streamingPlaylists) | |
75 | .reduce((a, b) => a + b.size, 0) | |
76 | ||
77 | totalSize = bytes(tmp) | |
78 | } | |
79 | ||
80 | const instances = uniq( | |
81 | webtorrentFiles.concat(streamingPlaylists) | |
82 | .map(r => r.fileUrl) | |
83 | .map(u => new URL(u).host) | |
84 | ) | |
85 | ||
86 | table.push([ | |
87 | redundancy.id.toString(), | |
88 | redundancy.name, | |
89 | redundancy.url, | |
90 | webtorrentFiles.length, | |
91 | streamingPlaylists.length, | |
92 | instances.join('\n'), | |
93 | totalSize | |
94 | ]) | |
95 | } | |
96 | ||
97 | console.log(table.toString()) | |
98 | process.exit(0) | |
99 | } | |
100 | ||
101 | async function addRedundancyCLI (options: { video: number }, command: Command) { | |
102 | const { url, username, password } = await getServerCredentials(command) | |
103 | const server = buildServer(url) | |
104 | await assignToken(server, username, password) | |
105 | ||
106 | if (!options.video || validator.isInt('' + options.video) === false) { | |
107 | console.error('You need to specify the video id to duplicate and it should be a number.\n') | |
108 | command.outputHelp() | |
109 | process.exit(-1) | |
110 | } | |
111 | ||
112 | try { | |
113 | await server.redundancy.addVideo({ videoId: options.video }) | |
114 | ||
115 | console.log('Video will be duplicated by your instance!') | |
116 | ||
117 | process.exit(0) | |
118 | } catch (err) { | |
119 | if (err.message.includes(HttpStatusCode.CONFLICT_409)) { | |
120 | console.error('This video is already duplicated by your instance.') | |
121 | } else if (err.message.includes(HttpStatusCode.NOT_FOUND_404)) { | |
122 | console.error('This video id does not exist.') | |
123 | } else { | |
124 | console.error(err) | |
125 | } | |
126 | ||
127 | process.exit(-1) | |
128 | } | |
129 | } | |
130 | ||
131 | async function removeRedundancyCLI (options: { video: number }, command: Command) { | |
132 | const { url, username, password } = await getServerCredentials(command) | |
133 | const server = buildServer(url) | |
134 | await assignToken(server, username, password) | |
135 | ||
136 | if (!options.video || validator.isInt('' + options.video) === false) { | |
137 | console.error('You need to specify the video id to remove from your redundancies.\n') | |
138 | command.outputHelp() | |
139 | process.exit(-1) | |
140 | } | |
141 | ||
142 | const videoId = parseInt(options.video + '', 10) | |
143 | ||
144 | const myVideoRedundancies = await server.redundancy.listVideos({ target: 'my-videos' }) | |
145 | let videoRedundancy = myVideoRedundancies.data.find(r => videoId === r.id) | |
146 | ||
147 | if (!videoRedundancy) { | |
148 | const remoteVideoRedundancies = await server.redundancy.listVideos({ target: 'remote-videos' }) | |
149 | videoRedundancy = remoteVideoRedundancies.data.find(r => videoId === r.id) | |
150 | } | |
151 | ||
152 | if (!videoRedundancy) { | |
153 | console.error('Video redundancy not found.') | |
154 | process.exit(-1) | |
155 | } | |
156 | ||
157 | try { | |
158 | const ids = videoRedundancy.redundancies.files | |
159 | .concat(videoRedundancy.redundancies.streamingPlaylists) | |
160 | .map(r => r.id) | |
161 | ||
162 | for (const id of ids) { | |
163 | await server.redundancy.removeVideo({ redundancyId: id }) | |
164 | } | |
165 | ||
166 | console.log('Video redundancy removed!') | |
167 | ||
168 | process.exit(0) | |
169 | } catch (err) { | |
170 | console.error(err) | |
171 | process.exit(-1) | |
172 | } | |
173 | } |