aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/activitypub/actor.ts9
-rw-r--r--server/lib/activitypub/audience.ts2
-rw-r--r--server/lib/activitypub/process/process-accept.ts4
-rw-r--r--server/lib/activitypub/process/process-delete.ts2
-rw-r--r--server/lib/activitypub/process/process-follow.ts14
-rw-r--r--server/lib/activitypub/process/process-reject.ts2
-rw-r--r--server/lib/activitypub/process/process-undo.ts4
-rw-r--r--server/lib/activitypub/process/process-update.ts20
-rw-r--r--server/lib/activitypub/send/send-delete.ts2
-rw-r--r--server/lib/activitypub/send/send-view.ts2
-rw-r--r--server/lib/activitypub/send/utils.ts12
-rw-r--r--server/lib/activitypub/videos.ts3
-rw-r--r--server/lib/auth/oauth-model.ts4
-rw-r--r--server/lib/client-html.ts18
-rw-r--r--server/lib/config.ts255
-rw-r--r--server/lib/hls.ts11
-rw-r--r--server/lib/job-queue/handlers/activitypub-follow.ts20
-rw-r--r--server/lib/job-queue/handlers/activitypub-refresher.ts8
-rw-r--r--server/lib/job-queue/handlers/actor-keys.ts2
-rw-r--r--server/lib/job-queue/handlers/utils/activitypub-http-utils.ts8
-rw-r--r--server/lib/job-queue/handlers/video-file-import.ts2
-rw-r--r--server/lib/job-queue/handlers/video-import.ts7
-rw-r--r--server/lib/job-queue/handlers/video-live-ending.ts2
-rw-r--r--server/lib/job-queue/handlers/video-transcoding.ts4
-rw-r--r--server/lib/job-queue/handlers/video-views.ts4
-rw-r--r--server/lib/live-manager.ts4
-rw-r--r--server/lib/moderation.ts11
-rw-r--r--server/lib/notifier.ts4
-rw-r--r--server/lib/plugins/hooks.ts6
-rw-r--r--server/lib/plugins/plugin-helpers-builder.ts12
-rw-r--r--server/lib/plugins/plugin-index.ts20
-rw-r--r--server/lib/plugins/plugin-manager.ts14
-rw-r--r--server/lib/plugins/register-helpers.ts6
-rw-r--r--server/lib/redundancy.ts12
-rw-r--r--server/lib/schedulers/actor-follow-scheduler.ts4
-rw-r--r--server/lib/schedulers/auto-follow-index-instances.ts2
-rw-r--r--server/lib/schedulers/remove-dangling-resumable-uploads-scheduler.ts61
-rw-r--r--server/lib/schedulers/remove-old-history-scheduler.ts2
-rw-r--r--server/lib/schedulers/videos-redundancy-scheduler.ts4
-rw-r--r--server/lib/schedulers/youtube-dl-update-scheduler.ts6
-rw-r--r--server/lib/server-config-manager.ts303
-rw-r--r--server/lib/stat-manager.ts4
-rw-r--r--server/lib/transcoding/video-transcoding-profiles.ts (renamed from server/lib/video-transcoding-profiles.ts)8
-rw-r--r--server/lib/transcoding/video-transcoding.ts (renamed from server/lib/video-transcoding.ts)35
-rw-r--r--server/lib/user.ts9
-rw-r--r--server/lib/video-channel.ts4
-rw-r--r--server/lib/video-comment.ts2
-rw-r--r--server/lib/video.ts5
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'
20import { MIMETYPES, WEBSERVER } from '../../initializers/constants' 20import { MIMETYPES, WEBSERVER } from '../../initializers/constants'
21import { sequelizeTypescript } from '../../initializers/database' 21import { sequelizeTypescript } from '../../initializers/database'
22import { AccountModel } from '../../models/account/account' 22import { AccountModel } from '../../models/account/account'
23import { ActorImageModel } from '../../models/account/actor-image' 23import { ActorModel } from '../../models/actor/actor'
24import { ActorModel } from '../../models/activitypub/actor' 24import { ActorImageModel } from '../../models/actor/actor-image'
25import { ServerModel } from '../../models/server/server' 25import { ServerModel } from '../../models/server/server'
26import { VideoChannelModel } from '../../models/video/video-channel' 26import { VideoChannelModel } from '../../models/video/video-channel'
27import { 27import {
@@ -132,12 +132,11 @@ async function getOrCreateActorAndServerAndModel (
132 return actorRefreshed 132 return actorRefreshed
133} 133}
134 134
135function buildActorInstance (type: ActivityPubActorType, url: string, preferredUsername: string, uuid?: string) { 135function 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 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { ActivityAudience } from '../../../shared/models/activitypub' 2import { ActivityAudience } from '../../../shared/models/activitypub'
3import { ACTIVITY_PUB } from '../../initializers/constants' 3import { ACTIVITY_PUB } from '../../initializers/constants'
4import { ActorModel } from '../../models/activitypub/actor' 4import { ActorModel } from '../../models/actor/actor'
5import { VideoModel } from '../../models/video/video' 5import { VideoModel } from '../../models/video/video'
6import { VideoShareModel } from '../../models/video/video-share' 6import { VideoShareModel } from '../../models/video/video-share'
7import { MActorFollowersUrl, MActorLight, MActorUrl, MCommentOwner, MCommentOwnerVideo, MVideoId } from '../../types/models' 7import { 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 @@
1import { ActivityAccept } from '../../../../shared/models/activitypub' 1import { ActivityAccept } from '../../../../shared/models/activitypub'
2import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 2import { ActorFollowModel } from '../../../models/actor/actor-follow'
3import { addFetchOutboxJob } from '../actor'
4import { APProcessorOptions } from '../../../types/activitypub-processor.model' 3import { APProcessorOptions } from '../../../types/activitypub-processor.model'
5import { MActorDefault, MActorSignature } from '../../../types/models' 4import { MActorDefault, MActorSignature } from '../../../types/models'
5import { addFetchOutboxJob } from '../actor'
6 6
7async function processAcceptActivity (options: APProcessorOptions<ActivityAccept>) { 7async 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'
2import { retryTransactionWrapper } from '../../../helpers/database-utils' 2import { retryTransactionWrapper } from '../../../helpers/database-utils'
3import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
4import { sequelizeTypescript } from '../../../initializers/database' 4import { sequelizeTypescript } from '../../../initializers/database'
5import { ActorModel } from '../../../models/activitypub/actor' 5import { ActorModel } from '../../../models/actor/actor'
6import { VideoModel } from '../../../models/video/video' 6import { VideoModel } from '../../../models/video/video'
7import { VideoCommentModel } from '../../../models/video/video-comment' 7import { VideoCommentModel } from '../../../models/video/video-comment'
8import { VideoPlaylistModel } from '../../../models/video/video-playlist' 8import { 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 @@
1import { getServerActor } from '@server/models/application/application'
1import { ActivityFollow } from '../../../../shared/models/activitypub' 2import { ActivityFollow } from '../../../../shared/models/activitypub'
3import { getAPId } from '../../../helpers/activitypub'
2import { retryTransactionWrapper } from '../../../helpers/database-utils' 4import { retryTransactionWrapper } from '../../../helpers/database-utils'
3import { logger } from '../../../helpers/logger' 5import { logger } from '../../../helpers/logger'
4import { sequelizeTypescript } from '../../../initializers/database'
5import { ActorModel } from '../../../models/activitypub/actor'
6import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
7import { sendAccept, sendReject } from '../send'
8import { Notifier } from '../../notifier'
9import { getAPId } from '../../../helpers/activitypub'
10import { CONFIG } from '../../../initializers/config' 6import { CONFIG } from '../../../initializers/config'
7import { sequelizeTypescript } from '../../../initializers/database'
8import { ActorModel } from '../../../models/actor/actor'
9import { ActorFollowModel } from '../../../models/actor/actor-follow'
11import { APProcessorOptions } from '../../../types/activitypub-processor.model' 10import { APProcessorOptions } from '../../../types/activitypub-processor.model'
12import { MActorFollowActors, MActorSignature } from '../../../types/models' 11import { MActorFollowActors, MActorSignature } from '../../../types/models'
12import { Notifier } from '../../notifier'
13import { autoFollowBackIfNeeded } from '../follow' 13import { autoFollowBackIfNeeded } from '../follow'
14import { getServerActor } from '@server/models/application/application' 14import { sendAccept, sendReject } from '../send'
15 15
16async function processFollowActivity (options: APProcessorOptions<ActivityFollow>) { 16async 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 @@
1import { ActivityReject } from '../../../../shared/models/activitypub/activity' 1import { ActivityReject } from '../../../../shared/models/activitypub/activity'
2import { sequelizeTypescript } from '../../../initializers/database' 2import { sequelizeTypescript } from '../../../initializers/database'
3import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 3import { ActorFollowModel } from '../../../models/actor/actor-follow'
4import { APProcessorOptions } from '../../../types/activitypub-processor.model' 4import { APProcessorOptions } from '../../../types/activitypub-processor.model'
5import { MActor } from '../../../types/models' 5import { 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'
4import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
5import { sequelizeTypescript } from '../../../initializers/database' 5import { sequelizeTypescript } from '../../../initializers/database'
6import { AccountVideoRateModel } from '../../../models/account/account-video-rate' 6import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
7import { ActorModel } from '../../../models/activitypub/actor' 7import { ActorModel } from '../../../models/actor/actor'
8import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 8import { ActorFollowModel } from '../../../models/actor/actor-follow'
9import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy' 9import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
10import { VideoShareModel } from '../../../models/video/video-share' 10import { VideoShareModel } from '../../../models/video/video-share'
11import { APProcessorOptions } from '../../../types/activitypub-processor.model' 11import { 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 @@
1import { isRedundancyAccepted } from '@server/lib/redundancy'
2import { ActorImageType } from '@shared/models'
1import { ActivityUpdate, CacheFileObject, VideoObject } from '../../../../shared/models/activitypub' 3import { ActivityUpdate, CacheFileObject, VideoObject } from '../../../../shared/models/activitypub'
2import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor' 4import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor'
5import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
6import { isCacheFileObjectValid } from '../../../helpers/custom-validators/activitypub/cache-file'
7import { sanitizeAndCheckVideoTorrentObject } from '../../../helpers/custom-validators/activitypub/videos'
3import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils' 8import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils'
4import { logger } from '../../../helpers/logger' 9import { logger } from '../../../helpers/logger'
5import { sequelizeTypescript } from '../../../initializers/database' 10import { sequelizeTypescript } from '../../../initializers/database'
6import { AccountModel } from '../../../models/account/account' 11import { AccountModel } from '../../../models/account/account'
7import { ActorModel } from '../../../models/activitypub/actor' 12import { ActorModel } from '../../../models/actor/actor'
8import { VideoChannelModel } from '../../../models/video/video-channel' 13import { VideoChannelModel } from '../../../models/video/video-channel'
14import { APProcessorOptions } from '../../../types/activitypub-processor.model'
15import { MAccountIdActor, MActorSignature } from '../../../types/models'
9import { getImageInfoIfExists, updateActorImageInstance, updateActorInstance } from '../actor' 16import { getImageInfoIfExists, updateActorImageInstance, updateActorInstance } from '../actor'
10import { getOrCreateVideoAndAccountAndChannel, getOrCreateVideoChannelFromVideoObject, updateVideoFromAP } from '../videos'
11import { sanitizeAndCheckVideoTorrentObject } from '../../../helpers/custom-validators/activitypub/videos'
12import { isCacheFileObjectValid } from '../../../helpers/custom-validators/activitypub/cache-file'
13import { createOrUpdateCacheFile } from '../cache-file' 17import { createOrUpdateCacheFile } from '../cache-file'
14import { forwardVideoRelatedActivity } from '../send/utils'
15import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
16import { createOrUpdateVideoPlaylist } from '../playlist' 18import { createOrUpdateVideoPlaylist } from '../playlist'
17import { APProcessorOptions } from '../../../types/activitypub-processor.model' 19import { forwardVideoRelatedActivity } from '../send/utils'
18import { MActorSignature, MAccountIdActor } from '../../../types/models' 20import { getOrCreateVideoAndAccountAndChannel, getOrCreateVideoChannelFromVideoObject, updateVideoFromAP } from '../videos'
19import { isRedundancyAccepted } from '@server/lib/redundancy'
20import { ActorImageType } from '@shared/models'
21 21
22async function processUpdateActivity (options: APProcessorOptions<ActivityUpdate>) { 22async 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'
2import { getServerActor } from '@server/models/application/application' 2import { getServerActor } from '@server/models/application/application'
3import { ActivityAudience, ActivityDelete } from '../../../../shared/models/activitypub' 3import { ActivityAudience, ActivityDelete } from '../../../../shared/models/activitypub'
4import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
5import { ActorModel } from '../../../models/activitypub/actor' 5import { ActorModel } from '../../../models/actor/actor'
6import { VideoCommentModel } from '../../../models/video/video-comment' 6import { VideoCommentModel } from '../../../models/video/video-comment'
7import { VideoShareModel } from '../../../models/video/video-share' 7import { VideoShareModel } from '../../../models/video/video-share'
8import { MActorUrl } from '../../../types/models' 8import { 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'
2import { MActorAudience, MVideoImmutable, MVideoUrl } from '@server/types/models' 2import { MActorAudience, MVideoImmutable, MVideoUrl } from '@server/types/models'
3import { ActivityAudience, ActivityView } from '../../../../shared/models/activitypub' 3import { ActivityAudience, ActivityView } from '../../../../shared/models/activitypub'
4import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
5import { ActorModel } from '../../../models/activitypub/actor' 5import { ActorModel } from '../../../models/actor/actor'
6import { audiencify, getAudience } from '../audience' 6import { audiencify, getAudience } from '../audience'
7import { getLocalVideoViewActivityPubUrl } from '../url' 7import { getLocalVideoViewActivityPubUrl } from '../url'
8import { sendVideoRelatedActivity } from './utils' 8import { 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 @@
1import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
2import { getServerActor } from '@server/models/application/application'
3import { ContextType } from '@shared/models/activitypub/context'
2import { Activity, ActivityAudience } from '../../../../shared/models/activitypub' 4import { Activity, ActivityAudience } from '../../../../shared/models/activitypub'
5import { afterCommitIfTransaction } from '../../../helpers/database-utils'
3import { logger } from '../../../helpers/logger' 6import { logger } from '../../../helpers/logger'
4import { ActorModel } from '../../../models/activitypub/actor' 7import { ActorModel } from '../../../models/actor/actor'
5import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 8import { ActorFollowModel } from '../../../models/actor/actor-follow'
9import { MActor, MActorId, MActorLight, MActorWithInboxes, MVideoAccountLight, MVideoId, MVideoImmutable } from '../../../types/models'
6import { JobQueue } from '../../job-queue' 10import { JobQueue } from '../../job-queue'
7import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience' 11import { getActorsInvolvedInVideo, getAudienceFromFollowersOf, getRemoteVideoAudience } from '../audience'
8import { afterCommitIfTransaction } from '../../../helpers/database-utils'
9import { MActor, MActorId, MActorLight, MActorWithInboxes, MVideoAccountLight, MVideoId, MVideoImmutable } from '../../../types/models'
10import { getServerActor } from '@server/models/application/application'
11import { ContextType } from '@shared/models/activitypub/context'
12 12
13async function sendVideoRelatedActivity (activityBuilder: (audience: ActivityAudience) => Activity, options: { 13async 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 @@
1import * as express from 'express' 1import * as express from 'express'
2import { AccessDeniedError } from 'oauth2-server' 2import { AccessDeniedError } from 'oauth2-server'
3import { PluginManager } from '@server/lib/plugins/plugin-manager' 3import { PluginManager } from '@server/lib/plugins/plugin-manager'
4import { ActorModel } from '@server/models/activitypub/actor' 4import { ActorModel } from '@server/models/actor/actor'
5import { MOAuthClient } from '@server/types/models' 5import { MOAuthClient } from '@server/types/models'
6import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' 6import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token'
7import { MUser } from '@server/types/models/user/user' 7import { MUser } from '@server/types/models/user/user'
@@ -9,7 +9,7 @@ import { UserAdminFlag } from '@shared/models/users/user-flag.model'
9import { UserRole } from '@shared/models/users/user-role' 9import { UserRole } from '@shared/models/users/user-role'
10import { logger } from '../../helpers/logger' 10import { logger } from '../../helpers/logger'
11import { CONFIG } from '../../initializers/config' 11import { CONFIG } from '../../initializers/config'
12import { UserModel } from '../../models/account/user' 12import { UserModel } from '../../models/user/user'
13import { OAuthClientModel } from '../../models/oauth/oauth-client' 13import { OAuthClientModel } from '../../models/oauth/oauth-client'
14import { OAuthTokenModel } from '../../models/oauth/oauth-token' 14import { OAuthTokenModel } from '../../models/oauth/oauth-token'
15import { createUserAccountAndChannelAndPlaylist } from '../user' 15import { 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'
2import { readFile } from 'fs-extra' 2import { readFile } from 'fs-extra'
3import { join } from 'path' 3import { join } from 'path'
4import validator from 'validator' 4import validator from 'validator'
5import { escapeHTML } from '@shared/core-utils/renderer'
6import { HTMLServerConfig } from '@shared/models'
5import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' 7import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
6import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes' 8import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
7import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos' 9import { VideoPlaylistPrivacy, VideoPrivacy } from '../../shared/models/videos'
8import { isTestInstance, sha256 } from '../helpers/core-utils' 10import { isTestInstance, sha256 } from '../helpers/core-utils'
9import { escapeHTML } from '@shared/core-utils/renderer'
10import { logger } from '../helpers/logger' 11import { logger } from '../helpers/logger'
12import { mdToPlainText } from '../helpers/markdown'
11import { CONFIG } from '../initializers/config' 13import { CONFIG } from '../initializers/config'
12import { 14import {
13 ACCEPT_HEADERS, 15 ACCEPT_HEADERS,
@@ -24,7 +26,7 @@ import { VideoChannelModel } from '../models/video/video-channel'
24import { getActivityStreamDuration } from '../models/video/video-format-utils' 26import { getActivityStreamDuration } from '../models/video/video-format-utils'
25import { VideoPlaylistModel } from '../models/video/video-playlist' 27import { VideoPlaylistModel } from '../models/video/video-playlist'
26import { MAccountActor, MChannelActor } from '../types/models' 28import { MAccountActor, MChannelActor } from '../types/models'
27import { mdToPlainText } from '../helpers/markdown' 29import { ServerConfigManager } from './server-config-manager'
28 30
29type Tags = { 31type 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 @@
1import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/helpers/signup'
2import { getServerCommit } from '@server/helpers/utils'
3import { CONFIG, isEmailEnabled } from '@server/initializers/config'
4import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants'
5import { RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models'
6import { Hooks } from './plugins/hooks'
7import { PluginManager } from './plugins/plugin-manager'
8import { getThemeOrDefault } from './plugins/theme-utils'
9import { getEnabledResolutions } from './video-transcoding'
10import { VideoTranscodingProfilesManager } from './video-transcoding-profiles'
11
12let serverCommit: string
13
14async 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
190function 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
201function 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
213export {
214 getServerConfig,
215 getRegisteredThemes,
216 getRegisteredPlugins
217}
218
219// ---------------------------------------------------------------------------
220
221function 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
239function 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 @@
1import * as Bull from 'bull' 1import * as Bull from 'bull'
2import { logger } from '../../../helpers/logger' 2import { getLocalActorFollowActivityPubUrl } from '@server/lib/activitypub/url'
3import { REMOTE_SCHEME, WEBSERVER } from '../../../initializers/constants' 3import { ActivitypubFollowPayload } from '@shared/models'
4import { sendFollow } from '../../activitypub/send'
5import { sanitizeHost } from '../../../helpers/core-utils' 4import { sanitizeHost } from '../../../helpers/core-utils'
6import { loadActorUrlOrGetFromWebfinger } from '../../../helpers/webfinger'
7import { getOrCreateActorAndServerAndModel } from '../../activitypub/actor'
8import { retryTransactionWrapper } from '../../../helpers/database-utils' 5import { retryTransactionWrapper } from '../../../helpers/database-utils'
9import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 6import { logger } from '../../../helpers/logger'
10import { ActorModel } from '../../../models/activitypub/actor' 7import { loadActorUrlOrGetFromWebfinger } from '../../../helpers/webfinger'
11import { Notifier } from '../../notifier' 8import { REMOTE_SCHEME, WEBSERVER } from '../../../initializers/constants'
12import { sequelizeTypescript } from '../../../initializers/database' 9import { sequelizeTypescript } from '../../../initializers/database'
10import { ActorModel } from '../../../models/actor/actor'
11import { ActorFollowModel } from '../../../models/actor/actor-follow'
13import { MActor, MActorFollowActors, MActorFull } from '../../../types/models' 12import { MActor, MActorFollowActors, MActorFull } from '../../../types/models'
14import { ActivitypubFollowPayload } from '@shared/models' 13import { getOrCreateActorAndServerAndModel } from '../../activitypub/actor'
15import { getLocalActorFollowActivityPubUrl } from '@server/lib/activitypub/url' 14import { sendFollow } from '../../activitypub/send'
15import { Notifier } from '../../notifier'
16 16
17async function processActivityPubFollow (job: Bull.Job) { 17async 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 @@
1import * as Bull from 'bull' 1import * as Bull from 'bull'
2import { refreshVideoPlaylistIfNeeded } from '@server/lib/activitypub/playlist'
3import { RefreshPayload } from '@shared/models'
2import { logger } from '../../../helpers/logger' 4import { logger } from '../../../helpers/logger'
3import { fetchVideoByUrl } from '../../../helpers/video' 5import { fetchVideoByUrl } from '../../../helpers/video'
6import { ActorModel } from '../../../models/actor/actor'
7import { VideoPlaylistModel } from '../../../models/video/video-playlist'
4import { refreshActorIfNeeded } from '../../activitypub/actor' 8import { refreshActorIfNeeded } from '../../activitypub/actor'
5import { refreshVideoIfNeeded } from '../../activitypub/videos' 9import { refreshVideoIfNeeded } from '../../activitypub/videos'
6import { ActorModel } from '../../../models/activitypub/actor'
7import { VideoPlaylistModel } from '../../../models/video/video-playlist'
8import { RefreshPayload } from '@shared/models'
9import { refreshVideoPlaylistIfNeeded } from '@server/lib/activitypub/playlist'
10 10
11async function refreshAPObject (job: Bull.Job) { 11async 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 @@
1import * as Bull from 'bull' 1import * as Bull from 'bull'
2import { generateAndSaveActorKeys } from '@server/lib/activitypub/actor' 2import { generateAndSaveActorKeys } from '@server/lib/activitypub/actor'
3import { ActorModel } from '@server/models/activitypub/actor' 3import { ActorModel } from '@server/models/actor/actor'
4import { ActorKeysPayload } from '@shared/models' 4import { ActorKeysPayload } from '@shared/models'
5import { logger } from '../../../helpers/logger' 5import { 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 @@
1import { buildDigest } from '@server/helpers/peertube-crypto'
2import { getServerActor } from '@server/models/application/application'
3import { ContextType } from '@shared/models/activitypub/context'
1import { buildSignedActivity } from '../../../../helpers/activitypub' 4import { buildSignedActivity } from '../../../../helpers/activitypub'
2import { ActorModel } from '../../../../models/activitypub/actor'
3import { ACTIVITY_PUB, HTTP_SIGNATURE } from '../../../../initializers/constants' 5import { ACTIVITY_PUB, HTTP_SIGNATURE } from '../../../../initializers/constants'
6import { ActorModel } from '../../../../models/actor/actor'
4import { MActor } from '../../../../types/models' 7import { MActor } from '../../../../types/models'
5import { getServerActor } from '@server/models/application/application'
6import { buildDigest } from '@server/helpers/peertube-crypto'
7import { ContextType } from '@shared/models/activitypub/context'
8 8
9type Payload <T> = { body: T, contextType?: ContextType, signatureActorId?: number } 9type 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'
3import { extname } from 'path' 3import { extname } from 'path'
4import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' 4import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
5import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' 5import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
6import { UserModel } from '@server/models/account/user' 6import { UserModel } from '@server/models/user/user'
7import { MVideoFullLight } from '@server/types/models' 7import { MVideoFullLight } from '@server/types/models'
8import { VideoFileImportPayload } from '@shared/models' 8import { VideoFileImportPayload } from '@shared/models'
9import { getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffprobe-utils' 9import { 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'
2import { move, remove, stat } from 'fs-extra' 2import { move, remove, stat } from 'fs-extra'
3import { extname } from 'path' 3import { extname } from 'path'
4import { retryTransactionWrapper } from '@server/helpers/database-utils' 4import { retryTransactionWrapper } from '@server/helpers/database-utils'
5import { YoutubeDL } from '@server/helpers/youtube-dl'
5import { isPostImportVideoAccepted } from '@server/lib/moderation' 6import { isPostImportVideoAccepted } from '@server/lib/moderation'
6import { Hooks } from '@server/lib/plugins/hooks' 7import { Hooks } from '@server/lib/plugins/hooks'
8import { ServerConfigManager } from '@server/lib/server-config-manager'
7import { isAbleToUploadVideo } from '@server/lib/user' 9import { isAbleToUploadVideo } from '@server/lib/user'
8import { addOptimizeOrMergeAudioJob } from '@server/lib/video' 10import { addOptimizeOrMergeAudioJob } from '@server/lib/video'
9import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths' 11import { generateVideoFilename, getVideoFilePath } from '@server/lib/video-paths'
@@ -23,7 +25,6 @@ import { getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } fro
23import { logger } from '../../../helpers/logger' 25import { logger } from '../../../helpers/logger'
24import { getSecureTorrentName } from '../../../helpers/utils' 26import { getSecureTorrentName } from '../../../helpers/utils'
25import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent' 27import { createTorrentAndSetInfoHash, downloadWebTorrentVideo } from '../../../helpers/webtorrent'
26import { downloadYoutubeDLVideo } from '../../../helpers/youtube-dl'
27import { CONFIG } from '../../../initializers/config' 28import { CONFIG } from '../../../initializers/config'
28import { VIDEO_IMPORT_TIMEOUT } from '../../../initializers/constants' 29import { VIDEO_IMPORT_TIMEOUT } from '../../../initializers/constants'
29import { sequelizeTypescript } from '../../../initializers/database' 30import { 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
5import { VIDEO_LIVE } from '@server/initializers/constants' 5import { VIDEO_LIVE } from '@server/initializers/constants'
6import { LiveManager } from '@server/lib/live-manager' 6import { LiveManager } from '@server/lib/live-manager'
7import { generateVideoMiniature } from '@server/lib/thumbnail' 7import { generateVideoMiniature } from '@server/lib/thumbnail'
8import { generateHlsPlaylistResolutionFromTS } from '@server/lib/transcoding/video-transcoding'
8import { publishAndFederateIfNeeded } from '@server/lib/video' 9import { publishAndFederateIfNeeded } from '@server/lib/video'
9import { getHLSDirectory } from '@server/lib/video-paths' 10import { getHLSDirectory } from '@server/lib/video-paths'
10import { generateHlsPlaylistResolutionFromTS } from '@server/lib/video-transcoding'
11import { VideoModel } from '@server/models/video/video' 11import { VideoModel } from '@server/models/video/video'
12import { VideoFileModel } from '@server/models/video/video-file' 12import { VideoFileModel } from '@server/models/video/video-file'
13import { VideoLiveModel } from '@server/models/video/video-live' 13import { 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'
2import { TranscodeOptionsType } from '@server/helpers/ffmpeg-utils' 2import { TranscodeOptionsType } from '@server/helpers/ffmpeg-utils'
3import { getTranscodingJobPriority, publishAndFederateIfNeeded } from '@server/lib/video' 3import { getTranscodingJobPriority, publishAndFederateIfNeeded } from '@server/lib/video'
4import { getVideoFilePath } from '@server/lib/video-paths' 4import { getVideoFilePath } from '@server/lib/video-paths'
5import { UserModel } from '@server/models/account/user' 5import { UserModel } from '@server/models/user/user'
6import { MUser, MUserId, MVideoFullLight, MVideoUUID, MVideoWithFile } from '@server/types/models' 6import { MUser, MUserId, MVideoFullLight, MVideoUUID, MVideoWithFile } from '@server/types/models'
7import { 7import {
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'
28import { JobQueue } from '../job-queue' 28import { JobQueue } from '../job-queue'
29 29
30type HandlerFunction = (job: Bull.Job, payload: VideoTranscodingPayload, video: MVideoFullLight, user: MUser) => Promise<any> 30type 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
11import { logger } from '@server/helpers/logger' 11import { logger } from '@server/helpers/logger'
12import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config' 12import { CONFIG, registerConfigChangedHandler } from '@server/initializers/config'
13import { MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, VIEW_LIFETIME, WEBSERVER } from '@server/initializers/constants' 13import { MEMOIZE_TTL, P2P_MEDIA_LOADER_PEER_VERSION, VIDEO_LIVE, VIEW_LIFETIME, WEBSERVER } from '@server/initializers/constants'
14import { UserModel } from '@server/models/account/user' 14import { UserModel } from '@server/models/user/user'
15import { VideoModel } from '@server/models/video/video' 15import { VideoModel } from '@server/models/video/video'
16import { VideoFileModel } from '@server/models/video/video-file' 16import { VideoFileModel } from '@server/models/video/video-file'
17import { VideoLiveModel } from '@server/models/video/video-live' 17import { VideoLiveModel } from '@server/models/video/video-live'
@@ -23,9 +23,9 @@ import { buildSha256Segment } from './hls'
23import { JobQueue } from './job-queue' 23import { JobQueue } from './job-queue'
24import { cleanupLive } from './job-queue/handlers/video-live-ending' 24import { cleanupLive } from './job-queue/handlers/video-live-ending'
25import { PeerTubeSocket } from './peertube-socket' 25import { PeerTubeSocket } from './peertube-socket'
26import { VideoTranscodingProfilesManager } from './transcoding/video-transcoding-profiles'
26import { isAbleToUploadVideo } from './user' 27import { isAbleToUploadVideo } from './user'
27import { getHLSDirectory } from './video-paths' 28import { getHLSDirectory } from './video-paths'
28import { VideoTranscodingProfilesManager } from './video-transcoding-profiles'
29 29
30import memoizee = require('memoizee') 30import memoizee = require('memoizee')
31const NodeRtmpSession = require('node-media-server/node_rtmp_session') 31const 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 @@
1import { VideoUploadFile } from 'express'
1import { PathLike } from 'fs-extra' 2import { PathLike } from 'fs-extra'
2import { Transaction } from 'sequelize/types' 3import { Transaction } from 'sequelize/types'
3import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger' 4import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger'
5import { afterCommitIfTransaction } from '@server/helpers/database-utils'
4import { logger } from '@server/helpers/logger' 6import { logger } from '@server/helpers/logger'
5import { AbuseModel } from '@server/models/abuse/abuse' 7import { AbuseModel } from '@server/models/abuse/abuse'
6import { VideoAbuseModel } from '@server/models/abuse/video-abuse' 8import { VideoAbuseModel } from '@server/models/abuse/video-abuse'
@@ -21,14 +23,13 @@ import { ActivityCreate } from '../../shared/models/activitypub'
21import { VideoObject } from '../../shared/models/activitypub/objects' 23import { VideoObject } from '../../shared/models/activitypub/objects'
22import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object' 24import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
23import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos' 25import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos'
24import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model' 26import { VideoCommentCreate } from '../../shared/models/videos/comment/video-comment.model'
25import { UserModel } from '../models/account/user' 27import { ActorModel } from '../models/actor/actor'
26import { ActorModel } from '../models/activitypub/actor' 28import { UserModel } from '../models/user/user'
27import { VideoModel } from '../models/video/video' 29import { VideoModel } from '../models/video/video'
28import { VideoCommentModel } from '../models/video/video-comment' 30import { VideoCommentModel } from '../models/video/video-comment'
29import { sendAbuse } from './activitypub/send/send-flag' 31import { sendAbuse } from './activitypub/send/send-flag'
30import { Notifier } from './notifier' 32import { Notifier } from './notifier'
31import { afterCommitIfTransaction } from '@server/helpers/database-utils'
32 33
33export type AcceptResult = { 34export 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
39function isLocalVideoAccepted (object: { 40function 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'
17import { logger } from '../helpers/logger' 17import { logger } from '../helpers/logger'
18import { CONFIG } from '../initializers/config' 18import { CONFIG } from '../initializers/config'
19import { AccountBlocklistModel } from '../models/account/account-blocklist' 19import { AccountBlocklistModel } from '../models/account/account-blocklist'
20import { UserModel } from '../models/account/user' 20import { UserModel } from '../models/user/user'
21import { UserNotificationModel } from '../models/account/user-notification' 21import { UserNotificationModel } from '../models/user/user-notification'
22import { MAbuseFull, MAbuseMessage, MAccountServer, MActorFollowFull, MApplication, MPlugin } from '../types/models' 22import { MAbuseFull, MAbuseMessage, MAccountServer, MActorFollowFull, MApplication, MPlugin } from '../types/models'
23import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../types/models/video' 23import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../types/models/video'
24import { isBlockedByServerOrAccount } from './blocklist' 24import { 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 @@
1import { ServerActionHookName, ServerFilterHookName } from '../../../shared/models/plugins/server-hook.model'
2import { PluginManager } from './plugin-manager'
3import { logger } from '../../helpers/logger'
4import * as Bluebird from 'bluebird' 1import * as Bluebird from 'bluebird'
2import { ServerActionHookName, ServerFilterHookName } from '../../../shared/models'
3import { logger } from '../../helpers/logger'
4import { PluginManager } from './plugin-manager'
5 5
6type PromiseFunction <U, T> = (params: U) => Promise<T> | Bluebird<T> 6type PromiseFunction <U, T> = (params: U) => Promise<T> | Bluebird<T>
7type RawFunction <U, T> = (params: U) => T 7type 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'
15import { PeerTubeHelpers } from '@server/types/plugins' 15import { PeerTubeHelpers } from '@server/types/plugins'
16import { VideoBlacklistCreate } from '@shared/models' 16import { VideoBlacklistCreate } from '@shared/models'
17import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../blocklist' 17import { addAccountInBlocklist, addServerInBlocklist, removeAccountFromBlocklist, removeServerFromBlocklist } from '../blocklist'
18import { getServerConfig } from '../config' 18import { ServerConfigManager } from '../server-config-manager'
19import { blacklistVideo, unblacklistVideo } from '../video-blacklist' 19import { blacklistVideo, unblacklistVideo } from '../video-blacklist'
20import { UserModel } from '@server/models/user/user'
20 21
21function buildPluginHelpers (pluginModel: MPlugin, npmName: string): PeerTubeHelpers { 22function 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
164function buildUserHelpers () { 165function 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 @@
1import { sanitizeUrl } from '@server/helpers/core-utils' 1import { sanitizeUrl } from '@server/helpers/core-utils'
2import { ResultList } from '../../../shared/models' 2import { logger } from '@server/helpers/logger'
3import { PeertubePluginIndexList } from '../../../shared/models/plugins/peertube-plugin-index-list.model' 3import { doJSONRequest } from '@server/helpers/requests'
4import { PeerTubePluginIndex } from '../../../shared/models/plugins/peertube-plugin-index.model' 4import { CONFIG } from '@server/initializers/config'
5import { PEERTUBE_VERSION } from '@server/initializers/constants'
6import { PluginModel } from '@server/models/server/plugin'
5import { 7import {
8 PeerTubePluginIndex,
9 PeertubePluginIndexList,
6 PeertubePluginLatestVersionRequest, 10 PeertubePluginLatestVersionRequest,
7 PeertubePluginLatestVersionResponse 11 PeertubePluginLatestVersionResponse,
8} from '../../../shared/models/plugins/peertube-plugin-latest-version.model' 12 ResultList
9import { logger } from '../../helpers/logger' 13} from '@shared/models'
10import { doJSONRequest } from '../../helpers/requests'
11import { CONFIG } from '../../initializers/config'
12import { PEERTUBE_VERSION } from '../../initializers/constants'
13import { PluginModel } from '../../models/server/plugin'
14import { PluginManager } from './plugin-manager' 14import { PluginManager } from './plugin-manager'
15 15
16async function listAvailablePluginsFromIndex (options: PeertubePluginIndexList) { 16async 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'
4import { ensureDir, outputFile, readJSON } from 'fs-extra' 4import { ensureDir, outputFile, readJSON } from 'fs-extra'
5import { basename, join } from 'path' 5import { basename, join } from 'path'
6import { MOAuthTokenUser, MUser } from '@server/types/models' 6import { MOAuthTokenUser, MUser } from '@server/types/models'
7import { RegisterServerHookOptions } from '@shared/models/plugins/register-server-hook.model' 7import { getCompleteLocale } from '@shared/core-utils'
8import { ClientScript, PluginPackageJson, PluginTranslation, PluginTranslationPaths, RegisterServerHookOptions } from '@shared/models'
8import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks' 9import { getHookType, internalRunHook } from '../../../shared/core-utils/plugins/hooks'
9import {
10 ClientScript,
11 PluginPackageJson,
12 PluginTranslationPaths as PackagePluginTranslations
13} from '../../../shared/models/plugins/plugin-package-json.model'
14import { PluginTranslation } from '../../../shared/models/plugins/plugin-translation.model'
15import { PluginType } from '../../../shared/models/plugins/plugin.type' 10import { PluginType } from '../../../shared/models/plugins/plugin.type'
16import { ServerHook, ServerHookName } from '../../../shared/models/plugins/server-hook.model' 11import { ServerHook, ServerHookName } from '../../../shared/models/plugins/server/server-hook.model'
17import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins' 12import { isLibraryCodeValid, isPackageJSONValid } from '../../helpers/custom-validators/plugins'
18import { logger } from '../../helpers/logger' 13import { logger } from '../../helpers/logger'
19import { CONFIG } from '../../initializers/config' 14import { CONFIG } from '../../initializers/config'
@@ -23,7 +18,6 @@ import { PluginLibrary, RegisterServerAuthExternalOptions, RegisterServerAuthPas
23import { ClientHtml } from '../client-html' 18import { ClientHtml } from '../client-html'
24import { RegisterHelpers } from './register-helpers' 19import { RegisterHelpers } from './register-helpers'
25import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn' 20import { installNpmPlugin, installNpmPluginFromDisk, removeNpmPlugin } from './yarn'
26import { getCompleteLocale } from '@shared/core-utils'
27 21
28export interface RegisteredPlugin { 22export 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'
31import { serverHookObject } from '@shared/models/plugins/server-hook.model' 32import { VideoTranscodingProfilesManager } from '../transcoding/video-transcoding-profiles'
32import { VideoTranscodingProfilesManager } from '../video-transcoding-profiles'
33import { buildPluginHelpers } from './plugin-helpers-builder' 33import { buildPluginHelpers } from './plugin-helpers-builder'
34 34
35type AlterableVideoConstant = 'language' | 'licence' | 'category' | 'privacy' | 'playlistPrivacy' 35type 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 @@
1import { VideoRedundancyModel } from '../models/redundancy/video-redundancy'
2import { sendUndoCacheFile } from './activitypub/send'
3import { Transaction } from 'sequelize' 1import { Transaction } from 'sequelize'
4import { MActorSignature, MVideoRedundancyVideo } from '@server/types/models'
5import { CONFIG } from '@server/initializers/config'
6import { logger } from '@server/helpers/logger' 2import { logger } from '@server/helpers/logger'
7import { ActorFollowModel } from '@server/models/activitypub/actor-follow' 3import { CONFIG } from '@server/initializers/config'
8import { Activity } from '@shared/models' 4import { ActorFollowModel } from '@server/models/actor/actor-follow'
9import { getServerActor } from '@server/models/application/application' 5import { getServerActor } from '@server/models/application/application'
6import { MActorSignature, MVideoRedundancyVideo } from '@server/types/models'
7import { Activity } from '@shared/models'
8import { VideoRedundancyModel } from '../models/redundancy/video-redundancy'
9import { sendUndoCacheFile } from './activitypub/send'
10 10
11async function removeVideoRedundancy (videoRedundancy: MVideoRedundancyVideo, t?: Transaction) { 11async 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 @@
1import { isTestInstance } from '../../helpers/core-utils' 1import { isTestInstance } from '../../helpers/core-utils'
2import { logger } from '../../helpers/logger' 2import { logger } from '../../helpers/logger'
3import { ActorFollowModel } from '../../models/activitypub/actor-follow'
4import { AbstractScheduler } from './abstract-scheduler'
5import { ACTOR_FOLLOW_SCORE, SCHEDULER_INTERVALS_MS } from '../../initializers/constants' 3import { ACTOR_FOLLOW_SCORE, SCHEDULER_INTERVALS_MS } from '../../initializers/constants'
4import { ActorFollowModel } from '../../models/actor/actor-follow'
6import { ActorFollowScoreCache } from '../files-cache' 5import { ActorFollowScoreCache } from '../files-cache'
6import { AbstractScheduler } from './abstract-scheduler'
7 7
8export class ActorFollowScheduler extends AbstractScheduler { 8export 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 @@
1import { chunk } from 'lodash' 1import { chunk } from 'lodash'
2import { doJSONRequest } from '@server/helpers/requests' 2import { doJSONRequest } from '@server/helpers/requests'
3import { JobQueue } from '@server/lib/job-queue' 3import { JobQueue } from '@server/lib/job-queue'
4import { ActorFollowModel } from '@server/models/activitypub/actor-follow' 4import { ActorFollowModel } from '@server/models/actor/actor-follow'
5import { getServerActor } from '@server/models/application/application' 5import { getServerActor } from '@server/models/application/application'
6import { logger } from '../../helpers/logger' 6import { logger } from '../../helpers/logger'
7import { CONFIG } from '../../initializers/config' 7import { 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 @@
1import * as bluebird from 'bluebird'
2import { readdir, remove, stat } from 'fs-extra'
3import { logger, loggerTagsFactory } from '@server/helpers/logger'
4import { getResumableUploadPath } from '@server/helpers/upload'
5import { SCHEDULER_INTERVALS_MS } from '@server/initializers/constants'
6import { METAFILE_EXTNAME } from '@uploadx/core'
7import { AbstractScheduler } from './abstract-scheduler'
8
9const lTags = loggerTagsFactory('scheduler', 'resumable-upload', 'cleaner')
10
11export 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 @@
1import { logger } from '../../helpers/logger' 1import { logger } from '../../helpers/logger'
2import { AbstractScheduler } from './abstract-scheduler' 2import { AbstractScheduler } from './abstract-scheduler'
3import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants' 3import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants'
4import { UserVideoHistoryModel } from '../../models/account/user-video-history' 4import { UserVideoHistoryModel } from '../../models/user/user-video-history'
5import { CONFIG } from '../../initializers/config' 5import { CONFIG } from '../../initializers/config'
6 6
7export class RemoveOldHistoryScheduler extends AbstractScheduler { 7export 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 @@
1import { AbstractScheduler } from './abstract-scheduler' 1import { YoutubeDL } from '@server/helpers/youtube-dl'
2import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants' 2import { SCHEDULER_INTERVALS_MS } from '../../initializers/constants'
3import { updateYoutubeDLBinary } from '../../helpers/youtube-dl' 3import { AbstractScheduler } from './abstract-scheduler'
4 4
5export class YoutubeDlUpdateScheduler extends AbstractScheduler { 5export 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 @@
1import { isSignupAllowed, isSignupAllowedForCurrentIP } from '@server/helpers/signup'
2import { getServerCommit } from '@server/helpers/utils'
3import { CONFIG, isEmailEnabled } from '@server/initializers/config'
4import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION } from '@server/initializers/constants'
5import { ActorCustomPageModel } from '@server/models/account/actor-custom-page'
6import { HTMLServerConfig, RegisteredExternalAuthConfig, RegisteredIdAndPassAuthConfig, ServerConfig } from '@shared/models'
7import { Hooks } from './plugins/hooks'
8import { PluginManager } from './plugins/plugin-manager'
9import { getThemeOrDefault } from './plugins/theme-utils'
10import { 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
19class 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
301export {
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 @@
1import { CONFIG } from '@server/initializers/config' 1import { CONFIG } from '@server/initializers/config'
2import { UserModel } from '@server/models/account/user' 2import { UserModel } from '@server/models/user/user'
3import { ActorFollowModel } from '@server/models/activitypub/actor-follow' 3import { ActorFollowModel } from '@server/models/actor/actor-follow'
4import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy' 4import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
5import { VideoModel } from '@server/models/video/video' 5import { VideoModel } from '@server/models/video/video'
6import { VideoChannelModel } from '@server/models/video/video-channel' 6import { 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 @@
1import { logger } from '@server/helpers/logger' 1import { logger } from '@server/helpers/logger'
2import { AvailableEncoders, EncoderOptionsBuilder, getTargetBitrate, VideoResolution } from '../../shared/models/videos' 2import { AvailableEncoders, EncoderOptionsBuilder, getTargetBitrate, VideoResolution } from '../../../shared/models/videos'
3import { buildStreamSuffix, resetSupportedEncoders } from '../helpers/ffmpeg-utils' 3import { buildStreamSuffix, resetSupportedEncoders } from '../../helpers/ffmpeg-utils'
4import { 4import {
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'
12import { VIDEO_TRANSCODING_FPS } from '../initializers/constants' 12import { 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'
3import { basename, extname as extnameUtil, join } from 'path' 3import { basename, extname as extnameUtil, join } from 'path'
4import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' 4import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
5import { MStreamingPlaylistFilesVideo, MVideoFile, MVideoFullLight } from '@server/types/models' 5import { MStreamingPlaylistFilesVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
6import { VideoResolution } from '../../shared/models/videos' 6import { VideoResolution } from '../../../shared/models/videos'
7import { VideoStreamingPlaylistType } from '../../shared/models/videos/video-streaming-playlist.type' 7import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type'
8import { transcode, TranscodeOptions, TranscodeOptionsType } from '../helpers/ffmpeg-utils' 8import { transcode, TranscodeOptions, TranscodeOptionsType } from '../../helpers/ffmpeg-utils'
9import { canDoQuickTranscode, getDurationFromVideoFile, getMetadataFromFile, getVideoFileFPS } from '../helpers/ffprobe-utils' 9import { canDoQuickTranscode, getDurationFromVideoFile, getMetadataFromFile, getVideoFileFPS } from '../../helpers/ffprobe-utils'
10import { logger } from '../helpers/logger' 10import { logger } from '../../helpers/logger'
11import { CONFIG } from '../initializers/config' 11import { CONFIG } from '../../initializers/config'
12import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSERVER } from '../initializers/constants' 12import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSERVER } from '../../initializers/constants'
13import { VideoFileModel } from '../models/video/video-file' 13import { VideoFileModel } from '../../models/video/video-file'
14import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist' 14import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist'
15import { updateMasterHLSPlaylist, updateSha256VODSegments } from './hls' 15import { updateMasterHLSPlaylist, updateSha256VODSegments } from '../hls'
16import { generateVideoFilename, generateVideoStreamingPlaylistName, getVideoFilePath } from './video-paths' 16import { generateVideoFilename, generateVideoStreamingPlaylistName, getVideoFilePath } from '../video-paths'
17import { VideoTranscodingProfilesManager } from './video-transcoding-profiles' 17import { VideoTranscodingProfilesManager } from './video-transcoding-profiles'
18 18
19/** 19/**
@@ -215,16 +215,6 @@ function generateHlsPlaylistResolution (options: {
215 }) 215 })
216} 216}
217 217
218function 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
230export { 220export {
@@ -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 @@
1import { Transaction } from 'sequelize/types' 1import { Transaction } from 'sequelize/types'
2import { v4 as uuidv4 } from 'uuid' 2import { v4 as uuidv4 } from 'uuid'
3import { UserModel } from '@server/models/account/user' 3import { UserModel } from '@server/models/user/user'
4import { MActorDefault } from '@server/types/models/actor'
4import { ActivityPubActorType } from '../../shared/models/activitypub' 5import { ActivityPubActorType } from '../../shared/models/activitypub'
5import { UserNotificationSetting, UserNotificationSettingValue } from '../../shared/models/users' 6import { UserNotificationSetting, UserNotificationSettingValue } from '../../shared/models/users'
6import { SERVER_ACTOR_NAME, WEBSERVER } from '../initializers/constants' 7import { SERVER_ACTOR_NAME, WEBSERVER } from '../initializers/constants'
7import { sequelizeTypescript } from '../initializers/database' 8import { sequelizeTypescript } from '../initializers/database'
8import { AccountModel } from '../models/account/account' 9import { AccountModel } from '../models/account/account'
9import { UserNotificationSettingModel } from '../models/account/user-notification-setting' 10import { ActorModel } from '../models/actor/actor'
10import { ActorModel } from '../models/activitypub/actor' 11import { UserNotificationSettingModel } from '../models/user/user-notification-setting'
11import { MAccountDefault, MActorDefault, MChannelActor } from '../types/models' 12import { MAccountDefault, MChannelActor } from '../types/models'
12import { MUser, MUserDefault, MUserId } from '../types/models/user' 13import { MUser, MUserDefault, MUserId } from '../types/models/user'
13import { buildActorInstance, generateAndSaveActorKeys } from './activitypub/actor' 14import { buildActorInstance, generateAndSaveActorKeys } from './activitypub/actor'
14import { getLocalAccountActivityPubUrl } from './activitypub/url' 15import { 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 @@
1import * as Sequelize from 'sequelize' 1import * as Sequelize from 'sequelize'
2import { v4 as uuidv4 } from 'uuid'
3import { VideoChannelCreate } from '../../shared/models' 2import { VideoChannelCreate } from '../../shared/models'
4import { VideoModel } from '../models/video/video' 3import { VideoModel } from '../models/video/video'
5import { VideoChannelModel } from '../models/video/video-channel' 4import { VideoChannelModel } from '../models/video/video-channel'
@@ -9,9 +8,8 @@ import { getLocalVideoChannelActivityPubUrl } from './activitypub/url'
9import { federateVideoIfNeeded } from './activitypub/videos' 8import { federateVideoIfNeeded } from './activitypub/videos'
10 9
11async function createLocalVideoChannel (videoChannelInfo: VideoChannelCreate, account: MAccountId, t: Sequelize.Transaction) { 10async 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'
3import { logger } from '@server/helpers/logger' 3import { logger } from '@server/helpers/logger'
4import { sequelizeTypescript } from '@server/initializers/database' 4import { sequelizeTypescript } from '@server/initializers/database'
5import { ResultList } from '../../shared/models' 5import { ResultList } from '../../shared/models'
6import { VideoCommentThreadTree } from '../../shared/models/videos/video-comment.model' 6import { VideoCommentThreadTree } from '../../shared/models/videos/comment/video-comment.model'
7import { VideoCommentModel } from '../models/video/video-comment' 7import { VideoCommentModel } from '../models/video/video-comment'
8import { MAccountDefault, MComment, MCommentOwnerVideo, MCommentOwnerVideoReply, MVideoFullLight } from '../types/models' 8import { MAccountDefault, MComment, MCommentOwnerVideo, MCommentOwnerVideoReply, MVideoFullLight } from '../types/models'
9import { sendCreateVideoComment, sendDeleteVideoComment } from './activitypub/send' 9import { 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 @@
1import { UploadFiles } from 'express'
1import { Transaction } from 'sequelize/types' 2import { Transaction } from 'sequelize/types'
2import { DEFAULT_AUDIO_RESOLUTION, JOB_PRIORITY } from '@server/initializers/constants' 3import { DEFAULT_AUDIO_RESOLUTION, JOB_PRIORITY } from '@server/initializers/constants'
3import { sequelizeTypescript } from '@server/initializers/database' 4import { 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
33async function buildVideoThumbnailsFromReq (options: { 36async 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}) {