diff options
author | Chocobozzz <me@florianbigard.com> | 2021-05-27 16:12:41 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-05-27 16:12:41 +0200 |
commit | 8f608a4cb22ab232cfab20665050764b38bac9c7 (patch) | |
tree | 6a6785aae79bf5939ad7b7a50a1bd8031268d2b4 /server/lib | |
parent | 030ccfce59a8cb8f2fee6ea8dd363ba635c5c5c2 (diff) | |
parent | c215e627b575d2c4085ccb222f4ca8d0237b7552 (diff) | |
download | PeerTube-8f608a4cb22ab232cfab20665050764b38bac9c7.tar.gz PeerTube-8f608a4cb22ab232cfab20665050764b38bac9c7.tar.zst PeerTube-8f608a4cb22ab232cfab20665050764b38bac9c7.zip |
Merge branch 'develop' into shorter-URLs-channels-accounts
Diffstat (limited to 'server/lib')
48 files changed, 540 insertions, 419 deletions
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index eec951d4e..1bcee7ef9 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts | |||
@@ -20,8 +20,8 @@ import { getUrlFromWebfinger } from '../../helpers/webfinger' | |||
20 | import { MIMETYPES, WEBSERVER } from '../../initializers/constants' | 20 | import { MIMETYPES, WEBSERVER } from '../../initializers/constants' |
21 | import { sequelizeTypescript } from '../../initializers/database' | 21 | import { sequelizeTypescript } from '../../initializers/database' |
22 | import { AccountModel } from '../../models/account/account' | 22 | import { AccountModel } from '../../models/account/account' |
23 | import { ActorImageModel } from '../../models/account/actor-image' | 23 | import { ActorModel } from '../../models/actor/actor' |
24 | import { ActorModel } from '../../models/activitypub/actor' | 24 | import { ActorImageModel } from '../../models/actor/actor-image' |
25 | import { ServerModel } from '../../models/server/server' | 25 | import { ServerModel } from '../../models/server/server' |
26 | import { VideoChannelModel } from '../../models/video/video-channel' | 26 | import { VideoChannelModel } from '../../models/video/video-channel' |
27 | import { | 27 | import { |
@@ -132,12 +132,11 @@ async function getOrCreateActorAndServerAndModel ( | |||
132 | return actorRefreshed | 132 | return actorRefreshed |
133 | } | 133 | } |
134 | 134 | ||
135 | function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string, uuid?: string) { | 135 | function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string) { |
136 | return new ActorModel({ | 136 | return new ActorModel({ |
137 | type, | 137 | type, |
138 | url, | 138 | url, |
139 | preferredUsername, | 139 | preferredUsername, |
140 | uuid, | ||
141 | publicKey: null, | 140 | publicKey: null, |
142 | privateKey: null, | 141 | privateKey: null, |
143 | followersCount: 0, | 142 | followersCount: 0, |
@@ -165,6 +164,8 @@ async function updateActorInstance (actorInstance: ActorModel, attributes: Activ | |||
165 | actorInstance.followersUrl = attributes.followers | 164 | actorInstance.followersUrl = attributes.followers |
166 | actorInstance.followingUrl = attributes.following | 165 | actorInstance.followingUrl = attributes.following |
167 | 166 | ||
167 | if (attributes.published) actorInstance.remoteCreatedAt = new Date(attributes.published) | ||
168 | |||
168 | if (attributes.endpoints?.sharedInbox) { | 169 | if (attributes.endpoints?.sharedInbox) { |
169 | actorInstance.sharedInboxUrl = attributes.endpoints.sharedInbox | 170 | actorInstance.sharedInboxUrl = attributes.endpoints.sharedInbox |
170 | } | 171 | } |
diff --git a/server/lib/activitypub/audience.ts b/server/lib/activitypub/audience.ts index 2986714d3..d0558f191 100644 --- a/server/lib/activitypub/audience.ts +++ b/server/lib/activitypub/audience.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Transaction } from 'sequelize' | 1 | import { Transaction } from 'sequelize' |
2 | import { ActivityAudience } from '../../../shared/models/activitypub' | 2 | import { ActivityAudience } from '../../../shared/models/activitypub' |
3 | import { ACTIVITY_PUB } from '../../initializers/constants' | 3 | import { ACTIVITY_PUB } from '../../initializers/constants' |
4 | import { ActorModel } from '../../models/activitypub/actor' | 4 | import { ActorModel } from '../../models/actor/actor' |
5 | import { VideoModel } from '../../models/video/video' | 5 | import { VideoModel } from '../../models/video/video' |
6 | import { VideoShareModel } from '../../models/video/video-share' | 6 | import { VideoShareModel } from '../../models/video/video-share' |
7 | import { MActorFollowersUrl, MActorLight, MActorUrl, MCommentOwner, MCommentOwnerVideo, MVideoId } from '../../types/models' | 7 | import { MActorFollowersUrl, MActorLight, MActorUrl, MCommentOwner, MCommentOwnerVideo, MVideoId } from '../../types/models' |
diff --git a/server/lib/activitypub/process/process-accept.ts b/server/lib/activitypub/process/process-accept.ts index 1799829f8..8ad470cf4 100644 --- a/server/lib/activitypub/process/process-accept.ts +++ b/server/lib/activitypub/process/process-accept.ts | |||
@@ -1,8 +1,8 @@ | |||
1 | import { ActivityAccept } from '../../../../shared/models/activitypub' | 1 | import { ActivityAccept } from '../../../../shared/models/activitypub' |
2 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | 2 | import { ActorFollowModel } from '../../../models/actor/actor-follow' |
3 | import { addFetchOutboxJob } from '../actor' | ||
4 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' | 3 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' |
5 | import { MActorDefault, MActorSignature } from '../../../types/models' | 4 | import { MActorDefault, MActorSignature } from '../../../types/models' |
5 | import { addFetchOutboxJob } from '../actor' | ||
6 | 6 | ||
7 | async function processAcceptActivity (options: APProcessorOptions<ActivityAccept>) { | 7 | async function processAcceptActivity (options: APProcessorOptions<ActivityAccept>) { |
8 | const { byActor: targetActor, inboxActor } = options | 8 | const { byActor: targetActor, inboxActor } = options |
diff --git a/server/lib/activitypub/process/process-delete.ts b/server/lib/activitypub/process/process-delete.ts index 88a968318..20214246c 100644 --- a/server/lib/activitypub/process/process-delete.ts +++ b/server/lib/activitypub/process/process-delete.ts | |||
@@ -2,7 +2,7 @@ import { ActivityDelete } from '../../../../shared/models/activitypub' | |||
2 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 2 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
3 | import { logger } from '../../../helpers/logger' | 3 | import { logger } from '../../../helpers/logger' |
4 | import { sequelizeTypescript } from '../../../initializers/database' | 4 | import { sequelizeTypescript } from '../../../initializers/database' |
5 | import { ActorModel } from '../../../models/activitypub/actor' | 5 | import { ActorModel } from '../../../models/actor/actor' |
6 | import { VideoModel } from '../../../models/video/video' | 6 | import { VideoModel } from '../../../models/video/video' |
7 | import { VideoCommentModel } from '../../../models/video/video-comment' | 7 | import { VideoCommentModel } from '../../../models/video/video-comment' |
8 | import { VideoPlaylistModel } from '../../../models/video/video-playlist' | 8 | import { VideoPlaylistModel } from '../../../models/video/video-playlist' |
diff --git a/server/lib/activitypub/process/process-follow.ts b/server/lib/activitypub/process/process-follow.ts index 38d684512..9009c6469 100644 --- a/server/lib/activitypub/process/process-follow.ts +++ b/server/lib/activitypub/process/process-follow.ts | |||
@@ -1,17 +1,17 @@ | |||
1 | import { getServerActor } from '@server/models/application/application' | ||
1 | import { ActivityFollow } from '../../../../shared/models/activitypub' | 2 | import { ActivityFollow } from '../../../../shared/models/activitypub' |
3 | import { getAPId } from '../../../helpers/activitypub' | ||
2 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 4 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
3 | import { logger } from '../../../helpers/logger' | 5 | import { logger } from '../../../helpers/logger' |
4 | import { sequelizeTypescript } from '../../../initializers/database' | ||
5 | import { ActorModel } from '../../../models/activitypub/actor' | ||
6 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | ||
7 | import { sendAccept, sendReject } from '../send' | ||
8 | import { Notifier } from '../../notifier' | ||
9 | import { getAPId } from '../../../helpers/activitypub' | ||
10 | import { CONFIG } from '../../../initializers/config' | 6 | import { CONFIG } from '../../../initializers/config' |
7 | import { sequelizeTypescript } from '../../../initializers/database' | ||
8 | import { ActorModel } from '../../../models/actor/actor' | ||
9 | import { ActorFollowModel } from '../../../models/actor/actor-follow' | ||
11 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' | 10 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' |
12 | import { MActorFollowActors, MActorSignature } from '../../../types/models' | 11 | import { MActorFollowActors, MActorSignature } from '../../../types/models' |
12 | import { Notifier } from '../../notifier' | ||
13 | import { autoFollowBackIfNeeded } from '../follow' | 13 | import { autoFollowBackIfNeeded } from '../follow' |
14 | import { getServerActor } from '@server/models/application/application' | 14 | import { sendAccept, sendReject } from '../send' |
15 | 15 | ||
16 | async function processFollowActivity (options: APProcessorOptions<ActivityFollow>) { | 16 | async function processFollowActivity (options: APProcessorOptions<ActivityFollow>) { |
17 | const { activity, byActor } = options | 17 | const { activity, byActor } = options |
diff --git a/server/lib/activitypub/process/process-reject.ts b/server/lib/activitypub/process/process-reject.ts index 03b669fd9..7f7ab305f 100644 --- a/server/lib/activitypub/process/process-reject.ts +++ b/server/lib/activitypub/process/process-reject.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { ActivityReject } from '../../../../shared/models/activitypub/activity' | 1 | import { ActivityReject } from '../../../../shared/models/activitypub/activity' |
2 | import { sequelizeTypescript } from '../../../initializers/database' | 2 | import { sequelizeTypescript } from '../../../initializers/database' |
3 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | 3 | import { ActorFollowModel } from '../../../models/actor/actor-follow' |
4 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' | 4 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' |
5 | import { MActor } from '../../../types/models' | 5 | import { MActor } from '../../../types/models' |
6 | 6 | ||
diff --git a/server/lib/activitypub/process/process-undo.ts b/server/lib/activitypub/process/process-undo.ts index e520c2f0d..9f031b528 100644 --- a/server/lib/activitypub/process/process-undo.ts +++ b/server/lib/activitypub/process/process-undo.ts | |||
@@ -4,8 +4,8 @@ import { retryTransactionWrapper } from '../../../helpers/database-utils' | |||
4 | import { logger } from '../../../helpers/logger' | 4 | import { logger } from '../../../helpers/logger' |
5 | import { sequelizeTypescript } from '../../../initializers/database' | 5 | import { sequelizeTypescript } from '../../../initializers/database' |
6 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' | 6 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' |
7 | import { ActorModel } from '../../../models/activitypub/actor' | 7 | import { ActorModel } from '../../../models/actor/actor' |
8 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | 8 | import { ActorFollowModel } from '../../../models/actor/actor-follow' |
9 | import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy' | 9 | import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy' |
10 | import { VideoShareModel } from '../../../models/video/video-share' | 10 | import { VideoShareModel } from '../../../models/video/video-share' |
11 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' | 11 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' |
diff --git a/server/lib/activitypub/process/process-update.ts b/server/lib/activitypub/process/process-update.ts index 6df9b93b2..6cd9d0fba 100644 --- a/server/lib/activitypub/process/process-update.ts +++ b/server/lib/activitypub/process/process-update.ts | |||
@@ -1,23 +1,23 @@ | |||
1 | import { isRedundancyAccepted } from '@server/lib/redundancy' | ||
2 | import { ActorImageType } from '@shared/models' | ||
1 | import { ActivityUpdate, CacheFileObject, VideoObject } from '../../../../shared/models/activitypub' | 3 | import { ActivityUpdate, CacheFileObject, VideoObject } from '../../../../shared/models/activitypub' |
2 | import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor' | 4 | import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor' |
5 | import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object' | ||
6 | import { isCacheFileObjectValid } from '../../../helpers/custom-validators/activitypub/cache-file' | ||
7 | import { sanitizeAndCheckVideoTorrentObject } from '../../../helpers/custom-validators/activitypub/videos' | ||
3 | import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils' | 8 | import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils' |
4 | import { logger } from '../../../helpers/logger' | 9 | import { logger } from '../../../helpers/logger' |
5 | import { sequelizeTypescript } from '../../../initializers/database' | 10 | import { sequelizeTypescript } from '../../../initializers/database' |
6 | import { AccountModel } from '../../../models/account/account' | 11 | import { AccountModel } from '../../../models/account/account' |
7 | import { ActorModel } from '../../../models/activitypub/actor' | 12 | import { ActorModel } from '../../../models/actor/actor' |
8 | import { VideoChannelModel } from '../../../models/video/video-channel' | 13 | import { VideoChannelModel } from '../../../models/video/video-channel' |
14 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' | ||
15 | import { MAccountIdActor, MActorSignature } from '../../../types/models' | ||
9 | import { getImageInfoIfExists, updateActorImageInstance, updateActorInstance } from '../actor' | 16 | import { getImageInfoIfExists, updateActorImageInstance, updateActorInstance } from '../actor' |
10 | import { getOrCreateVideoAndAccountAndChannel, getOrCreateVideoChannelFromVideoObject, updateVideoFromAP } from '../videos' | ||
11 | import { sanitizeAndCheckVideoTorrentObject } from '../../../helpers/custom-validators/activitypub/videos' | ||
12 | import { isCacheFileObjectValid } from '../../../helpers/custom-validators/activitypub/cache-file' | ||
13 | import { createOrUpdateCacheFile } from '../cache-file' | 17 | import { createOrUpdateCacheFile } from '../cache-file' |
14 | import { forwardVideoRelatedActivity } from '../send/utils' | ||
15 | import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object' | ||
16 | import { createOrUpdateVideoPlaylist } from '../playlist' | 18 | import { createOrUpdateVideoPlaylist } from '../playlist' |
17 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' | 19 | import { forwardVideoRelatedActivity } from '../send/utils' |
18 | import { MActorSignature, MAccountIdActor } from '../../../types/models' | 20 | import { getOrCreateVideoAndAccountAndChannel, getOrCreateVideoChannelFromVideoObject, updateVideoFromAP } from '../videos' |
19 | import { isRedundancyAccepted } from '@server/lib/redundancy' | ||
20 | import { ActorImageType } from '@shared/models' | ||
21 | 21 | ||
22 | async function processUpdateActivity (options: APProcessorOptions<ActivityUpdate>) { | 22 | async function processUpdateActivity (options: APProcessorOptions<ActivityUpdate>) { |
23 | const { activity, byActor } = options | 23 | const { activity, byActor } = options |
diff --git a/server/lib/activitypub/send/send-delete.ts b/server/lib/activitypub/send/send-delete.ts index e0acced18..d31f8c10b 100644 --- a/server/lib/activitypub/send/send-delete.ts +++ b/server/lib/activitypub/send/send-delete.ts | |||
@@ -2,7 +2,7 @@ import { Transaction } from 'sequelize' | |||
2 | import { getServerActor } from '@server/models/application/application' | 2 | import { getServerActor } from '@server/models/application/application' |
3 | import { ActivityAudience, ActivityDelete } from '../../../../shared/models/activitypub' | 3 | import { ActivityAudience, ActivityDelete } from '../../../../shared/models/activitypub' |
4 | import { logger } from '../../../helpers/logger' | 4 | import { logger } from '../../../helpers/logger' |
5 | import { ActorModel } from '../../../models/activitypub/actor' | 5 | import { ActorModel } from '../../../models/actor/actor' |
6 | import { VideoCommentModel } from '../../../models/video/video-comment' | 6 | import { VideoCommentModel } from '../../../models/video/video-comment' |
7 | import { VideoShareModel } from '../../../models/video/video-share' | 7 | import { VideoShareModel } from '../../../models/video/video-share' |
8 | import { MActorUrl } from '../../../types/models' | 8 | import { MActorUrl } from '../../../types/models' |
diff --git a/server/lib/activitypub/send/send-view.ts b/server/lib/activitypub/send/send-view.ts index 9254dc7c5..153e94295 100644 --- a/server/lib/activitypub/send/send-view.ts +++ b/server/lib/activitypub/send/send-view.ts | |||
@@ -2,7 +2,7 @@ import { Transaction } from 'sequelize' | |||
2 | import { MActorAudience, MVideoImmutable, MVideoUrl } from '@server/types/models' | 2 | import { MActorAudience, MVideoImmutable, MVideoUrl } from '@server/types/models' |
3 | import { ActivityAudience, ActivityView } from '../../../../shared/models/activitypub' | 3 | import { ActivityAudience, ActivityView } from '../../../../shared/models/activitypub' |
4 | import { logger } from '../../../helpers/logger' | 4 | import { logger } from '../../../helpers/logger' |
5 | import { ActorModel } from '../../../models/activitypub/actor' | 5 | import { ActorModel } from '../../../models/actor/actor' |
6 | import { audiencify, getAudience } from '../audience' | 6 | import { audiencify, getAudience } from '../audience' |
7 | import { getLocalVideoViewActivityPubUrl } from '../url' | 7 | import { getLocalVideoViewActivityPubUrl } from '../url' |
8 | import { sendVideoRelatedActivity } from './utils' | 8 | import { sendVideoRelatedActivity } from './utils' |
diff --git a/server/lib/activitypub/send/utils.ts b/server/lib/activitypub/send/utils.ts index 85a9f009d..db0e91b71 100644 --- a/server/lib/activitypub/send/utils.ts +++ b/server/lib/activitypub/send/utils.ts | |||
@@ -1,14 +1,14 @@ | |||
1 | import { Transaction } from 'sequelize' | 1 | import { Transaction } from 'sequelize' |
2 | import { getServerActor } from '@server/models/application/application' | ||
3 | import { ContextType } from '@shared/models/activitypub/context' | ||
2 | import { Activity, ActivityAudience } from '../../../../shared/models/activitypub' | 4 | import { Activity, ActivityAudience } from '../../../../shared/models/activitypub' |
5 | import { afterCommitIfTransaction } from '../../../helpers/database-utils' | ||
3 | import { logger } from '../../../helpers/logger' | 6 | import { logger } from '../../../helpers/logger' |
4 | import { ActorModel } from '../../../models/activitypub/actor' | 7 | import { ActorModel } from '../../../models/actor/actor' |
5 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | 8 | import { ActorFollowModel } from '../../../models/actor/actor-follow' |
9 | import { MActor, MActorId, MActorLight, MActorWithInboxes, MVideoAccountLight, MVideoId, MVideoImmutable } from '../../../types/models' | ||
6 | import { JobQueue } from '../../job-queue' | 10 | import { JobQueue } from '../../job-queue' |
7 | import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience' | 11 | import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience' |
8 | import { afterCommitIfTransaction } from '../../../helpers/database-utils' | ||
9 | import { MActor, MActorId, MActorLight, MActorWithInboxes, MVideoAccountLight, MVideoId, MVideoImmutable } from '../../../types/models' | ||
10 | import { getServerActor } from '@server/models/application/application' | ||
11 | import { ContextType } from '@shared/models/activitypub/context' | ||
12 | 12 | ||
13 | async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { | 13 | async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { |
14 | byActor: MActorLight | 14 | byActor: MActorLight |
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index 506204674..15726f90b 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -697,6 +697,9 @@ async function createVideo (videoObject: VideoObject, channel: MChannelAccountLi | |||
697 | videoCreated.VideoLive = await videoLive.save({ transaction: t }) | 697 | videoCreated.VideoLive = await videoLive.save({ transaction: t }) |
698 | } | 698 | } |
699 | 699 | ||
700 | // We added a video in this channel, set it as updated | ||
701 | await channel.setAsUpdated(t) | ||
702 | |||
700 | const autoBlacklisted = await autoBlacklistVideoIfNeeded({ | 703 | const autoBlacklisted = await autoBlacklistVideoIfNeeded({ |
701 | video: videoCreated, | 704 | video: videoCreated, |
702 | user: undefined, | 705 | user: undefined, |
diff --git a/server/lib/auth/oauth-model.ts b/server/lib/auth/oauth-model.ts index b9c69eb2d..ae728d080 100644 --- a/server/lib/auth/oauth-model.ts +++ b/server/lib/auth/oauth-model.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { AccessDeniedError } from 'oauth2-server' | 2 | import { AccessDeniedError } from 'oauth2-server' |
3 | import { PluginManager } from '@server/lib/plugins/plugin-manager' | 3 | import { PluginManager } from '@server/lib/plugins/plugin-manager' |
4 | import { ActorModel } from '@server/models/activitypub/actor' | 4 | import { ActorModel } from '@server/models/actor/actor' |
5 | import { MOAuthClient } from '@server/types/models' | 5 | import { MOAuthClient } from '@server/types/models' |
6 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' | 6 | import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' |
7 | import { MUser } from '@server/types/models/user/user' | 7 | import { MUser } from '@server/types/models/user/user' |
@@ -9,7 +9,7 @@ import { UserAdminFlag } from '@shared/models/users/user-flag.model' | |||
9 | import { UserRole } from '@shared/models/users/user-role' | 9 | import { UserRole } from '@shared/models/users/user-role' |
10 | import { logger } from '../../helpers/logger' | 10 | import { logger } from '../../helpers/logger' |
11 | import { CONFIG } from '../../initializers/config' | 11 | import { CONFIG } from '../../initializers/config' |
12 | import { UserModel } from '../../models/account/user' | 12 | import { UserModel } from '../../models/user/user' |
13 | import { OAuthClientModel } from '../../models/oauth/oauth-client' | 13 | import { OAuthClientModel } from '../../models/oauth/oauth-client' |
14 | import { OAuthTokenModel } from '../../models/oauth/oauth-token' | 14 | import { OAuthTokenModel } from '../../models/oauth/oauth-token' |
15 | import { createUserAccountAndChannelAndPlaylist } from '../user' | 15 | import { createUserAccountAndChannelAndPlaylist } from '../user' |
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts index cac9edb30..2f6bce1c7 100644 --- a/server/lib/client-html.ts +++ b/server/lib/client-html.ts | |||
@@ -2,12 +2,14 @@ import * as express from 'express' | |||
2 | import { readFile } from 'fs-extra' | 2 | import { readFile } from 'fs-extra' |
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import validator from 'validator' | 4 | import validator from 'validator' |
5 | import { escapeHTML } from '@shared/core-utils/renderer' | ||
6 | import { HTMLServerConfig } from '@shared/models' | ||
5 | import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' | 7 | import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' |
6 | import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' | 8 | import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' |
7 | import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos' | 9 | import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos' |
8 | import { isTestInstance, sha256 } from '../helpers/core-utils' | 10 | import { isTestInstance, sha256 } from '../helpers/core-utils' |
9 | import { escapeHTML } from '@shared/core-utils/renderer' | ||
10 | import { logger } from '../helpers/logger' | 11 | import { logger } from '../helpers/logger' |
12 | import { mdToPlainText } from '../helpers/markdown' | ||
11 | import { CONFIG } from '../initializers/config' | 13 | import { CONFIG } from '../initializers/config' |
12 | import { | 14 | import { |
13 | ACCEPT_HEADERS, | 15 | ACCEPT_HEADERS, |
@@ -24,7 +26,7 @@ import { VideoChannelModel } from '../models/video/video-channel' | |||
24 | import { getActivityStreamDuration } from '../models/video/video-format-utils' | 26 | import { getActivityStreamDuration } from '../models/video/video-format-utils' |
25 | import { VideoPlaylistModel } from '../models/video/video-playlist' | 27 | import { VideoPlaylistModel } from '../models/video/video-playlist' |
26 | import { MAccountActor, MChannelActor } from '../types/models' | 28 | import { MAccountActor, MChannelActor } from '../types/models' |
27 | import { mdToPlainText } from '../helpers/markdown' | 29 | import { ServerConfigManager } from './server-config-manager' |
28 | 30 | ||
29 | type Tags = { | 31 | type Tags = { |
30 | ogType: string | 32 | ogType: string |
@@ -222,11 +224,14 @@ class ClientHtml { | |||
222 | if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path] | 224 | if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path] |
223 | 225 | ||
224 | const buffer = await readFile(path) | 226 | const buffer = await readFile(path) |
227 | const serverConfig = await ServerConfigManager.Instance.getHTMLServerConfig() | ||
225 | 228 | ||
226 | let html = buffer.toString() | 229 | let html = buffer.toString() |
227 | html = await ClientHtml.addAsyncPluginCSS(html) | 230 | html = await ClientHtml.addAsyncPluginCSS(html) |
228 | html = ClientHtml.addCustomCSS(html) | 231 | html = ClientHtml.addCustomCSS(html) |
229 | html = ClientHtml.addTitleTag(html) | 232 | html = ClientHtml.addTitleTag(html) |
233 | html = ClientHtml.addDescriptionTag(html) | ||
234 | html = ClientHtml.addServerConfig(html, serverConfig) | ||
230 | 235 | ||
231 | ClientHtml.htmlCache[path] = html | 236 | ClientHtml.htmlCache[path] = html |
232 | 237 | ||
@@ -288,6 +293,7 @@ class ClientHtml { | |||
288 | if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path] | 293 | if (!isTestInstance() && ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path] |
289 | 294 | ||
290 | const buffer = await readFile(path) | 295 | const buffer = await readFile(path) |
296 | const serverConfig = await ServerConfigManager.Instance.getHTMLServerConfig() | ||
291 | 297 | ||
292 | let html = buffer.toString() | 298 | let html = buffer.toString() |
293 | 299 | ||
@@ -296,6 +302,7 @@ class ClientHtml { | |||
296 | html = ClientHtml.addFaviconContentHash(html) | 302 | html = ClientHtml.addFaviconContentHash(html) |
297 | html = ClientHtml.addLogoContentHash(html) | 303 | html = ClientHtml.addLogoContentHash(html) |
298 | html = ClientHtml.addCustomCSS(html) | 304 | html = ClientHtml.addCustomCSS(html) |
305 | html = ClientHtml.addServerConfig(html, serverConfig) | ||
299 | html = await ClientHtml.addAsyncPluginCSS(html) | 306 | html = await ClientHtml.addAsyncPluginCSS(html) |
300 | 307 | ||
301 | ClientHtml.htmlCache[path] = html | 308 | ClientHtml.htmlCache[path] = html |
@@ -368,6 +375,13 @@ class ClientHtml { | |||
368 | return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag) | 375 | return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.CUSTOM_CSS, styleTag) |
369 | } | 376 | } |
370 | 377 | ||
378 | private static addServerConfig (htmlStringPage: string, serverConfig: HTMLServerConfig) { | ||
379 | const serverConfigString = JSON.stringify(serverConfig) | ||
380 | const configScriptTag = `<script type="application/javascript">window.PeerTubeServerConfig = '${serverConfigString}'</script>` | ||
381 | |||
382 | return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.SERVER_CONFIG, configScriptTag) | ||
383 | } | ||
384 | |||
371 | private static async addAsyncPluginCSS (htmlStringPage: string) { | 385 | private static async addAsyncPluginCSS (htmlStringPage: string) { |
372 | const globalCSSContent = await readFile(PLUGIN_GLOBAL_CSS_PATH) | 386 | const globalCSSContent = await readFile(PLUGIN_GLOBAL_CSS_PATH) |
373 | if (globalCSSContent.byteLength === 0) return htmlStringPage | 387 | if (globalCSSContent.byteLength === 0) return htmlStringPage |
diff --git a/server/lib/config.ts b/server/lib/config.ts deleted file mode 100644 index b4c4c9299..000000000 --- a/server/lib/config.ts +++ /dev/null | |||
@@ -1,255 +0,0 @@ | |||
1 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/helpers/signup' | ||
2 | import { getServerCommit } from '@server/helpers/utils' | ||
3 | import { CONFIG, isEmailEnabled } from '@server/initializers/config' | ||
4 | import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants' | ||
5 | import { RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models' | ||
6 | import { Hooks } from './plugins/hooks' | ||
7 | import { PluginManager } from './plugins/plugin-manager' | ||
8 | import { getThemeOrDefault } from './plugins/theme-utils' | ||
9 | import { getEnabledResolutions } from './video-transcoding' | ||
10 | import { VideoTranscodingProfilesManager } from './video-transcoding-profiles' | ||
11 | |||
12 | let serverCommit: string | ||
13 | |||
14 | async function getServerConfig (ip?: string): Promise<ServerConfig> { | ||
15 | if (serverCommit === undefined) serverCommit = await getServerCommit() | ||
16 | |||
17 | const { allowed } = await Hooks.wrapPromiseFun( | ||
18 | isSignupAllowed, | ||
19 | { | ||
20 | ip | ||
21 | }, | ||
22 | 'filter:api.user.signup.allowed.result' | ||
23 | ) | ||
24 | |||
25 | const allowedForCurrentIP = isSignupAllowedForCurrentIP(ip) | ||
26 | const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) | ||
27 | |||
28 | return { | ||
29 | instance: { | ||
30 | name: CONFIG.INSTANCE.NAME, | ||
31 | shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION, | ||
32 | isNSFW: CONFIG.INSTANCE.IS_NSFW, | ||
33 | defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY, | ||
34 | defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE, | ||
35 | customizations: { | ||
36 | javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT, | ||
37 | css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS | ||
38 | } | ||
39 | }, | ||
40 | search: { | ||
41 | remoteUri: { | ||
42 | users: CONFIG.SEARCH.REMOTE_URI.USERS, | ||
43 | anonymous: CONFIG.SEARCH.REMOTE_URI.ANONYMOUS | ||
44 | }, | ||
45 | searchIndex: { | ||
46 | enabled: CONFIG.SEARCH.SEARCH_INDEX.ENABLED, | ||
47 | url: CONFIG.SEARCH.SEARCH_INDEX.URL, | ||
48 | disableLocalSearch: CONFIG.SEARCH.SEARCH_INDEX.DISABLE_LOCAL_SEARCH, | ||
49 | isDefaultSearch: CONFIG.SEARCH.SEARCH_INDEX.IS_DEFAULT_SEARCH | ||
50 | } | ||
51 | }, | ||
52 | plugin: { | ||
53 | registered: getRegisteredPlugins(), | ||
54 | registeredExternalAuths: getExternalAuthsPlugins(), | ||
55 | registeredIdAndPassAuths: getIdAndPassAuthPlugins() | ||
56 | }, | ||
57 | theme: { | ||
58 | registered: getRegisteredThemes(), | ||
59 | default: defaultTheme | ||
60 | }, | ||
61 | email: { | ||
62 | enabled: isEmailEnabled() | ||
63 | }, | ||
64 | contactForm: { | ||
65 | enabled: CONFIG.CONTACT_FORM.ENABLED | ||
66 | }, | ||
67 | serverVersion: PEERTUBE_VERSION, | ||
68 | serverCommit, | ||
69 | signup: { | ||
70 | allowed, | ||
71 | allowedForCurrentIP, | ||
72 | requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION | ||
73 | }, | ||
74 | transcoding: { | ||
75 | hls: { | ||
76 | enabled: CONFIG.TRANSCODING.HLS.ENABLED | ||
77 | }, | ||
78 | webtorrent: { | ||
79 | enabled: CONFIG.TRANSCODING.WEBTORRENT.ENABLED | ||
80 | }, | ||
81 | enabledResolutions: getEnabledResolutions('vod'), | ||
82 | profile: CONFIG.TRANSCODING.PROFILE, | ||
83 | availableProfiles: VideoTranscodingProfilesManager.Instance.getAvailableProfiles('vod') | ||
84 | }, | ||
85 | live: { | ||
86 | enabled: CONFIG.LIVE.ENABLED, | ||
87 | |||
88 | allowReplay: CONFIG.LIVE.ALLOW_REPLAY, | ||
89 | maxDuration: CONFIG.LIVE.MAX_DURATION, | ||
90 | maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES, | ||
91 | maxUserLives: CONFIG.LIVE.MAX_USER_LIVES, | ||
92 | |||
93 | transcoding: { | ||
94 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, | ||
95 | enabledResolutions: getEnabledResolutions('live'), | ||
96 | profile: CONFIG.LIVE.TRANSCODING.PROFILE, | ||
97 | availableProfiles: VideoTranscodingProfilesManager.Instance.getAvailableProfiles('live') | ||
98 | }, | ||
99 | |||
100 | rtmp: { | ||
101 | port: CONFIG.LIVE.RTMP.PORT | ||
102 | } | ||
103 | }, | ||
104 | import: { | ||
105 | videos: { | ||
106 | http: { | ||
107 | enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED | ||
108 | }, | ||
109 | torrent: { | ||
110 | enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED | ||
111 | } | ||
112 | } | ||
113 | }, | ||
114 | autoBlacklist: { | ||
115 | videos: { | ||
116 | ofUsers: { | ||
117 | enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED | ||
118 | } | ||
119 | } | ||
120 | }, | ||
121 | avatar: { | ||
122 | file: { | ||
123 | size: { | ||
124 | max: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
125 | }, | ||
126 | extensions: CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | ||
127 | } | ||
128 | }, | ||
129 | banner: { | ||
130 | file: { | ||
131 | size: { | ||
132 | max: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
133 | }, | ||
134 | extensions: CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | ||
135 | } | ||
136 | }, | ||
137 | video: { | ||
138 | image: { | ||
139 | extensions: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME, | ||
140 | size: { | ||
141 | max: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max | ||
142 | } | ||
143 | }, | ||
144 | file: { | ||
145 | extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME | ||
146 | } | ||
147 | }, | ||
148 | videoCaption: { | ||
149 | file: { | ||
150 | size: { | ||
151 | max: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max | ||
152 | }, | ||
153 | extensions: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.EXTNAME | ||
154 | } | ||
155 | }, | ||
156 | user: { | ||
157 | videoQuota: CONFIG.USER.VIDEO_QUOTA, | ||
158 | videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY | ||
159 | }, | ||
160 | trending: { | ||
161 | videos: { | ||
162 | intervalDays: CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS, | ||
163 | algorithms: { | ||
164 | enabled: CONFIG.TRENDING.VIDEOS.ALGORITHMS.ENABLED, | ||
165 | default: CONFIG.TRENDING.VIDEOS.ALGORITHMS.DEFAULT | ||
166 | } | ||
167 | } | ||
168 | }, | ||
169 | tracker: { | ||
170 | enabled: CONFIG.TRACKER.ENABLED | ||
171 | }, | ||
172 | |||
173 | followings: { | ||
174 | instance: { | ||
175 | autoFollowIndex: { | ||
176 | indexUrl: CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_INDEX.INDEX_URL | ||
177 | } | ||
178 | } | ||
179 | }, | ||
180 | |||
181 | broadcastMessage: { | ||
182 | enabled: CONFIG.BROADCAST_MESSAGE.ENABLED, | ||
183 | message: CONFIG.BROADCAST_MESSAGE.MESSAGE, | ||
184 | level: CONFIG.BROADCAST_MESSAGE.LEVEL, | ||
185 | dismissable: CONFIG.BROADCAST_MESSAGE.DISMISSABLE | ||
186 | } | ||
187 | } | ||
188 | } | ||
189 | |||
190 | function getRegisteredThemes () { | ||
191 | return PluginManager.Instance.getRegisteredThemes() | ||
192 | .map(t => ({ | ||
193 | name: t.name, | ||
194 | version: t.version, | ||
195 | description: t.description, | ||
196 | css: t.css, | ||
197 | clientScripts: t.clientScripts | ||
198 | })) | ||
199 | } | ||
200 | |||
201 | function getRegisteredPlugins () { | ||
202 | return PluginManager.Instance.getRegisteredPlugins() | ||
203 | .map(p => ({ | ||
204 | name: p.name, | ||
205 | version: p.version, | ||
206 | description: p.description, | ||
207 | clientScripts: p.clientScripts | ||
208 | })) | ||
209 | } | ||
210 | |||
211 | // --------------------------------------------------------------------------- | ||
212 | |||
213 | export { | ||
214 | getServerConfig, | ||
215 | getRegisteredThemes, | ||
216 | getRegisteredPlugins | ||
217 | } | ||
218 | |||
219 | // --------------------------------------------------------------------------- | ||
220 | |||
221 | function getIdAndPassAuthPlugins () { | ||
222 | const result: RegisteredIdAndPassAuthConfig[] = [] | ||
223 | |||
224 | for (const p of PluginManager.Instance.getIdAndPassAuths()) { | ||
225 | for (const auth of p.idAndPassAuths) { | ||
226 | result.push({ | ||
227 | npmName: p.npmName, | ||
228 | name: p.name, | ||
229 | version: p.version, | ||
230 | authName: auth.authName, | ||
231 | weight: auth.getWeight() | ||
232 | }) | ||
233 | } | ||
234 | } | ||
235 | |||
236 | return result | ||
237 | } | ||
238 | |||
239 | function getExternalAuthsPlugins () { | ||
240 | const result: RegisteredExternalAuthConfig[] = [] | ||
241 | |||
242 | for (const p of PluginManager.Instance.getExternalAuths()) { | ||
243 | for (const auth of p.externalAuths) { | ||
244 | result.push({ | ||
245 | npmName: p.npmName, | ||
246 | name: p.name, | ||
247 | version: p.version, | ||
248 | authName: auth.authName, | ||
249 | authDisplayName: auth.authDisplayName() | ||
250 | }) | ||
251 | } | ||
252 | } | ||
253 | |||
254 | return result | ||
255 | } | ||
diff --git a/server/lib/hls.ts b/server/lib/hls.ts index 84539e2c1..05be403f3 100644 --- a/server/lib/hls.ts +++ b/server/lib/hls.ts | |||
@@ -50,13 +50,12 @@ async function updateMasterHLSPlaylist (video: MVideoWithFile) { | |||
50 | let line = `#EXT-X-STREAM-INF:${bandwidth},${resolution}` | 50 | let line = `#EXT-X-STREAM-INF:${bandwidth},${resolution}` |
51 | if (file.fps) line += ',FRAME-RATE=' + file.fps | 51 | if (file.fps) line += ',FRAME-RATE=' + file.fps |
52 | 52 | ||
53 | const videoCodec = await getVideoStreamCodec(videoFilePath) | 53 | const codecs = await Promise.all([ |
54 | line += `,CODECS="${videoCodec}` | 54 | getVideoStreamCodec(videoFilePath), |
55 | getAudioStreamCodec(videoFilePath) | ||
56 | ]) | ||
55 | 57 | ||
56 | const audioCodec = await getAudioStreamCodec(videoFilePath) | 58 | line += `,CODECS="${codecs.filter(c => !!c).join(',')}"` |
57 | if (audioCodec) line += `,${audioCodec}` | ||
58 | |||
59 | line += '"' | ||
60 | 59 | ||
61 | masterPlaylists.push(line) | 60 | masterPlaylists.push(line) |
62 | masterPlaylists.push(VideoStreamingPlaylistModel.getHlsPlaylistFilename(file.resolution)) | 61 | masterPlaylists.push(VideoStreamingPlaylistModel.getHlsPlaylistFilename(file.resolution)) |
diff --git a/server/lib/job-queue/handlers/activitypub-follow.ts b/server/lib/job-queue/handlers/activitypub-follow.ts index 82c95be80..ec8df8969 100644 --- a/server/lib/job-queue/handlers/activitypub-follow.ts +++ b/server/lib/job-queue/handlers/activitypub-follow.ts | |||
@@ -1,18 +1,18 @@ | |||
1 | import * as Bull from 'bull' | 1 | import * as Bull from 'bull' |
2 | import { logger } from '../../../helpers/logger' | 2 | import { getLocalActorFollowActivityPubUrl } from '@server/lib/activitypub/url' |
3 | import { REMOTE_SCHEME, WEBSERVER } from '../../../initializers/constants' | 3 | import { ActivitypubFollowPayload } from '@shared/models' |
4 | import { sendFollow } from '../../activitypub/send' | ||
5 | import { sanitizeHost } from '../../../helpers/core-utils' | 4 | import { sanitizeHost } from '../../../helpers/core-utils' |
6 | import { loadActorUrlOrGetFromWebfinger } from '../../../helpers/webfinger' | ||
7 | import { getOrCreateActorAndServerAndModel } from '../../activitypub/actor' | ||
8 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | 5 | import { retryTransactionWrapper } from '../../../helpers/database-utils' |
9 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | 6 | import { logger } from '../../../helpers/logger' |
10 | import { ActorModel } from '../../../models/activitypub/actor' | 7 | import { loadActorUrlOrGetFromWebfinger } from '../../../helpers/webfinger' |
11 | import { Notifier } from '../../notifier' | 8 | import { REMOTE_SCHEME, WEBSERVER } from '../../../initializers/constants' |
12 | import { sequelizeTypescript } from '../../../initializers/database' | 9 | import { sequelizeTypescript } from '../../../initializers/database' |
10 | import { ActorModel } from '../../../models/actor/actor' | ||
11 | import { ActorFollowModel } from '../../../models/actor/actor-follow' | ||
13 | import { MActor, MActorFollowActors, MActorFull } from '../../../types/models' | 12 | import { MActor, MActorFollowActors, MActorFull } from '../../../types/models' |
14 | import { ActivitypubFollowPayload } from '@shared/models' | 13 | import { getOrCreateActorAndServerAndModel } from '../../activitypub/actor' |
15 | import { getLocalActorFollowActivityPubUrl } from '@server/lib/activitypub/url' | 14 | import { sendFollow } from '../../activitypub/send' |
15 | import { Notifier } from '../../notifier' | ||
16 | 16 | ||
17 | async function processActivityPubFollow (job: Bull.Job) { | 17 | async function processActivityPubFollow (job: Bull.Job) { |
18 | const payload = job.data as ActivitypubFollowPayload | 18 | const payload = job.data as ActivitypubFollowPayload |
diff --git a/server/lib/job-queue/handlers/activitypub-refresher.ts b/server/lib/job-queue/handlers/activitypub-refresher.ts index 666e56868..c09b1bcc8 100644 --- a/server/lib/job-queue/handlers/activitypub-refresher.ts +++ b/server/lib/job-queue/handlers/activitypub-refresher.ts | |||
@@ -1,12 +1,12 @@ | |||
1 | import * as Bull from 'bull' | 1 | import * as Bull from 'bull' |
2 | import { refreshVideoPlaylistIfNeeded } from '@server/lib/activitypub/playlist' | ||
3 | import { RefreshPayload } from '@shared/models' | ||
2 | import { logger } from '../../../helpers/logger' | 4 | import { logger } from '../../../helpers/logger' |
3 | import { fetchVideoByUrl } from '../../../helpers/video' | 5 | import { fetchVideoByUrl } from '../../../helpers/video' |
6 | import { ActorModel } from '../../../models/actor/actor' | ||
7 | import { VideoPlaylistModel } from '../../../models/video/video-playlist' | ||
4 | import { refreshActorIfNeeded } from '../../activitypub/actor' | 8 | import { refreshActorIfNeeded } from '../../activitypub/actor' |
5 | import { refreshVideoIfNeeded } from '../../activitypub/videos' | 9 | import { refreshVideoIfNeeded } from '../../activitypub/videos' |
6 | import { ActorModel } from '../../../models/activitypub/actor' | ||
7 | import { VideoPlaylistModel } from '../../../models/video/video-playlist' | ||
8 | import { RefreshPayload } from '@shared/models' | ||
9 | import { refreshVideoPlaylistIfNeeded } from '@server/lib/activitypub/playlist' | ||
10 | 10 | ||
11 | async function refreshAPObject (job: Bull.Job) { | 11 | async function refreshAPObject (job: Bull.Job) { |
12 | const payload = job.data as RefreshPayload | 12 | const payload = job.data as RefreshPayload |
diff --git a/server/lib/job-queue/handlers/actor-keys.ts b/server/lib/job-queue/handlers/actor-keys.ts index 125307843..3eef565d0 100644 --- a/server/lib/job-queue/handlers/actor-keys.ts +++ b/server/lib/job-queue/handlers/actor-keys.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import * as Bull from 'bull' | 1 | import * as Bull from 'bull' |
2 | import { generateAndSaveActorKeys } from '@server/lib/activitypub/actor' | 2 | import { generateAndSaveActorKeys } from '@server/lib/activitypub/actor' |
3 | import { ActorModel } from '@server/models/activitypub/actor' | 3 | import { ActorModel } from '@server/models/actor/actor' |
4 | import { ActorKeysPayload } from '@shared/models' | 4 | import { ActorKeysPayload } from '@shared/models' |
5 | import { logger } from '../../../helpers/logger' | 5 | import { logger } from '../../../helpers/logger' |
6 | 6 | ||
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 e8a91450d..37e7c1fad 100644 --- a/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts +++ b/server/lib/job-queue/handlers/utils/activitypub-http-utils.ts | |||
@@ -1,10 +1,10 @@ | |||
1 | import { buildDigest } from '@server/helpers/peertube-crypto' | ||
2 | import { getServerActor } from '@server/models/application/application' | ||
3 | import { ContextType } from '@shared/models/activitypub/context' | ||
1 | import { buildSignedActivity } from '../../../../helpers/activitypub' | 4 | import { buildSignedActivity } from '../../../../helpers/activitypub' |
2 | import { ActorModel } from '../../../../models/activitypub/actor' | ||
3 | import { ACTIVITY_PUB, HTTP_SIGNATURE } from '../../../../initializers/constants' | 5 | import { ACTIVITY_PUB, HTTP_SIGNATURE } from '../../../../initializers/constants' |
6 | import { ActorModel } from '../../../../models/actor/actor' | ||
4 | import { MActor } from '../../../../types/models' | 7 | import { MActor } from '../../../../types/models' |
5 | import { getServerActor } from '@server/models/application/application' | ||
6 | import { buildDigest } from '@server/helpers/peertube-crypto' | ||
7 | import { ContextType } from '@shared/models/activitypub/context' | ||
8 | 8 | ||
9 | type Payload <T> = { body: T, contextType?: ContextType, signatureActorId?: number } | 9 | type Payload <T> = { body: T, contextType?: ContextType, signatureActorId?: number } |
10 | 10 | ||
diff --git a/server/lib/job-queue/handlers/video-file-import.ts b/server/lib/job-queue/handlers/video-file-import.ts index 71f2cafcd..8297a1571 100644 --- a/server/lib/job-queue/handlers/video-file-import.ts +++ b/server/lib/job-queue/handlers/video-file-import.ts | |||
@@ -3,7 +3,7 @@ import { copy, stat } from 'fs-extra' | |||
3 | import { extname } from 'path' | 3 | import { extname } from 'path' |
4 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | 4 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' |
5 | import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' | 5 | import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' |
6 | import { UserModel } from '@server/models/account/user' | 6 | import { UserModel } from '@server/models/user/user' |
7 | import { MVideoFullLight } from '@server/types/models' | 7 | import { MVideoFullLight } from '@server/types/models' |
8 | import { VideoFileImportPayload } from '@shared/models' | 8 | import { VideoFileImportPayload } from '@shared/models' |
9 | import { getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils' | 9 | import { getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils' |
diff --git a/server/lib/job-queue/handlers/video-import.ts b/server/lib/job-queue/handlers/video-import.ts index ed2c5eac0..d71053e87 100644 --- a/server/lib/job-queue/handlers/video-import.ts +++ b/server/lib/job-queue/handlers/video-import.ts | |||
@@ -2,8 +2,10 @@ import * as Bull from 'bull' | |||
2 | import { move, remove, stat } from 'fs-extra' | 2 | import { move, remove, stat } from 'fs-extra' |
3 | import { extname } from 'path' | 3 | import { extname } from 'path' |
4 | import { retryTransactionWrapper } from '@server/helpers/database-utils' | 4 | import { retryTransactionWrapper } from '@server/helpers/database-utils' |
5 | import { YoutubeDL } from '@server/helpers/youtube-dl' | ||
5 | import { isPostImportVideoAccepted } from '@server/lib/moderation' | 6 | import { isPostImportVideoAccepted } from '@server/lib/moderation' |
6 | import { Hooks } from '@server/lib/plugins/hooks' | 7 | import { Hooks } from '@server/lib/plugins/hooks' |
8 | import { ServerConfigManager } from '@server/lib/server-config-manager' | ||
7 | import { isAbleToUploadVideo } from '@server/lib/user' | 9 | import { isAbleToUploadVideo } from '@server/lib/user' |
8 | import { addOptimizeOrMergeAudioJob } from '@server/lib/video' | 10 | import { addOptimizeOrMergeAudioJob } from '@server/lib/video' |
9 | import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' | 11 | import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' |
@@ -23,7 +25,6 @@ import { getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } fro | |||
23 | import { logger } from '../../../helpers/logger' | 25 | import { logger } from '../../../helpers/logger' |
24 | import { getSecureTorrentName } from '../../../helpers/utils' | 26 | import { getSecureTorrentName } from '../../../helpers/utils' |
25 | import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent' | 27 | import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent' |
26 | import { downloadYoutubeDLVideo } from '../../../helpers/youtube-dl' | ||
27 | import { CONFIG } from '../../../initializers/config' | 28 | import { CONFIG } from '../../../initializers/config' |
28 | import { VIDEO_IMPORT_TIMEOUT } from '../../../initializers/constants' | 29 | import { VIDEO_IMPORT_TIMEOUT } from '../../../initializers/constants' |
29 | import { sequelizeTypescript } from '../../../initializers/database' | 30 | import { sequelizeTypescript } from '../../../initializers/database' |
@@ -75,8 +76,10 @@ async function processYoutubeDLImport (job: Bull.Job, payload: VideoImportYoutub | |||
75 | videoImportId: videoImport.id | 76 | videoImportId: videoImport.id |
76 | } | 77 | } |
77 | 78 | ||
79 | const youtubeDL = new YoutubeDL(videoImport.targetUrl, ServerConfigManager.Instance.getEnabledResolutions('vod')) | ||
80 | |||
78 | return processFile( | 81 | return processFile( |
79 | () => downloadYoutubeDLVideo(videoImport.targetUrl, payload.fileExt, VIDEO_IMPORT_TIMEOUT), | 82 | () => youtubeDL.downloadYoutubeDLVideo(payload.fileExt, VIDEO_IMPORT_TIMEOUT), |
80 | videoImport, | 83 | videoImport, |
81 | options | 84 | options |
82 | ) | 85 | ) |
diff --git a/server/lib/job-queue/handlers/video-live-ending.ts b/server/lib/job-queue/handlers/video-live-ending.ts index d57202ca5..517b90abc 100644 --- a/server/lib/job-queue/handlers/video-live-ending.ts +++ b/server/lib/job-queue/handlers/video-live-ending.ts | |||
@@ -5,9 +5,9 @@ import { ffprobePromise, getAudioStream, getDurationFromVideoFile, getVideoFileR | |||
5 | import { VIDEO_LIVE } from '@server/initializers/constants' | 5 | import { VIDEO_LIVE } from '@server/initializers/constants' |
6 | import { LiveManager } from '@server/lib/live-manager' | 6 | import { LiveManager } from '@server/lib/live-manager' |
7 | import { generateVideoMiniature } from '@server/lib/thumbnail' | 7 | import { generateVideoMiniature } from '@server/lib/thumbnail' |
8 | import { generateHlsPlaylistResolutionFromTS } from '@server/lib/transcoding/video-transcoding' | ||
8 | import { publishAndFederateIfNeeded } from '@server/lib/video' | 9 | import { publishAndFederateIfNeeded } from '@server/lib/video' |
9 | import { getHLSDirectory } from '@server/lib/video-paths' | 10 | import { getHLSDirectory } from '@server/lib/video-paths' |
10 | import { generateHlsPlaylistResolutionFromTS } from '@server/lib/video-transcoding' | ||
11 | import { VideoModel } from '@server/models/video/video' | 11 | import { VideoModel } from '@server/models/video/video' |
12 | import { VideoFileModel } from '@server/models/video/video-file' | 12 | import { VideoFileModel } from '@server/models/video/video-file' |
13 | import { VideoLiveModel } from '@server/models/video/video-live' | 13 | import { VideoLiveModel } from '@server/models/video/video-live' |
diff --git a/server/lib/job-queue/handlers/video-transcoding.ts b/server/lib/job-queue/handlers/video-transcoding.ts index 010b95b05..8d659daa6 100644 --- a/server/lib/job-queue/handlers/video-transcoding.ts +++ b/server/lib/job-queue/handlers/video-transcoding.ts | |||
@@ -2,7 +2,7 @@ import * as Bull from 'bull' | |||
2 | import { TranscodeOptionsType } from '@server/helpers/ffmpeg-utils' | 2 | import { TranscodeOptionsType } from '@server/helpers/ffmpeg-utils' |
3 | import { getTranscodingJobPriority, publishAndFederateIfNeeded } from '@server/lib/video' | 3 | import { getTranscodingJobPriority, publishAndFederateIfNeeded } from '@server/lib/video' |
4 | import { getVideoFilePath } from '@server/lib/video-paths' | 4 | import { getVideoFilePath } from '@server/lib/video-paths' |
5 | import { UserModel } from '@server/models/account/user' | 5 | import { UserModel } from '@server/models/user/user' |
6 | import { MUser, MUserId, MVideoFullLight, MVideoUUID, MVideoWithFile } from '@server/types/models' | 6 | import { MUser, MUserId, MVideoFullLight, MVideoUUID, MVideoWithFile } from '@server/types/models' |
7 | import { | 7 | import { |
8 | HLSTranscodingPayload, | 8 | HLSTranscodingPayload, |
@@ -24,7 +24,7 @@ import { | |||
24 | mergeAudioVideofile, | 24 | mergeAudioVideofile, |
25 | optimizeOriginalVideofile, | 25 | optimizeOriginalVideofile, |
26 | transcodeNewWebTorrentResolution | 26 | transcodeNewWebTorrentResolution |
27 | } from '../../video-transcoding' | 27 | } from '../../transcoding/video-transcoding' |
28 | import { JobQueue } from '../job-queue' | 28 | import { JobQueue } from '../job-queue' |
29 | 29 | ||
30 | type HandlerFunction = (job: Bull.Job, payload: VideoTranscodingPayload, video: MVideoFullLight, user: MUser) => Promise<any> | 30 | type HandlerFunction = (job: Bull.Job, payload: VideoTranscodingPayload, video: MVideoFullLight, user: MUser) => Promise<any> |
diff --git a/server/lib/job-queue/handlers/video-views.ts b/server/lib/job-queue/handlers/video-views.ts index 897235ec0..86d0a271f 100644 --- a/server/lib/job-queue/handlers/video-views.ts +++ b/server/lib/job-queue/handlers/video-views.ts | |||
@@ -36,8 +36,8 @@ async function processVideosViews () { | |||
36 | } | 36 | } |
37 | 37 | ||
38 | await VideoViewModel.create({ | 38 | await VideoViewModel.create({ |
39 | startDate, | 39 | startDate: new Date(startDate), |
40 | endDate, | 40 | endDate: new Date(endDate), |
41 | views, | 41 | views, |
42 | videoId | 42 | videoId |
43 | }) | 43 | }) |
diff --git a/server/lib/live-manager.ts b/server/lib/live-manager.ts index 66b5d119b..8e7fd5511 100644 --- a/server/lib/live-manager.ts +++ b/server/lib/live-manager.ts | |||
@@ -11,7 +11,7 @@ import { computeResolutionsToTranscode, getVideoFileFPS, getVideoFileResolution | |||
11 | import { logger } from '@server/helpers/logger' | 11 | import { logger } from '@server/helpers/logger' |
12 | import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' | 12 | import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' |
13 | import { MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, VIEW_LIFETIME, WEBSERVER } from '@server/initializers/constants' | 13 | import { MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, VIEW_LIFETIME, WEBSERVER } from '@server/initializers/constants' |
14 | import { UserModel } from '@server/models/account/user' | 14 | import { UserModel } from '@server/models/user/user' |
15 | import { VideoModel } from '@server/models/video/video' | 15 | import { VideoModel } from '@server/models/video/video' |
16 | import { VideoFileModel } from '@server/models/video/video-file' | 16 | import { VideoFileModel } from '@server/models/video/video-file' |
17 | import { VideoLiveModel } from '@server/models/video/video-live' | 17 | import { VideoLiveModel } from '@server/models/video/video-live' |
@@ -23,9 +23,9 @@ import { buildSha256Segment } from './hls' | |||
23 | import { JobQueue } from './job-queue' | 23 | import { JobQueue } from './job-queue' |
24 | import { cleanupLive } from './job-queue/handlers/video-live-ending' | 24 | import { cleanupLive } from './job-queue/handlers/video-live-ending' |
25 | import { PeerTubeSocket } from './peertube-socket' | 25 | import { PeerTubeSocket } from './peertube-socket' |
26 | import { VideoTranscodingProfilesManager } from './transcoding/video-transcoding-profiles' | ||
26 | import { isAbleToUploadVideo } from './user' | 27 | import { isAbleToUploadVideo } from './user' |
27 | import { getHLSDirectory } from './video-paths' | 28 | import { getHLSDirectory } from './video-paths' |
28 | import { VideoTranscodingProfilesManager } from './video-transcoding-profiles' | ||
29 | 29 | ||
30 | import memoizee = require('memoizee') | 30 | import memoizee = require('memoizee') |
31 | const NodeRtmpSession = require('node-media-server/node_rtmp_session') | 31 | const NodeRtmpSession = require('node-media-server/node_rtmp_session') |
diff --git a/server/lib/moderation.ts b/server/lib/moderation.ts index 5180b3299..0cefe1648 100644 --- a/server/lib/moderation.ts +++ b/server/lib/moderation.ts | |||
@@ -1,6 +1,8 @@ | |||
1 | import { VideoUploadFile } from 'express' | ||
1 | import { PathLike } from 'fs-extra' | 2 | import { PathLike } from 'fs-extra' |
2 | import { Transaction } from 'sequelize/types' | 3 | import { Transaction } from 'sequelize/types' |
3 | import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger' | 4 | import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger' |
5 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' | ||
4 | import { logger } from '@server/helpers/logger' | 6 | import { logger } from '@server/helpers/logger' |
5 | import { AbuseModel } from '@server/models/abuse/abuse' | 7 | import { AbuseModel } from '@server/models/abuse/abuse' |
6 | import { VideoAbuseModel } from '@server/models/abuse/video-abuse' | 8 | import { VideoAbuseModel } from '@server/models/abuse/video-abuse' |
@@ -21,14 +23,13 @@ import { ActivityCreate } from '../../shared/models/activitypub' | |||
21 | import { VideoObject } from '../../shared/models/activitypub/objects' | 23 | import { VideoObject } from '../../shared/models/activitypub/objects' |
22 | import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object' | 24 | import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object' |
23 | import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos' | 25 | import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos' |
24 | import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model' | 26 | import { VideoCommentCreate } from '../../shared/models/videos/comment/video-comment.model' |
25 | import { UserModel } from '../models/account/user' | 27 | import { ActorModel } from '../models/actor/actor' |
26 | import { ActorModel } from '../models/activitypub/actor' | 28 | import { UserModel } from '../models/user/user' |
27 | import { VideoModel } from '../models/video/video' | 29 | import { VideoModel } from '../models/video/video' |
28 | import { VideoCommentModel } from '../models/video/video-comment' | 30 | import { VideoCommentModel } from '../models/video/video-comment' |
29 | import { sendAbuse } from './activitypub/send/send-flag' | 31 | import { sendAbuse } from './activitypub/send/send-flag' |
30 | import { Notifier } from './notifier' | 32 | import { Notifier } from './notifier' |
31 | import { afterCommitIfTransaction } from '@server/helpers/database-utils' | ||
32 | 33 | ||
33 | export type AcceptResult = { | 34 | export type AcceptResult = { |
34 | accepted: boolean | 35 | accepted: boolean |
@@ -38,7 +39,7 @@ export type AcceptResult = { | |||
38 | // Can be filtered by plugins | 39 | // Can be filtered by plugins |
39 | function isLocalVideoAccepted (object: { | 40 | function isLocalVideoAccepted (object: { |
40 | videoBody: VideoCreate | 41 | videoBody: VideoCreate |
41 | videoFile: Express.Multer.File & { duration?: number } | 42 | videoFile: VideoUploadFile |
42 | user: UserModel | 43 | user: UserModel |
43 | }): AcceptResult { | 44 | }): AcceptResult { |
44 | return { accepted: true } | 45 | return { accepted: true } |
diff --git a/server/lib/notifier.ts b/server/lib/notifier.ts index da7f7cc05..1f9ff16df 100644 --- a/server/lib/notifier.ts +++ b/server/lib/notifier.ts | |||
@@ -17,8 +17,8 @@ import { VideoPrivacy, VideoState } from '../../shared/models/videos' | |||
17 | import { logger } from '../helpers/logger' | 17 | import { logger } from '../helpers/logger' |
18 | import { CONFIG } from '../initializers/config' | 18 | import { CONFIG } from '../initializers/config' |
19 | import { AccountBlocklistModel } from '../models/account/account-blocklist' | 19 | import { AccountBlocklistModel } from '../models/account/account-blocklist' |
20 | import { UserModel } from '../models/account/user' | 20 | import { UserModel } from '../models/user/user' |
21 | import { UserNotificationModel } from '../models/account/user-notification' | 21 | import { UserNotificationModel } from '../models/user/user-notification' |
22 | import { MAbuseFull, MAbuseMessage, MAccountServer, MActorFollowFull, MApplication, MPlugin } from '../types/models' | 22 | import { MAbuseFull, MAbuseMessage, MAccountServer, MActorFollowFull, MApplication, MPlugin } from '../types/models' |
23 | import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../types/models/video' | 23 | import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../types/models/video' |
24 | import { isBlockedByServerOrAccount } from './blocklist' | 24 | import { isBlockedByServerOrAccount } from './blocklist' |
diff --git a/server/lib/plugins/hooks.ts b/server/lib/plugins/hooks.ts index aa92f03cc..5e97b52a0 100644 --- a/server/lib/plugins/hooks.ts +++ b/server/lib/plugins/hooks.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { ServerActionHookName, ServerFilterHookName } from '../../../shared/models/plugins/server-hook.model' | ||
2 | import { PluginManager } from './plugin-manager' | ||
3 | import { logger } from '../../helpers/logger' | ||
4 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import { ServerActionHookName, ServerFilterHookName } from '../../../shared/models' | ||
3 | import { logger } from '../../helpers/logger' | ||
4 | import { PluginManager } from './plugin-manager' | ||
5 | 5 | ||
6 | type PromiseFunction <U, T> = (params: U) => Promise<T> | Bluebird<T> | 6 | type PromiseFunction <U, T> = (params: U) => Promise<T> | Bluebird<T> |
7 | type RawFunction <U, T> = (params: U) => T | 7 | type RawFunction <U, T> = (params: U) => T |
diff --git a/server/lib/plugins/plugin-helpers-builder.ts b/server/lib/plugins/plugin-helpers-builder.ts index d57c69ef0..8487672ba 100644 --- a/server/lib/plugins/plugin-helpers-builder.ts +++ b/server/lib/plugins/plugin-helpers-builder.ts | |||
@@ -15,8 +15,9 @@ import { MPlugin } from '@server/types/models' | |||
15 | import { PeerTubeHelpers } from '@server/types/plugins' | 15 | import { PeerTubeHelpers } from '@server/types/plugins' |
16 | import { VideoBlacklistCreate } from '@shared/models' | 16 | import { VideoBlacklistCreate } from '@shared/models' |
17 | import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../blocklist' | 17 | import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../blocklist' |
18 | import { getServerConfig } from '../config' | 18 | import { ServerConfigManager } from '../server-config-manager' |
19 | import { blacklistVideo, unblacklistVideo } from '../video-blacklist' | 19 | import { blacklistVideo, unblacklistVideo } from '../video-blacklist' |
20 | import { UserModel } from '@server/models/user/user' | ||
20 | 21 | ||
21 | function buildPluginHelpers (pluginModel: MPlugin, npmName: string): PeerTubeHelpers { | 22 | function buildPluginHelpers (pluginModel: MPlugin, npmName: string): PeerTubeHelpers { |
22 | const logger = buildPluginLogger(npmName) | 23 | const logger = buildPluginLogger(npmName) |
@@ -146,7 +147,7 @@ function buildConfigHelpers () { | |||
146 | }, | 147 | }, |
147 | 148 | ||
148 | getServerConfig () { | 149 | getServerConfig () { |
149 | return getServerConfig() | 150 | return ServerConfigManager.Instance.getServerConfig() |
150 | } | 151 | } |
151 | } | 152 | } |
152 | } | 153 | } |
@@ -163,6 +164,11 @@ function buildPluginRelatedHelpers (plugin: MPlugin, npmName: string) { | |||
163 | 164 | ||
164 | function buildUserHelpers () { | 165 | function buildUserHelpers () { |
165 | return { | 166 | return { |
166 | getAuthUser: (res: express.Response) => res.locals.oauth?.token?.User | 167 | getAuthUser: (res: express.Response) => { |
168 | const user = res.locals.oauth?.token?.User | ||
169 | if (!user) return undefined | ||
170 | |||
171 | return UserModel.loadByIdFull(user.id) | ||
172 | } | ||
167 | } | 173 | } |
168 | } | 174 | } |
diff --git a/server/lib/plugins/plugin-index.ts b/server/lib/plugins/plugin-index.ts index 165bc91b3..119cee8e0 100644 --- a/server/lib/plugins/plugin-index.ts +++ b/server/lib/plugins/plugin-index.ts | |||
@@ -1,16 +1,16 @@ | |||
1 | import { sanitizeUrl } from '@server/helpers/core-utils' | 1 | import { sanitizeUrl } from '@server/helpers/core-utils' |
2 | import { ResultList } from '../../../shared/models' | 2 | import { logger } from '@server/helpers/logger' |
3 | import { PeertubePluginIndexList } from '../../../shared/models/plugins/peertube-plugin-index-list.model' | 3 | import { doJSONRequest } from '@server/helpers/requests' |
4 | import { PeerTubePluginIndex } from '../../../shared/models/plugins/peertube-plugin-index.model' | 4 | import { CONFIG } from '@server/initializers/config' |
5 | import { PEERTUBE_VERSION } from '@server/initializers/constants' | ||
6 | import { PluginModel } from '@server/models/server/plugin' | ||
5 | import { | 7 | import { |
8 | PeerTubePluginIndex, | ||
9 | PeertubePluginIndexList, | ||
6 | PeertubePluginLatestVersionRequest, | 10 | PeertubePluginLatestVersionRequest, |
7 | PeertubePluginLatestVersionResponse | 11 | PeertubePluginLatestVersionResponse, |
8 | } from '../../../shared/models/plugins/peertube-plugin-latest-version.model' | 12 | ResultList |
9 | import { logger } from '../../helpers/logger' | 13 | } from '@shared/models' |
10 | import { doJSONRequest } from '../../helpers/requests' | ||
11 | import { CONFIG } from '../../initializers/config' | ||
12 | import { PEERTUBE_VERSION } from '../../initializers/constants' | ||
13 | import { PluginModel } from '../../models/server/plugin' | ||
14 | import { PluginManager } from './plugin-manager' | 14 | import { PluginManager } from './plugin-manager' |
15 | 15 | ||
16 | async function listAvailablePluginsFromIndex (options: PeertubePluginIndexList) { | 16 | async function listAvailablePluginsFromIndex (options: PeertubePluginIndexList) { |
diff --git a/server/lib/plugins/plugin-manager.ts b/server/lib/plugins/plugin-manager.ts index ba9814383..6b9a255a4 100644 --- a/server/lib/plugins/plugin-manager.ts +++ b/server/lib/plugins/plugin-manager.ts | |||
@@ -4,16 +4,11 @@ import { createReadStream, createWriteStream } from 'fs' | |||
4 | import { ensureDir, outputFile, readJSON } from 'fs-extra' | 4 | import { ensureDir, outputFile, readJSON } from 'fs-extra' |
5 | import { basename, join } from 'path' | 5 | import { basename, join } from 'path' |
6 | import { MOAuthTokenUser, MUser } from '@server/types/models' | 6 | import { MOAuthTokenUser, MUser } from '@server/types/models' |
7 | import { RegisterServerHookOptions } from '@shared/models/plugins/register-server-hook.model' | 7 | import { getCompleteLocale } from '@shared/core-utils' |
8 | import { ClientScript, PluginPackageJson, PluginTranslation, PluginTranslationPaths, RegisterServerHookOptions } from '@shared/models' | ||
8 | import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks' | 9 | import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks' |
9 | import { | ||
10 | ClientScript, | ||
11 | PluginPackageJson, | ||
12 | PluginTranslationPaths as PackagePluginTranslations | ||
13 | } from '../../../shared/models/plugins/plugin-package-json.model' | ||
14 | import { PluginTranslation } from '../../../shared/models/plugins/plugin-translation.model' | ||
15 | import { PluginType } from '../../../shared/models/plugins/plugin.type' | 10 | import { PluginType } from '../../../shared/models/plugins/plugin.type' |
16 | import { ServerHook, ServerHookName } from '../../../shared/models/plugins/server-hook.model' | 11 | import { ServerHook, ServerHookName } from '../../../shared/models/plugins/server/server-hook.model' |
17 | import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins' | 12 | import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins' |
18 | import { logger } from '../../helpers/logger' | 13 | import { logger } from '../../helpers/logger' |
19 | import { CONFIG } from '../../initializers/config' | 14 | import { CONFIG } from '../../initializers/config' |
@@ -23,7 +18,6 @@ import { PluginLibrary, RegisterServerAuthExternalOptions, RegisterServerAuthPas | |||
23 | import { ClientHtml } from '../client-html' | 18 | import { ClientHtml } from '../client-html' |
24 | import { RegisterHelpers } from './register-helpers' | 19 | import { RegisterHelpers } from './register-helpers' |
25 | import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' | 20 | import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' |
26 | import { getCompleteLocale } from '@shared/core-utils' | ||
27 | 21 | ||
28 | export interface RegisteredPlugin { | 22 | export interface RegisteredPlugin { |
29 | npmName: string | 23 | npmName: string |
@@ -443,7 +437,7 @@ export class PluginManager implements ServerHook { | |||
443 | 437 | ||
444 | // ###################### Translations ###################### | 438 | // ###################### Translations ###################### |
445 | 439 | ||
446 | private async addTranslations (plugin: PluginModel, npmName: string, translationPaths: PackagePluginTranslations) { | 440 | private async addTranslations (plugin: PluginModel, npmName: string, translationPaths: PluginTranslationPaths) { |
447 | for (const locale of Object.keys(translationPaths)) { | 441 | for (const locale of Object.keys(translationPaths)) { |
448 | const path = translationPaths[locale] | 442 | const path = translationPaths[locale] |
449 | const json = await readJSON(join(this.getPluginPath(plugin.name, plugin.type), path)) | 443 | const json = await readJSON(join(this.getPluginPath(plugin.name, plugin.type), path)) |
diff --git a/server/lib/plugins/register-helpers.ts b/server/lib/plugins/register-helpers.ts index aa69ca2a2..f5b573370 100644 --- a/server/lib/plugins/register-helpers.ts +++ b/server/lib/plugins/register-helpers.ts | |||
@@ -26,10 +26,10 @@ import { | |||
26 | PluginVideoLicenceManager, | 26 | PluginVideoLicenceManager, |
27 | PluginVideoPrivacyManager, | 27 | PluginVideoPrivacyManager, |
28 | RegisterServerHookOptions, | 28 | RegisterServerHookOptions, |
29 | RegisterServerSettingOptions | 29 | RegisterServerSettingOptions, |
30 | serverHookObject | ||
30 | } from '@shared/models' | 31 | } from '@shared/models' |
31 | import { serverHookObject } from '@shared/models/plugins/server-hook.model' | 32 | import { VideoTranscodingProfilesManager } from '../transcoding/video-transcoding-profiles' |
32 | import { VideoTranscodingProfilesManager } from '../video-transcoding-profiles' | ||
33 | import { buildPluginHelpers } from './plugin-helpers-builder' | 33 | import { buildPluginHelpers } from './plugin-helpers-builder' |
34 | 34 | ||
35 | type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy' | 35 | type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy' |
diff --git a/server/lib/redundancy.ts b/server/lib/redundancy.ts index da620b607..2a9241249 100644 --- a/server/lib/redundancy.ts +++ b/server/lib/redundancy.ts | |||
@@ -1,12 +1,12 @@ | |||
1 | import { VideoRedundancyModel } from '../models/redundancy/video-redundancy' | ||
2 | import { sendUndoCacheFile } from './activitypub/send' | ||
3 | import { Transaction } from 'sequelize' | 1 | import { Transaction } from 'sequelize' |
4 | import { MActorSignature, MVideoRedundancyVideo } from '@server/types/models' | ||
5 | import { CONFIG } from '@server/initializers/config' | ||
6 | import { logger } from '@server/helpers/logger' | 2 | import { logger } from '@server/helpers/logger' |
7 | import { ActorFollowModel } from '@server/models/activitypub/actor-follow' | 3 | import { CONFIG } from '@server/initializers/config' |
8 | import { Activity } from '@shared/models' | 4 | import { ActorFollowModel } from '@server/models/actor/actor-follow' |
9 | import { getServerActor } from '@server/models/application/application' | 5 | import { getServerActor } from '@server/models/application/application' |
6 | import { MActorSignature, MVideoRedundancyVideo } from '@server/types/models' | ||
7 | import { Activity } from '@shared/models' | ||
8 | import { VideoRedundancyModel } from '../models/redundancy/video-redundancy' | ||
9 | import { sendUndoCacheFile } from './activitypub/send' | ||
10 | 10 | ||
11 | async function removeVideoRedundancy (videoRedundancy: MVideoRedundancyVideo, t?: Transaction) { | 11 | async function removeVideoRedundancy (videoRedundancy: MVideoRedundancyVideo, t?: Transaction) { |
12 | const serverActor = await getServerActor() | 12 | const serverActor = await getServerActor() |
diff --git a/server/lib/schedulers/actor-follow-scheduler.ts b/server/lib/schedulers/actor-follow-scheduler.ts index 598c0211f..1b80316e9 100644 --- a/server/lib/schedulers/actor-follow-scheduler.ts +++ b/server/lib/schedulers/actor-follow-scheduler.ts | |||
@@ -1,9 +1,9 @@ | |||
1 | import { isTestInstance } from '../../helpers/core-utils' | 1 | import { isTestInstance } from '../../helpers/core-utils' |
2 | import { logger } from '../../helpers/logger' | 2 | import { logger } from '../../helpers/logger' |
3 | import { ActorFollowModel } from '../../models/activitypub/actor-follow' | ||
4 | import { AbstractScheduler } from './abstract-scheduler' | ||
5 | import { ACTOR_FOLLOW_SCORE, SCHEDULER_INTERVALS_MS } from '../../initializers/constants' | 3 | import { ACTOR_FOLLOW_SCORE, SCHEDULER_INTERVALS_MS } from '../../initializers/constants' |
4 | import { ActorFollowModel } from '../../models/actor/actor-follow' | ||
6 | import { ActorFollowScoreCache } from '../files-cache' | 5 | import { ActorFollowScoreCache } from '../files-cache' |
6 | import { AbstractScheduler } from './abstract-scheduler' | ||
7 | 7 | ||
8 | export class ActorFollowScheduler extends AbstractScheduler { | 8 | export class ActorFollowScheduler extends AbstractScheduler { |
9 | 9 | ||
diff --git a/server/lib/schedulers/auto-follow-index-instances.ts b/server/lib/schedulers/auto-follow-index-instances.ts index 0b8cd1389..aaa5feed5 100644 --- a/server/lib/schedulers/auto-follow-index-instances.ts +++ b/server/lib/schedulers/auto-follow-index-instances.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { chunk } from 'lodash' | 1 | import { chunk } from 'lodash' |
2 | import { doJSONRequest } from '@server/helpers/requests' | 2 | import { doJSONRequest } from '@server/helpers/requests' |
3 | import { JobQueue } from '@server/lib/job-queue' | 3 | import { JobQueue } from '@server/lib/job-queue' |
4 | import { ActorFollowModel } from '@server/models/activitypub/actor-follow' | 4 | import { ActorFollowModel } from '@server/models/actor/actor-follow' |
5 | import { getServerActor } from '@server/models/application/application' | 5 | import { getServerActor } from '@server/models/application/application' |
6 | import { logger } from '../../helpers/logger' | 6 | import { logger } from '../../helpers/logger' |
7 | import { CONFIG } from '../../initializers/config' | 7 | import { CONFIG } from '../../initializers/config' |
diff --git a/server/lib/schedulers/remove-dangling-resumable-uploads-scheduler.ts b/server/lib/schedulers/remove-dangling-resumable-uploads-scheduler.ts new file mode 100644 index 000000000..1acea7998 --- /dev/null +++ b/server/lib/schedulers/remove-dangling-resumable-uploads-scheduler.ts | |||
@@ -0,0 +1,61 @@ | |||
1 | import * as bluebird from 'bluebird' | ||
2 | import { readdir, remove, stat } from 'fs-extra' | ||
3 | import { logger, loggerTagsFactory } from '@server/helpers/logger' | ||
4 | import { getResumableUploadPath } from '@server/helpers/upload' | ||
5 | import { SCHEDULER_INTERVALS_MS } from '@server/initializers/constants' | ||
6 | import { METAFILE_EXTNAME } from '@uploadx/core' | ||
7 | import { AbstractScheduler } from './abstract-scheduler' | ||
8 | |||
9 | const lTags = loggerTagsFactory('scheduler', 'resumable-upload', 'cleaner') | ||
10 | |||
11 | export class RemoveDanglingResumableUploadsScheduler extends AbstractScheduler { | ||
12 | |||
13 | private static instance: AbstractScheduler | ||
14 | private lastExecutionTimeMs: number | ||
15 | |||
16 | protected schedulerIntervalMs = SCHEDULER_INTERVALS_MS.removeDanglingResumableUploads | ||
17 | |||
18 | private constructor () { | ||
19 | super() | ||
20 | |||
21 | this.lastExecutionTimeMs = new Date().getTime() | ||
22 | } | ||
23 | |||
24 | protected async internalExecute () { | ||
25 | const path = getResumableUploadPath() | ||
26 | const files = await readdir(path) | ||
27 | |||
28 | const metafiles = files.filter(f => f.endsWith(METAFILE_EXTNAME)) | ||
29 | |||
30 | if (metafiles.length === 0) return | ||
31 | |||
32 | logger.debug('Reading resumable video upload folder %s with %d files', path, metafiles.length, lTags()) | ||
33 | |||
34 | try { | ||
35 | await bluebird.map(metafiles, metafile => { | ||
36 | return this.deleteIfOlderThan(metafile, this.lastExecutionTimeMs) | ||
37 | }, { concurrency: 5 }) | ||
38 | } catch (error) { | ||
39 | logger.error('Failed to handle file during resumable video upload folder cleanup', { error, ...lTags() }) | ||
40 | } finally { | ||
41 | this.lastExecutionTimeMs = new Date().getTime() | ||
42 | } | ||
43 | } | ||
44 | |||
45 | private async deleteIfOlderThan (metafile: string, olderThan: number) { | ||
46 | const metafilePath = getResumableUploadPath(metafile) | ||
47 | const statResult = await stat(metafilePath) | ||
48 | |||
49 | // Delete uploads that started since a long time | ||
50 | if (statResult.ctimeMs < olderThan) { | ||
51 | await remove(metafilePath) | ||
52 | |||
53 | const datafile = metafilePath.replace(new RegExp(`${METAFILE_EXTNAME}$`), '') | ||
54 | await remove(datafile) | ||
55 | } | ||
56 | } | ||
57 | |||
58 | static get Instance () { | ||
59 | return this.instance || (this.instance = new this()) | ||
60 | } | ||
61 | } | ||
diff --git a/server/lib/schedulers/remove-old-history-scheduler.ts b/server/lib/schedulers/remove-old-history-scheduler.ts index 17a42b2c4..225669ea2 100644 --- a/server/lib/schedulers/remove-old-history-scheduler.ts +++ b/server/lib/schedulers/remove-old-history-scheduler.ts | |||
@@ -1,7 +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' | 4 | import { UserVideoHistoryModel } from '../../models/user/user-video-history' |
5 | import { CONFIG } from '../../initializers/config' | 5 | import { CONFIG } from '../../initializers/config' |
6 | 6 | ||
7 | export class RemoveOldHistoryScheduler extends AbstractScheduler { | 7 | export class RemoveOldHistoryScheduler extends AbstractScheduler { |
diff --git a/server/lib/schedulers/videos-redundancy-scheduler.ts b/server/lib/schedulers/videos-redundancy-scheduler.ts index 9e2667416..59b55cccc 100644 --- a/server/lib/schedulers/videos-redundancy-scheduler.ts +++ b/server/lib/schedulers/videos-redundancy-scheduler.ts | |||
@@ -317,8 +317,8 @@ export class VideosRedundancyScheduler extends AbstractScheduler { | |||
317 | private async isTooHeavy (candidateToDuplicate: CandidateToDuplicate) { | 317 | private async isTooHeavy (candidateToDuplicate: CandidateToDuplicate) { |
318 | const maxSize = candidateToDuplicate.redundancy.size | 318 | const maxSize = candidateToDuplicate.redundancy.size |
319 | 319 | ||
320 | const totalDuplicated = await VideoRedundancyModel.getTotalDuplicated(candidateToDuplicate.redundancy.strategy) | 320 | const { totalUsed } = await VideoRedundancyModel.getStats(candidateToDuplicate.redundancy.strategy) |
321 | const totalWillDuplicate = totalDuplicated + this.getTotalFileSizes(candidateToDuplicate.files, candidateToDuplicate.streamingPlaylists) | 321 | const totalWillDuplicate = totalUsed + this.getTotalFileSizes(candidateToDuplicate.files, candidateToDuplicate.streamingPlaylists) |
322 | 322 | ||
323 | return totalWillDuplicate > maxSize | 323 | return totalWillDuplicate > maxSize |
324 | } | 324 | } |
diff --git a/server/lib/schedulers/youtube-dl-update-scheduler.ts b/server/lib/schedulers/youtube-dl-update-scheduler.ts index aefe6aba4..898691c13 100644 --- a/server/lib/schedulers/youtube-dl-update-scheduler.ts +++ b/server/lib/schedulers/youtube-dl-update-scheduler.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { AbstractScheduler } from './abstract-scheduler' | 1 | import { YoutubeDL } from '@server/helpers/youtube-dl' |
2 | import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants' | 2 | import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants' |
3 | import { updateYoutubeDLBinary } from '../../helpers/youtube-dl' | 3 | import { AbstractScheduler } from './abstract-scheduler' |
4 | 4 | ||
5 | export class YoutubeDlUpdateScheduler extends AbstractScheduler { | 5 | export class YoutubeDlUpdateScheduler extends AbstractScheduler { |
6 | 6 | ||
@@ -13,7 +13,7 @@ export class YoutubeDlUpdateScheduler extends AbstractScheduler { | |||
13 | } | 13 | } |
14 | 14 | ||
15 | protected internalExecute () { | 15 | protected internalExecute () { |
16 | return updateYoutubeDLBinary() | 16 | return YoutubeDL.updateYoutubeDLBinary() |
17 | } | 17 | } |
18 | 18 | ||
19 | static get Instance () { | 19 | static get Instance () { |
diff --git a/server/lib/server-config-manager.ts b/server/lib/server-config-manager.ts new file mode 100644 index 000000000..1aff6f446 --- /dev/null +++ b/server/lib/server-config-manager.ts | |||
@@ -0,0 +1,303 @@ | |||
1 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/helpers/signup' | ||
2 | import { getServerCommit } from '@server/helpers/utils' | ||
3 | import { CONFIG, isEmailEnabled } from '@server/initializers/config' | ||
4 | import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants' | ||
5 | import { ActorCustomPageModel } from '@server/models/account/actor-custom-page' | ||
6 | import { HTMLServerConfig, RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models' | ||
7 | import { Hooks } from './plugins/hooks' | ||
8 | import { PluginManager } from './plugins/plugin-manager' | ||
9 | import { getThemeOrDefault } from './plugins/theme-utils' | ||
10 | import { VideoTranscodingProfilesManager } from './transcoding/video-transcoding-profiles' | ||
11 | |||
12 | /** | ||
13 | * | ||
14 | * Used to send the server config to clients (using REST/API or plugins API) | ||
15 | * We need a singleton class to manage config state depending on external events (to build menu entries etc) | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | class ServerConfigManager { | ||
20 | |||
21 | private static instance: ServerConfigManager | ||
22 | |||
23 | private serverCommit: string | ||
24 | |||
25 | private homepageEnabled = false | ||
26 | |||
27 | private constructor () {} | ||
28 | |||
29 | async init () { | ||
30 | const instanceHomepage = await ActorCustomPageModel.loadInstanceHomepage() | ||
31 | |||
32 | this.updateHomepageState(instanceHomepage?.content) | ||
33 | } | ||
34 | |||
35 | updateHomepageState (content: string) { | ||
36 | this.homepageEnabled = !!content | ||
37 | } | ||
38 | |||
39 | async getHTMLServerConfig (): Promise<HTMLServerConfig> { | ||
40 | if (this.serverCommit === undefined) this.serverCommit = await getServerCommit() | ||
41 | |||
42 | const defaultTheme = getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) | ||
43 | |||
44 | return { | ||
45 | instance: { | ||
46 | name: CONFIG.INSTANCE.NAME, | ||
47 | shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION, | ||
48 | isNSFW: CONFIG.INSTANCE.IS_NSFW, | ||
49 | defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY, | ||
50 | defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE, | ||
51 | customizations: { | ||
52 | javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT, | ||
53 | css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS | ||
54 | } | ||
55 | }, | ||
56 | search: { | ||
57 | remoteUri: { | ||
58 | users: CONFIG.SEARCH.REMOTE_URI.USERS, | ||
59 | anonymous: CONFIG.SEARCH.REMOTE_URI.ANONYMOUS | ||
60 | }, | ||
61 | searchIndex: { | ||
62 | enabled: CONFIG.SEARCH.SEARCH_INDEX.ENABLED, | ||
63 | url: CONFIG.SEARCH.SEARCH_INDEX.URL, | ||
64 | disableLocalSearch: CONFIG.SEARCH.SEARCH_INDEX.DISABLE_LOCAL_SEARCH, | ||
65 | isDefaultSearch: CONFIG.SEARCH.SEARCH_INDEX.IS_DEFAULT_SEARCH | ||
66 | } | ||
67 | }, | ||
68 | plugin: { | ||
69 | registered: this.getRegisteredPlugins(), | ||
70 | registeredExternalAuths: this.getExternalAuthsPlugins(), | ||
71 | registeredIdAndPassAuths: this.getIdAndPassAuthPlugins() | ||
72 | }, | ||
73 | theme: { | ||
74 | registered: this.getRegisteredThemes(), | ||
75 | default: defaultTheme | ||
76 | }, | ||
77 | email: { | ||
78 | enabled: isEmailEnabled() | ||
79 | }, | ||
80 | contactForm: { | ||
81 | enabled: CONFIG.CONTACT_FORM.ENABLED | ||
82 | }, | ||
83 | serverVersion: PEERTUBE_VERSION, | ||
84 | serverCommit: this.serverCommit, | ||
85 | transcoding: { | ||
86 | hls: { | ||
87 | enabled: CONFIG.TRANSCODING.HLS.ENABLED | ||
88 | }, | ||
89 | webtorrent: { | ||
90 | enabled: CONFIG.TRANSCODING.WEBTORRENT.ENABLED | ||
91 | }, | ||
92 | enabledResolutions: this.getEnabledResolutions('vod'), | ||
93 | profile: CONFIG.TRANSCODING.PROFILE, | ||
94 | availableProfiles: VideoTranscodingProfilesManager.Instance.getAvailableProfiles('vod') | ||
95 | }, | ||
96 | live: { | ||
97 | enabled: CONFIG.LIVE.ENABLED, | ||
98 | |||
99 | allowReplay: CONFIG.LIVE.ALLOW_REPLAY, | ||
100 | maxDuration: CONFIG.LIVE.MAX_DURATION, | ||
101 | maxInstanceLives: CONFIG.LIVE.MAX_INSTANCE_LIVES, | ||
102 | maxUserLives: CONFIG.LIVE.MAX_USER_LIVES, | ||
103 | |||
104 | transcoding: { | ||
105 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, | ||
106 | enabledResolutions: this.getEnabledResolutions('live'), | ||
107 | profile: CONFIG.LIVE.TRANSCODING.PROFILE, | ||
108 | availableProfiles: VideoTranscodingProfilesManager.Instance.getAvailableProfiles('live') | ||
109 | }, | ||
110 | |||
111 | rtmp: { | ||
112 | port: CONFIG.LIVE.RTMP.PORT | ||
113 | } | ||
114 | }, | ||
115 | import: { | ||
116 | videos: { | ||
117 | http: { | ||
118 | enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED | ||
119 | }, | ||
120 | torrent: { | ||
121 | enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED | ||
122 | } | ||
123 | } | ||
124 | }, | ||
125 | autoBlacklist: { | ||
126 | videos: { | ||
127 | ofUsers: { | ||
128 | enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED | ||
129 | } | ||
130 | } | ||
131 | }, | ||
132 | avatar: { | ||
133 | file: { | ||
134 | size: { | ||
135 | max: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
136 | }, | ||
137 | extensions: CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | ||
138 | } | ||
139 | }, | ||
140 | banner: { | ||
141 | file: { | ||
142 | size: { | ||
143 | max: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
144 | }, | ||
145 | extensions: CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | ||
146 | } | ||
147 | }, | ||
148 | video: { | ||
149 | image: { | ||
150 | extensions: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME, | ||
151 | size: { | ||
152 | max: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max | ||
153 | } | ||
154 | }, | ||
155 | file: { | ||
156 | extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME | ||
157 | } | ||
158 | }, | ||
159 | videoCaption: { | ||
160 | file: { | ||
161 | size: { | ||
162 | max: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max | ||
163 | }, | ||
164 | extensions: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.EXTNAME | ||
165 | } | ||
166 | }, | ||
167 | user: { | ||
168 | videoQuota: CONFIG.USER.VIDEO_QUOTA, | ||
169 | videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY | ||
170 | }, | ||
171 | trending: { | ||
172 | videos: { | ||
173 | intervalDays: CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS, | ||
174 | algorithms: { | ||
175 | enabled: CONFIG.TRENDING.VIDEOS.ALGORITHMS.ENABLED, | ||
176 | default: CONFIG.TRENDING.VIDEOS.ALGORITHMS.DEFAULT | ||
177 | } | ||
178 | } | ||
179 | }, | ||
180 | tracker: { | ||
181 | enabled: CONFIG.TRACKER.ENABLED | ||
182 | }, | ||
183 | |||
184 | followings: { | ||
185 | instance: { | ||
186 | autoFollowIndex: { | ||
187 | indexUrl: CONFIG.FOLLOWINGS.INSTANCE.AUTO_FOLLOW_INDEX.INDEX_URL | ||
188 | } | ||
189 | } | ||
190 | }, | ||
191 | |||
192 | broadcastMessage: { | ||
193 | enabled: CONFIG.BROADCAST_MESSAGE.ENABLED, | ||
194 | message: CONFIG.BROADCAST_MESSAGE.MESSAGE, | ||
195 | level: CONFIG.BROADCAST_MESSAGE.LEVEL, | ||
196 | dismissable: CONFIG.BROADCAST_MESSAGE.DISMISSABLE | ||
197 | }, | ||
198 | |||
199 | homepage: { | ||
200 | enabled: this.homepageEnabled | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | |||
205 | async getServerConfig (ip?: string): Promise<ServerConfig> { | ||
206 | const { allowed } = await Hooks.wrapPromiseFun( | ||
207 | isSignupAllowed, | ||
208 | { | ||
209 | ip | ||
210 | }, | ||
211 | 'filter:api.user.signup.allowed.result' | ||
212 | ) | ||
213 | |||
214 | const allowedForCurrentIP = isSignupAllowedForCurrentIP(ip) | ||
215 | |||
216 | const signup = { | ||
217 | allowed, | ||
218 | allowedForCurrentIP, | ||
219 | requiresEmailVerification: CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION | ||
220 | } | ||
221 | |||
222 | const htmlConfig = await this.getHTMLServerConfig() | ||
223 | |||
224 | return { ...htmlConfig, signup } | ||
225 | } | ||
226 | |||
227 | getRegisteredThemes () { | ||
228 | return PluginManager.Instance.getRegisteredThemes() | ||
229 | .map(t => ({ | ||
230 | name: t.name, | ||
231 | version: t.version, | ||
232 | description: t.description, | ||
233 | css: t.css, | ||
234 | clientScripts: t.clientScripts | ||
235 | })) | ||
236 | } | ||
237 | |||
238 | getRegisteredPlugins () { | ||
239 | return PluginManager.Instance.getRegisteredPlugins() | ||
240 | .map(p => ({ | ||
241 | name: p.name, | ||
242 | version: p.version, | ||
243 | description: p.description, | ||
244 | clientScripts: p.clientScripts | ||
245 | })) | ||
246 | } | ||
247 | |||
248 | getEnabledResolutions (type: 'vod' | 'live') { | ||
249 | const transcoding = type === 'vod' | ||
250 | ? CONFIG.TRANSCODING | ||
251 | : CONFIG.LIVE.TRANSCODING | ||
252 | |||
253 | return Object.keys(transcoding.RESOLUTIONS) | ||
254 | .filter(key => transcoding.ENABLED && transcoding.RESOLUTIONS[key] === true) | ||
255 | .map(r => parseInt(r, 10)) | ||
256 | } | ||
257 | |||
258 | private getIdAndPassAuthPlugins () { | ||
259 | const result: RegisteredIdAndPassAuthConfig[] = [] | ||
260 | |||
261 | for (const p of PluginManager.Instance.getIdAndPassAuths()) { | ||
262 | for (const auth of p.idAndPassAuths) { | ||
263 | result.push({ | ||
264 | npmName: p.npmName, | ||
265 | name: p.name, | ||
266 | version: p.version, | ||
267 | authName: auth.authName, | ||
268 | weight: auth.getWeight() | ||
269 | }) | ||
270 | } | ||
271 | } | ||
272 | |||
273 | return result | ||
274 | } | ||
275 | |||
276 | private getExternalAuthsPlugins () { | ||
277 | const result: RegisteredExternalAuthConfig[] = [] | ||
278 | |||
279 | for (const p of PluginManager.Instance.getExternalAuths()) { | ||
280 | for (const auth of p.externalAuths) { | ||
281 | result.push({ | ||
282 | npmName: p.npmName, | ||
283 | name: p.name, | ||
284 | version: p.version, | ||
285 | authName: auth.authName, | ||
286 | authDisplayName: auth.authDisplayName() | ||
287 | }) | ||
288 | } | ||
289 | } | ||
290 | |||
291 | return result | ||
292 | } | ||
293 | |||
294 | static get Instance () { | ||
295 | return this.instance || (this.instance = new this()) | ||
296 | } | ||
297 | } | ||
298 | |||
299 | // --------------------------------------------------------------------------- | ||
300 | |||
301 | export { | ||
302 | ServerConfigManager | ||
303 | } | ||
diff --git a/server/lib/stat-manager.ts b/server/lib/stat-manager.ts index 09ba208bd..25ed21927 100644 --- a/server/lib/stat-manager.ts +++ b/server/lib/stat-manager.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { CONFIG } from '@server/initializers/config' | 1 | import { CONFIG } from '@server/initializers/config' |
2 | import { UserModel } from '@server/models/account/user' | 2 | import { UserModel } from '@server/models/user/user' |
3 | import { ActorFollowModel } from '@server/models/activitypub/actor-follow' | 3 | import { ActorFollowModel } from '@server/models/actor/actor-follow' |
4 | import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy' | 4 | import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy' |
5 | import { VideoModel } from '@server/models/video/video' | 5 | import { VideoModel } from '@server/models/video/video' |
6 | import { VideoChannelModel } from '@server/models/video/video-channel' | 6 | import { VideoChannelModel } from '@server/models/video/video-channel' |
diff --git a/server/lib/video-transcoding-profiles.ts b/server/lib/transcoding/video-transcoding-profiles.ts index 81f5e1962..c5ea72a5f 100644 --- a/server/lib/video-transcoding-profiles.ts +++ b/server/lib/transcoding/video-transcoding-profiles.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { logger } from '@server/helpers/logger' | 1 | import { logger } from '@server/helpers/logger' |
2 | import { AvailableEncoders, EncoderOptionsBuilder, getTargetBitrate, VideoResolution } from '../../shared/models/videos' | 2 | import { AvailableEncoders, EncoderOptionsBuilder, getTargetBitrate, VideoResolution } from '../../../shared/models/videos' |
3 | import { buildStreamSuffix, resetSupportedEncoders } from '../helpers/ffmpeg-utils' | 3 | import { buildStreamSuffix, resetSupportedEncoders } from '../../helpers/ffmpeg-utils' |
4 | import { | 4 | import { |
5 | canDoQuickAudioTranscode, | 5 | canDoQuickAudioTranscode, |
6 | ffprobePromise, | 6 | ffprobePromise, |
@@ -8,8 +8,8 @@ import { | |||
8 | getMaxAudioBitrate, | 8 | getMaxAudioBitrate, |
9 | getVideoFileBitrate, | 9 | getVideoFileBitrate, |
10 | getVideoStreamFromFile | 10 | getVideoStreamFromFile |
11 | } from '../helpers/ffprobe-utils' | 11 | } from '../../helpers/ffprobe-utils' |
12 | import { VIDEO_TRANSCODING_FPS } from '../initializers/constants' | 12 | import { VIDEO_TRANSCODING_FPS } from '../../initializers/constants' |
13 | 13 | ||
14 | /** | 14 | /** |
15 | * | 15 | * |
diff --git a/server/lib/video-transcoding.ts b/server/lib/transcoding/video-transcoding.ts index c949dca2e..5df192575 100644 --- a/server/lib/video-transcoding.ts +++ b/server/lib/transcoding/video-transcoding.ts | |||
@@ -3,17 +3,17 @@ import { copyFile, ensureDir, move, remove, stat } from 'fs-extra' | |||
3 | import { basename, extname as extnameUtil, join } from 'path' | 3 | import { basename, extname as extnameUtil, join } from 'path' |
4 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | 4 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' |
5 | import { MStreamingPlaylistFilesVideo, MVideoFile, MVideoFullLight } from '@server/types/models' | 5 | import { MStreamingPlaylistFilesVideo, MVideoFile, MVideoFullLight } from '@server/types/models' |
6 | import { VideoResolution } from '../../shared/models/videos' | 6 | import { VideoResolution } from '../../../shared/models/videos' |
7 | import { VideoStreamingPlaylistType } from '../../shared/models/videos/video-streaming-playlist.type' | 7 | import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' |
8 | import { transcode, TranscodeOptions, TranscodeOptionsType } from '../helpers/ffmpeg-utils' | 8 | import { transcode, TranscodeOptions, TranscodeOptionsType } from '../../helpers/ffmpeg-utils' |
9 | import { canDoQuickTranscode, getDurationFromVideoFile, getMetadataFromFile, getVideoFileFPS } from '../helpers/ffprobe-utils' | 9 | import { canDoQuickTranscode, getDurationFromVideoFile, getMetadataFromFile, getVideoFileFPS } from '../../helpers/ffprobe-utils' |
10 | import { logger } from '../helpers/logger' | 10 | import { logger } from '../../helpers/logger' |
11 | import { CONFIG } from '../initializers/config' | 11 | import { CONFIG } from '../../initializers/config' |
12 | import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSERVER } from '../initializers/constants' | 12 | import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSERVER } from '../../initializers/constants' |
13 | import { VideoFileModel } from '../models/video/video-file' | 13 | import { VideoFileModel } from '../../models/video/video-file' |
14 | import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist' | 14 | import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist' |
15 | import { updateMasterHLSPlaylist, updateSha256VODSegments } from './hls' | 15 | import { updateMasterHLSPlaylist, updateSha256VODSegments } from '../hls' |
16 | import { generateVideoFilename, generateVideoStreamingPlaylistName, getVideoFilePath } from './video-paths' | 16 | import { generateVideoFilename, generateVideoStreamingPlaylistName, getVideoFilePath } from '../video-paths' |
17 | import { VideoTranscodingProfilesManager } from './video-transcoding-profiles' | 17 | import { VideoTranscodingProfilesManager } from './video-transcoding-profiles' |
18 | 18 | ||
19 | /** | 19 | /** |
@@ -215,16 +215,6 @@ function generateHlsPlaylistResolution (options: { | |||
215 | }) | 215 | }) |
216 | } | 216 | } |
217 | 217 | ||
218 | function getEnabledResolutions (type: 'vod' | 'live') { | ||
219 | const transcoding = type === 'vod' | ||
220 | ? CONFIG.TRANSCODING | ||
221 | : CONFIG.LIVE.TRANSCODING | ||
222 | |||
223 | return Object.keys(transcoding.RESOLUTIONS) | ||
224 | .filter(key => transcoding.ENABLED && transcoding.RESOLUTIONS[key] === true) | ||
225 | .map(r => parseInt(r, 10)) | ||
226 | } | ||
227 | |||
228 | // --------------------------------------------------------------------------- | 218 | // --------------------------------------------------------------------------- |
229 | 219 | ||
230 | export { | 220 | export { |
@@ -232,8 +222,7 @@ export { | |||
232 | generateHlsPlaylistResolutionFromTS, | 222 | generateHlsPlaylistResolutionFromTS, |
233 | optimizeOriginalVideofile, | 223 | optimizeOriginalVideofile, |
234 | transcodeNewWebTorrentResolution, | 224 | transcodeNewWebTorrentResolution, |
235 | mergeAudioVideofile, | 225 | mergeAudioVideofile |
236 | getEnabledResolutions | ||
237 | } | 226 | } |
238 | 227 | ||
239 | // --------------------------------------------------------------------------- | 228 | // --------------------------------------------------------------------------- |
diff --git a/server/lib/user.ts b/server/lib/user.ts index 9b0a0a2f1..8a6fcebc7 100644 --- a/server/lib/user.ts +++ b/server/lib/user.ts | |||
@@ -1,14 +1,15 @@ | |||
1 | import { Transaction } from 'sequelize/types' | 1 | import { Transaction } from 'sequelize/types' |
2 | import { v4 as uuidv4 } from 'uuid' | 2 | import { v4 as uuidv4 } from 'uuid' |
3 | import { UserModel } from '@server/models/account/user' | 3 | import { UserModel } from '@server/models/user/user' |
4 | import { MActorDefault } from '@server/types/models/actor' | ||
4 | import { ActivityPubActorType } from '../../shared/models/activitypub' | 5 | import { ActivityPubActorType } from '../../shared/models/activitypub' |
5 | import { UserNotificationSetting, UserNotificationSettingValue } from '../../shared/models/users' | 6 | import { UserNotificationSetting, UserNotificationSettingValue } from '../../shared/models/users' |
6 | import { SERVER_ACTOR_NAME, WEBSERVER } from '../initializers/constants' | 7 | import { SERVER_ACTOR_NAME, WEBSERVER } from '../initializers/constants' |
7 | import { sequelizeTypescript } from '../initializers/database' | 8 | import { sequelizeTypescript } from '../initializers/database' |
8 | import { AccountModel } from '../models/account/account' | 9 | import { AccountModel } from '../models/account/account' |
9 | import { UserNotificationSettingModel } from '../models/account/user-notification-setting' | 10 | import { ActorModel } from '../models/actor/actor' |
10 | import { ActorModel } from '../models/activitypub/actor' | 11 | import { UserNotificationSettingModel } from '../models/user/user-notification-setting' |
11 | import { MAccountDefault, MActorDefault, MChannelActor } from '../types/models' | 12 | import { MAccountDefault, MChannelActor } from '../types/models' |
12 | import { MUser, MUserDefault, MUserId } from '../types/models/user' | 13 | import { MUser, MUserDefault, MUserId } from '../types/models/user' |
13 | import { buildActorInstance, generateAndSaveActorKeys } from './activitypub/actor' | 14 | import { buildActorInstance, generateAndSaveActorKeys } from './activitypub/actor' |
14 | import { getLocalAccountActivityPubUrl } from './activitypub/url' | 15 | import { getLocalAccountActivityPubUrl } from './activitypub/url' |
diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts index 0476cb2d5..d57e832fe 100644 --- a/server/lib/video-channel.ts +++ b/server/lib/video-channel.ts | |||
@@ -1,5 +1,4 @@ | |||
1 | import * as Sequelize from 'sequelize' | 1 | import * as Sequelize from 'sequelize' |
2 | import { v4 as uuidv4 } from 'uuid' | ||
3 | import { VideoChannelCreate } from '../../shared/models' | 2 | import { VideoChannelCreate } from '../../shared/models' |
4 | import { VideoModel } from '../models/video/video' | 3 | import { VideoModel } from '../models/video/video' |
5 | import { VideoChannelModel } from '../models/video/video-channel' | 4 | import { VideoChannelModel } from '../models/video/video-channel' |
@@ -9,9 +8,8 @@ import { getLocalVideoChannelActivityPubUrl } from './activitypub/url' | |||
9 | import { federateVideoIfNeeded } from './activitypub/videos' | 8 | import { federateVideoIfNeeded } from './activitypub/videos' |
10 | 9 | ||
11 | async function createLocalVideoChannel (videoChannelInfo: VideoChannelCreate, account: MAccountId, t: Sequelize.Transaction) { | 10 | async function createLocalVideoChannel (videoChannelInfo: VideoChannelCreate, account: MAccountId, t: Sequelize.Transaction) { |
12 | const uuid = uuidv4() | ||
13 | const url = getLocalVideoChannelActivityPubUrl(videoChannelInfo.name) | 11 | const url = getLocalVideoChannelActivityPubUrl(videoChannelInfo.name) |
14 | const actorInstance = buildActorInstance('Group', url, videoChannelInfo.name, uuid) | 12 | const actorInstance = buildActorInstance('Group', url, videoChannelInfo.name) |
15 | 13 | ||
16 | const actorInstanceCreated = await actorInstance.save({ transaction: t }) | 14 | const actorInstanceCreated = await actorInstance.save({ transaction: t }) |
17 | 15 | ||
diff --git a/server/lib/video-comment.ts b/server/lib/video-comment.ts index 736ebb2f8..51a9c747e 100644 --- a/server/lib/video-comment.ts +++ b/server/lib/video-comment.ts | |||
@@ -3,7 +3,7 @@ import * as Sequelize from 'sequelize' | |||
3 | import { logger } from '@server/helpers/logger' | 3 | import { logger } from '@server/helpers/logger' |
4 | import { sequelizeTypescript } from '@server/initializers/database' | 4 | import { sequelizeTypescript } from '@server/initializers/database' |
5 | import { ResultList } from '../../shared/models' | 5 | import { ResultList } from '../../shared/models' |
6 | import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model' | 6 | import { VideoCommentThreadTree } from '../../shared/models/videos/comment/video-comment.model' |
7 | import { VideoCommentModel } from '../models/video/video-comment' | 7 | import { VideoCommentModel } from '../models/video/video-comment' |
8 | import { MAccountDefault, MComment, MCommentOwnerVideo, MCommentOwnerVideoReply, MVideoFullLight } from '../types/models' | 8 | import { MAccountDefault, MComment, MCommentOwnerVideo, MCommentOwnerVideoReply, MVideoFullLight } from '../types/models' |
9 | import { sendCreateVideoComment, sendDeleteVideoComment } from './activitypub/send' | 9 | import { sendCreateVideoComment, sendDeleteVideoComment } from './activitypub/send' |
diff --git a/server/lib/video.ts b/server/lib/video.ts index 9469b8178..d26cf85cd 100644 --- a/server/lib/video.ts +++ b/server/lib/video.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | import { UploadFiles } from 'express' | ||
1 | import { Transaction } from 'sequelize/types' | 2 | import { Transaction } from 'sequelize/types' |
2 | import { DEFAULT_AUDIO_RESOLUTION, JOB_PRIORITY } from '@server/initializers/constants' | 3 | import { DEFAULT_AUDIO_RESOLUTION, JOB_PRIORITY } from '@server/initializers/constants' |
3 | import { sequelizeTypescript } from '@server/initializers/database' | 4 | import { sequelizeTypescript } from '@server/initializers/database' |
@@ -27,12 +28,14 @@ function buildLocalVideoFromReq (videoInfo: VideoCreate, channelId: number): Fil | |||
27 | privacy: videoInfo.privacy || VideoPrivacy.PRIVATE, | 28 | privacy: videoInfo.privacy || VideoPrivacy.PRIVATE, |
28 | channelId: channelId, | 29 | channelId: channelId, |
29 | originallyPublishedAt: videoInfo.originallyPublishedAt | 30 | originallyPublishedAt: videoInfo.originallyPublishedAt |
31 | ? new Date(videoInfo.originallyPublishedAt) | ||
32 | : null | ||
30 | } | 33 | } |
31 | } | 34 | } |
32 | 35 | ||
33 | async function buildVideoThumbnailsFromReq (options: { | 36 | async function buildVideoThumbnailsFromReq (options: { |
34 | video: MVideoThumbnail | 37 | video: MVideoThumbnail |
35 | files: { [fieldname: string]: Express.Multer.File[] } | Express.Multer.File[] | 38 | files: UploadFiles |
36 | fallback: (type: ThumbnailType) => Promise<MThumbnail> | 39 | fallback: (type: ThumbnailType) => Promise<MThumbnail> |
37 | automaticallyGenerated?: boolean | 40 | automaticallyGenerated?: boolean |
38 | }) { | 41 | }) { |