]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/tools/peertube-redundancy.ts
Translated using Weblate (Russian)
[github/Chocobozzz/PeerTube.git] / server / tools / peertube-redundancy.ts
CommitLineData
a1587156
C
1// eslint-disable @typescript-eslint/no-unnecessary-type-assertion
2
26fcf2ef
C
3import { registerTSPaths } from '../helpers/register-ts-paths'
4registerTSPaths()
5
6import * as program from 'commander'
7import { getAdminTokenOrDie, getServerCredentials } from './cli'
8import { VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
9import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy } from '@shared/extra-utils/server/redundancy'
f2eb23cd 10import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
26fcf2ef 11import validator from 'validator'
26fcf2ef 12import * as CliTable3 from 'cli-table3'
a1587156 13import { URL } from 'url'
26fcf2ef
C
14import { uniq } from 'lodash'
15
a1587156
C
16import bytes = require('bytes')
17
26fcf2ef
C
18program
19 .name('plugins')
20 .usage('[command] [options]')
21
22program
23 .command('list-remote-redundancies')
24 .description('List remote redundancies on your videos')
25 .option('-u, --url <url>', 'Server url')
26 .option('-U, --username <username>', 'Username')
27 .option('-p, --password <token>', 'Password')
28 .action(() => listRedundanciesCLI('my-videos'))
29
30program
31 .command('list-my-redundancies')
32 .description('List your redundancies of remote videos')
33 .option('-u, --url <url>', 'Server url')
34 .option('-U, --username <username>', 'Username')
35 .option('-p, --password <token>', 'Password')
36 .action(() => listRedundanciesCLI('remote-videos'))
37
38program
39 .command('add')
40 .description('Duplicate a video in your redundancy system')
41 .option('-u, --url <url>', 'Server url')
42 .option('-U, --username <username>', 'Username')
43 .option('-p, --password <token>', 'Password')
44 .option('-v, --video <videoId>', 'Video id to duplicate')
45 .action((options) => addRedundancyCLI(options))
46
47program
48 .command('remove')
49 .description('Remove a video from your redundancies')
50 .option('-u, --url <url>', 'Server url')
51 .option('-U, --username <username>', 'Username')
52 .option('-p, --password <token>', 'Password')
53 .option('-v, --video <videoId>', 'Video id to remove from redundancies')
54 .action((options) => removeRedundancyCLI(options))
55
56if (!process.argv.slice(2).length) {
57 program.outputHelp()
58}
59
60program.parse(process.argv)
61
62// ----------------------------------------------------------------------------
63
64async function listRedundanciesCLI (target: VideoRedundanciesTarget) {
65 const { url, username, password } = await getServerCredentials(program)
66 const accessToken = await getAdminTokenOrDie(url, username, password)
67
68 const redundancies = await listVideoRedundanciesData(url, accessToken, target)
69
70 const table = new CliTable3({
71 head: [ 'video id', 'video name', 'video url', 'files', 'playlists', 'by instances', 'total size' ]
a1587156 72 }) as any
26fcf2ef
C
73
74 for (const redundancy of redundancies) {
75 const webtorrentFiles = redundancy.redundancies.files
76 const streamingPlaylists = redundancy.redundancies.streamingPlaylists
77
78 let totalSize = ''
79 if (target === 'remote-videos') {
80 const tmp = webtorrentFiles.concat(streamingPlaylists)
81 .reduce((a, b) => a + b.size, 0)
82
83 totalSize = bytes(tmp)
84 }
85
86 const instances = uniq(
87 webtorrentFiles.concat(streamingPlaylists)
88 .map(r => r.fileUrl)
a1587156 89 .map(u => new URL(u).host)
26fcf2ef
C
90 )
91
92 table.push([
93 redundancy.id.toString(),
94 redundancy.name,
95 redundancy.url,
96 webtorrentFiles.length,
97 streamingPlaylists.length,
98 instances.join('\n'),
99 totalSize
100 ])
101 }
102
103 console.log(table.toString())
104 process.exit(0)
105}
106
107async function addRedundancyCLI (options: { videoId: number }) {
108 const { url, username, password } = await getServerCredentials(program)
109 const accessToken = await getAdminTokenOrDie(url, username, password)
110
a1587156 111 if (!options['video'] || validator.isInt('' + options['video']) === false) {
26fcf2ef
C
112 console.error('You need to specify the video id to duplicate and it should be a number.\n')
113 program.outputHelp()
114 process.exit(-1)
115 }
116
117 try {
118 await addVideoRedundancy({
119 url,
120 accessToken,
a1587156 121 videoId: options['video']
26fcf2ef
C
122 })
123
124 console.log('Video will be duplicated by your instance!')
125
126 process.exit(0)
127 } catch (err) {
f2eb23cd 128 if (err.message.includes(HttpStatusCode.CONFLICT_409)) {
26fcf2ef 129 console.error('This video is already duplicated by your instance.')
f2eb23cd 130 } else if (err.message.includes(HttpStatusCode.NOT_FOUND_404)) {
26fcf2ef
C
131 console.error('This video id does not exist.')
132 } else {
133 console.error(err)
134 }
135
136 process.exit(-1)
137 }
138}
139
140async function removeRedundancyCLI (options: { videoId: number }) {
141 const { url, username, password } = await getServerCredentials(program)
142 const accessToken = await getAdminTokenOrDie(url, username, password)
143
a1587156 144 if (!options['video'] || validator.isInt('' + options['video']) === false) {
26fcf2ef
C
145 console.error('You need to specify the video id to remove from your redundancies.\n')
146 program.outputHelp()
147 process.exit(-1)
148 }
149
a1587156 150 const videoId = parseInt(options['video'] + '', 10)
26fcf2ef
C
151
152 let redundancies = await listVideoRedundanciesData(url, accessToken, 'my-videos')
153 let videoRedundancy = redundancies.find(r => videoId === r.id)
154
155 if (!videoRedundancy) {
156 redundancies = await listVideoRedundanciesData(url, accessToken, 'remote-videos')
157 videoRedundancy = redundancies.find(r => videoId === r.id)
158 }
159
160 if (!videoRedundancy) {
161 console.error('Video redundancy not found.')
162 process.exit(-1)
163 }
164
165 try {
166 const ids = videoRedundancy.redundancies.files
167 .concat(videoRedundancy.redundancies.streamingPlaylists)
168 .map(r => r.id)
169
170 for (const id of ids) {
171 await removeVideoRedundancy({
172 url,
173 accessToken,
174 redundancyId: id
175 })
176 }
177
178 console.log('Video redundancy removed!')
179
180 process.exit(0)
181 } catch (err) {
182 console.error(err)
183 process.exit(-1)
184 }
185}
186
187async function listVideoRedundanciesData (url: string, accessToken: string, target: VideoRedundanciesTarget) {
188 const res = await listVideoRedundancies({
189 url,
190 accessToken,
191 start: 0,
192 count: 100,
193 sort: 'name',
194 target
195 })
196
197 return res.body.data as VideoRedundancy[]
198}