diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/helpers/webtorrent.ts | 61 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/move-to-object-storage.ts | 4 | ||||
-rw-r--r-- | server/tests/api/object-storage/videos.ts | 7 |
3 files changed, 57 insertions, 15 deletions
diff --git a/server/helpers/webtorrent.ts b/server/helpers/webtorrent.ts index c84376304..012918468 100644 --- a/server/helpers/webtorrent.ts +++ b/server/helpers/webtorrent.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import * as bencode from 'bencode' | ||
1 | import * as createTorrent from 'create-torrent' | 2 | import * as createTorrent from 'create-torrent' |
2 | import { createWriteStream, ensureDir, remove, writeFile } from 'fs-extra' | 3 | import { createWriteStream, ensureDir, readFile, remove, writeFile } from 'fs-extra' |
3 | import * as magnetUtil from 'magnet-uri' | 4 | import * as magnetUtil from 'magnet-uri' |
4 | import * as parseTorrent from 'parse-torrent' | 5 | import * as parseTorrent from 'parse-torrent' |
5 | import { dirname, join } from 'path' | 6 | import { dirname, join } from 'path' |
@@ -79,43 +80,65 @@ async function downloadWebTorrentVideo (target: { magnetUri: string, torrentName | |||
79 | }) | 80 | }) |
80 | } | 81 | } |
81 | 82 | ||
82 | function createTorrentAndSetInfoHash ( | 83 | function createTorrentAndSetInfoHash (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile) { |
83 | videoOrPlaylist: MVideo | MStreamingPlaylistVideo, | ||
84 | videoFile: MVideoFile | ||
85 | ) { | ||
86 | const video = extractVideo(videoOrPlaylist) | 84 | const video = extractVideo(videoOrPlaylist) |
87 | 85 | ||
88 | const options = { | 86 | const options = { |
89 | // Keep the extname, it's used by the client to stream the file inside a web browser | 87 | // Keep the extname, it's used by the client to stream the file inside a web browser |
90 | name: `${video.name} ${videoFile.resolution}p${videoFile.extname}`, | 88 | name: `${video.name} ${videoFile.resolution}p${videoFile.extname}`, |
91 | createdBy: 'PeerTube', | 89 | createdBy: 'PeerTube', |
92 | announceList: [ | 90 | announceList: buildAnnounceList(), |
93 | [ WEBSERVER.WS + '://' + WEBSERVER.HOSTNAME + ':' + WEBSERVER.PORT + '/tracker/socket' ], | 91 | urlList: buildUrlList(video, videoFile) |
94 | [ WEBSERVER.URL + '/tracker/announce' ] | ||
95 | ], | ||
96 | urlList: [ videoFile.getFileUrl(video) ] | ||
97 | } | 92 | } |
98 | 93 | ||
99 | return VideoPathManager.Instance.makeAvailableVideoFile(videoOrPlaylist, videoFile, async videoPath => { | 94 | return VideoPathManager.Instance.makeAvailableVideoFile(videoOrPlaylist, videoFile, async videoPath => { |
100 | const torrent = await createTorrentPromise(videoPath, options) | 95 | const torrentContent = await createTorrentPromise(videoPath, options) |
101 | 96 | ||
102 | const torrentFilename = generateTorrentFileName(videoOrPlaylist, videoFile.resolution) | 97 | const torrentFilename = generateTorrentFileName(videoOrPlaylist, videoFile.resolution) |
103 | const torrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, torrentFilename) | 98 | const torrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, torrentFilename) |
104 | logger.info('Creating torrent %s.', torrentPath) | 99 | logger.info('Creating torrent %s.', torrentPath) |
105 | 100 | ||
106 | await writeFile(torrentPath, torrent) | 101 | await writeFile(torrentPath, torrentContent) |
107 | 102 | ||
108 | // Remove old torrent file if it existed | 103 | // Remove old torrent file if it existed |
109 | if (videoFile.hasTorrent()) { | 104 | if (videoFile.hasTorrent()) { |
110 | await remove(join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename)) | 105 | await remove(join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename)) |
111 | } | 106 | } |
112 | 107 | ||
113 | const parsedTorrent = parseTorrent(torrent) | 108 | const parsedTorrent = parseTorrent(torrentContent) |
114 | videoFile.infoHash = parsedTorrent.infoHash | 109 | videoFile.infoHash = parsedTorrent.infoHash |
115 | videoFile.torrentFilename = torrentFilename | 110 | videoFile.torrentFilename = torrentFilename |
116 | }) | 111 | }) |
117 | } | 112 | } |
118 | 113 | ||
114 | async function updateTorrentUrls (videoOrPlaylist: MVideo | MStreamingPlaylistVideo, videoFile: MVideoFile) { | ||
115 | const video = extractVideo(videoOrPlaylist) | ||
116 | |||
117 | const oldTorrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename) | ||
118 | |||
119 | const torrentContent = await readFile(oldTorrentPath) | ||
120 | const decoded = bencode.decode(torrentContent) | ||
121 | |||
122 | decoded['announce-list'] = buildAnnounceList() | ||
123 | decoded.announce = decoded['announce-list'][0][0] | ||
124 | |||
125 | decoded['url-list'] = buildUrlList(video, videoFile) | ||
126 | |||
127 | const newTorrentFilename = generateTorrentFileName(videoOrPlaylist, videoFile.resolution) | ||
128 | const newTorrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, newTorrentFilename) | ||
129 | |||
130 | logger.info('Updating torrent URLs %s.', newTorrentPath) | ||
131 | |||
132 | await writeFile(newTorrentPath, bencode.encode(decoded)) | ||
133 | |||
134 | // Remove old torrent file if it existed | ||
135 | if (videoFile.hasTorrent()) { | ||
136 | await remove(join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename)) | ||
137 | } | ||
138 | |||
139 | videoFile.torrentFilename = newTorrentFilename | ||
140 | } | ||
141 | |||
119 | function generateMagnetUri ( | 142 | function generateMagnetUri ( |
120 | video: MVideo, | 143 | video: MVideo, |
121 | videoFile: MVideoFileRedundanciesOpt, | 144 | videoFile: MVideoFileRedundanciesOpt, |
@@ -143,6 +166,7 @@ function generateMagnetUri ( | |||
143 | 166 | ||
144 | export { | 167 | export { |
145 | createTorrentPromise, | 168 | createTorrentPromise, |
169 | updateTorrentUrls, | ||
146 | createTorrentAndSetInfoHash, | 170 | createTorrentAndSetInfoHash, |
147 | generateMagnetUri, | 171 | generateMagnetUri, |
148 | downloadWebTorrentVideo | 172 | downloadWebTorrentVideo |
@@ -186,3 +210,14 @@ function deleteDownloadedFile (downloadedFile: { directoryPath: string, filepath | |||
186 | remove(toRemovePath) | 210 | remove(toRemovePath) |
187 | .catch(err => logger.error('Cannot remove torrent file %s in webtorrent download.', toRemovePath, { err })) | 211 | .catch(err => logger.error('Cannot remove torrent file %s in webtorrent download.', toRemovePath, { err })) |
188 | } | 212 | } |
213 | |||
214 | function buildAnnounceList () { | ||
215 | return [ | ||
216 | [ WEBSERVER.WS + '://' + WEBSERVER.HOSTNAME + ':' + WEBSERVER.PORT + '/tracker/socket' ], | ||
217 | [ WEBSERVER.URL + '/tracker/announce' ] | ||
218 | ] | ||
219 | } | ||
220 | |||
221 | function buildUrlList (video: MVideo, videoFile: MVideoFile) { | ||
222 | return [ videoFile.getFileUrl(video) ] | ||
223 | } | ||
diff --git a/server/lib/job-queue/handlers/move-to-object-storage.ts b/server/lib/job-queue/handlers/move-to-object-storage.ts index a0c58d211..f3b8726eb 100644 --- a/server/lib/job-queue/handlers/move-to-object-storage.ts +++ b/server/lib/job-queue/handlers/move-to-object-storage.ts | |||
@@ -2,7 +2,7 @@ import * as Bull from 'bull' | |||
2 | import { remove } from 'fs-extra' | 2 | import { remove } from 'fs-extra' |
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { logger } from '@server/helpers/logger' | 4 | import { logger } from '@server/helpers/logger' |
5 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | 5 | import { updateTorrentUrls } from '@server/helpers/webtorrent' |
6 | import { CONFIG } from '@server/initializers/config' | 6 | import { CONFIG } from '@server/initializers/config' |
7 | import { storeHLSFile, storeWebTorrentFile } from '@server/lib/object-storage' | 7 | import { storeHLSFile, storeWebTorrentFile } from '@server/lib/object-storage' |
8 | import { getHLSDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths' | 8 | import { getHLSDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths' |
@@ -106,7 +106,7 @@ async function onFileMoved (options: { | |||
106 | file.fileUrl = fileUrl | 106 | file.fileUrl = fileUrl |
107 | file.storage = VideoStorage.OBJECT_STORAGE | 107 | file.storage = VideoStorage.OBJECT_STORAGE |
108 | 108 | ||
109 | await createTorrentAndSetInfoHash(videoOrPlaylist, file) | 109 | await updateTorrentUrls(videoOrPlaylist, file) |
110 | await file.save() | 110 | await file.save() |
111 | 111 | ||
112 | logger.debug('Removing %s because it\'s now on object storage', oldPath) | 112 | logger.debug('Removing %s because it\'s now on object storage', oldPath) |
diff --git a/server/tests/api/object-storage/videos.ts b/server/tests/api/object-storage/videos.ts index 3958bd3d7..6c9c224eb 100644 --- a/server/tests/api/object-storage/videos.ts +++ b/server/tests/api/object-storage/videos.ts | |||
@@ -10,6 +10,7 @@ import { | |||
10 | createMultipleServers, | 10 | createMultipleServers, |
11 | createSingleServer, | 11 | createSingleServer, |
12 | doubleFollow, | 12 | doubleFollow, |
13 | expectLogDoesNotContain, | ||
13 | expectStartWith, | 14 | expectStartWith, |
14 | killallServers, | 15 | killallServers, |
15 | makeRawRequest, | 16 | makeRawRequest, |
@@ -235,6 +236,12 @@ function runTestSuite (options: { | |||
235 | } | 236 | } |
236 | }) | 237 | }) |
237 | 238 | ||
239 | it('Should not have downloaded files from object storage', async function () { | ||
240 | for (const server of servers) { | ||
241 | await expectLogDoesNotContain(server, 'from object storage') | ||
242 | } | ||
243 | }) | ||
244 | |||
238 | after(async function () { | 245 | after(async function () { |
239 | mockObjectStorage.terminate() | 246 | mockObjectStorage.terminate() |
240 | 247 | ||