aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'server/helpers')
-rw-r--r--server/helpers/actor.ts13
-rw-r--r--server/helpers/audit-logger.ts8
-rw-r--r--server/helpers/custom-validators/activitypub/videos.ts2
-rw-r--r--server/helpers/custom-validators/video-ownership.ts2
-rw-r--r--server/helpers/custom-validators/videos.ts13
-rw-r--r--server/helpers/utils.ts24
-rw-r--r--server/helpers/video.ts25
-rw-r--r--server/helpers/webfinger.ts5
-rw-r--r--server/helpers/webtorrent.ts2
-rw-r--r--server/helpers/youtube-dl.ts69
10 files changed, 128 insertions, 35 deletions
diff --git a/server/helpers/actor.ts b/server/helpers/actor.ts
new file mode 100644
index 000000000..12a7ace9f
--- /dev/null
+++ b/server/helpers/actor.ts
@@ -0,0 +1,13 @@
1import { ActorModel } from '../models/activitypub/actor'
2
3type ActorFetchByUrlType = 'all' | 'actor-and-association-ids'
4function fetchActorByUrl (url: string, fetchType: ActorFetchByUrlType) {
5 if (fetchType === 'all') return ActorModel.loadByUrlAndPopulateAccountAndChannel(url)
6
7 if (fetchType === 'actor-and-association-ids') return ActorModel.loadByUrl(url)
8}
9
10export {
11 ActorFetchByUrlType,
12 fetchActorByUrl
13}
diff --git a/server/helpers/audit-logger.ts b/server/helpers/audit-logger.ts
index 7db72b69c..00311fce1 100644
--- a/server/helpers/audit-logger.ts
+++ b/server/helpers/audit-logger.ts
@@ -1,4 +1,5 @@
1import * as path from 'path' 1import * as path from 'path'
2import * as express from 'express'
2import { diff } from 'deep-object-diff' 3import { diff } from 'deep-object-diff'
3import { chain } from 'lodash' 4import { chain } from 'lodash'
4import * as flatten from 'flat' 5import * as flatten from 'flat'
@@ -8,6 +9,11 @@ import { jsonLoggerFormat, labelFormatter } from './logger'
8import { VideoDetails, User, VideoChannel, VideoAbuse, VideoImport } from '../../shared' 9import { VideoDetails, User, VideoChannel, VideoAbuse, VideoImport } from '../../shared'
9import { VideoComment } from '../../shared/models/videos/video-comment.model' 10import { VideoComment } from '../../shared/models/videos/video-comment.model'
10import { CustomConfig } from '../../shared/models/server/custom-config.model' 11import { CustomConfig } from '../../shared/models/server/custom-config.model'
12import { UserModel } from '../models/account/user'
13
14function getAuditIdFromRes (res: express.Response) {
15 return (res.locals.oauth.token.User as UserModel).username
16}
11 17
12enum AUDIT_TYPE { 18enum AUDIT_TYPE {
13 CREATE = 'create', 19 CREATE = 'create',
@@ -255,6 +261,8 @@ class CustomConfigAuditView extends EntityAuditView {
255} 261}
256 262
257export { 263export {
264 getAuditIdFromRes,
265
258 auditLoggerFactory, 266 auditLoggerFactory,
259 VideoImportAuditView, 267 VideoImportAuditView,
260 VideoChannelAuditView, 268 VideoChannelAuditView,
diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts
index f76eba474..8772e74cf 100644
--- a/server/helpers/custom-validators/activitypub/videos.ts
+++ b/server/helpers/custom-validators/activitypub/videos.ts
@@ -171,5 +171,3 @@ function setRemoteVideoTruncatedContent (video: any) {
171 171
172 return true 172 return true
173} 173}
174
175
diff --git a/server/helpers/custom-validators/video-ownership.ts b/server/helpers/custom-validators/video-ownership.ts
index aaa0c736b..a7771e07b 100644
--- a/server/helpers/custom-validators/video-ownership.ts
+++ b/server/helpers/custom-validators/video-ownership.ts
@@ -31,7 +31,7 @@ export function checkUserCanTerminateOwnershipChange (
31 videoChangeOwnership: VideoChangeOwnershipModel, 31 videoChangeOwnership: VideoChangeOwnershipModel,
32 res: Response 32 res: Response
33): boolean { 33): boolean {
34 if (videoChangeOwnership.NextOwner.userId === user.Account.userId) { 34 if (videoChangeOwnership.NextOwner.userId === user.id) {
35 return true 35 return true
36 } 36 }
37 37
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts
index edafba6e2..9875c68bd 100644
--- a/server/helpers/custom-validators/videos.ts
+++ b/server/helpers/custom-validators/videos.ts
@@ -18,6 +18,7 @@ import { exists, isArray, isFileValid } from './misc'
18import { VideoChannelModel } from '../../models/video/video-channel' 18import { VideoChannelModel } from '../../models/video/video-channel'
19import { UserModel } from '../../models/account/user' 19import { UserModel } from '../../models/account/user'
20import * as magnetUtil from 'magnet-uri' 20import * as magnetUtil from 'magnet-uri'
21import { fetchVideo, VideoFetchType } from '../video'
21 22
22const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS 23const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
23 24
@@ -152,14 +153,8 @@ function checkUserCanManageVideo (user: UserModel, video: VideoModel, right: Use
152 return true 153 return true
153} 154}
154 155
155async function isVideoExist (id: string, res: Response) { 156async function isVideoExist (id: string, res: Response, fetchType: VideoFetchType = 'all') {
156 let video: VideoModel | null 157 const video = await fetchVideo(id, fetchType)
157
158 if (validator.isInt(id)) {
159 video = await VideoModel.loadAndPopulateAccountAndServerAndTags(+id)
160 } else { // UUID
161 video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(id)
162 }
163 158
164 if (video === null) { 159 if (video === null) {
165 res.status(404) 160 res.status(404)
@@ -169,7 +164,7 @@ async function isVideoExist (id: string, res: Response) {
169 return false 164 return false
170 } 165 }
171 166
172 res.locals.video = video 167 if (fetchType !== 'none') res.locals.video = video
173 return true 168 return true
174} 169}
175 170
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts
index a1ed8e72d..a42474417 100644
--- a/server/helpers/utils.ts
+++ b/server/helpers/utils.ts
@@ -1,12 +1,12 @@
1import { ResultList } from '../../shared' 1import { ResultList } from '../../shared'
2import { CONFIG } from '../initializers' 2import { CONFIG } from '../initializers'
3import { ActorModel } from '../models/activitypub/actor'
4import { ApplicationModel } from '../models/application/application' 3import { ApplicationModel } from '../models/application/application'
5import { pseudoRandomBytesPromise, sha256 } from './core-utils' 4import { pseudoRandomBytesPromise, sha256 } from './core-utils'
6import { logger } from './logger' 5import { logger } from './logger'
7import { join } from 'path' 6import { join } from 'path'
8import { Instance as ParseTorrent } from 'parse-torrent' 7import { Instance as ParseTorrent } from 'parse-torrent'
9import { remove } from 'fs-extra' 8import { remove } from 'fs-extra'
9import * as memoizee from 'memoizee'
10 10
11function deleteFileAsync (path: string) { 11function deleteFileAsync (path: string) {
12 remove(path) 12 remove(path)
@@ -36,24 +36,12 @@ function getFormattedObjects<U, T extends FormattableToJSON> (objects: T[], obje
36 } as ResultList<U> 36 } as ResultList<U>
37} 37}
38 38
39async function getServerActor () { 39const getServerActor = memoizee(async function () {
40 if (getServerActor.serverActor === undefined) { 40 const application = await ApplicationModel.load()
41 const application = await ApplicationModel.load() 41 if (!application) throw Error('Could not load Application from database.')
42 if (!application) throw Error('Could not load Application from database.')
43 42
44 getServerActor.serverActor = application.Account.Actor 43 return application.Account.Actor
45 } 44})
46
47 if (!getServerActor.serverActor) {
48 logger.error('Cannot load server actor.')
49 process.exit(0)
50 }
51
52 return Promise.resolve(getServerActor.serverActor)
53}
54namespace getServerActor {
55 export let serverActor: ActorModel
56}
57 45
58function generateVideoTmpPath (target: string | ParseTorrent) { 46function generateVideoTmpPath (target: string | ParseTorrent) {
59 const id = typeof target === 'string' ? target : target.infoHash 47 const id = typeof target === 'string' ? target : target.infoHash
diff --git a/server/helpers/video.ts b/server/helpers/video.ts
new file mode 100644
index 000000000..b1577a6b0
--- /dev/null
+++ b/server/helpers/video.ts
@@ -0,0 +1,25 @@
1import { VideoModel } from '../models/video/video'
2
3type VideoFetchType = 'all' | 'only-video' | 'id' | 'none'
4
5function fetchVideo (id: number | string, fetchType: VideoFetchType) {
6 if (fetchType === 'all') return VideoModel.loadAndPopulateAccountAndServerAndTags(id)
7
8 if (fetchType === 'only-video') return VideoModel.load(id)
9
10 if (fetchType === 'id' || fetchType === 'none') return VideoModel.loadOnlyId(id)
11}
12
13type VideoFetchByUrlType = 'all' | 'only-video'
14function fetchVideoByUrl (url: string, fetchType: VideoFetchByUrlType) {
15 if (fetchType === 'all') return VideoModel.loadByUrlAndPopulateAccount(url)
16
17 if (fetchType === 'only-video') return VideoModel.loadByUrl(url)
18}
19
20export {
21 VideoFetchType,
22 VideoFetchByUrlType,
23 fetchVideo,
24 fetchVideoByUrl
25}
diff --git a/server/helpers/webfinger.ts b/server/helpers/webfinger.ts
index 10fcec462..156376943 100644
--- a/server/helpers/webfinger.ts
+++ b/server/helpers/webfinger.ts
@@ -12,7 +12,10 @@ const webfinger = new WebFinger({
12 request_timeout: 3000 12 request_timeout: 3000
13}) 13})
14 14
15async function loadActorUrlOrGetFromWebfinger (uri: string) { 15async function loadActorUrlOrGetFromWebfinger (uriArg: string) {
16 // Handle strings like @toto@example.com
17 const uri = uriArg.startsWith('@') ? uriArg.slice(1) : uriArg
18
16 const [ name, host ] = uri.split('@') 19 const [ name, host ] = uri.split('@')
17 let actor: ActorModel 20 let actor: ActorModel
18 21
diff --git a/server/helpers/webtorrent.ts b/server/helpers/webtorrent.ts
index 2fdfd1876..f4b44bc4f 100644
--- a/server/helpers/webtorrent.ts
+++ b/server/helpers/webtorrent.ts
@@ -24,7 +24,7 @@ function downloadWebTorrentVideo (target: { magnetUri: string, torrentName?: str
24 if (timer) clearTimeout(timer) 24 if (timer) clearTimeout(timer)
25 25
26 return safeWebtorrentDestroy(webtorrent, torrentId, file.name, target.torrentName) 26 return safeWebtorrentDestroy(webtorrent, torrentId, file.name, target.torrentName)
27 .then(() => rej(new Error('The number of files is not equal to 1 for ' + torrentId))) 27 .then(() => rej(new Error('Cannot import torrent ' + torrentId + ': there are multiple files in it')))
28 } 28 }
29 29
30 file = torrent.files[ 0 ] 30 file = torrent.files[ 0 ]
diff --git a/server/helpers/youtube-dl.ts b/server/helpers/youtube-dl.ts
index 8b2bc1782..25e719cc3 100644
--- a/server/helpers/youtube-dl.ts
+++ b/server/helpers/youtube-dl.ts
@@ -2,7 +2,11 @@ import { truncate } from 'lodash'
2import { CONSTRAINTS_FIELDS, VIDEO_CATEGORIES } from '../initializers' 2import { CONSTRAINTS_FIELDS, VIDEO_CATEGORIES } from '../initializers'
3import { logger } from './logger' 3import { logger } from './logger'
4import { generateVideoTmpPath } from './utils' 4import { generateVideoTmpPath } from './utils'
5import { YoutubeDlUpdateScheduler } from '../lib/schedulers/youtube-dl-update-scheduler' 5import { join } from 'path'
6import { root } from './core-utils'
7import { ensureDir, writeFile } from 'fs-extra'
8import * as request from 'request'
9import { createWriteStream } from 'fs'
6 10
7export type YoutubeDLInfo = { 11export type YoutubeDLInfo = {
8 name?: string 12 name?: string
@@ -40,7 +44,7 @@ function downloadYoutubeDLVideo (url: string) {
40 44
41 return new Promise<string>(async (res, rej) => { 45 return new Promise<string>(async (res, rej) => {
42 const youtubeDL = await safeGetYoutubeDL() 46 const youtubeDL = await safeGetYoutubeDL()
43 youtubeDL.exec(url, options, async (err, output) => { 47 youtubeDL.exec(url, options, err => {
44 if (err) return rej(err) 48 if (err) return rej(err)
45 49
46 return res(path) 50 return res(path)
@@ -48,6 +52,64 @@ function downloadYoutubeDLVideo (url: string) {
48 }) 52 })
49} 53}
50 54
55// Thanks: https://github.com/przemyslawpluta/node-youtube-dl/blob/master/lib/downloader.js
56// We rewrote it to avoid sync calls
57async function updateYoutubeDLBinary () {
58 logger.info('Updating youtubeDL binary.')
59
60 const binDirectory = join(root(), 'node_modules', 'youtube-dl', 'bin')
61 const bin = join(binDirectory, 'youtube-dl')
62 const detailsPath = join(binDirectory, 'details')
63 const url = 'https://yt-dl.org/downloads/latest/youtube-dl'
64
65 await ensureDir(binDirectory)
66
67 return new Promise(res => {
68 request.get(url, { followRedirect: false }, (err, result) => {
69 if (err) {
70 logger.error('Cannot update youtube-dl.', { err })
71 return res()
72 }
73
74 if (result.statusCode !== 302) {
75 logger.error('youtube-dl update error: did not get redirect for the latest version link. Status %d', result.statusCode)
76 return res()
77 }
78
79 const url = result.headers.location
80 const downloadFile = request.get(url)
81 const newVersion = /yt-dl\.org\/downloads\/(\d{4}\.\d\d\.\d\d(\.\d)?)\/youtube-dl/.exec(url)[ 1 ]
82
83 downloadFile.on('response', result => {
84 if (result.statusCode !== 200) {
85 logger.error('Cannot update youtube-dl: new version response is not 200, it\'s %d.', result.statusCode)
86 return res()
87 }
88
89 downloadFile.pipe(createWriteStream(bin, { mode: 493 }))
90 })
91
92 downloadFile.on('error', err => {
93 logger.error('youtube-dl update error.', { err })
94 return res()
95 })
96
97 downloadFile.on('end', () => {
98 const details = JSON.stringify({ version: newVersion, path: bin, exec: 'youtube-dl' })
99 writeFile(detailsPath, details, { encoding: 'utf8' }, err => {
100 if (err) {
101 logger.error('youtube-dl update error: cannot write details.', { err })
102 return res()
103 }
104
105 logger.info('youtube-dl updated to version %s.', newVersion)
106 return res()
107 })
108 })
109 })
110 })
111}
112
51async function safeGetYoutubeDL () { 113async function safeGetYoutubeDL () {
52 let youtubeDL 114 let youtubeDL
53 115
@@ -55,7 +117,7 @@ async function safeGetYoutubeDL () {
55 youtubeDL = require('youtube-dl') 117 youtubeDL = require('youtube-dl')
56 } catch (e) { 118 } catch (e) {
57 // Download binary 119 // Download binary
58 await YoutubeDlUpdateScheduler.Instance.execute() 120 await updateYoutubeDLBinary()
59 youtubeDL = require('youtube-dl') 121 youtubeDL = require('youtube-dl')
60 } 122 }
61 123
@@ -65,6 +127,7 @@ async function safeGetYoutubeDL () {
65// --------------------------------------------------------------------------- 127// ---------------------------------------------------------------------------
66 128
67export { 129export {
130 updateYoutubeDLBinary,
68 downloadYoutubeDLVideo, 131 downloadYoutubeDLVideo,
69 getYoutubeDLInfo, 132 getYoutubeDLInfo,
70 safeGetYoutubeDL 133 safeGetYoutubeDL