diff options
Diffstat (limited to 'server/helpers/webtorrent.ts')
-rw-r--r-- | server/helpers/webtorrent.ts | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/server/helpers/webtorrent.ts b/server/helpers/webtorrent.ts index 87c029fcd..f6469ef32 100644 --- a/server/helpers/webtorrent.ts +++ b/server/helpers/webtorrent.ts | |||
@@ -1,41 +1,54 @@ | |||
1 | import { logger } from './logger' | 1 | import { logger } from './logger' |
2 | import { generateVideoTmpPath } from './utils' | ||
2 | import * as WebTorrent from 'webtorrent' | 3 | import * as WebTorrent from 'webtorrent' |
3 | import { remove } from 'fs-extra' | 4 | import { createWriteStream, ensureDir, remove } from 'fs-extra' |
4 | import { CONFIG } from '../initializers' | 5 | import { CONFIG } from '../initializers' |
5 | import { join } from 'path' | 6 | import { join } from 'path' |
6 | 7 | ||
7 | function downloadWebTorrentVideo (target: { magnetUri: string, torrentName?: string }, timeout?: number) { | 8 | async function downloadWebTorrentVideo (target: { magnetUri: string, torrentName?: string }, timeout?: number) { |
8 | const id = target.magnetUri || target.torrentName | 9 | const id = target.magnetUri || target.torrentName |
9 | let timer | 10 | let timer |
10 | 11 | ||
12 | const path = generateVideoTmpPath(id) | ||
11 | logger.info('Importing torrent video %s', id) | 13 | logger.info('Importing torrent video %s', id) |
12 | 14 | ||
15 | const directoryPath = join(CONFIG.STORAGE.VIDEOS_DIR, 'import') | ||
16 | await ensureDir(directoryPath) | ||
17 | |||
13 | return new Promise<string>((res, rej) => { | 18 | return new Promise<string>((res, rej) => { |
14 | const webtorrent = new WebTorrent() | 19 | const webtorrent = new WebTorrent() |
15 | let file: WebTorrent.TorrentFile | 20 | let file: WebTorrent.TorrentFile |
16 | 21 | ||
17 | const torrentId = target.magnetUri || join(CONFIG.STORAGE.TORRENTS_DIR, target.torrentName) | 22 | const torrentId = target.magnetUri || join(CONFIG.STORAGE.TORRENTS_DIR, target.torrentName) |
18 | 23 | ||
19 | const options = { path: CONFIG.STORAGE.VIDEOS_DIR } | 24 | const options = { path: directoryPath } |
20 | const torrent = webtorrent.add(torrentId, options, torrent => { | 25 | const torrent = webtorrent.add(torrentId, options, torrent => { |
21 | if (torrent.files.length !== 1) { | 26 | if (torrent.files.length !== 1) { |
22 | if (timer) clearTimeout(timer) | 27 | if (timer) clearTimeout(timer) |
23 | 28 | ||
24 | return safeWebtorrentDestroy(webtorrent, torrentId, file.name, target.torrentName) | 29 | return safeWebtorrentDestroy(webtorrent, torrentId, join(directoryPath, file.name), target.torrentName) |
25 | .then(() => rej(new Error('Cannot import torrent ' + torrentId + ': there are multiple files in it'))) | 30 | .then(() => rej(new Error('Cannot import torrent ' + torrentId + ': there are multiple files in it'))) |
26 | } | 31 | } |
27 | 32 | ||
28 | torrent.on('done', () => { | 33 | file = torrent.files[ 0 ] |
29 | // FIXME: Dirty fix, we need to wait the FS sync but webtorrent does not provide such method | 34 | |
30 | setTimeout(() => res(join(CONFIG.STORAGE.VIDEOS_DIR, torrent.files[ 0 ].name)), 1000) | 35 | // FIXME: avoid creating another stream when https://github.com/webtorrent/webtorrent/issues/1517 is fixed |
36 | const writeStream = createWriteStream(path) | ||
37 | writeStream.on('finish', () => { | ||
38 | if (timer) clearTimeout(timer) | ||
39 | |||
40 | return safeWebtorrentDestroy(webtorrent, torrentId, join(directoryPath, file.name), target.torrentName) | ||
41 | .then(() => res(path)) | ||
31 | }) | 42 | }) |
43 | |||
44 | file.createReadStream().pipe(writeStream) | ||
32 | }) | 45 | }) |
33 | 46 | ||
34 | torrent.on('error', err => rej(err)) | 47 | torrent.on('error', err => rej(err)) |
35 | 48 | ||
36 | if (timeout) { | 49 | if (timeout) { |
37 | timer = setTimeout(async () => { | 50 | timer = setTimeout(async () => { |
38 | return safeWebtorrentDestroy(webtorrent, torrentId, file ? file.name : undefined, target.torrentName) | 51 | return safeWebtorrentDestroy(webtorrent, torrentId, file ? join(directoryPath, file.name) : undefined, target.torrentName) |
39 | .then(() => rej(new Error('Webtorrent download timeout.'))) | 52 | .then(() => rej(new Error('Webtorrent download timeout.'))) |
40 | }, timeout) | 53 | }, timeout) |
41 | } | 54 | } |
@@ -50,7 +63,7 @@ export { | |||
50 | 63 | ||
51 | // --------------------------------------------------------------------------- | 64 | // --------------------------------------------------------------------------- |
52 | 65 | ||
53 | function safeWebtorrentDestroy (webtorrent: WebTorrent.Instance, torrentId: string, filename?: string, torrentName?: string) { | 66 | function safeWebtorrentDestroy (webtorrent: WebTorrent.Instance, torrentId: string, filepath?: string, torrentName?: string) { |
54 | return new Promise(res => { | 67 | return new Promise(res => { |
55 | webtorrent.destroy(err => { | 68 | webtorrent.destroy(err => { |
56 | // Delete torrent file | 69 | // Delete torrent file |
@@ -60,9 +73,9 @@ function safeWebtorrentDestroy (webtorrent: WebTorrent.Instance, torrentId: stri | |||
60 | } | 73 | } |
61 | 74 | ||
62 | // Delete downloaded file | 75 | // Delete downloaded file |
63 | if (filename) { | 76 | if (filepath) { |
64 | remove(join(CONFIG.STORAGE.VIDEOS_DIR, filename)) | 77 | remove(filepath) |
65 | .catch(err => logger.error('Cannot remove torrent file %s in webtorrent download.', filename, { err })) | 78 | .catch(err => logger.error('Cannot remove torrent file %s in webtorrent download.', filepath, { err })) |
66 | } | 79 | } |
67 | 80 | ||
68 | if (err) { | 81 | if (err) { |