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