diff options
Diffstat (limited to 'server/lib')
37 files changed, 278 insertions, 271 deletions
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index f802658cf..3f6edc070 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import { Transaction } from 'sequelize' | 2 | import { Transaction } from 'sequelize' |
3 | import * as url from 'url' | 3 | import { URL } from 'url' |
4 | import * as uuidv4 from 'uuid/v4' | 4 | import * as uuidv4 from 'uuid/v4' |
5 | import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' | 5 | import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' |
6 | import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' | 6 | import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' |
@@ -33,8 +33,7 @@ import { | |||
33 | MActorFull, | 33 | MActorFull, |
34 | MActorFullActor, | 34 | MActorFullActor, |
35 | MActorId, | 35 | MActorId, |
36 | MChannel, | 36 | MChannel |
37 | MChannelAccountDefault | ||
38 | } from '../../typings/models' | 37 | } from '../../typings/models' |
39 | 38 | ||
40 | // Set account keys, this could be long so process after the account creation and do not block the client | 39 | // Set account keys, this could be long so process after the account creation and do not block the client |
@@ -121,13 +120,13 @@ async function getOrCreateActorAndServerAndModel ( | |||
121 | 120 | ||
122 | if ((created === true || refreshed === true) && updateCollections === true) { | 121 | if ((created === true || refreshed === true) && updateCollections === true) { |
123 | const payload = { uri: actor.outboxUrl, type: 'activity' as 'activity' } | 122 | const payload = { uri: actor.outboxUrl, type: 'activity' as 'activity' } |
124 | await JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload }) | 123 | await JobQueue.Instance.createJobWithPromise({ type: 'activitypub-http-fetcher', payload }) |
125 | } | 124 | } |
126 | 125 | ||
127 | // We created a new account: fetch the playlists | 126 | // We created a new account: fetch the playlists |
128 | if (created === true && actor.Account && accountPlaylistsUrl) { | 127 | if (created === true && actor.Account && accountPlaylistsUrl) { |
129 | const payload = { uri: accountPlaylistsUrl, accountId: actor.Account.id, type: 'account-playlists' as 'account-playlists' } | 128 | const payload = { uri: accountPlaylistsUrl, accountId: actor.Account.id, type: 'account-playlists' as 'account-playlists' } |
130 | await JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload }) | 129 | await JobQueue.Instance.createJobWithPromise({ type: 'activitypub-http-fetcher', payload }) |
131 | } | 130 | } |
132 | 131 | ||
133 | return actorRefreshed | 132 | return actorRefreshed |
@@ -215,7 +214,7 @@ async function fetchActorTotalItems (url: string) { | |||
215 | } | 214 | } |
216 | } | 215 | } |
217 | 216 | ||
218 | async function getAvatarInfoIfExists (actorJSON: ActivityPubActor) { | 217 | function getAvatarInfoIfExists (actorJSON: ActivityPubActor) { |
219 | if ( | 218 | if ( |
220 | actorJSON.icon && actorJSON.icon.type === 'Image' && MIMETYPES.IMAGE.MIMETYPE_EXT[actorJSON.icon.mediaType] !== undefined && | 219 | actorJSON.icon && actorJSON.icon.type === 'Image' && MIMETYPES.IMAGE.MIMETYPE_EXT[actorJSON.icon.mediaType] !== undefined && |
221 | isActivityPubUrlValid(actorJSON.icon.url) | 220 | isActivityPubUrlValid(actorJSON.icon.url) |
@@ -271,7 +270,10 @@ async function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannel | |||
271 | 270 | ||
272 | if (statusCode === 404) { | 271 | if (statusCode === 404) { |
273 | logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url) | 272 | logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url) |
274 | actor.Account ? actor.Account.destroy() : actor.VideoChannel.destroy() | 273 | actor.Account |
274 | ? await actor.Account.destroy() | ||
275 | : await actor.VideoChannel.destroy() | ||
276 | |||
275 | return { actor: undefined, refreshed: false } | 277 | return { actor: undefined, refreshed: false } |
276 | } | 278 | } |
277 | 279 | ||
@@ -337,14 +339,14 @@ function saveActorAndServerAndModelIfNotExist ( | |||
337 | ownerActor?: MActorFullActor, | 339 | ownerActor?: MActorFullActor, |
338 | t?: Transaction | 340 | t?: Transaction |
339 | ): Bluebird<MActorFullActor> | Promise<MActorFullActor> { | 341 | ): Bluebird<MActorFullActor> | Promise<MActorFullActor> { |
340 | let actor = result.actor | 342 | const actor = result.actor |
341 | 343 | ||
342 | if (t !== undefined) return save(t) | 344 | if (t !== undefined) return save(t) |
343 | 345 | ||
344 | return sequelizeTypescript.transaction(t => save(t)) | 346 | return sequelizeTypescript.transaction(t => save(t)) |
345 | 347 | ||
346 | async function save (t: Transaction) { | 348 | async function save (t: Transaction) { |
347 | const actorHost = url.parse(actor.url).host | 349 | const actorHost = new URL(actor.url).host |
348 | 350 | ||
349 | const serverOptions = { | 351 | const serverOptions = { |
350 | where: { | 352 | where: { |
@@ -402,7 +404,7 @@ type FetchRemoteActorResult = { | |||
402 | support?: string | 404 | support?: string |
403 | playlists?: string | 405 | playlists?: string |
404 | avatar?: { | 406 | avatar?: { |
405 | name: string, | 407 | name: string |
406 | fileUrl: string | 408 | fileUrl: string |
407 | } | 409 | } |
408 | attributedTo: ActivityPubAttributedTo[] | 410 | attributedTo: ActivityPubAttributedTo[] |
diff --git a/server/lib/activitypub/crawl.ts b/server/lib/activitypub/crawl.ts index 9e469e3e6..eeafdf4ba 100644 --- a/server/lib/activitypub/crawl.ts +++ b/server/lib/activitypub/crawl.ts | |||
@@ -3,7 +3,7 @@ import { doRequest } from '../../helpers/requests' | |||
3 | import { logger } from '../../helpers/logger' | 3 | import { logger } from '../../helpers/logger' |
4 | import * as Bluebird from 'bluebird' | 4 | import * as Bluebird from 'bluebird' |
5 | import { ActivityPubOrderedCollection } from '../../../shared/models/activitypub' | 5 | import { ActivityPubOrderedCollection } from '../../../shared/models/activitypub' |
6 | import { parse } from 'url' | 6 | import { URL } from 'url' |
7 | 7 | ||
8 | type HandlerFunction<T> = (items: T[]) => (Promise<any> | Bluebird<any>) | 8 | type HandlerFunction<T> = (items: T[]) => (Promise<any> | Bluebird<any>) |
9 | type CleanerFunction = (startedDate: Date) => (Promise<any> | Bluebird<any>) | 9 | type CleanerFunction = (startedDate: Date) => (Promise<any> | Bluebird<any>) |
@@ -24,7 +24,7 @@ async function crawlCollectionPage <T> (uri: string, handler: HandlerFunction<T> | |||
24 | const response = await doRequest<ActivityPubOrderedCollection<T>>(options) | 24 | const response = await doRequest<ActivityPubOrderedCollection<T>>(options) |
25 | const firstBody = response.body | 25 | const firstBody = response.body |
26 | 26 | ||
27 | let limit = ACTIVITY_PUB.FETCH_PAGE_LIMIT | 27 | const limit = ACTIVITY_PUB.FETCH_PAGE_LIMIT |
28 | let i = 0 | 28 | let i = 0 |
29 | let nextLink = firstBody.first | 29 | let nextLink = firstBody.first |
30 | while (nextLink && i < limit) { | 30 | while (nextLink && i < limit) { |
@@ -32,7 +32,7 @@ async function crawlCollectionPage <T> (uri: string, handler: HandlerFunction<T> | |||
32 | 32 | ||
33 | if (typeof nextLink === 'string') { | 33 | if (typeof nextLink === 'string') { |
34 | // Don't crawl ourselves | 34 | // Don't crawl ourselves |
35 | const remoteHost = parse(nextLink).host | 35 | const remoteHost = new URL(nextLink).host |
36 | if (remoteHost === WEBSERVER.HOST) continue | 36 | if (remoteHost === WEBSERVER.HOST) continue |
37 | 37 | ||
38 | options.uri = nextLink | 38 | options.uri = nextLink |
diff --git a/server/lib/activitypub/follow.ts b/server/lib/activitypub/follow.ts index 1abf43cd4..a1c95504e 100644 --- a/server/lib/activitypub/follow.ts +++ b/server/lib/activitypub/follow.ts | |||
@@ -27,7 +27,6 @@ async function autoFollowBackIfNeeded (actorFollow: MActorFollowActors) { | |||
27 | } | 27 | } |
28 | 28 | ||
29 | JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) | 29 | JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) |
30 | .catch(err => logger.error('Cannot create auto follow back job for %s.', host, err)) | ||
31 | } | 30 | } |
32 | } | 31 | } |
33 | 32 | ||
diff --git a/server/lib/activitypub/send/send-accept.ts b/server/lib/activitypub/send/send-accept.ts index 9f0225b64..c4c6b849b 100644 --- a/server/lib/activitypub/send/send-accept.ts +++ b/server/lib/activitypub/send/send-accept.ts | |||
@@ -5,7 +5,7 @@ import { buildFollowActivity } from './send-follow' | |||
5 | import { logger } from '../../../helpers/logger' | 5 | import { logger } from '../../../helpers/logger' |
6 | import { MActor, MActorFollowActors } from '../../../typings/models' | 6 | import { MActor, MActorFollowActors } from '../../../typings/models' |
7 | 7 | ||
8 | async function sendAccept (actorFollow: MActorFollowActors) { | 8 | function sendAccept (actorFollow: MActorFollowActors) { |
9 | const follower = actorFollow.ActorFollower | 9 | const follower = actorFollow.ActorFollower |
10 | const me = actorFollow.ActorFollowing | 10 | const me = actorFollow.ActorFollowing |
11 | 11 | ||
diff --git a/server/lib/activitypub/send/send-create.ts b/server/lib/activitypub/send/send-create.ts index 1709d8348..3585d704a 100644 --- a/server/lib/activitypub/send/send-create.ts +++ b/server/lib/activitypub/send/send-create.ts | |||
@@ -130,10 +130,10 @@ export { | |||
130 | // --------------------------------------------------------------------------- | 130 | // --------------------------------------------------------------------------- |
131 | 131 | ||
132 | async function sendVideoRelatedCreateActivity (options: { | 132 | async function sendVideoRelatedCreateActivity (options: { |
133 | byActor: MActorLight, | 133 | byActor: MActorLight |
134 | video: MVideoAccountLight, | 134 | video: MVideoAccountLight |
135 | url: string, | 135 | url: string |
136 | object: any, | 136 | object: any |
137 | transaction?: Transaction | 137 | transaction?: Transaction |
138 | }) { | 138 | }) { |
139 | const activityBuilder = (audience: ActivityAudience) => { | 139 | const activityBuilder = (audience: ActivityAudience) => { |
diff --git a/server/lib/activitypub/send/send-dislike.ts b/server/lib/activitypub/send/send-dislike.ts index 6e41f241f..600469c71 100644 --- a/server/lib/activitypub/send/send-dislike.ts +++ b/server/lib/activitypub/send/send-dislike.ts | |||
@@ -6,7 +6,7 @@ import { sendVideoRelatedActivity } from './utils' | |||
6 | import { audiencify, getAudience } from '../audience' | 6 | import { audiencify, getAudience } from '../audience' |
7 | import { MActor, MActorAudience, MVideoAccountLight, MVideoUrl } from '../../../typings/models' | 7 | import { MActor, MActorAudience, MVideoAccountLight, MVideoUrl } from '../../../typings/models' |
8 | 8 | ||
9 | async function sendDislike (byActor: MActor, video: MVideoAccountLight, t: Transaction) { | 9 | function sendDislike (byActor: MActor, video: MVideoAccountLight, t: Transaction) { |
10 | logger.info('Creating job to dislike %s.', video.url) | 10 | logger.info('Creating job to dislike %s.', video.url) |
11 | 11 | ||
12 | const activityBuilder = (audience: ActivityAudience) => { | 12 | const activityBuilder = (audience: ActivityAudience) => { |
diff --git a/server/lib/activitypub/send/send-flag.ts b/server/lib/activitypub/send/send-flag.ts index da7638a7b..e4e523631 100644 --- a/server/lib/activitypub/send/send-flag.ts +++ b/server/lib/activitypub/send/send-flag.ts | |||
@@ -7,7 +7,7 @@ import { Transaction } from 'sequelize' | |||
7 | import { MActor, MVideoFullLight } from '../../../typings/models' | 7 | import { MActor, MVideoFullLight } from '../../../typings/models' |
8 | import { MVideoAbuseVideo } from '../../../typings/models/video' | 8 | import { MVideoAbuseVideo } from '../../../typings/models/video' |
9 | 9 | ||
10 | async function sendVideoAbuse (byActor: MActor, videoAbuse: MVideoAbuseVideo, video: MVideoFullLight, t: Transaction) { | 10 | function sendVideoAbuse (byActor: MActor, videoAbuse: MVideoAbuseVideo, video: MVideoFullLight, t: Transaction) { |
11 | if (!video.VideoChannel.Account.Actor.serverId) return // Local user | 11 | if (!video.VideoChannel.Account.Actor.serverId) return // Local user |
12 | 12 | ||
13 | const url = getVideoAbuseActivityPubUrl(videoAbuse) | 13 | const url = getVideoAbuseActivityPubUrl(videoAbuse) |
diff --git a/server/lib/activitypub/send/send-like.ts b/server/lib/activitypub/send/send-like.ts index e84a6f98b..5db252325 100644 --- a/server/lib/activitypub/send/send-like.ts +++ b/server/lib/activitypub/send/send-like.ts | |||
@@ -6,7 +6,7 @@ import { audiencify, getAudience } from '../audience' | |||
6 | import { logger } from '../../../helpers/logger' | 6 | import { logger } from '../../../helpers/logger' |
7 | import { MActor, MActorAudience, MVideoAccountLight, MVideoUrl } from '../../../typings/models' | 7 | import { MActor, MActorAudience, MVideoAccountLight, MVideoUrl } from '../../../typings/models' |
8 | 8 | ||
9 | async function sendLike (byActor: MActor, video: MVideoAccountLight, t: Transaction) { | 9 | function sendLike (byActor: MActor, video: MVideoAccountLight, t: Transaction) { |
10 | logger.info('Creating job to like %s.', video.url) | 10 | logger.info('Creating job to like %s.', video.url) |
11 | 11 | ||
12 | const activityBuilder = (audience: ActivityAudience) => { | 12 | const activityBuilder = (audience: ActivityAudience) => { |
diff --git a/server/lib/activitypub/send/send-reject.ts b/server/lib/activitypub/send/send-reject.ts index 4258a3c36..643c468a9 100644 --- a/server/lib/activitypub/send/send-reject.ts +++ b/server/lib/activitypub/send/send-reject.ts | |||
@@ -5,7 +5,7 @@ import { buildFollowActivity } from './send-follow' | |||
5 | import { logger } from '../../../helpers/logger' | 5 | import { logger } from '../../../helpers/logger' |
6 | import { MActor } from '../../../typings/models' | 6 | import { MActor } from '../../../typings/models' |
7 | 7 | ||
8 | async function sendReject (follower: MActor, following: MActor) { | 8 | function sendReject (follower: MActor, following: MActor) { |
9 | if (!follower.serverId) { // This should never happen | 9 | if (!follower.serverId) { // This should never happen |
10 | logger.warn('Do not sending reject to local follower.') | 10 | logger.warn('Do not sending reject to local follower.') |
11 | return | 11 | return |
diff --git a/server/lib/activitypub/send/send-undo.ts b/server/lib/activitypub/send/send-undo.ts index e9ab5b3c5..33f1d4921 100644 --- a/server/lib/activitypub/send/send-undo.ts +++ b/server/lib/activitypub/send/send-undo.ts | |||
@@ -28,7 +28,7 @@ import { | |||
28 | MVideoShare | 28 | MVideoShare |
29 | } from '../../../typings/models' | 29 | } from '../../../typings/models' |
30 | 30 | ||
31 | async function sendUndoFollow (actorFollow: MActorFollowActors, t: Transaction) { | 31 | function sendUndoFollow (actorFollow: MActorFollowActors, t: Transaction) { |
32 | const me = actorFollow.ActorFollower | 32 | const me = actorFollow.ActorFollower |
33 | const following = actorFollow.ActorFollowing | 33 | const following = actorFollow.ActorFollowing |
34 | 34 | ||
@@ -118,10 +118,10 @@ function undoActivityData ( | |||
118 | } | 118 | } |
119 | 119 | ||
120 | async function sendUndoVideoRelatedActivity (options: { | 120 | async function sendUndoVideoRelatedActivity (options: { |
121 | byActor: MActor, | 121 | byActor: MActor |
122 | video: MVideoAccountLight, | 122 | video: MVideoAccountLight |
123 | url: string, | 123 | url: string |
124 | activity: ActivityFollow | ActivityLike | ActivityDislike | ActivityCreate | ActivityAnnounce, | 124 | activity: ActivityFollow | ActivityLike | ActivityDislike | ActivityCreate | ActivityAnnounce |
125 | transaction: Transaction | 125 | transaction: Transaction |
126 | }) { | 126 | }) { |
127 | const activityBuilder = (audience: ActivityAudience) => { | 127 | const activityBuilder = (audience: ActivityAudience) => { |
diff --git a/server/lib/activitypub/send/send-update.ts b/server/lib/activitypub/send/send-update.ts index 9c76671b5..cb500bd34 100644 --- a/server/lib/activitypub/send/send-update.ts +++ b/server/lib/activitypub/send/send-update.ts | |||
@@ -8,7 +8,6 @@ import { getUpdateActivityPubUrl } from '../url' | |||
8 | import { broadcastToFollowers, sendVideoRelatedActivity } from './utils' | 8 | import { broadcastToFollowers, sendVideoRelatedActivity } from './utils' |
9 | import { audiencify, getActorsInvolvedInVideo, getAudience } from '../audience' | 9 | import { audiencify, getActorsInvolvedInVideo, getAudience } from '../audience' |
10 | import { logger } from '../../../helpers/logger' | 10 | import { logger } from '../../../helpers/logger' |
11 | import { VideoCaptionModel } from '../../../models/video/video-caption' | ||
12 | import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model' | 11 | import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model' |
13 | import { getServerActor } from '../../../helpers/utils' | 12 | import { getServerActor } from '../../../helpers/utils' |
14 | import { | 13 | import { |
@@ -29,7 +28,7 @@ async function sendUpdateVideo (videoArg: MVideoAPWithoutCaption, t: Transaction | |||
29 | 28 | ||
30 | logger.info('Creating job to update video %s.', video.url) | 29 | logger.info('Creating job to update video %s.', video.url) |
31 | 30 | ||
32 | const byActor = overrodeByActor ? overrodeByActor : video.VideoChannel.Account.Actor | 31 | const byActor = overrodeByActor || video.VideoChannel.Account.Actor |
33 | 32 | ||
34 | const url = getUpdateActivityPubUrl(video.url, video.updatedAt.toISOString()) | 33 | const url = getUpdateActivityPubUrl(video.url, video.updatedAt.toISOString()) |
35 | 34 | ||
diff --git a/server/lib/activitypub/send/utils.ts b/server/lib/activitypub/send/utils.ts index 77b723479..6fb4efd60 100644 --- a/server/lib/activitypub/send/utils.ts +++ b/server/lib/activitypub/send/utils.ts | |||
@@ -10,8 +10,8 @@ import { afterCommitIfTransaction } from '../../../helpers/database-utils' | |||
10 | import { MActorWithInboxes, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models' | 10 | import { MActorWithInboxes, MActor, MActorId, MActorLight, MVideo, MVideoAccountLight } from '../../../typings/models' |
11 | 11 | ||
12 | async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { | 12 | async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { |
13 | byActor: MActorLight, | 13 | byActor: MActorLight |
14 | video: MVideoAccountLight, | 14 | video: MVideoAccountLight |
15 | transaction?: Transaction | 15 | transaction?: Transaction |
16 | }) { | 16 | }) { |
17 | const { byActor, video, transaction } = options | 17 | const { byActor, video, transaction } = options |
diff --git a/server/lib/activitypub/video-comments.ts b/server/lib/activitypub/video-comments.ts index d5c078a29..8642d2432 100644 --- a/server/lib/activitypub/video-comments.ts +++ b/server/lib/activitypub/video-comments.ts | |||
@@ -10,9 +10,9 @@ import { checkUrlsSameHost } from '../../helpers/activitypub' | |||
10 | import { MCommentOwner, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../typings/models/video' | 10 | import { MCommentOwner, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../typings/models/video' |
11 | 11 | ||
12 | type ResolveThreadParams = { | 12 | type ResolveThreadParams = { |
13 | url: string, | 13 | url: string |
14 | comments?: MCommentOwner[], | 14 | comments?: MCommentOwner[] |
15 | isVideo?: boolean, | 15 | isVideo?: boolean |
16 | commentCreated?: boolean | 16 | commentCreated?: boolean |
17 | } | 17 | } |
18 | type ResolveThreadResult = Promise<{ video: MVideoAccountLightBlacklistAllFiles, comment: MCommentOwnerVideo, commentCreated: boolean }> | 18 | type ResolveThreadResult = Promise<{ video: MVideoAccountLightBlacklistAllFiles, comment: MCommentOwnerVideo, commentCreated: boolean }> |
@@ -28,7 +28,7 @@ async function resolveThread (params: ResolveThreadParams): ResolveThreadResult | |||
28 | if (params.commentCreated === undefined) params.commentCreated = false | 28 | if (params.commentCreated === undefined) params.commentCreated = false |
29 | if (params.comments === undefined) params.comments = [] | 29 | if (params.comments === undefined) params.comments = [] |
30 | 30 | ||
31 | // Already have this comment? | 31 | // Already have this comment? |
32 | if (isVideo !== true) { | 32 | if (isVideo !== true) { |
33 | const result = await resolveCommentFromDB(params) | 33 | const result = await resolveCommentFromDB(params) |
34 | if (result) return result | 34 | if (result) return result |
@@ -87,7 +87,7 @@ async function tryResolveThreadFromVideo (params: ResolveThreadParams) { | |||
87 | 87 | ||
88 | let resultComment: MCommentOwnerVideo | 88 | let resultComment: MCommentOwnerVideo |
89 | if (comments.length !== 0) { | 89 | if (comments.length !== 0) { |
90 | const firstReply = comments[ comments.length - 1 ] as MCommentOwnerVideo | 90 | const firstReply = comments[comments.length - 1] as MCommentOwnerVideo |
91 | firstReply.inReplyToCommentId = null | 91 | firstReply.inReplyToCommentId = null |
92 | firstReply.originCommentId = null | 92 | firstReply.originCommentId = null |
93 | firstReply.videoId = video.id | 93 | firstReply.videoId = video.id |
@@ -97,9 +97,9 @@ async function tryResolveThreadFromVideo (params: ResolveThreadParams) { | |||
97 | comments[comments.length - 1] = await firstReply.save() | 97 | comments[comments.length - 1] = await firstReply.save() |
98 | 98 | ||
99 | for (let i = comments.length - 2; i >= 0; i--) { | 99 | for (let i = comments.length - 2; i >= 0; i--) { |
100 | const comment = comments[ i ] as MCommentOwnerVideo | 100 | const comment = comments[i] as MCommentOwnerVideo |
101 | comment.originCommentId = firstReply.id | 101 | comment.originCommentId = firstReply.id |
102 | comment.inReplyToCommentId = comments[ i + 1 ].id | 102 | comment.inReplyToCommentId = comments[i + 1].id |
103 | comment.videoId = video.id | 103 | comment.videoId = video.id |
104 | comment.changed('updatedAt', true) | 104 | comment.changed('updatedAt', true) |
105 | comment.Video = video | 105 | comment.Video = video |
diff --git a/server/lib/activitypub/video-rates.ts b/server/lib/activitypub/video-rates.ts index 6bd46bb58..79ccfbc7e 100644 --- a/server/lib/activitypub/video-rates.ts +++ b/server/lib/activitypub/video-rates.ts | |||
@@ -58,8 +58,6 @@ async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateTy | |||
58 | const field = rate === 'like' ? 'likes' : 'dislikes' | 58 | const field = rate === 'like' ? 'likes' : 'dislikes' |
59 | await video.increment(field, { by: rateCounts }) | 59 | await video.increment(field, { by: rateCounts }) |
60 | } | 60 | } |
61 | |||
62 | return | ||
63 | } | 61 | } |
64 | 62 | ||
65 | async function sendVideoRateChange ( | 63 | async function sendVideoRateChange ( |
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index 6bc2258cc..9e43caa20 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -197,25 +197,25 @@ async function syncVideoExternalAttributes (video: MVideo, fetchedVideo: VideoTo | |||
197 | jobPayloads.push({ uri: fetchedVideo.comments, videoId: video.id, type: 'video-comments' as 'video-comments' }) | 197 | jobPayloads.push({ uri: fetchedVideo.comments, videoId: video.id, type: 'video-comments' as 'video-comments' }) |
198 | } | 198 | } |
199 | 199 | ||
200 | await Bluebird.map(jobPayloads, payload => JobQueue.Instance.createJob({ type: 'activitypub-http-fetcher', payload })) | 200 | await Bluebird.map(jobPayloads, payload => JobQueue.Instance.createJobWithPromise({ type: 'activitypub-http-fetcher', payload })) |
201 | } | 201 | } |
202 | 202 | ||
203 | function getOrCreateVideoAndAccountAndChannel (options: { | 203 | function getOrCreateVideoAndAccountAndChannel (options: { |
204 | videoObject: { id: string } | string, | 204 | videoObject: { id: string } | string |
205 | syncParam?: SyncParam, | 205 | syncParam?: SyncParam |
206 | fetchType?: 'all', | 206 | fetchType?: 'all' |
207 | allowRefresh?: boolean | 207 | allowRefresh?: boolean |
208 | }): Promise<{ video: MVideoAccountLightBlacklistAllFiles, created: boolean, autoBlacklisted?: boolean }> | 208 | }): Promise<{ video: MVideoAccountLightBlacklistAllFiles, created: boolean, autoBlacklisted?: boolean }> |
209 | function getOrCreateVideoAndAccountAndChannel (options: { | 209 | function getOrCreateVideoAndAccountAndChannel (options: { |
210 | videoObject: { id: string } | string, | 210 | videoObject: { id: string } | string |
211 | syncParam?: SyncParam, | 211 | syncParam?: SyncParam |
212 | fetchType?: VideoFetchByUrlType, | 212 | fetchType?: VideoFetchByUrlType |
213 | allowRefresh?: boolean | 213 | allowRefresh?: boolean |
214 | }): Promise<{ video: MVideoAccountLightBlacklistAllFiles | MVideoThumbnail, created: boolean, autoBlacklisted?: boolean }> | 214 | }): Promise<{ video: MVideoAccountLightBlacklistAllFiles | MVideoThumbnail, created: boolean, autoBlacklisted?: boolean }> |
215 | async function getOrCreateVideoAndAccountAndChannel (options: { | 215 | async function getOrCreateVideoAndAccountAndChannel (options: { |
216 | videoObject: { id: string } | string, | 216 | videoObject: { id: string } | string |
217 | syncParam?: SyncParam, | 217 | syncParam?: SyncParam |
218 | fetchType?: VideoFetchByUrlType, | 218 | fetchType?: VideoFetchByUrlType |
219 | allowRefresh?: boolean // true by default | 219 | allowRefresh?: boolean // true by default |
220 | }): Promise<{ video: MVideoAccountLightBlacklistAllFiles | MVideoThumbnail, created: boolean, autoBlacklisted?: boolean }> { | 220 | }): Promise<{ video: MVideoAccountLightBlacklistAllFiles | MVideoThumbnail, created: boolean, autoBlacklisted?: boolean }> { |
221 | // Default params | 221 | // Default params |
@@ -235,8 +235,14 @@ async function getOrCreateVideoAndAccountAndChannel (options: { | |||
235 | syncParam | 235 | syncParam |
236 | } | 236 | } |
237 | 237 | ||
238 | if (syncParam.refreshVideo === true) videoFromDatabase = await refreshVideoIfNeeded(refreshOptions) | 238 | if (syncParam.refreshVideo === true) { |
239 | else await JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', url: videoFromDatabase.url } }) | 239 | videoFromDatabase = await refreshVideoIfNeeded(refreshOptions) |
240 | } else { | ||
241 | await JobQueue.Instance.createJobWithPromise({ | ||
242 | type: 'activitypub-refresher', | ||
243 | payload: { type: 'video', url: videoFromDatabase.url } | ||
244 | }) | ||
245 | } | ||
240 | } | 246 | } |
241 | 247 | ||
242 | return { video: videoFromDatabase, created: false } | 248 | return { video: videoFromDatabase, created: false } |
@@ -255,10 +261,10 @@ async function getOrCreateVideoAndAccountAndChannel (options: { | |||
255 | } | 261 | } |
256 | 262 | ||
257 | async function updateVideoFromAP (options: { | 263 | async function updateVideoFromAP (options: { |
258 | video: MVideoAccountLightBlacklistAllFiles, | 264 | video: MVideoAccountLightBlacklistAllFiles |
259 | videoObject: VideoTorrentObject, | 265 | videoObject: VideoTorrentObject |
260 | account: MAccountIdActor, | 266 | account: MAccountIdActor |
261 | channel: MChannelDefault, | 267 | channel: MChannelDefault |
262 | overrideTo?: string[] | 268 | overrideTo?: string[] |
263 | }) { | 269 | }) { |
264 | const { video, videoObject, account, channel, overrideTo } = options | 270 | const { video, videoObject, account, channel, overrideTo } = options |
@@ -289,7 +295,7 @@ async function updateVideoFromAP (options: { | |||
289 | throw new Error('Account ' + account.Actor.url + ' does not own video channel ' + videoChannel.Actor.url) | 295 | throw new Error('Account ' + account.Actor.url + ' does not own video channel ' + videoChannel.Actor.url) |
290 | } | 296 | } |
291 | 297 | ||
292 | const to = overrideTo ? overrideTo : videoObject.to | 298 | const to = overrideTo || videoObject.to |
293 | const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, to) | 299 | const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, to) |
294 | video.name = videoData.name | 300 | video.name = videoData.name |
295 | video.uuid = videoData.uuid | 301 | video.uuid = videoData.uuid |
@@ -412,8 +418,8 @@ async function updateVideoFromAP (options: { | |||
412 | } | 418 | } |
413 | 419 | ||
414 | async function refreshVideoIfNeeded (options: { | 420 | async function refreshVideoIfNeeded (options: { |
415 | video: MVideoThumbnail, | 421 | video: MVideoThumbnail |
416 | fetchedType: VideoFetchByUrlType, | 422 | fetchedType: VideoFetchByUrlType |
417 | syncParam: SyncParam | 423 | syncParam: SyncParam |
418 | }): Promise<MVideoThumbnail> { | 424 | }): Promise<MVideoThumbnail> { |
419 | if (!options.video.isOutdated()) return options.video | 425 | if (!options.video.isOutdated()) return options.video |
@@ -582,13 +588,13 @@ async function createVideo (videoObject: VideoTorrentObject, channel: MChannelAc | |||
582 | thumbnailModel = videoCreated.id | 588 | thumbnailModel = videoCreated.id |
583 | 589 | ||
584 | return thumbnailModel.save() | 590 | return thumbnailModel.save() |
585 | }) | 591 | }).catch(err => logger.error('Cannot create miniature from url.', { err })) |
586 | } | 592 | } |
587 | 593 | ||
588 | return { autoBlacklisted, videoCreated } | 594 | return { autoBlacklisted, videoCreated } |
589 | } | 595 | } |
590 | 596 | ||
591 | async function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObject: VideoTorrentObject, to: string[] = []) { | 597 | function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObject: VideoTorrentObject, to: string[] = []) { |
592 | const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPrivacy.PUBLIC : VideoPrivacy.UNLISTED | 598 | const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPrivacy.PUBLIC : VideoPrivacy.UNLISTED |
593 | const duration = videoObject.duration.replace(/[^\d]+/, '') | 599 | const duration = videoObject.duration.replace(/[^\d]+/, '') |
594 | 600 | ||
@@ -661,7 +667,7 @@ function videoFileActivityUrlToDBAttributes ( | |||
661 | 667 | ||
662 | const mediaType = fileUrl.mediaType | 668 | const mediaType = fileUrl.mediaType |
663 | const attribute = { | 669 | const attribute = { |
664 | extname: MIMETYPES.VIDEO.MIMETYPE_EXT[ mediaType ], | 670 | extname: MIMETYPES.VIDEO.MIMETYPE_EXT[mediaType], |
665 | infoHash: parsed.infoHash, | 671 | infoHash: parsed.infoHash, |
666 | resolution: fileUrl.height, | 672 | resolution: fileUrl.height, |
667 | size: fileUrl.size, | 673 | size: fileUrl.size, |
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts index 1d8a08ed0..572bd03bd 100644 --- a/server/lib/client-html.ts +++ b/server/lib/client-html.ts | |||
@@ -17,7 +17,7 @@ import { MAccountActor, MChannelActor, MVideo } from '../typings/models' | |||
17 | 17 | ||
18 | export class ClientHtml { | 18 | export class ClientHtml { |
19 | 19 | ||
20 | private static htmlCache: { [ path: string ]: string } = {} | 20 | private static htmlCache: { [path: string]: string } = {} |
21 | 21 | ||
22 | static invalidCache () { | 22 | static invalidCache () { |
23 | logger.info('Cleaning HTML cache.') | 23 | logger.info('Cleaning HTML cache.') |
@@ -94,7 +94,7 @@ export class ClientHtml { | |||
94 | 94 | ||
95 | private static async getIndexHTML (req: express.Request, res: express.Response, paramLang?: string) { | 95 | private static async getIndexHTML (req: express.Request, res: express.Response, paramLang?: string) { |
96 | const path = ClientHtml.getIndexPath(req, res, paramLang) | 96 | const path = ClientHtml.getIndexPath(req, res, paramLang) |
97 | if (ClientHtml.htmlCache[ path ]) return ClientHtml.htmlCache[ path ] | 97 | if (ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path] |
98 | 98 | ||
99 | const buffer = await readFile(path) | 99 | const buffer = await readFile(path) |
100 | 100 | ||
@@ -104,7 +104,7 @@ export class ClientHtml { | |||
104 | html = ClientHtml.addCustomCSS(html) | 104 | html = ClientHtml.addCustomCSS(html) |
105 | html = await ClientHtml.addAsyncPluginCSS(html) | 105 | html = await ClientHtml.addAsyncPluginCSS(html) |
106 | 106 | ||
107 | ClientHtml.htmlCache[ path ] = html | 107 | ClientHtml.htmlCache[path] = html |
108 | 108 | ||
109 | return html | 109 | return html |
110 | } | 110 | } |
@@ -214,21 +214,21 @@ export class ClientHtml { | |||
214 | const schemaTags = { | 214 | const schemaTags = { |
215 | '@context': 'http://schema.org', | 215 | '@context': 'http://schema.org', |
216 | '@type': 'VideoObject', | 216 | '@type': 'VideoObject', |
217 | name: videoNameEscaped, | 217 | 'name': videoNameEscaped, |
218 | description: videoDescriptionEscaped, | 218 | 'description': videoDescriptionEscaped, |
219 | thumbnailUrl: previewUrl, | 219 | 'thumbnailUrl': previewUrl, |
220 | uploadDate: video.createdAt.toISOString(), | 220 | 'uploadDate': video.createdAt.toISOString(), |
221 | duration: getActivityStreamDuration(video.duration), | 221 | 'duration': getActivityStreamDuration(video.duration), |
222 | contentUrl: videoUrl, | 222 | 'contentUrl': videoUrl, |
223 | embedUrl: embedUrl, | 223 | 'embedUrl': embedUrl, |
224 | interactionCount: video.views | 224 | 'interactionCount': video.views |
225 | } | 225 | } |
226 | 226 | ||
227 | let tagsString = '' | 227 | let tagsString = '' |
228 | 228 | ||
229 | // Opengraph | 229 | // Opengraph |
230 | Object.keys(openGraphMetaTags).forEach(tagName => { | 230 | Object.keys(openGraphMetaTags).forEach(tagName => { |
231 | const tagValue = openGraphMetaTags[ tagName ] | 231 | const tagValue = openGraphMetaTags[tagName] |
232 | 232 | ||
233 | tagsString += `<meta property="${tagName}" content="${tagValue}" />` | 233 | tagsString += `<meta property="${tagName}" content="${tagValue}" />` |
234 | }) | 234 | }) |
diff --git a/server/lib/emailer.ts b/server/lib/emailer.ts index 7484524a4..9ce6186b1 100644 --- a/server/lib/emailer.ts +++ b/server/lib/emailer.ts | |||
@@ -32,7 +32,8 @@ class Emailer { | |||
32 | private initialized = false | 32 | private initialized = false |
33 | private transporter: Transporter | 33 | private transporter: Transporter |
34 | 34 | ||
35 | private constructor () {} | 35 | private constructor () { |
36 | } | ||
36 | 37 | ||
37 | init () { | 38 | init () { |
38 | // Already initialized | 39 | // Already initialized |
@@ -97,12 +98,12 @@ class Emailer { | |||
97 | const channelName = video.VideoChannel.getDisplayName() | 98 | const channelName = video.VideoChannel.getDisplayName() |
98 | const videoUrl = WEBSERVER.URL + video.getWatchStaticPath() | 99 | const videoUrl = WEBSERVER.URL + video.getWatchStaticPath() |
99 | 100 | ||
100 | const text = `Hi dear user,\n\n` + | 101 | const text = 'Hi dear user,\n\n' + |
101 | `Your subscription ${channelName} just published a new video: ${video.name}` + | 102 | `Your subscription ${channelName} just published a new video: ${video.name}` + |
102 | `\n\n` + | 103 | '\n\n' + |
103 | `You can view it on ${videoUrl} ` + | 104 | `You can view it on ${videoUrl} ` + |
104 | `\n\n` + | 105 | '\n\n' + |
105 | `Cheers,\n` + | 106 | 'Cheers,\n' + |
106 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 107 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
107 | 108 | ||
108 | const emailPayload: EmailPayload = { | 109 | const emailPayload: EmailPayload = { |
@@ -118,10 +119,10 @@ class Emailer { | |||
118 | const followerName = actorFollow.ActorFollower.Account.getDisplayName() | 119 | const followerName = actorFollow.ActorFollower.Account.getDisplayName() |
119 | const followingName = (actorFollow.ActorFollowing.VideoChannel || actorFollow.ActorFollowing.Account).getDisplayName() | 120 | const followingName = (actorFollow.ActorFollowing.VideoChannel || actorFollow.ActorFollowing.Account).getDisplayName() |
120 | 121 | ||
121 | const text = `Hi dear user,\n\n` + | 122 | const text = 'Hi dear user,\n\n' + |
122 | `Your ${followType} ${followingName} has a new subscriber: ${followerName}` + | 123 | `Your ${followType} ${followingName} has a new subscriber: ${followerName}` + |
123 | `\n\n` + | 124 | '\n\n' + |
124 | `Cheers,\n` + | 125 | 'Cheers,\n' + |
125 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 126 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
126 | 127 | ||
127 | const emailPayload: EmailPayload = { | 128 | const emailPayload: EmailPayload = { |
@@ -136,10 +137,10 @@ class Emailer { | |||
136 | addNewInstanceFollowerNotification (to: string[], actorFollow: MActorFollowActors) { | 137 | addNewInstanceFollowerNotification (to: string[], actorFollow: MActorFollowActors) { |
137 | const awaitingApproval = actorFollow.state === 'pending' ? ' awaiting manual approval.' : '' | 138 | const awaitingApproval = actorFollow.state === 'pending' ? ' awaiting manual approval.' : '' |
138 | 139 | ||
139 | const text = `Hi dear admin,\n\n` + | 140 | const text = 'Hi dear admin,\n\n' + |
140 | `Your instance has a new follower: ${actorFollow.ActorFollower.url}${awaitingApproval}` + | 141 | `Your instance has a new follower: ${actorFollow.ActorFollower.url}${awaitingApproval}` + |
141 | `\n\n` + | 142 | '\n\n' + |
142 | `Cheers,\n` + | 143 | 'Cheers,\n' + |
143 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 144 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
144 | 145 | ||
145 | const emailPayload: EmailPayload = { | 146 | const emailPayload: EmailPayload = { |
@@ -152,10 +153,10 @@ class Emailer { | |||
152 | } | 153 | } |
153 | 154 | ||
154 | addAutoInstanceFollowingNotification (to: string[], actorFollow: MActorFollowActors) { | 155 | addAutoInstanceFollowingNotification (to: string[], actorFollow: MActorFollowActors) { |
155 | const text = `Hi dear admin,\n\n` + | 156 | const text = 'Hi dear admin,\n\n' + |
156 | `Your instance automatically followed a new instance: ${actorFollow.ActorFollowing.url}` + | 157 | `Your instance automatically followed a new instance: ${actorFollow.ActorFollowing.url}` + |
157 | `\n\n` + | 158 | '\n\n' + |
158 | `Cheers,\n` + | 159 | 'Cheers,\n' + |
159 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 160 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
160 | 161 | ||
161 | const emailPayload: EmailPayload = { | 162 | const emailPayload: EmailPayload = { |
@@ -170,12 +171,12 @@ class Emailer { | |||
170 | myVideoPublishedNotification (to: string[], video: MVideo) { | 171 | myVideoPublishedNotification (to: string[], video: MVideo) { |
171 | const videoUrl = WEBSERVER.URL + video.getWatchStaticPath() | 172 | const videoUrl = WEBSERVER.URL + video.getWatchStaticPath() |
172 | 173 | ||
173 | const text = `Hi dear user,\n\n` + | 174 | const text = 'Hi dear user,\n\n' + |
174 | `Your video ${video.name} has been published.` + | 175 | `Your video ${video.name} has been published.` + |
175 | `\n\n` + | 176 | '\n\n' + |
176 | `You can view it on ${videoUrl} ` + | 177 | `You can view it on ${videoUrl} ` + |
177 | `\n\n` + | 178 | '\n\n' + |
178 | `Cheers,\n` + | 179 | 'Cheers,\n' + |
179 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 180 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
180 | 181 | ||
181 | const emailPayload: EmailPayload = { | 182 | const emailPayload: EmailPayload = { |
@@ -190,12 +191,12 @@ class Emailer { | |||
190 | myVideoImportSuccessNotification (to: string[], videoImport: MVideoImportVideo) { | 191 | myVideoImportSuccessNotification (to: string[], videoImport: MVideoImportVideo) { |
191 | const videoUrl = WEBSERVER.URL + videoImport.Video.getWatchStaticPath() | 192 | const videoUrl = WEBSERVER.URL + videoImport.Video.getWatchStaticPath() |
192 | 193 | ||
193 | const text = `Hi dear user,\n\n` + | 194 | const text = 'Hi dear user,\n\n' + |
194 | `Your video import ${videoImport.getTargetIdentifier()} is finished.` + | 195 | `Your video import ${videoImport.getTargetIdentifier()} is finished.` + |
195 | `\n\n` + | 196 | '\n\n' + |
196 | `You can view the imported video on ${videoUrl} ` + | 197 | `You can view the imported video on ${videoUrl} ` + |
197 | `\n\n` + | 198 | '\n\n' + |
198 | `Cheers,\n` + | 199 | 'Cheers,\n' + |
199 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 200 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
200 | 201 | ||
201 | const emailPayload: EmailPayload = { | 202 | const emailPayload: EmailPayload = { |
@@ -210,12 +211,12 @@ class Emailer { | |||
210 | myVideoImportErrorNotification (to: string[], videoImport: MVideoImport) { | 211 | myVideoImportErrorNotification (to: string[], videoImport: MVideoImport) { |
211 | const importUrl = WEBSERVER.URL + '/my-account/video-imports' | 212 | const importUrl = WEBSERVER.URL + '/my-account/video-imports' |
212 | 213 | ||
213 | const text = `Hi dear user,\n\n` + | 214 | const text = 'Hi dear user,\n\n' + |
214 | `Your video import ${videoImport.getTargetIdentifier()} encountered an error.` + | 215 | `Your video import ${videoImport.getTargetIdentifier()} encountered an error.` + |
215 | `\n\n` + | 216 | '\n\n' + |
216 | `See your videos import dashboard for more information: ${importUrl}` + | 217 | `See your videos import dashboard for more information: ${importUrl}` + |
217 | `\n\n` + | 218 | '\n\n' + |
218 | `Cheers,\n` + | 219 | 'Cheers,\n' + |
219 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 220 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
220 | 221 | ||
221 | const emailPayload: EmailPayload = { | 222 | const emailPayload: EmailPayload = { |
@@ -232,12 +233,12 @@ class Emailer { | |||
232 | const video = comment.Video | 233 | const video = comment.Video |
233 | const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath() | 234 | const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath() |
234 | 235 | ||
235 | const text = `Hi dear user,\n\n` + | 236 | const text = 'Hi dear user,\n\n' + |
236 | `A new comment has been posted by ${accountName} on your video ${video.name}` + | 237 | `A new comment has been posted by ${accountName} on your video ${video.name}` + |
237 | `\n\n` + | 238 | '\n\n' + |
238 | `You can view it on ${commentUrl} ` + | 239 | `You can view it on ${commentUrl} ` + |
239 | `\n\n` + | 240 | '\n\n' + |
240 | `Cheers,\n` + | 241 | 'Cheers,\n' + |
241 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 242 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
242 | 243 | ||
243 | const emailPayload: EmailPayload = { | 244 | const emailPayload: EmailPayload = { |
@@ -254,12 +255,12 @@ class Emailer { | |||
254 | const video = comment.Video | 255 | const video = comment.Video |
255 | const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath() | 256 | const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath() |
256 | 257 | ||
257 | const text = `Hi dear user,\n\n` + | 258 | const text = 'Hi dear user,\n\n' + |
258 | `${accountName} mentioned you on video ${video.name}` + | 259 | `${accountName} mentioned you on video ${video.name}` + |
259 | `\n\n` + | 260 | '\n\n' + |
260 | `You can view the comment on ${commentUrl} ` + | 261 | `You can view the comment on ${commentUrl} ` + |
261 | `\n\n` + | 262 | '\n\n' + |
262 | `Cheers,\n` + | 263 | 'Cheers,\n' + |
263 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 264 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
264 | 265 | ||
265 | const emailPayload: EmailPayload = { | 266 | const emailPayload: EmailPayload = { |
@@ -274,9 +275,9 @@ class Emailer { | |||
274 | addVideoAbuseModeratorsNotification (to: string[], videoAbuse: MVideoAbuseVideo) { | 275 | addVideoAbuseModeratorsNotification (to: string[], videoAbuse: MVideoAbuseVideo) { |
275 | const videoUrl = WEBSERVER.URL + videoAbuse.Video.getWatchStaticPath() | 276 | const videoUrl = WEBSERVER.URL + videoAbuse.Video.getWatchStaticPath() |
276 | 277 | ||
277 | const text = `Hi,\n\n` + | 278 | const text = 'Hi,\n\n' + |
278 | `${WEBSERVER.HOST} received an abuse for the following video ${videoUrl}\n\n` + | 279 | `${WEBSERVER.HOST} received an abuse for the following video ${videoUrl}\n\n` + |
279 | `Cheers,\n` + | 280 | 'Cheers,\n' + |
280 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 281 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
281 | 282 | ||
282 | const emailPayload: EmailPayload = { | 283 | const emailPayload: EmailPayload = { |
@@ -292,14 +293,14 @@ class Emailer { | |||
292 | const VIDEO_AUTO_BLACKLIST_URL = WEBSERVER.URL + '/admin/moderation/video-auto-blacklist/list' | 293 | const VIDEO_AUTO_BLACKLIST_URL = WEBSERVER.URL + '/admin/moderation/video-auto-blacklist/list' |
293 | const videoUrl = WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath() | 294 | const videoUrl = WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath() |
294 | 295 | ||
295 | const text = `Hi,\n\n` + | 296 | const text = 'Hi,\n\n' + |
296 | `A recently added video was auto-blacklisted and requires moderator review before publishing.` + | 297 | 'A recently added video was auto-blacklisted and requires moderator review before publishing.' + |
297 | `\n\n` + | 298 | '\n\n' + |
298 | `You can view it and take appropriate action on ${videoUrl}` + | 299 | `You can view it and take appropriate action on ${videoUrl}` + |
299 | `\n\n` + | 300 | '\n\n' + |
300 | `A full list of auto-blacklisted videos can be reviewed here: ${VIDEO_AUTO_BLACKLIST_URL}` + | 301 | `A full list of auto-blacklisted videos can be reviewed here: ${VIDEO_AUTO_BLACKLIST_URL}` + |
301 | `\n\n` + | 302 | '\n\n' + |
302 | `Cheers,\n` + | 303 | 'Cheers,\n' + |
303 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 304 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
304 | 305 | ||
305 | const emailPayload: EmailPayload = { | 306 | const emailPayload: EmailPayload = { |
@@ -312,9 +313,9 @@ class Emailer { | |||
312 | } | 313 | } |
313 | 314 | ||
314 | addNewUserRegistrationNotification (to: string[], user: MUser) { | 315 | addNewUserRegistrationNotification (to: string[], user: MUser) { |
315 | const text = `Hi,\n\n` + | 316 | const text = 'Hi,\n\n' + |
316 | `User ${user.username} just registered on ${WEBSERVER.HOST} PeerTube instance.\n\n` + | 317 | `User ${user.username} just registered on ${WEBSERVER.HOST} PeerTube instance.\n\n` + |
317 | `Cheers,\n` + | 318 | 'Cheers,\n' + |
318 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 319 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
319 | 320 | ||
320 | const emailPayload: EmailPayload = { | 321 | const emailPayload: EmailPayload = { |
@@ -367,11 +368,11 @@ class Emailer { | |||
367 | } | 368 | } |
368 | 369 | ||
369 | addPasswordResetEmailJob (to: string, resetPasswordUrl: string) { | 370 | addPasswordResetEmailJob (to: string, resetPasswordUrl: string) { |
370 | const text = `Hi dear user,\n\n` + | 371 | const text = 'Hi dear user,\n\n' + |
371 | `A reset password procedure for your account ${to} has been requested on ${WEBSERVER.HOST} ` + | 372 | `A reset password procedure for your account ${to} has been requested on ${WEBSERVER.HOST} ` + |
372 | `Please follow this link to reset it: ${resetPasswordUrl} (the link will expire within 1 hour)\n\n` + | 373 | `Please follow this link to reset it: ${resetPasswordUrl} (the link will expire within 1 hour)\n\n` + |
373 | `If you are not the person who initiated this request, please ignore this email.\n\n` + | 374 | 'If you are not the person who initiated this request, please ignore this email.\n\n' + |
374 | `Cheers,\n` + | 375 | 'Cheers,\n' + |
375 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 376 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
376 | 377 | ||
377 | const emailPayload: EmailPayload = { | 378 | const emailPayload: EmailPayload = { |
@@ -384,11 +385,11 @@ class Emailer { | |||
384 | } | 385 | } |
385 | 386 | ||
386 | addVerifyEmailJob (to: string, verifyEmailUrl: string) { | 387 | addVerifyEmailJob (to: string, verifyEmailUrl: string) { |
387 | const text = `Welcome to PeerTube,\n\n` + | 388 | const text = 'Welcome to PeerTube,\n\n' + |
388 | `To start using PeerTube on ${WEBSERVER.HOST} you must verify your email! ` + | 389 | `To start using PeerTube on ${WEBSERVER.HOST} you must verify your email! ` + |
389 | `Please follow this link to verify this email belongs to you: ${verifyEmailUrl}\n\n` + | 390 | `Please follow this link to verify this email belongs to you: ${verifyEmailUrl}\n\n` + |
390 | `If you are not the person who initiated this request, please ignore this email.\n\n` + | 391 | 'If you are not the person who initiated this request, please ignore this email.\n\n' + |
391 | `Cheers,\n` + | 392 | 'Cheers,\n' + |
392 | `${CONFIG.EMAIL.BODY.SIGNATURE}` | 393 | `${CONFIG.EMAIL.BODY.SIGNATURE}` |
393 | 394 | ||
394 | const emailPayload: EmailPayload = { | 395 | const emailPayload: EmailPayload = { |
diff --git a/server/lib/files-cache/videos-preview-cache.ts b/server/lib/files-cache/videos-preview-cache.ts index 7bfeb5783..d0d4fc5b5 100644 --- a/server/lib/files-cache/videos-preview-cache.ts +++ b/server/lib/files-cache/videos-preview-cache.ts | |||
@@ -1,9 +1,8 @@ | |||
1 | import { join } from 'path' | 1 | import { join } from 'path' |
2 | import { FILES_CACHE, STATIC_PATHS } from '../../initializers/constants' | 2 | import { FILES_CACHE } from '../../initializers/constants' |
3 | import { VideoModel } from '../../models/video/video' | 3 | import { VideoModel } from '../../models/video/video' |
4 | import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' | 4 | import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache' |
5 | import { doRequestAndSaveToFile } from '@server/helpers/requests' | 5 | import { doRequestAndSaveToFile } from '@server/helpers/requests' |
6 | import { buildRemoteVideoBaseUrl } from '@server/helpers/activitypub' | ||
7 | 6 | ||
8 | class VideosPreviewCache extends AbstractVideoStaticFileCache <string> { | 7 | class VideosPreviewCache extends AbstractVideoStaticFileCache <string> { |
9 | 8 | ||
diff --git a/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts b/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts index d3bde6e6a..a28f3596f 100644 --- a/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts +++ b/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts | |||
@@ -42,7 +42,7 @@ async function buildSignedRequestOptions (payload: Payload) { | |||
42 | 42 | ||
43 | function buildGlobalHeaders (body: any) { | 43 | function buildGlobalHeaders (body: any) { |
44 | return { | 44 | return { |
45 | 'Digest': buildDigest(body) | 45 | Digest: buildDigest(body) |
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
diff --git a/server/lib/job-queue/handlers/video-file-import.ts b/server/lib/job-queue/handlers/video-file-import.ts index 99c991e72..be9e7d181 100644 --- a/server/lib/job-queue/handlers/video-file-import.ts +++ b/server/lib/job-queue/handlers/video-file-import.ts | |||
@@ -11,7 +11,7 @@ import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | |||
11 | import { getVideoFilePath } from '@server/lib/video-paths' | 11 | import { getVideoFilePath } from '@server/lib/video-paths' |
12 | 12 | ||
13 | export type VideoFileImportPayload = { | 13 | export type VideoFileImportPayload = { |
14 | videoUUID: string, | 14 | videoUUID: string |
15 | filePath: string | 15 | filePath: string |
16 | } | 16 | } |
17 | 17 | ||
diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts index 1fca17584..09f225cec 100644 --- a/server/lib/job-queue/handlers/video-import.ts +++ b/server/lib/job-queue/handlers/video-import.ts | |||
@@ -221,7 +221,7 @@ async function processFile (downloader: () => Promise<string>, videoImport: MVid | |||
221 | isNewVideo: true | 221 | isNewVideo: true |
222 | } | 222 | } |
223 | 223 | ||
224 | await JobQueue.Instance.createJob({ type: 'video-transcoding', payload: dataInput }) | 224 | await JobQueue.Instance.createJobWithPromise({ type: 'video-transcoding', payload: dataInput }) |
225 | } | 225 | } |
226 | 226 | ||
227 | } catch (err) { | 227 | } catch (err) { |
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts index 39b9fac98..c020057c9 100644 --- a/server/lib/job-queue/handlers/video-transcoding.ts +++ b/server/lib/job-queue/handlers/video-transcoding.ts | |||
@@ -6,7 +6,6 @@ import { JobQueue } from '../job-queue' | |||
6 | import { federateVideoIfNeeded } from '../../activitypub' | 6 | import { federateVideoIfNeeded } from '../../activitypub' |
7 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 7 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
8 | import { sequelizeTypescript } from '../../../initializers' | 8 | import { sequelizeTypescript } from '../../../initializers' |
9 | import * as Bluebird from 'bluebird' | ||
10 | import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils' | 9 | import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils' |
11 | import { generateHlsPlaylist, mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewResolution } from '../../video-transcoding' | 10 | import { generateHlsPlaylist, mergeAudioVideofile, optimizeOriginalVideofile, transcodeNewResolution } from '../../video-transcoding' |
12 | import { Notifier } from '../../notifier' | 11 | import { Notifier } from '../../notifier' |
@@ -40,8 +39,11 @@ interface OptimizeTranscodingPayload extends BaseTranscodingPayload { | |||
40 | type: 'optimize' | 39 | type: 'optimize' |
41 | } | 40 | } |
42 | 41 | ||
43 | export type VideoTranscodingPayload = HLSTranscodingPayload | NewResolutionTranscodingPayload | 42 | export type VideoTranscodingPayload = |
44 | | OptimizeTranscodingPayload | MergeAudioTranscodingPayload | 43 | HLSTranscodingPayload |
44 | | NewResolutionTranscodingPayload | ||
45 | | OptimizeTranscodingPayload | ||
46 | | MergeAudioTranscodingPayload | ||
45 | 47 | ||
46 | async function processVideoTranscoding (job: Bull.Job) { | 48 | async function processVideoTranscoding (job: Bull.Job) { |
47 | const payload = job.data as VideoTranscodingPayload | 49 | const payload = job.data as VideoTranscodingPayload |
@@ -105,7 +107,7 @@ async function onVideoFileOptimizerSuccess (videoArg: MVideoWithFile, payload: O | |||
105 | 107 | ||
106 | const { videoDatabase, videoPublished } = await sequelizeTypescript.transaction(async t => { | 108 | const { videoDatabase, videoPublished } = await sequelizeTypescript.transaction(async t => { |
107 | // Maybe the video changed in database, refresh it | 109 | // Maybe the video changed in database, refresh it |
108 | let videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoArg.uuid, t) | 110 | const videoDatabase = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoArg.uuid, t) |
109 | // Video does not exist anymore | 111 | // Video does not exist anymore |
110 | if (!videoDatabase) return undefined | 112 | if (!videoDatabase) return undefined |
111 | 113 | ||
@@ -122,8 +124,6 @@ async function onVideoFileOptimizerSuccess (videoArg: MVideoWithFile, payload: O | |||
122 | await createHlsJobIfEnabled(hlsPayload) | 124 | await createHlsJobIfEnabled(hlsPayload) |
123 | 125 | ||
124 | if (resolutionsEnabled.length !== 0) { | 126 | if (resolutionsEnabled.length !== 0) { |
125 | const tasks: (Bluebird<Bull.Job<any>> | Promise<Bull.Job<any>>)[] = [] | ||
126 | |||
127 | for (const resolution of resolutionsEnabled) { | 127 | for (const resolution of resolutionsEnabled) { |
128 | let dataInput: VideoTranscodingPayload | 128 | let dataInput: VideoTranscodingPayload |
129 | 129 | ||
@@ -143,12 +143,9 @@ async function onVideoFileOptimizerSuccess (videoArg: MVideoWithFile, payload: O | |||
143 | } | 143 | } |
144 | } | 144 | } |
145 | 145 | ||
146 | const p = JobQueue.Instance.createJob({ type: 'video-transcoding', payload: dataInput }) | 146 | JobQueue.Instance.createJob({ type: 'video-transcoding', payload: dataInput }) |
147 | tasks.push(p) | ||
148 | } | 147 | } |
149 | 148 | ||
150 | await Promise.all(tasks) | ||
151 | |||
152 | logger.info('Transcoding jobs created for uuid %s.', videoDatabase.uuid, { resolutionsEnabled }) | 149 | logger.info('Transcoding jobs created for uuid %s.', videoDatabase.uuid, { resolutionsEnabled }) |
153 | } else { | 150 | } else { |
154 | // No transcoding to do, it's now published | 151 | // No transcoding to do, it's now published |
diff --git a/server/lib/job-queue/job-queue.ts b/server/lib/job-queue/job-queue.ts index 61f07c487..14acace7d 100644 --- a/server/lib/job-queue/job-queue.ts +++ b/server/lib/job-queue/job-queue.ts | |||
@@ -28,7 +28,7 @@ type CreateJobArgument = | |||
28 | { type: 'videos-views', payload: {} } | | 28 | { type: 'videos-views', payload: {} } | |
29 | { type: 'video-redundancy', payload: VideoRedundancyPayload } | 29 | { type: 'video-redundancy', payload: VideoRedundancyPayload } |
30 | 30 | ||
31 | const handlers: { [ id in JobType ]: (job: Bull.Job) => Promise<any>} = { | 31 | const handlers: { [id in JobType]: (job: Bull.Job) => Promise<any> } = { |
32 | 'activitypub-http-broadcast': processActivityPubHttpBroadcast, | 32 | 'activitypub-http-broadcast': processActivityPubHttpBroadcast, |
33 | 'activitypub-http-unicast': processActivityPubHttpUnicast, | 33 | 'activitypub-http-unicast': processActivityPubHttpUnicast, |
34 | 'activitypub-http-fetcher': processActivityPubHttpFetcher, | 34 | 'activitypub-http-fetcher': processActivityPubHttpFetcher, |
@@ -60,13 +60,14 @@ class JobQueue { | |||
60 | 60 | ||
61 | private static instance: JobQueue | 61 | private static instance: JobQueue |
62 | 62 | ||
63 | private queues: { [ id in JobType ]?: Bull.Queue } = {} | 63 | private queues: { [id in JobType]?: Bull.Queue } = {} |
64 | private initialized = false | 64 | private initialized = false |
65 | private jobRedisPrefix: string | 65 | private jobRedisPrefix: string |
66 | 66 | ||
67 | private constructor () {} | 67 | private constructor () { |
68 | } | ||
68 | 69 | ||
69 | async init () { | 70 | init () { |
70 | // Already initialized | 71 | // Already initialized |
71 | if (this.initialized === true) return | 72 | if (this.initialized === true) return |
72 | this.initialized = true | 73 | this.initialized = true |
@@ -108,11 +109,16 @@ class JobQueue { | |||
108 | } | 109 | } |
109 | } | 110 | } |
110 | 111 | ||
111 | createJob (obj: CreateJobArgument) { | 112 | createJob (obj: CreateJobArgument): void { |
113 | this.createJobWithPromise(obj) | ||
114 | .catch(err => logger.error('Cannot create job.', { err, obj })) | ||
115 | } | ||
116 | |||
117 | createJobWithPromise (obj: CreateJobArgument) { | ||
112 | const queue = this.queues[obj.type] | 118 | const queue = this.queues[obj.type] |
113 | if (queue === undefined) { | 119 | if (queue === undefined) { |
114 | logger.error('Unknown queue %s: cannot create job.', obj.type) | 120 | logger.error('Unknown queue %s: cannot create job.', obj.type) |
115 | throw Error('Unknown queue, cannot create job') | 121 | return |
116 | } | 122 | } |
117 | 123 | ||
118 | const jobArgs: Bull.JobOptions = { | 124 | const jobArgs: Bull.JobOptions = { |
@@ -125,10 +131,10 @@ class JobQueue { | |||
125 | } | 131 | } |
126 | 132 | ||
127 | async listForApi (options: { | 133 | async listForApi (options: { |
128 | state: JobState, | 134 | state: JobState |
129 | start: number, | 135 | start: number |
130 | count: number, | 136 | count: number |
131 | asc?: boolean, | 137 | asc?: boolean |
132 | jobType: JobType | 138 | jobType: JobType |
133 | }): Promise<Bull.Job[]> { | 139 | }): Promise<Bull.Job[]> { |
134 | const { state, start, count, asc, jobType } = options | 140 | const { state, start, count, asc, jobType } = options |
@@ -137,7 +143,7 @@ class JobQueue { | |||
137 | const filteredJobTypes = this.filterJobTypes(jobType) | 143 | const filteredJobTypes = this.filterJobTypes(jobType) |
138 | 144 | ||
139 | for (const jobType of filteredJobTypes) { | 145 | for (const jobType of filteredJobTypes) { |
140 | const queue = this.queues[ jobType ] | 146 | const queue = this.queues[jobType] |
141 | if (queue === undefined) { | 147 | if (queue === undefined) { |
142 | logger.error('Unknown queue %s to list jobs.', jobType) | 148 | logger.error('Unknown queue %s to list jobs.', jobType) |
143 | continue | 149 | continue |
@@ -165,7 +171,7 @@ class JobQueue { | |||
165 | const filteredJobTypes = this.filterJobTypes(jobType) | 171 | const filteredJobTypes = this.filterJobTypes(jobType) |
166 | 172 | ||
167 | for (const type of filteredJobTypes) { | 173 | for (const type of filteredJobTypes) { |
168 | const queue = this.queues[ type ] | 174 | const queue = this.queues[type] |
169 | if (queue === undefined) { | 175 | if (queue === undefined) { |
170 | logger.error('Unknown queue %s to count jobs.', type) | 176 | logger.error('Unknown queue %s to count jobs.', type) |
171 | continue | 177 | continue |
@@ -173,7 +179,7 @@ class JobQueue { | |||
173 | 179 | ||
174 | const counts = await queue.getJobCounts() | 180 | const counts = await queue.getJobCounts() |
175 | 181 | ||
176 | total += counts[ state ] | 182 | total += counts[state] |
177 | } | 183 | } |
178 | 184 | ||
179 | return total | 185 | return total |
@@ -189,7 +195,7 @@ class JobQueue { | |||
189 | private addRepeatableJobs () { | 195 | private addRepeatableJobs () { |
190 | this.queues['videos-views'].add({}, { | 196 | this.queues['videos-views'].add({}, { |
191 | repeat: REPEAT_JOBS['videos-views'] | 197 | repeat: REPEAT_JOBS['videos-views'] |
192 | }) | 198 | }).catch(err => logger.error('Cannot add repeatable job.', { err })) |
193 | } | 199 | } |
194 | 200 | ||
195 | private filterJobTypes (jobType?: JobType) { | 201 | private filterJobTypes (jobType?: JobType) { |
diff --git a/server/lib/moderation.ts b/server/lib/moderation.ts index b609f4585..55f7a985d 100644 --- a/server/lib/moderation.ts +++ b/server/lib/moderation.ts | |||
@@ -15,41 +15,41 @@ export type AcceptResult = { | |||
15 | 15 | ||
16 | // Can be filtered by plugins | 16 | // Can be filtered by plugins |
17 | function isLocalVideoAccepted (object: { | 17 | function isLocalVideoAccepted (object: { |
18 | videoBody: VideoCreate, | 18 | videoBody: VideoCreate |
19 | videoFile: Express.Multer.File & { duration?: number }, | 19 | videoFile: Express.Multer.File & { duration?: number } |
20 | user: UserModel | 20 | user: UserModel |
21 | }): AcceptResult { | 21 | }): AcceptResult { |
22 | return { accepted: true } | 22 | return { accepted: true } |
23 | } | 23 | } |
24 | 24 | ||
25 | function isLocalVideoThreadAccepted (_object: { | 25 | function isLocalVideoThreadAccepted (_object: { |
26 | commentBody: VideoCommentCreate, | 26 | commentBody: VideoCommentCreate |
27 | video: VideoModel, | 27 | video: VideoModel |
28 | user: UserModel | 28 | user: UserModel |
29 | }): AcceptResult { | 29 | }): AcceptResult { |
30 | return { accepted: true } | 30 | return { accepted: true } |
31 | } | 31 | } |
32 | 32 | ||
33 | function isLocalVideoCommentReplyAccepted (_object: { | 33 | function isLocalVideoCommentReplyAccepted (_object: { |
34 | commentBody: VideoCommentCreate, | 34 | commentBody: VideoCommentCreate |
35 | parentComment: VideoCommentModel, | 35 | parentComment: VideoCommentModel |
36 | video: VideoModel, | 36 | video: VideoModel |
37 | user: UserModel | 37 | user: UserModel |
38 | }): AcceptResult { | 38 | }): AcceptResult { |
39 | return { accepted: true } | 39 | return { accepted: true } |
40 | } | 40 | } |
41 | 41 | ||
42 | function isRemoteVideoAccepted (_object: { | 42 | function isRemoteVideoAccepted (_object: { |
43 | activity: ActivityCreate, | 43 | activity: ActivityCreate |
44 | videoAP: VideoTorrentObject, | 44 | videoAP: VideoTorrentObject |
45 | byActor: ActorModel | 45 | byActor: ActorModel |
46 | }): AcceptResult { | 46 | }): AcceptResult { |
47 | return { accepted: true } | 47 | return { accepted: true } |
48 | } | 48 | } |
49 | 49 | ||
50 | function isRemoteVideoCommentAccepted (_object: { | 50 | function isRemoteVideoCommentAccepted (_object: { |
51 | activity: ActivityCreate, | 51 | activity: ActivityCreate |
52 | commentAP: VideoCommentObject, | 52 | commentAP: VideoCommentObject |
53 | byActor: ActorModel | 53 | byActor: ActorModel |
54 | }): AcceptResult { | 54 | }): AcceptResult { |
55 | return { accepted: true } | 55 | return { accepted: true } |
diff --git a/server/lib/notifier.ts b/server/lib/notifier.ts index 679b9bcf6..63197eee1 100644 --- a/server/lib/notifier.ts +++ b/server/lib/notifier.ts | |||
@@ -6,7 +6,6 @@ import { UserModel } from '../models/account/user' | |||
6 | import { PeerTubeSocket } from './peertube-socket' | 6 | import { PeerTubeSocket } from './peertube-socket' |
7 | import { CONFIG } from '../initializers/config' | 7 | import { CONFIG } from '../initializers/config' |
8 | import { VideoPrivacy, VideoState } from '../../shared/models/videos' | 8 | import { VideoPrivacy, VideoState } from '../../shared/models/videos' |
9 | import * as Bluebird from 'bluebird' | ||
10 | import { AccountBlocklistModel } from '../models/account/account-blocklist' | 9 | import { AccountBlocklistModel } from '../models/account/account-blocklist' |
11 | import { | 10 | import { |
12 | MCommentOwnerVideo, | 11 | MCommentOwnerVideo, |
@@ -17,7 +16,8 @@ import { | |||
17 | MVideoFullLight | 16 | MVideoFullLight |
18 | } from '../typings/models/video' | 17 | } from '../typings/models/video' |
19 | import { | 18 | import { |
20 | MUser, MUserAccount, | 19 | MUser, |
20 | MUserAccount, | ||
21 | MUserDefault, | 21 | MUserDefault, |
22 | MUserNotifSettingAccount, | 22 | MUserNotifSettingAccount, |
23 | MUserWithNotificationSetting, | 23 | MUserWithNotificationSetting, |
@@ -32,14 +32,15 @@ class Notifier { | |||
32 | 32 | ||
33 | private static instance: Notifier | 33 | private static instance: Notifier |
34 | 34 | ||
35 | private constructor () {} | 35 | private constructor () { |
36 | } | ||
36 | 37 | ||
37 | notifyOnNewVideoIfNeeded (video: MVideoAccountLight): void { | 38 | notifyOnNewVideoIfNeeded (video: MVideoAccountLight): void { |
38 | // Only notify on public and published videos which are not blacklisted | 39 | // Only notify on public and published videos which are not blacklisted |
39 | if (video.privacy !== VideoPrivacy.PUBLIC || video.state !== VideoState.PUBLISHED || video.isBlacklisted()) return | 40 | if (video.privacy !== VideoPrivacy.PUBLIC || video.state !== VideoState.PUBLISHED || video.isBlacklisted()) return |
40 | 41 | ||
41 | this.notifySubscribersOfNewVideo(video) | 42 | this.notifySubscribersOfNewVideo(video) |
42 | .catch(err => logger.error('Cannot notify subscribers of new video %s.', video.url, { err })) | 43 | .catch(err => logger.error('Cannot notify subscribers of new video %s.', video.url, { err })) |
43 | } | 44 | } |
44 | 45 | ||
45 | notifyOnVideoPublishedAfterTranscoding (video: MVideoFullLight): void { | 46 | notifyOnVideoPublishedAfterTranscoding (video: MVideoFullLight): void { |
@@ -63,7 +64,9 @@ class Notifier { | |||
63 | if (video.ScheduleVideoUpdate || (video.waitTranscoding && video.state !== VideoState.PUBLISHED)) return | 64 | if (video.ScheduleVideoUpdate || (video.waitTranscoding && video.state !== VideoState.PUBLISHED)) return |
64 | 65 | ||
65 | this.notifyOwnedVideoHasBeenPublished(video) | 66 | this.notifyOwnedVideoHasBeenPublished(video) |
66 | .catch(err => logger.error('Cannot notify owner that its video %s has been published after removed from auto-blacklist.', video.url, { err })) // tslint:disable-line:max-line-length | 67 | .catch(err => { |
68 | logger.error('Cannot notify owner that its video %s has been published after removed from auto-blacklist.', video.url, { err }) | ||
69 | }) | ||
67 | } | 70 | } |
68 | 71 | ||
69 | notifyOnNewComment (comment: MCommentOwnerVideo): void { | 72 | notifyOnNewComment (comment: MCommentOwnerVideo): void { |
@@ -76,17 +79,17 @@ class Notifier { | |||
76 | 79 | ||
77 | notifyOnNewVideoAbuse (videoAbuse: MVideoAbuseVideo): void { | 80 | notifyOnNewVideoAbuse (videoAbuse: MVideoAbuseVideo): void { |
78 | this.notifyModeratorsOfNewVideoAbuse(videoAbuse) | 81 | this.notifyModeratorsOfNewVideoAbuse(videoAbuse) |
79 | .catch(err => logger.error('Cannot notify of new video abuse of video %s.', videoAbuse.Video.url, { err })) | 82 | .catch(err => logger.error('Cannot notify of new video abuse of video %s.', videoAbuse.Video.url, { err })) |
80 | } | 83 | } |
81 | 84 | ||
82 | notifyOnVideoAutoBlacklist (videoBlacklist: MVideoBlacklistLightVideo): void { | 85 | notifyOnVideoAutoBlacklist (videoBlacklist: MVideoBlacklistLightVideo): void { |
83 | this.notifyModeratorsOfVideoAutoBlacklist(videoBlacklist) | 86 | this.notifyModeratorsOfVideoAutoBlacklist(videoBlacklist) |
84 | .catch(err => logger.error('Cannot notify of auto-blacklist of video %s.', videoBlacklist.Video.url, { err })) | 87 | .catch(err => logger.error('Cannot notify of auto-blacklist of video %s.', videoBlacklist.Video.url, { err })) |
85 | } | 88 | } |
86 | 89 | ||
87 | notifyOnVideoBlacklist (videoBlacklist: MVideoBlacklistVideo): void { | 90 | notifyOnVideoBlacklist (videoBlacklist: MVideoBlacklistVideo): void { |
88 | this.notifyVideoOwnerOfBlacklist(videoBlacklist) | 91 | this.notifyVideoOwnerOfBlacklist(videoBlacklist) |
89 | .catch(err => logger.error('Cannot notify video owner of new video blacklist of %s.', videoBlacklist.Video.url, { err })) | 92 | .catch(err => logger.error('Cannot notify video owner of new video blacklist of %s.', videoBlacklist.Video.url, { err })) |
90 | } | 93 | } |
91 | 94 | ||
92 | notifyOnVideoUnblacklist (video: MVideoFullLight): void { | 95 | notifyOnVideoUnblacklist (video: MVideoFullLight): void { |
@@ -96,7 +99,7 @@ class Notifier { | |||
96 | 99 | ||
97 | notifyOnFinishedVideoImport (videoImport: MVideoImportVideo, success: boolean): void { | 100 | notifyOnFinishedVideoImport (videoImport: MVideoImportVideo, success: boolean): void { |
98 | this.notifyOwnerVideoImportIsFinished(videoImport, success) | 101 | this.notifyOwnerVideoImportIsFinished(videoImport, success) |
99 | .catch(err => logger.error('Cannot notify owner that its video import %s is finished.', videoImport.getTargetIdentifier(), { err })) | 102 | .catch(err => logger.error('Cannot notify owner that its video import %s is finished.', videoImport.getTargetIdentifier(), { err })) |
100 | } | 103 | } |
101 | 104 | ||
102 | notifyOnNewUserRegistration (user: MUserDefault): void { | 105 | notifyOnNewUserRegistration (user: MUserDefault): void { |
@@ -106,14 +109,14 @@ class Notifier { | |||
106 | 109 | ||
107 | notifyOfNewUserFollow (actorFollow: MActorFollowFull): void { | 110 | notifyOfNewUserFollow (actorFollow: MActorFollowFull): void { |
108 | this.notifyUserOfNewActorFollow(actorFollow) | 111 | this.notifyUserOfNewActorFollow(actorFollow) |
109 | .catch(err => { | 112 | .catch(err => { |
110 | logger.error( | 113 | logger.error( |
111 | 'Cannot notify owner of channel %s of a new follow by %s.', | 114 | 'Cannot notify owner of channel %s of a new follow by %s.', |
112 | actorFollow.ActorFollowing.VideoChannel.getDisplayName(), | 115 | actorFollow.ActorFollowing.VideoChannel.getDisplayName(), |
113 | actorFollow.ActorFollower.Account.getDisplayName(), | 116 | actorFollow.ActorFollower.Account.getDisplayName(), |
114 | { err } | 117 | { err } |
115 | ) | 118 | ) |
116 | }) | 119 | }) |
117 | } | 120 | } |
118 | 121 | ||
119 | notifyOfNewInstanceFollow (actorFollow: MActorFollowFull): void { | 122 | notifyOfNewInstanceFollow (actorFollow: MActorFollowFull): void { |
@@ -548,10 +551,10 @@ class Notifier { | |||
548 | return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender }) | 551 | return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender }) |
549 | } | 552 | } |
550 | 553 | ||
551 | private async notify <T extends MUserWithNotificationSetting> (options: { | 554 | private async notify<T extends MUserWithNotificationSetting> (options: { |
552 | users: T[], | 555 | users: T[] |
553 | notificationCreator: (user: T) => Promise<UserNotificationModelForApi>, | 556 | notificationCreator: (user: T) => Promise<UserNotificationModelForApi> |
554 | emailSender: (emails: string[]) => Promise<any> | Bluebird<any>, | 557 | emailSender: (emails: string[]) => void |
555 | settingGetter: (user: T) => UserNotificationSettingValue | 558 | settingGetter: (user: T) => UserNotificationSettingValue |
556 | }) { | 559 | }) { |
557 | const emails: string[] = [] | 560 | const emails: string[] = [] |
@@ -569,7 +572,7 @@ class Notifier { | |||
569 | } | 572 | } |
570 | 573 | ||
571 | if (emails.length !== 0) { | 574 | if (emails.length !== 0) { |
572 | await options.emailSender(emails) | 575 | options.emailSender(emails) |
573 | } | 576 | } |
574 | } | 577 | } |
575 | 578 | ||
diff --git a/server/lib/plugins/plugin-index.ts b/server/lib/plugins/plugin-index.ts index 25b4f3c61..dcdfba28c 100644 --- a/server/lib/plugins/plugin-index.ts +++ b/server/lib/plugins/plugin-index.ts | |||
@@ -31,7 +31,7 @@ async function listAvailablePluginsFromIndex (options: PeertubePluginIndexList) | |||
31 | 31 | ||
32 | logger.debug('Got result from PeerTube index.', { body }) | 32 | logger.debug('Got result from PeerTube index.', { body }) |
33 | 33 | ||
34 | await addInstanceInformation(body) | 34 | addInstanceInformation(body) |
35 | 35 | ||
36 | return body as ResultList<PeerTubePluginIndex> | 36 | return body as ResultList<PeerTubePluginIndex> |
37 | } catch (err) { | 37 | } catch (err) { |
@@ -40,7 +40,7 @@ async function listAvailablePluginsFromIndex (options: PeertubePluginIndexList) | |||
40 | } | 40 | } |
41 | } | 41 | } |
42 | 42 | ||
43 | async function addInstanceInformation (result: ResultList<PeerTubePluginIndex>) { | 43 | function addInstanceInformation (result: ResultList<PeerTubePluginIndex>) { |
44 | for (const d of result.data) { | 44 | for (const d of result.data) { |
45 | d.installed = PluginManager.Instance.isRegistered(d.npmName) | 45 | d.installed = PluginManager.Instance.isRegistered(d.npmName) |
46 | d.name = PluginModel.normalizePluginName(d.npmName) | 46 | d.name = PluginModel.normalizePluginName(d.npmName) |
diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts index 7ebdabd34..73f7a71ce 100644 --- a/server/lib/plugins/plugin-manager.ts +++ b/server/lib/plugins/plugin-manager.ts | |||
@@ -55,30 +55,30 @@ export interface HookInformationValue { | |||
55 | } | 55 | } |
56 | 56 | ||
57 | type AlterableVideoConstant = 'language' | 'licence' | 'category' | 57 | type AlterableVideoConstant = 'language' | 'licence' | 'category' |
58 | type VideoConstant = { [ key in number | string ]: string } | 58 | type VideoConstant = { [key in number | string]: string } |
59 | type UpdatedVideoConstant = { | 59 | type UpdatedVideoConstant = { |
60 | [ name in AlterableVideoConstant ]: { | 60 | [name in AlterableVideoConstant]: { |
61 | [ npmName: string ]: { | 61 | [npmName: string]: { |
62 | added: { key: number | string, label: string }[], | 62 | added: { key: number | string, label: string }[] |
63 | deleted: { key: number | string, label: string }[] | 63 | deleted: { key: number | string, label: string }[] |
64 | } | 64 | } |
65 | } | 65 | } |
66 | } | 66 | } |
67 | 67 | ||
68 | type PluginLocalesTranslations = { | 68 | type PluginLocalesTranslations = { |
69 | [ locale: string ]: PluginTranslation | 69 | [locale: string]: PluginTranslation |
70 | } | 70 | } |
71 | 71 | ||
72 | export class PluginManager implements ServerHook { | 72 | export class PluginManager implements ServerHook { |
73 | 73 | ||
74 | private static instance: PluginManager | 74 | private static instance: PluginManager |
75 | 75 | ||
76 | private registeredPlugins: { [ name: string ]: RegisteredPlugin } = {} | 76 | private registeredPlugins: { [name: string]: RegisteredPlugin } = {} |
77 | private settings: { [ name: string ]: RegisterServerSettingOptions[] } = {} | 77 | private settings: { [name: string]: RegisterServerSettingOptions[] } = {} |
78 | private hooks: { [ name: string ]: HookInformationValue[] } = {} | 78 | private hooks: { [name: string]: HookInformationValue[] } = {} |
79 | private translations: PluginLocalesTranslations = {} | 79 | private translations: PluginLocalesTranslations = {} |
80 | 80 | ||
81 | private updatedVideoConstants: UpdatedVideoConstant = { | 81 | private readonly updatedVideoConstants: UpdatedVideoConstant = { |
82 | language: {}, | 82 | language: {}, |
83 | licence: {}, | 83 | licence: {}, |
84 | category: {} | 84 | category: {} |
@@ -133,7 +133,7 @@ export class PluginManager implements ServerHook { | |||
133 | 133 | ||
134 | // ###################### Hooks ###################### | 134 | // ###################### Hooks ###################### |
135 | 135 | ||
136 | async runHook <T> (hookName: ServerHookName, result?: T, params?: any): Promise<T> { | 136 | async runHook<T> (hookName: ServerHookName, result?: T, params?: any): Promise<T> { |
137 | if (!this.hooks[hookName]) return Promise.resolve(result) | 137 | if (!this.hooks[hookName]) return Promise.resolve(result) |
138 | 138 | ||
139 | const hookType = getHookType(hookName) | 139 | const hookType = getHookType(hookName) |
@@ -312,7 +312,7 @@ export class PluginManager implements ServerHook { | |||
312 | clientScripts[c.script] = c | 312 | clientScripts[c.script] = c |
313 | } | 313 | } |
314 | 314 | ||
315 | this.registeredPlugins[ npmName ] = { | 315 | this.registeredPlugins[npmName] = { |
316 | npmName, | 316 | npmName, |
317 | name: plugin.name, | 317 | name: plugin.name, |
318 | type: plugin.type, | 318 | type: plugin.type, |
@@ -438,7 +438,7 @@ export class PluginManager implements ServerHook { | |||
438 | const plugins: RegisteredPlugin[] = [] | 438 | const plugins: RegisteredPlugin[] = [] |
439 | 439 | ||
440 | for (const npmName of Object.keys(this.registeredPlugins)) { | 440 | for (const npmName of Object.keys(this.registeredPlugins)) { |
441 | const plugin = this.registeredPlugins[ npmName ] | 441 | const plugin = this.registeredPlugins[npmName] |
442 | if (plugin.type !== type) continue | 442 | if (plugin.type !== type) continue |
443 | 443 | ||
444 | plugins.push(plugin) | 444 | plugins.push(plugin) |
@@ -518,11 +518,11 @@ export class PluginManager implements ServerHook { | |||
518 | } | 518 | } |
519 | } | 519 | } |
520 | 520 | ||
521 | private addConstant <T extends string | number> (parameters: { | 521 | private addConstant<T extends string | number> (parameters: { |
522 | npmName: string, | 522 | npmName: string |
523 | type: AlterableVideoConstant, | 523 | type: AlterableVideoConstant |
524 | obj: VideoConstant, | 524 | obj: VideoConstant |
525 | key: T, | 525 | key: T |
526 | label: string | 526 | label: string |
527 | }) { | 527 | }) { |
528 | const { npmName, type, obj, key, label } = parameters | 528 | const { npmName, type, obj, key, label } = parameters |
@@ -545,10 +545,10 @@ export class PluginManager implements ServerHook { | |||
545 | return true | 545 | return true |
546 | } | 546 | } |
547 | 547 | ||
548 | private deleteConstant <T extends string | number> (parameters: { | 548 | private deleteConstant<T extends string | number> (parameters: { |
549 | npmName: string, | 549 | npmName: string |
550 | type: AlterableVideoConstant, | 550 | type: AlterableVideoConstant |
551 | obj: VideoConstant, | 551 | obj: VideoConstant |
552 | key: T | 552 | key: T |
553 | }) { | 553 | }) { |
554 | const { npmName, type, obj, key } = parameters | 554 | const { npmName, type, obj, key } = parameters |
@@ -604,7 +604,7 @@ export class PluginManager implements ServerHook { | |||
604 | const { result: packageJSONValid, badFields } = isPackageJSONValid(packageJSON, pluginType) | 604 | const { result: packageJSONValid, badFields } = isPackageJSONValid(packageJSON, pluginType) |
605 | if (!packageJSONValid) { | 605 | if (!packageJSONValid) { |
606 | const formattedFields = badFields.map(f => `"${f}"`) | 606 | const formattedFields = badFields.map(f => `"${f}"`) |
607 | .join(', ') | 607 | .join(', ') |
608 | 608 | ||
609 | throw new Error(`PackageJSON is invalid (invalid fields: ${formattedFields}).`) | 609 | throw new Error(`PackageJSON is invalid (invalid fields: ${formattedFields}).`) |
610 | } | 610 | } |
diff --git a/server/lib/redis.ts b/server/lib/redis.ts index f77d0b62c..0c5dbdd3e 100644 --- a/server/lib/redis.ts +++ b/server/lib/redis.ts | |||
@@ -12,7 +12,7 @@ import { | |||
12 | import { CONFIG } from '../initializers/config' | 12 | import { CONFIG } from '../initializers/config' |
13 | 13 | ||
14 | type CachedRoute = { | 14 | type CachedRoute = { |
15 | body: string, | 15 | body: string |
16 | contentType?: string | 16 | contentType?: string |
17 | statusCode?: string | 17 | statusCode?: string |
18 | } | 18 | } |
@@ -24,7 +24,8 @@ class Redis { | |||
24 | private client: RedisClient | 24 | private client: RedisClient |
25 | private prefix: string | 25 | private prefix: string |
26 | 26 | ||
27 | private constructor () {} | 27 | private constructor () { |
28 | } | ||
28 | 29 | ||
29 | init () { | 30 | init () { |
30 | // Already initialized | 31 | // Already initialized |
@@ -49,9 +50,9 @@ class Redis { | |||
49 | return Object.assign({}, | 50 | return Object.assign({}, |
50 | (CONFIG.REDIS.AUTH && CONFIG.REDIS.AUTH != null) ? { password: CONFIG.REDIS.AUTH } : {}, | 51 | (CONFIG.REDIS.AUTH && CONFIG.REDIS.AUTH != null) ? { password: CONFIG.REDIS.AUTH } : {}, |
51 | (CONFIG.REDIS.DB) ? { db: CONFIG.REDIS.DB } : {}, | 52 | (CONFIG.REDIS.DB) ? { db: CONFIG.REDIS.DB } : {}, |
52 | (CONFIG.REDIS.HOSTNAME && CONFIG.REDIS.PORT) ? | 53 | (CONFIG.REDIS.HOSTNAME && CONFIG.REDIS.PORT) |
53 | { host: CONFIG.REDIS.HOSTNAME, port: CONFIG.REDIS.PORT } : | 54 | ? { host: CONFIG.REDIS.HOSTNAME, port: CONFIG.REDIS.PORT } |
54 | { path: CONFIG.REDIS.SOCKET } | 55 | : { path: CONFIG.REDIS.SOCKET } |
55 | ) | 56 | ) |
56 | } | 57 | } |
57 | 58 | ||
@@ -63,7 +64,7 @@ class Redis { | |||
63 | return this.prefix | 64 | return this.prefix |
64 | } | 65 | } |
65 | 66 | ||
66 | /************* Forgot password *************/ | 67 | /* ************ Forgot password ************ */ |
67 | 68 | ||
68 | async setResetPasswordVerificationString (userId: number) { | 69 | async setResetPasswordVerificationString (userId: number) { |
69 | const generatedString = await generateRandomString(32) | 70 | const generatedString = await generateRandomString(32) |
@@ -77,7 +78,7 @@ class Redis { | |||
77 | return this.getValue(this.generateResetPasswordKey(userId)) | 78 | return this.getValue(this.generateResetPasswordKey(userId)) |
78 | } | 79 | } |
79 | 80 | ||
80 | /************* Email verification *************/ | 81 | /* ************ Email verification ************ */ |
81 | 82 | ||
82 | async setVerifyEmailVerificationString (userId: number) { | 83 | async setVerifyEmailVerificationString (userId: number) { |
83 | const generatedString = await generateRandomString(32) | 84 | const generatedString = await generateRandomString(32) |
@@ -91,7 +92,7 @@ class Redis { | |||
91 | return this.getValue(this.generateVerifyEmailKey(userId)) | 92 | return this.getValue(this.generateVerifyEmailKey(userId)) |
92 | } | 93 | } |
93 | 94 | ||
94 | /************* Contact form per IP *************/ | 95 | /* ************ Contact form per IP ************ */ |
95 | 96 | ||
96 | async setContactFormIp (ip: string) { | 97 | async setContactFormIp (ip: string) { |
97 | return this.setValue(this.generateContactFormKey(ip), '1', CONTACT_FORM_LIFETIME) | 98 | return this.setValue(this.generateContactFormKey(ip), '1', CONTACT_FORM_LIFETIME) |
@@ -101,7 +102,7 @@ class Redis { | |||
101 | return this.exists(this.generateContactFormKey(ip)) | 102 | return this.exists(this.generateContactFormKey(ip)) |
102 | } | 103 | } |
103 | 104 | ||
104 | /************* Views per IP *************/ | 105 | /* ************ Views per IP ************ */ |
105 | 106 | ||
106 | setIPVideoView (ip: string, videoUUID: string) { | 107 | setIPVideoView (ip: string, videoUUID: string) { |
107 | return this.setValue(this.generateViewKey(ip, videoUUID), '1', VIDEO_VIEW_LIFETIME) | 108 | return this.setValue(this.generateViewKey(ip, videoUUID), '1', VIDEO_VIEW_LIFETIME) |
@@ -111,7 +112,7 @@ class Redis { | |||
111 | return this.exists(this.generateViewKey(ip, videoUUID)) | 112 | return this.exists(this.generateViewKey(ip, videoUUID)) |
112 | } | 113 | } |
113 | 114 | ||
114 | /************* API cache *************/ | 115 | /* ************ API cache ************ */ |
115 | 116 | ||
116 | async getCachedRoute (req: express.Request) { | 117 | async getCachedRoute (req: express.Request) { |
117 | const cached = await this.getObject(this.generateCachedRouteKey(req)) | 118 | const cached = await this.getObject(this.generateCachedRouteKey(req)) |
@@ -120,17 +121,17 @@ class Redis { | |||
120 | } | 121 | } |
121 | 122 | ||
122 | setCachedRoute (req: express.Request, body: any, lifetime: number, contentType?: string, statusCode?: number) { | 123 | setCachedRoute (req: express.Request, body: any, lifetime: number, contentType?: string, statusCode?: number) { |
123 | const cached: CachedRoute = Object.assign({}, { | 124 | const cached: CachedRoute = Object.assign( |
124 | body: body.toString() | 125 | {}, |
125 | }, | 126 | { body: body.toString() }, |
126 | (contentType) ? { contentType } : null, | 127 | (contentType) ? { contentType } : null, |
127 | (statusCode) ? { statusCode: statusCode.toString() } : null | 128 | (statusCode) ? { statusCode: statusCode.toString() } : null |
128 | ) | 129 | ) |
129 | 130 | ||
130 | return this.setObject(this.generateCachedRouteKey(req), cached, lifetime) | 131 | return this.setObject(this.generateCachedRouteKey(req), cached, lifetime) |
131 | } | 132 | } |
132 | 133 | ||
133 | /************* Video views *************/ | 134 | /* ************ Video views ************ */ |
134 | 135 | ||
135 | addVideoView (videoId: number) { | 136 | addVideoView (videoId: number) { |
136 | const keyIncr = this.generateVideoViewKey(videoId) | 137 | const keyIncr = this.generateVideoViewKey(videoId) |
@@ -173,7 +174,7 @@ class Redis { | |||
173 | ]) | 174 | ]) |
174 | } | 175 | } |
175 | 176 | ||
176 | /************* Keys generation *************/ | 177 | /* ************ Keys generation ************ */ |
177 | 178 | ||
178 | generateCachedRouteKey (req: express.Request) { | 179 | generateCachedRouteKey (req: express.Request) { |
179 | return req.method + '-' + req.originalUrl | 180 | return req.method + '-' + req.originalUrl |
@@ -207,7 +208,7 @@ class Redis { | |||
207 | return 'contact-form-' + ip | 208 | return 'contact-form-' + ip |
208 | } | 209 | } |
209 | 210 | ||
210 | /************* Redis helpers *************/ | 211 | /* ************ Redis helpers ************ */ |
211 | 212 | ||
212 | private getValue (key: string) { | 213 | private getValue (key: string) { |
213 | return new Promise<string>((res, rej) => { | 214 | return new Promise<string>((res, rej) => { |
@@ -265,7 +266,7 @@ class Redis { | |||
265 | }) | 266 | }) |
266 | } | 267 | } |
267 | 268 | ||
268 | private setObject (key: string, obj: { [ id: string ]: string }, expirationMilliseconds: number) { | 269 | private setObject (key: string, obj: { [id: string]: string }, expirationMilliseconds: number) { |
269 | return new Promise<void>((res, rej) => { | 270 | return new Promise<void>((res, rej) => { |
270 | this.client.hmset(this.prefix + key, obj, (err, ok) => { | 271 | this.client.hmset(this.prefix + key, obj, (err, ok) => { |
271 | if (err) return rej(err) | 272 | if (err) return rej(err) |
@@ -282,7 +283,7 @@ class Redis { | |||
282 | } | 283 | } |
283 | 284 | ||
284 | private getObject (key: string) { | 285 | private getObject (key: string) { |
285 | return new Promise<{ [ id: string ]: string }>((res, rej) => { | 286 | return new Promise<{ [id: string]: string }>((res, rej) => { |
286 | this.client.hgetall(this.prefix + key, (err, value) => { | 287 | this.client.hgetall(this.prefix + key, (err, value) => { |
287 | if (err) return rej(err) | 288 | if (err) return rej(err) |
288 | 289 | ||
diff --git a/server/lib/schedulers/auto-follow-index-instances.ts b/server/lib/schedulers/auto-follow-index-instances.ts index dd326bc1e..d700a99f0 100644 --- a/server/lib/schedulers/auto-follow-index-instances.ts +++ b/server/lib/schedulers/auto-follow-index-instances.ts | |||
@@ -57,8 +57,7 @@ export class AutoFollowIndexInstances extends AbstractScheduler { | |||
57 | isAutoFollow: true | 57 | isAutoFollow: true |
58 | } | 58 | } |
59 | 59 | ||
60 | await JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) | 60 | JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) |
61 | .catch(err => logger.error('Cannot create follow job for %s.', unfollowedHost, err)) | ||
62 | } | 61 | } |
63 | } | 62 | } |
64 | 63 | ||
diff --git a/server/lib/schedulers/plugins-check-scheduler.ts b/server/lib/schedulers/plugins-check-scheduler.ts index 7ff41e639..014993e94 100644 --- a/server/lib/schedulers/plugins-check-scheduler.ts +++ b/server/lib/schedulers/plugins-check-scheduler.ts | |||
@@ -43,7 +43,7 @@ export class PluginsCheckScheduler extends AbstractScheduler { | |||
43 | const results = await getLatestPluginsVersion(npmNames) | 43 | const results = await getLatestPluginsVersion(npmNames) |
44 | 44 | ||
45 | for (const result of results) { | 45 | for (const result of results) { |
46 | const plugin = pluginIndex[ result.npmName ] | 46 | const plugin = pluginIndex[result.npmName] |
47 | if (!result.latestVersion) continue | 47 | if (!result.latestVersion) continue |
48 | 48 | ||
49 | if ( | 49 | if ( |
diff --git a/server/lib/schedulers/remove-old-views-scheduler.ts b/server/lib/schedulers/remove-old-views-scheduler.ts index 39fbb9163..5ae87fe50 100644 --- a/server/lib/schedulers/remove-old-views-scheduler.ts +++ b/server/lib/schedulers/remove-old-views-scheduler.ts | |||
@@ -1,9 +1,7 @@ | |||
1 | import { logger } from '../../helpers/logger' | 1 | import { logger } from '../../helpers/logger' |
2 | import { AbstractScheduler } from './abstract-scheduler' | 2 | import { AbstractScheduler } from './abstract-scheduler' |
3 | import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants' | 3 | import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants' |
4 | import { UserVideoHistoryModel } from '../../models/account/user-video-history' | ||
5 | import { CONFIG } from '../../initializers/config' | 4 | import { CONFIG } from '../../initializers/config' |
6 | import { isTestInstance } from '../../helpers/core-utils' | ||
7 | import { VideoViewModel } from '../../models/video/video-views' | 5 | import { VideoViewModel } from '../../models/video/video-views' |
8 | 6 | ||
9 | export class RemoveOldViewsScheduler extends AbstractScheduler { | 7 | export class RemoveOldViewsScheduler extends AbstractScheduler { |
diff --git a/server/lib/schedulers/videos-redundancy-scheduler.ts b/server/lib/schedulers/videos-redundancy-scheduler.ts index 6e61cbe7d..e33a4133a 100644 --- a/server/lib/schedulers/videos-redundancy-scheduler.ts +++ b/server/lib/schedulers/videos-redundancy-scheduler.ts | |||
@@ -28,9 +28,9 @@ import { getVideoFilename } from '../video-paths' | |||
28 | import { VideoModel } from '@server/models/video/video' | 28 | import { VideoModel } from '@server/models/video/video' |
29 | 29 | ||
30 | type CandidateToDuplicate = { | 30 | type CandidateToDuplicate = { |
31 | redundancy: VideosRedundancyStrategy, | 31 | redundancy: VideosRedundancyStrategy |
32 | video: MVideoWithAllFiles, | 32 | video: MVideoWithAllFiles |
33 | files: MVideoFile[], | 33 | files: MVideoFile[] |
34 | streamingPlaylists: MStreamingPlaylistFiles[] | 34 | streamingPlaylists: MStreamingPlaylistFiles[] |
35 | } | 35 | } |
36 | 36 | ||
diff --git a/server/lib/thumbnail.ts b/server/lib/thumbnail.ts index a99f71629..8dbd41771 100644 --- a/server/lib/thumbnail.ts +++ b/server/lib/thumbnail.ts | |||
@@ -69,7 +69,7 @@ function generateVideoMiniature (video: MVideoThumbnail, videoFile: MVideoFile, | |||
69 | function createPlaceholderThumbnail (fileUrl: string, video: MVideoThumbnail, type: ThumbnailType, size: ImageSize) { | 69 | function createPlaceholderThumbnail (fileUrl: string, video: MVideoThumbnail, type: ThumbnailType, size: ImageSize) { |
70 | const { filename, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) | 70 | const { filename, height, width, existingThumbnail } = buildMetadataFromVideo(video, type, size) |
71 | 71 | ||
72 | const thumbnail = existingThumbnail ? existingThumbnail : new ThumbnailModel() | 72 | const thumbnail = existingThumbnail || new ThumbnailModel() |
73 | 73 | ||
74 | thumbnail.filename = filename | 74 | thumbnail.filename = filename |
75 | thumbnail.height = height | 75 | thumbnail.height = height |
@@ -142,18 +142,18 @@ function buildMetadataFromVideo (video: MVideoThumbnail, type: ThumbnailType, si | |||
142 | } | 142 | } |
143 | 143 | ||
144 | async function createThumbnailFromFunction (parameters: { | 144 | async function createThumbnailFromFunction (parameters: { |
145 | thumbnailCreator: () => Promise<any>, | 145 | thumbnailCreator: () => Promise<any> |
146 | filename: string, | 146 | filename: string |
147 | height: number, | 147 | height: number |
148 | width: number, | 148 | width: number |
149 | type: ThumbnailType, | 149 | type: ThumbnailType |
150 | automaticallyGenerated?: boolean, | 150 | automaticallyGenerated?: boolean |
151 | fileUrl?: string, | 151 | fileUrl?: string |
152 | existingThumbnail?: MThumbnail | 152 | existingThumbnail?: MThumbnail |
153 | }) { | 153 | }) { |
154 | const { thumbnailCreator, filename, width, height, type, existingThumbnail, automaticallyGenerated = null, fileUrl = null } = parameters | 154 | const { thumbnailCreator, filename, width, height, type, existingThumbnail, automaticallyGenerated = null, fileUrl = null } = parameters |
155 | 155 | ||
156 | const thumbnail = existingThumbnail ? existingThumbnail : new ThumbnailModel() | 156 | const thumbnail = existingThumbnail || new ThumbnailModel() |
157 | 157 | ||
158 | thumbnail.filename = filename | 158 | thumbnail.filename = filename |
159 | thumbnail.height = height | 159 | thumbnail.height = height |
diff --git a/server/lib/user.ts b/server/lib/user.ts index c45438d95..88e60a7df 100644 --- a/server/lib/user.ts +++ b/server/lib/user.ts | |||
@@ -18,9 +18,9 @@ import { MUser, MUserDefault, MUserId } from '../typings/models/user' | |||
18 | type ChannelNames = { name: string, displayName: string } | 18 | type ChannelNames = { name: string, displayName: string } |
19 | 19 | ||
20 | async function createUserAccountAndChannelAndPlaylist (parameters: { | 20 | async function createUserAccountAndChannelAndPlaylist (parameters: { |
21 | userToCreate: MUser, | 21 | userToCreate: MUser |
22 | userDisplayName?: string, | 22 | userDisplayName?: string |
23 | channelNames?: ChannelNames, | 23 | channelNames?: ChannelNames |
24 | validateUser?: boolean | 24 | validateUser?: boolean |
25 | }): Promise<{ user: MUserDefault, account: MAccountDefault, videoChannel: MChannelActor }> { | 25 | }): Promise<{ user: MUserDefault, account: MAccountDefault, videoChannel: MChannelActor }> { |
26 | const { userToCreate, userDisplayName, channelNames, validateUser = true } = parameters | 26 | const { userToCreate, userDisplayName, channelNames, validateUser = true } = parameters |
@@ -63,11 +63,11 @@ async function createUserAccountAndChannelAndPlaylist (parameters: { | |||
63 | } | 63 | } |
64 | 64 | ||
65 | async function createLocalAccountWithoutKeys (parameters: { | 65 | async function createLocalAccountWithoutKeys (parameters: { |
66 | name: string, | 66 | name: string |
67 | displayName?: string, | 67 | displayName?: string |
68 | userId: number | null, | 68 | userId: number | null |
69 | applicationId: number | null, | 69 | applicationId: number | null |
70 | t: Transaction | undefined, | 70 | t: Transaction | undefined |
71 | type?: ActivityPubActorType | 71 | type?: ActivityPubActorType |
72 | }) { | 72 | }) { |
73 | const { name, displayName, userId, applicationId, t, type = 'Person' } = parameters | 73 | const { name, displayName, userId, applicationId, t, type = 'Person' } = parameters |
diff --git a/server/lib/video-blacklist.ts b/server/lib/video-blacklist.ts index 1dd45b76d..3b90b1b94 100644 --- a/server/lib/video-blacklist.ts +++ b/server/lib/video-blacklist.ts | |||
@@ -9,15 +9,15 @@ import { Notifier } from './notifier' | |||
9 | import { MUser, MVideoBlacklistVideo, MVideoWithBlacklistLight } from '@server/typings/models' | 9 | import { MUser, MVideoBlacklistVideo, MVideoWithBlacklistLight } from '@server/typings/models' |
10 | 10 | ||
11 | async function autoBlacklistVideoIfNeeded (parameters: { | 11 | async function autoBlacklistVideoIfNeeded (parameters: { |
12 | video: MVideoWithBlacklistLight, | 12 | video: MVideoWithBlacklistLight |
13 | user?: MUser, | 13 | user?: MUser |
14 | isRemote: boolean, | 14 | isRemote: boolean |
15 | isNew: boolean, | 15 | isNew: boolean |
16 | notify?: boolean, | 16 | notify?: boolean |
17 | transaction?: Transaction | 17 | transaction?: Transaction |
18 | }) { | 18 | }) { |
19 | const { video, user, isRemote, isNew, notify = true, transaction } = parameters | 19 | const { video, user, isRemote, isNew, notify = true, transaction } = parameters |
20 | const doAutoBlacklist = await Hooks.wrapPromiseFun( | 20 | const doAutoBlacklist = await Hooks.wrapFun( |
21 | autoBlacklistNeeded, | 21 | autoBlacklistNeeded, |
22 | { video, user, isRemote, isNew }, | 22 | { video, user, isRemote, isNew }, |
23 | 'filter:video.auto-blacklist.result' | 23 | 'filter:video.auto-blacklist.result' |
@@ -49,10 +49,10 @@ async function autoBlacklistVideoIfNeeded (parameters: { | |||
49 | return true | 49 | return true |
50 | } | 50 | } |
51 | 51 | ||
52 | async function autoBlacklistNeeded (parameters: { | 52 | function autoBlacklistNeeded (parameters: { |
53 | video: MVideoWithBlacklistLight, | 53 | video: MVideoWithBlacklistLight |
54 | isRemote: boolean, | 54 | isRemote: boolean |
55 | isNew: boolean, | 55 | isNew: boolean |
56 | user?: MUser | 56 | user?: MUser |
57 | }) { | 57 | }) { |
58 | const { user, video, isRemote, isNew } = parameters | 58 | const { user, video, isRemote, isNew } = parameters |
diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts index 41eab456b..14829c9d6 100644 --- a/server/lib/video-channel.ts +++ b/server/lib/video-channel.ts | |||
@@ -6,8 +6,7 @@ import { buildActorInstance, federateVideoIfNeeded, getVideoChannelActivityPubUr | |||
6 | import { VideoModel } from '../models/video/video' | 6 | import { VideoModel } from '../models/video/video' |
7 | import { MAccountId, MChannelDefault, MChannelId } from '../typings/models' | 7 | import { MAccountId, MChannelDefault, MChannelId } from '../typings/models' |
8 | 8 | ||
9 | type CustomVideoChannelModelAccount <T extends MAccountId> = MChannelDefault & | 9 | type CustomVideoChannelModelAccount <T extends MAccountId> = MChannelDefault & { Account?: T } |
10 | { Account?: T } | ||
11 | 10 | ||
12 | async function createLocalVideoChannel <T extends MAccountId> ( | 11 | async function createLocalVideoChannel <T extends MAccountId> ( |
13 | videoChannelInfo: VideoChannelCreate, | 12 | videoChannelInfo: VideoChannelCreate, |
diff --git a/server/lib/video-comment.ts b/server/lib/video-comment.ts index b8074e6d2..fe83d23e7 100644 --- a/server/lib/video-comment.ts +++ b/server/lib/video-comment.ts | |||
@@ -7,9 +7,9 @@ import { sendCreateVideoComment } from './activitypub/send' | |||
7 | import { MAccountDefault, MComment, MCommentOwnerVideoReply, MVideoFullLight } from '../typings/models' | 7 | import { MAccountDefault, MComment, MCommentOwnerVideoReply, MVideoFullLight } from '../typings/models' |
8 | 8 | ||
9 | async function createVideoComment (obj: { | 9 | async function createVideoComment (obj: { |
10 | text: string, | 10 | text: string |
11 | inReplyToComment: MComment | null, | 11 | inReplyToComment: MComment | null |
12 | video: MVideoFullLight, | 12 | video: MVideoFullLight |
13 | account: MAccountDefault | 13 | account: MAccountDefault |
14 | }, t: Sequelize.Transaction) { | 14 | }, t: Sequelize.Transaction) { |
15 | let originCommentId: number | null = null | 15 | let originCommentId: number | null = null |