Federated video streaming platform using ActivityPub and P2P in the web browser with Angular. https://joinpeertube.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

174 lines
5.5 KiB

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