Move config in its own file
This commit is contained in:
parent
2c3abc4fa7
commit
6dd9de95df
79 changed files with 523 additions and 458 deletions
|
@ -2,7 +2,7 @@
|
|||
import * as express from 'express'
|
||||
import { VideoPrivacy, VideoRateType } from '../../../shared/models/videos'
|
||||
import { activityPubCollectionPagination, activityPubContextify } from '../../helpers/activitypub'
|
||||
import { CONFIG, ROUTE_CACHE_LIFETIME } from '../../initializers'
|
||||
import { ROUTE_CACHE_LIFETIME, WEBSERVER } from '../../initializers'
|
||||
import { buildAnnounceWithVideoAudience, buildLikeActivity } from '../../lib/activitypub/send'
|
||||
import { audiencify, getAudience } from '../../lib/activitypub/audience'
|
||||
import { buildCreateActivity } from '../../lib/activitypub/send/send-create'
|
||||
|
@ -19,7 +19,6 @@ import { AccountModel } from '../../models/account/account'
|
|||
import { ActorModel } from '../../models/activitypub/actor'
|
||||
import { ActorFollowModel } from '../../models/activitypub/actor-follow'
|
||||
import { VideoModel } from '../../models/video/video'
|
||||
import { VideoChannelModel } from '../../models/video/video-channel'
|
||||
import { VideoCommentModel } from '../../models/video/video-comment'
|
||||
import { VideoShareModel } from '../../models/video/video-share'
|
||||
import { cacheRoute } from '../../middlewares/cache'
|
||||
|
@ -35,11 +34,9 @@ import {
|
|||
import { VideoCaptionModel } from '../../models/video/video-caption'
|
||||
import { videoFileRedundancyGetValidator, videoPlaylistRedundancyGetValidator } from '../../middlewares/validators/redundancy'
|
||||
import { getServerActor } from '../../helpers/utils'
|
||||
import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy'
|
||||
import { buildDislikeActivity } from '../../lib/activitypub/send/send-dislike'
|
||||
import { videoPlaylistElementAPGetValidator, videoPlaylistsGetValidator } from '../../middlewares/validators/videos/video-playlists'
|
||||
import { VideoPlaylistModel } from '../../models/video/video-playlist'
|
||||
import { VideoPlaylistElementModel } from '../../models/video/video-playlist-element'
|
||||
import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
|
||||
|
||||
const activityPubClientRouter = express.Router()
|
||||
|
@ -213,7 +210,7 @@ async function videoController (req: express.Request, res: express.Response) {
|
|||
// We need more attributes
|
||||
const video = await VideoModel.loadForGetAPI(res.locals.video.id)
|
||||
|
||||
if (video.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(video.url)
|
||||
if (video.url.startsWith(WEBSERVER.URL) === false) return res.redirect(video.url)
|
||||
|
||||
// We need captions to render AP object
|
||||
video.VideoCaptions = await VideoCaptionModel.listVideoCaptions(video.id)
|
||||
|
@ -232,7 +229,7 @@ async function videoController (req: express.Request, res: express.Response) {
|
|||
async function videoAnnounceController (req: express.Request, res: express.Response) {
|
||||
const share = res.locals.videoShare
|
||||
|
||||
if (share.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(share.url)
|
||||
if (share.url.startsWith(WEBSERVER.URL) === false) return res.redirect(share.url)
|
||||
|
||||
const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.video, undefined)
|
||||
|
||||
|
@ -306,7 +303,7 @@ async function videoChannelFollowingController (req: express.Request, res: expre
|
|||
async function videoCommentController (req: express.Request, res: express.Response) {
|
||||
const videoComment = res.locals.videoComment
|
||||
|
||||
if (videoComment.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(videoComment.url)
|
||||
if (videoComment.url.startsWith(WEBSERVER.URL) === false) return res.redirect(videoComment.url)
|
||||
|
||||
const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined)
|
||||
const isPublic = true // Comments are always public
|
||||
|
@ -324,7 +321,7 @@ async function videoCommentController (req: express.Request, res: express.Respon
|
|||
|
||||
async function videoRedundancyController (req: express.Request, res: express.Response) {
|
||||
const videoRedundancy = res.locals.videoRedundancy
|
||||
if (videoRedundancy.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(videoRedundancy.url)
|
||||
if (videoRedundancy.url.startsWith(WEBSERVER.URL) === false) return res.redirect(videoRedundancy.url)
|
||||
|
||||
const serverActor = await getServerActor()
|
||||
|
||||
|
@ -366,7 +363,7 @@ async function actorFollowing (req: express.Request, actor: ActorModel) {
|
|||
return ActorFollowModel.listAcceptedFollowingUrlsForApi([ actor.id ], undefined, start, count)
|
||||
}
|
||||
|
||||
return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.path, handler, req.query.page)
|
||||
return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page)
|
||||
}
|
||||
|
||||
async function actorFollowers (req: express.Request, actor: ActorModel) {
|
||||
|
@ -374,7 +371,7 @@ async function actorFollowers (req: express.Request, actor: ActorModel) {
|
|||
return ActorFollowModel.listAcceptedFollowerUrlsForAP([ actor.id ], undefined, start, count)
|
||||
}
|
||||
|
||||
return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.path, handler, req.query.page)
|
||||
return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page)
|
||||
}
|
||||
|
||||
async function actorPlaylists (req: express.Request, account: AccountModel) {
|
||||
|
@ -382,7 +379,7 @@ async function actorPlaylists (req: express.Request, account: AccountModel) {
|
|||
return VideoPlaylistModel.listPublicUrlsOfForAP(account.id, start, count)
|
||||
}
|
||||
|
||||
return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.path, handler, req.query.page)
|
||||
return activityPubCollectionPagination(WEBSERVER.URL + req.path, handler, req.query.page)
|
||||
}
|
||||
|
||||
function videoRates (req: express.Request, rateType: VideoRateType, video: VideoModel, url: string) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { ServerConfig, UserRight } from '../../../shared'
|
|||
import { About } from '../../../shared/models/server/about.model'
|
||||
import { CustomConfig } from '../../../shared/models/server/custom-config.model'
|
||||
import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/signup'
|
||||
import { CONFIG, CONSTRAINTS_FIELDS, reloadConfig } from '../../initializers'
|
||||
import { CONSTRAINTS_FIELDS } from '../../initializers'
|
||||
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares'
|
||||
import { customConfigUpdateValidator } from '../../middlewares/validators/config'
|
||||
import { ClientHtml } from '../../lib/client-html'
|
||||
|
@ -14,6 +14,7 @@ import { getServerCommit } from '../../helpers/utils'
|
|||
import { Emailer } from '../../lib/emailer'
|
||||
import { isNumeric } from 'validator'
|
||||
import { objectConverter } from '../../helpers/core-utils'
|
||||
import { CONFIG, reloadConfig } from '../../initializers/config'
|
||||
|
||||
const packageJSON = require('../../../../package.json')
|
||||
const configRouter = express.Router()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as express from 'express'
|
||||
import { OAuthClientLocal } from '../../../shared'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { CONFIG } from '../../initializers'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
import { asyncMiddleware } from '../../middlewares'
|
||||
import { OAuthClientModel } from '../../models/oauth/oauth-client'
|
||||
|
||||
|
|
|
@ -3,10 +3,11 @@ import { UserRight } from '../../../../shared/models/users'
|
|||
import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares'
|
||||
import { mtimeSortFilesDesc } from '../../../../shared/utils/logs/logs'
|
||||
import { readdir, readFile } from 'fs-extra'
|
||||
import { CONFIG, MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers'
|
||||
import { MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers'
|
||||
import { join } from 'path'
|
||||
import { getLogsValidator } from '../../../middlewares/validators/logs'
|
||||
import { LogLevel } from '../../../../shared/models/server/log-level.type'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
const logsRouter = express.Router()
|
||||
|
||||
|
|
|
@ -6,9 +6,10 @@ import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
|
|||
import { VideoModel } from '../../../models/video/video'
|
||||
import { VideoCommentModel } from '../../../models/video/video-comment'
|
||||
import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
|
||||
import { CONFIG, ROUTE_CACHE_LIFETIME } from '../../../initializers/constants'
|
||||
import { ROUTE_CACHE_LIFETIME } from '../../../initializers/constants'
|
||||
import { cacheRoute } from '../../../middlewares/cache'
|
||||
import { VideoFileModel } from '../../../models/video/video-file'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
const statsRouter = express.Router()
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as RateLimit from 'express-rate-limit'
|
|||
import { UserCreate, UserRight, UserRole, UserUpdate } from '../../../../shared'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { getFormattedObjects } from '../../../helpers/utils'
|
||||
import { CONFIG, RATES_LIMIT, sequelizeTypescript } from '../../../initializers'
|
||||
import { RATES_LIMIT, sequelizeTypescript, WEBSERVER } from '../../../initializers'
|
||||
import { Emailer } from '../../../lib/emailer'
|
||||
import { Redis } from '../../../lib/redis'
|
||||
import { createUserAccountAndChannelAndPlaylist } from '../../../lib/user'
|
||||
|
@ -43,6 +43,7 @@ import { myVideosHistoryRouter } from './my-history'
|
|||
import { myNotificationsRouter } from './my-notifications'
|
||||
import { Notifier } from '../../../lib/notifier'
|
||||
import { mySubscriptionsRouter } from './my-subscriptions'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
const auditLogger = auditLoggerFactory('users')
|
||||
|
||||
|
@ -293,7 +294,7 @@ async function askResetUserPassword (req: express.Request, res: express.Response
|
|||
const user = res.locals.user
|
||||
|
||||
const verificationString = await Redis.Instance.setResetPasswordVerificationString(user.id)
|
||||
const url = CONFIG.WEBSERVER.URL + '/reset-password?userId=' + user.id + '&verificationString=' + verificationString
|
||||
const url = WEBSERVER.URL + '/reset-password?userId=' + user.id + '&verificationString=' + verificationString
|
||||
await Emailer.Instance.addPasswordResetEmailJob(user.email, url)
|
||||
|
||||
return res.status(204).end()
|
||||
|
@ -310,7 +311,7 @@ async function resetUserPassword (req: express.Request, res: express.Response) {
|
|||
|
||||
async function sendVerifyUserEmail (user: UserModel) {
|
||||
const verificationString = await Redis.Instance.setVerifyEmailVerificationString(user.id)
|
||||
const url = CONFIG.WEBSERVER.URL + '/verify-account/email?userId=' + user.id + '&verificationString=' + verificationString
|
||||
const url = WEBSERVER.URL + '/verify-account/email?userId=' + user.id + '&verificationString=' + verificationString
|
||||
await Emailer.Instance.addVerifyEmailJob(user.email, url)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as express from 'express'
|
|||
import 'multer'
|
||||
import { UserUpdateMe, UserVideoRate as FormattedUserVideoRate } from '../../../../shared'
|
||||
import { getFormattedObjects } from '../../../helpers/utils'
|
||||
import { CONFIG, MIMETYPES, sequelizeTypescript } from '../../../initializers'
|
||||
import { MIMETYPES, sequelizeTypescript } from '../../../initializers'
|
||||
import { sendUpdateActor } from '../../../lib/activitypub/send'
|
||||
import {
|
||||
asyncMiddleware,
|
||||
|
@ -26,6 +26,7 @@ import { updateActorAvatarFile } from '../../../lib/avatar'
|
|||
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger'
|
||||
import { VideoImportModel } from '../../../models/video/video-import'
|
||||
import { AccountModel } from '../../../models/account/account'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
const auditLogger = auditLoggerFactory('users-me')
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as express from 'express'
|
||||
import 'multer'
|
||||
import { getFormattedObjects } from '../../../helpers/utils'
|
||||
import { CONFIG, sequelizeTypescript } from '../../../initializers'
|
||||
import { sequelizeTypescript, WEBSERVER } from '../../../initializers'
|
||||
import {
|
||||
asyncMiddleware,
|
||||
asyncRetryTransactionMiddleware,
|
||||
|
@ -80,7 +80,7 @@ async function areSubscriptionsExist (req: express.Request, res: express.Respons
|
|||
|
||||
const handles = uris.map(u => {
|
||||
let [ name, host ] = u.split('@')
|
||||
if (host === CONFIG.WEBSERVER.HOST) host = null
|
||||
if (host === WEBSERVER.HOST) host = null
|
||||
|
||||
return { name, host, uri: u }
|
||||
})
|
||||
|
|
|
@ -23,7 +23,7 @@ import { createVideoChannel } from '../../lib/video-channel'
|
|||
import { buildNSFWFilter, createReqFiles, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
|
||||
import { setAsyncActorKeys } from '../../lib/activitypub'
|
||||
import { AccountModel } from '../../models/account/account'
|
||||
import { CONFIG, MIMETYPES, sequelizeTypescript } from '../../initializers'
|
||||
import { MIMETYPES, sequelizeTypescript } from '../../initializers'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { VideoModel } from '../../models/video/video'
|
||||
import { updateAvatarValidator } from '../../middlewares/validators/avatar'
|
||||
|
@ -33,6 +33,7 @@ import { resetSequelizeInstance } from '../../helpers/database-utils'
|
|||
import { JobQueue } from '../../lib/job-queue'
|
||||
import { VideoPlaylistModel } from '../../models/video/video-playlist'
|
||||
import { commonVideoPlaylistFiltersValidator } from '../../middlewares/validators/videos/video-playlists'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
const auditLogger = auditLoggerFactory('channels')
|
||||
const reqAvatarFile = createReqFiles([ 'avatarfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR })
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
} from '../../middlewares'
|
||||
import { videoPlaylistsSortValidator } from '../../middlewares/validators'
|
||||
import { buildNSFWFilter, createReqFiles, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
|
||||
import { CONFIG, MIMETYPES, sequelizeTypescript, THUMBNAILS_SIZE, VIDEO_PLAYLIST_PRIVACIES } from '../../initializers'
|
||||
import { MIMETYPES, sequelizeTypescript, THUMBNAILS_SIZE, VIDEO_PLAYLIST_PRIVACIES } from '../../initializers'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { resetSequelizeInstance } from '../../helpers/database-utils'
|
||||
import { VideoPlaylistModel } from '../../models/video/video-playlist'
|
||||
|
@ -41,6 +41,7 @@ import { copy, pathExists } from 'fs-extra'
|
|||
import { AccountModel } from '../../models/account/account'
|
||||
import { VideoPlaylistReorder } from '../../../shared/models/videos/playlist/video-playlist-reorder.model'
|
||||
import { JobQueue } from '../../lib/job-queue'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
const reqThumbnailFile = createReqFiles([ 'thumbnailfile' ], MIMETYPES.IMAGE.MIMETYPE_EXT, { thumbnailfile: CONFIG.STORAGE.TMP_DIR })
|
||||
|
||||
|
|
|
@ -2,12 +2,13 @@ import * as express from 'express'
|
|||
import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate } from '../../../middlewares'
|
||||
import { addVideoCaptionValidator, deleteVideoCaptionValidator, listVideoCaptionsValidator } from '../../../middlewares/validators'
|
||||
import { createReqFiles } from '../../../helpers/express-utils'
|
||||
import { CONFIG, MIMETYPES, sequelizeTypescript } from '../../../initializers'
|
||||
import { MIMETYPES, sequelizeTypescript } from '../../../initializers'
|
||||
import { getFormattedObjects } from '../../../helpers/utils'
|
||||
import { VideoCaptionModel } from '../../../models/video/video-caption'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { federateVideoIfNeeded } from '../../../lib/activitypub'
|
||||
import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
const reqVideoCaptionAdd = createReqFiles(
|
||||
[ 'captionfile' ],
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as magnetUtil from 'magnet-uri'
|
|||
import 'multer'
|
||||
import { auditLoggerFactory, getAuditIdFromRes, VideoImportAuditView } from '../../../helpers/audit-logger'
|
||||
import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videoImportAddValidator } from '../../../middlewares'
|
||||
import { CONFIG, MIMETYPES, PREVIEWS_SIZE, sequelizeTypescript, THUMBNAILS_SIZE } from '../../../initializers'
|
||||
import { MIMETYPES, PREVIEWS_SIZE, sequelizeTypescript, THUMBNAILS_SIZE } from '../../../initializers'
|
||||
import { getYoutubeDLInfo, YoutubeDLInfo } from '../../../helpers/youtube-dl'
|
||||
import { createReqFiles } from '../../../helpers/express-utils'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
|
@ -22,8 +22,9 @@ import { UserModel } from '../../../models/account/user'
|
|||
import * as Bluebird from 'bluebird'
|
||||
import * as parseTorrent from 'parse-torrent'
|
||||
import { getSecureTorrentName } from '../../../helpers/utils'
|
||||
import { readFile, move } from 'fs-extra'
|
||||
import { move, readFile } from 'fs-extra'
|
||||
import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
const auditLogger = auditLoggerFactory('video-imports')
|
||||
const videoImportsRouter = express.Router()
|
||||
|
|
|
@ -8,7 +8,6 @@ import { auditLoggerFactory, getAuditIdFromRes, VideoAuditView } from '../../../
|
|||
import { getFormattedObjects, getServerActor } from '../../../helpers/utils'
|
||||
import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist'
|
||||
import {
|
||||
CONFIG,
|
||||
MIMETYPES,
|
||||
PREVIEWS_SIZE,
|
||||
sequelizeTypescript,
|
||||
|
@ -61,6 +60,7 @@ import { move } from 'fs-extra'
|
|||
import { watchingRouter } from './watching'
|
||||
import { Notifier } from '../../../lib/notifier'
|
||||
import { sendView } from '../../../lib/activitypub/send/send-view'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
const auditLogger = auditLoggerFactory('videos')
|
||||
const videosRouter = express.Router()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as express from 'express'
|
||||
import { asyncMiddleware } from '../middlewares'
|
||||
import { CONFIG, ROUTE_CACHE_LIFETIME } from '../initializers'
|
||||
import { ROUTE_CACHE_LIFETIME, WEBSERVER } from '../initializers'
|
||||
import * as sitemapModule from 'sitemap'
|
||||
import { logger } from '../helpers/logger'
|
||||
import { VideoModel } from '../models/video/video'
|
||||
|
@ -35,7 +35,7 @@ async function getSitemap (req: express.Request, res: express.Response) {
|
|||
urls = urls.concat(await getSitemapAccountUrls())
|
||||
|
||||
const sitemap = sitemapModule.createSitemap({
|
||||
hostname: CONFIG.WEBSERVER.URL,
|
||||
hostname: WEBSERVER.URL,
|
||||
urls: urls
|
||||
})
|
||||
|
||||
|
@ -54,7 +54,7 @@ async function getSitemapVideoChannelUrls () {
|
|||
const rows = await VideoChannelModel.listLocalsForSitemap('createdAt')
|
||||
|
||||
return rows.map(channel => ({
|
||||
url: CONFIG.WEBSERVER.URL + '/video-channels/' + channel.Actor.preferredUsername
|
||||
url: WEBSERVER.URL + '/video-channels/' + channel.Actor.preferredUsername
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ async function getSitemapAccountUrls () {
|
|||
const rows = await AccountModel.listLocalsForSitemap('createdAt')
|
||||
|
||||
return rows.map(channel => ({
|
||||
url: CONFIG.WEBSERVER.URL + '/accounts/' + channel.Actor.preferredUsername
|
||||
url: WEBSERVER.URL + '/accounts/' + channel.Actor.preferredUsername
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -78,14 +78,14 @@ async function getSitemapLocalVideoUrls () {
|
|||
})
|
||||
|
||||
return resultList.data.map(v => ({
|
||||
url: CONFIG.WEBSERVER.URL + '/videos/watch/' + v.uuid,
|
||||
url: WEBSERVER.URL + '/videos/watch/' + v.uuid,
|
||||
video: [
|
||||
{
|
||||
title: v.name,
|
||||
// Sitemap description should be < 2000 characters
|
||||
description: truncate(v.description || v.name, { length: 2000, omission: '...' }),
|
||||
player_loc: CONFIG.WEBSERVER.URL + '/videos/embed/' + v.uuid,
|
||||
thumbnail_loc: CONFIG.WEBSERVER.URL + v.getThumbnailStaticPath()
|
||||
player_loc: WEBSERVER.URL + '/videos/embed/' + v.uuid,
|
||||
thumbnail_loc: WEBSERVER.URL + v.getThumbnailStaticPath()
|
||||
}
|
||||
]
|
||||
}))
|
||||
|
@ -97,5 +97,5 @@ function getSitemapBasicUrls () {
|
|||
'/videos/local'
|
||||
]
|
||||
|
||||
return paths.map(p => ({ url: CONFIG.WEBSERVER.URL + p }))
|
||||
return paths.map(p => ({ url: WEBSERVER.URL + p }))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as express from 'express'
|
||||
import { CONFIG, FEEDS, ROUTE_CACHE_LIFETIME } from '../initializers/constants'
|
||||
import { FEEDS, ROUTE_CACHE_LIFETIME, WEBSERVER } from '../initializers/constants'
|
||||
import { THUMBNAILS_SIZE } from '../initializers'
|
||||
import {
|
||||
asyncMiddleware,
|
||||
|
@ -14,6 +14,7 @@ import * as Feed from 'pfeed'
|
|||
import { cacheRoute } from '../middlewares/cache'
|
||||
import { VideoCommentModel } from '../models/video/video-comment'
|
||||
import { buildNSFWFilter } from '../helpers/express-utils'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
const feedsRouter = express.Router()
|
||||
|
||||
|
@ -54,7 +55,7 @@ async function generateVideoCommentsFeed (req: express.Request, res: express.Res
|
|||
|
||||
// Adding video items to the feed, one at a time
|
||||
comments.forEach(comment => {
|
||||
const link = CONFIG.WEBSERVER.URL + comment.getCommentStaticPath()
|
||||
const link = WEBSERVER.URL + comment.getCommentStaticPath()
|
||||
|
||||
feed.addItem({
|
||||
title: `${comment.Video.name} - ${comment.Account.getDisplayName()}`,
|
||||
|
@ -122,7 +123,7 @@ async function generateVideoFeed (req: express.Request, res: express.Response) {
|
|||
feed.addItem({
|
||||
title: video.name,
|
||||
id: video.url,
|
||||
link: CONFIG.WEBSERVER.URL + '/videos/watch/' + video.uuid,
|
||||
link: WEBSERVER.URL + '/videos/watch/' + video.uuid,
|
||||
description: video.getTruncatedDescription(),
|
||||
content: video.description,
|
||||
author: [
|
||||
|
@ -137,7 +138,7 @@ async function generateVideoFeed (req: express.Request, res: express.Response) {
|
|||
torrent: torrents,
|
||||
thumbnail: [
|
||||
{
|
||||
url: CONFIG.WEBSERVER.URL + video.getThumbnailStaticPath(),
|
||||
url: WEBSERVER.URL + video.getThumbnailStaticPath(),
|
||||
height: THUMBNAILS_SIZE.height,
|
||||
width: THUMBNAILS_SIZE.width
|
||||
}
|
||||
|
@ -150,7 +151,7 @@ async function generateVideoFeed (req: express.Request, res: express.Response) {
|
|||
}
|
||||
|
||||
function initFeed (name: string, description: string) {
|
||||
const webserverUrl = CONFIG.WEBSERVER.URL
|
||||
const webserverUrl = WEBSERVER.URL
|
||||
|
||||
return new Feed({
|
||||
title: name,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import * as express from 'express'
|
||||
import { CONFIG, EMBED_SIZE, PREVIEWS_SIZE } from '../initializers'
|
||||
import { EMBED_SIZE, PREVIEWS_SIZE, WEBSERVER } from '../initializers'
|
||||
import { asyncMiddleware, oembedValidator } from '../middlewares'
|
||||
import { accountNameWithHostGetValidator } from '../middlewares/validators'
|
||||
import { VideoModel } from '../models/video/video'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
const servicesRouter = express.Router()
|
||||
|
||||
|
@ -25,7 +25,7 @@ export {
|
|||
|
||||
function generateOEmbed (req: express.Request, res: express.Response) {
|
||||
const video = res.locals.video
|
||||
const webserverUrl = CONFIG.WEBSERVER.URL
|
||||
const webserverUrl = WEBSERVER.URL
|
||||
const maxHeight = parseInt(req.query.maxheight, 10)
|
||||
const maxWidth = parseInt(req.query.maxwidth, 10)
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import * as cors from 'cors'
|
||||
import * as express from 'express'
|
||||
import {
|
||||
CONFIG,
|
||||
HLS_STREAMING_PLAYLIST_DIRECTORY,
|
||||
ROUTE_CACHE_LIFETIME,
|
||||
STATIC_DOWNLOAD_PATHS,
|
||||
STATIC_MAX_AGE,
|
||||
STATIC_PATHS
|
||||
STATIC_PATHS,
|
||||
WEBSERVER
|
||||
} from '../initializers'
|
||||
import { VideosCaptionCache, VideosPreviewCache } from '../lib/files-cache'
|
||||
import { cacheRoute } from '../middlewares/cache'
|
||||
|
@ -17,6 +17,7 @@ import { VideoCommentModel } from '../models/video/video-comment'
|
|||
import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo'
|
||||
import { join } from 'path'
|
||||
import { root } from '../helpers/core-utils'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
const packageJSON = require('../../../package.json')
|
||||
const staticRouter = express.Router()
|
||||
|
@ -121,7 +122,7 @@ staticRouter.use('/.well-known/nodeinfo',
|
|||
links: [
|
||||
{
|
||||
rel: 'http://nodeinfo.diaspora.software/ns/schema/2.0',
|
||||
href: CONFIG.WEBSERVER.URL + '/nodeinfo/2.0.json'
|
||||
href: WEBSERVER.URL + '/nodeinfo/2.0.json'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
|
@ -4,10 +4,11 @@ import * as http from 'http'
|
|||
import * as bitTorrentTracker from 'bittorrent-tracker'
|
||||
import * as proxyAddr from 'proxy-addr'
|
||||
import { Server as WebSocketServer } from 'ws'
|
||||
import { CONFIG, TRACKER_RATE_LIMITS } from '../initializers/constants'
|
||||
import { TRACKER_RATE_LIMITS } from '../initializers/constants'
|
||||
import { VideoFileModel } from '../models/video/video-file'
|
||||
import { parse } from 'url'
|
||||
import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
const TrackerServer = bitTorrentTracker.Server
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ import { diff } from 'deep-object-diff'
|
|||
import { chain } from 'lodash'
|
||||
import * as flatten from 'flat'
|
||||
import * as winston from 'winston'
|
||||
import { CONFIG } from '../initializers'
|
||||
import { jsonLoggerFormat, labelFormatter } from './logger'
|
||||
import { User, VideoAbuse, VideoChannel, VideoDetails, VideoImport } from '../../shared'
|
||||
import { VideoComment } from '../../shared/models/videos/video-comment.model'
|
||||
import { CustomConfig } from '../../shared/models/server/custom-config.model'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
function getAuditIdFromRes (res: express.Response) {
|
||||
return res.locals.oauth.token.User.username
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { join } from 'path'
|
||||
import { CONFIG } from '../initializers'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
import { VideoCaptionModel } from '../models/video/video-caption'
|
||||
import * as srt2vtt from 'srt-to-vtt'
|
||||
import { createReadStream, createWriteStream, remove, move } from 'fs-extra'
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as express from 'express'
|
|||
import 'express-validator'
|
||||
import 'multer'
|
||||
import * as validator from 'validator'
|
||||
import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers'
|
||||
import { CONSTRAINTS_FIELDS } from '../../initializers'
|
||||
import { VideoChannelModel } from '../../models/video/video-channel'
|
||||
import { exists } from './misc'
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { CONFIG, REMOTE_SCHEME } from '../../initializers'
|
||||
import { REMOTE_SCHEME, WEBSERVER } from '../../initializers'
|
||||
import { sanitizeHost } from '../core-utils'
|
||||
import { exists } from './misc'
|
||||
|
||||
|
@ -11,7 +11,7 @@ function isWebfingerLocalResourceValid (value: string) {
|
|||
if (actorParts.length !== 2) return false
|
||||
|
||||
const host = actorParts[1]
|
||||
return sanitizeHost(host, REMOTE_SCHEME.HTTP) === CONFIG.WEBSERVER.HOST
|
||||
return sanitizeHost(host, REMOTE_SCHEME.HTTP) === WEBSERVER.HOST
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import * as express from 'express'
|
||||
import * as multer from 'multer'
|
||||
import { CONFIG, REMOTE_SCHEME } from '../initializers'
|
||||
import { REMOTE_SCHEME } from '../initializers'
|
||||
import { logger } from './logger'
|
||||
import { deleteFileAsync, generateRandomString } from './utils'
|
||||
import { extname } from 'path'
|
||||
import { isArray } from './custom-validators/misc'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
function buildNSFWFilter (res?: express.Response, paramNSFW?: string) {
|
||||
if (paramNSFW === 'true') return true
|
||||
|
@ -58,7 +59,7 @@ function getHostWithPort (host: string) {
|
|||
return host
|
||||
}
|
||||
|
||||
function badRequest (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
function badRequest (req: express.Request, res: express.Response) {
|
||||
return res.type('json').status(400).end()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import * as ffmpeg from 'fluent-ffmpeg'
|
||||
import { dirname, join } from 'path'
|
||||
import { getTargetBitrate, VideoResolution } from '../../shared/models/videos'
|
||||
import { CONFIG, FFMPEG_NICE, VIDEO_TRANSCODING_FPS } from '../initializers/constants'
|
||||
import { FFMPEG_NICE, VIDEO_TRANSCODING_FPS } from '../initializers/constants'
|
||||
import { processImage } from './image-utils'
|
||||
import { logger } from './logger'
|
||||
import { checkFFmpegEncoders } from '../initializers/checker-before-init'
|
||||
import { remove, readFile, writeFile } from 'fs-extra'
|
||||
import { readFile, remove, writeFile } from 'fs-extra'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
function computeResolutionsToTranscode (videoFileHeight: number) {
|
||||
const resolutionsEnabled: number[] = []
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { mkdirpSync } from 'fs-extra'
|
||||
import * as path from 'path'
|
||||
import * as winston from 'winston'
|
||||
import { CONFIG } from '../initializers'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
import { omit } from 'lodash'
|
||||
|
||||
const label = CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import * as Bluebird from 'bluebird'
|
||||
import { createWriteStream, remove } from 'fs-extra'
|
||||
import * as request from 'request'
|
||||
import { ACTIVITY_PUB, CONFIG } from '../initializers'
|
||||
import { ACTIVITY_PUB } from '../initializers'
|
||||
import { processImage } from './image-utils'
|
||||
import { join } from 'path'
|
||||
import { logger } from './logger'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
function doRequest <T> (
|
||||
requestOptions: request.CoreOptions & request.UriOptions & { activityPub?: boolean },
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { CONFIG } from '../initializers'
|
||||
import { UserModel } from '../models/account/user'
|
||||
import * as ipaddr from 'ipaddr.js'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
const isCidr = require('is-cidr')
|
||||
|
||||
async function isSignupAllowed () {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { ResultList } from '../../shared'
|
||||
import { CONFIG } from '../initializers'
|
||||
import { ApplicationModel } from '../models/application/application'
|
||||
import { execPromise, execPromise2, pseudoRandomBytesPromise, sha256 } from './core-utils'
|
||||
import { logger } from './logger'
|
||||
|
@ -7,6 +6,7 @@ import { join } from 'path'
|
|||
import { Instance as ParseTorrent } from 'parse-torrent'
|
||||
import { remove } from 'fs-extra'
|
||||
import * as memoizee from 'memoizee'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
function deleteFileAsync (path: string) {
|
||||
remove(path)
|
||||
|
|
|
@ -3,7 +3,7 @@ import { WebFingerData } from '../../shared'
|
|||
import { ActorModel } from '../models/activitypub/actor'
|
||||
import { isTestInstance } from './core-utils'
|
||||
import { isActivityPubUrlValid } from './custom-validators/activitypub/misc'
|
||||
import { CONFIG } from '../initializers'
|
||||
import { WEBSERVER } from '../initializers/constants'
|
||||
|
||||
const webfinger = new WebFinger({
|
||||
webfist_fallback: false,
|
||||
|
@ -19,7 +19,7 @@ async function loadActorUrlOrGetFromWebfinger (uriArg: string) {
|
|||
const [ name, host ] = uri.split('@')
|
||||
let actor: ActorModel
|
||||
|
||||
if (host === CONFIG.WEBSERVER.HOST) {
|
||||
if (host === WEBSERVER.HOST) {
|
||||
actor = await ActorModel.loadLocalByName(name)
|
||||
} else {
|
||||
actor = await ActorModel.loadByNameAndHost(name, host)
|
||||
|
|
|
@ -2,7 +2,7 @@ import { logger } from './logger'
|
|||
import { generateVideoImportTmpPath } from './utils'
|
||||
import * as WebTorrent from 'webtorrent'
|
||||
import { createWriteStream, ensureDir, remove } from 'fs-extra'
|
||||
import { CONFIG } from '../initializers'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
import { dirname, join } from 'path'
|
||||
|
||||
async function downloadWebTorrentVideo (target: { magnetUri: string, torrentName?: string }, timeout: number) {
|
||||
|
|
|
@ -4,19 +4,20 @@ import { UserModel } from '../models/account/user'
|
|||
import { ApplicationModel } from '../models/application/application'
|
||||
import { OAuthClientModel } from '../models/oauth/oauth-client'
|
||||
import { parse } from 'url'
|
||||
import { CONFIG } from './constants'
|
||||
import { CONFIG } from './config'
|
||||
import { logger } from '../helpers/logger'
|
||||
import { getServerActor } from '../helpers/utils'
|
||||
import { RecentlyAddedStrategy } from '../../shared/models/redundancy'
|
||||
import { isArray } from '../helpers/custom-validators/misc'
|
||||
import { uniq } from 'lodash'
|
||||
import { Emailer } from '../lib/emailer'
|
||||
import { WEBSERVER } from './constants'
|
||||
|
||||
async function checkActivityPubUrls () {
|
||||
const actor = await getServerActor()
|
||||
|
||||
const parsed = parse(actor.url)
|
||||
if (CONFIG.WEBSERVER.HOST !== parsed.host) {
|
||||
if (WEBSERVER.HOST !== parsed.host) {
|
||||
const NODE_ENV = config.util.getEnv('NODE_ENV')
|
||||
const NODE_CONFIG_DIR = config.util.getEnv('NODE_CONFIG_DIR')
|
||||
|
||||
|
|
255
server/initializers/config.ts
Normal file
255
server/initializers/config.ts
Normal file
|
@ -0,0 +1,255 @@
|
|||
import { IConfig } from 'config'
|
||||
import { dirname, join } from 'path'
|
||||
import { VideosRedundancy } from '../../shared/models'
|
||||
// Do not use barrels, remain constants as independent as possible
|
||||
import { buildPath, parseBytes, parseDuration, root } from '../helpers/core-utils'
|
||||
import { NSFWPolicyType } from '../../shared/models/videos/nsfw-policy.type'
|
||||
import * as bytes from 'bytes'
|
||||
|
||||
// Use a variable to reload the configuration if we need
|
||||
let config: IConfig = require('config')
|
||||
|
||||
const configChangedHandlers: Function[] = []
|
||||
|
||||
const CONFIG = {
|
||||
CUSTOM_FILE: getLocalConfigFilePath(),
|
||||
LISTEN: {
|
||||
PORT: config.get<number>('listen.port'),
|
||||
HOSTNAME: config.get<string>('listen.hostname')
|
||||
},
|
||||
DATABASE: {
|
||||
DBNAME: 'peertube' + config.get<string>('database.suffix'),
|
||||
HOSTNAME: config.get<string>('database.hostname'),
|
||||
PORT: config.get<number>('database.port'),
|
||||
USERNAME: config.get<string>('database.username'),
|
||||
PASSWORD: config.get<string>('database.password'),
|
||||
POOL: {
|
||||
MAX: config.get<number>('database.pool.max')
|
||||
}
|
||||
},
|
||||
REDIS: {
|
||||
HOSTNAME: config.has('redis.hostname') ? config.get<string>('redis.hostname') : null,
|
||||
PORT: config.has('redis.port') ? config.get<number>('redis.port') : null,
|
||||
SOCKET: config.has('redis.socket') ? config.get<string>('redis.socket') : null,
|
||||
AUTH: config.has('redis.auth') ? config.get<string>('redis.auth') : null,
|
||||
DB: config.has('redis.db') ? config.get<number>('redis.db') : null
|
||||
},
|
||||
SMTP: {
|
||||
HOSTNAME: config.get<string>('smtp.hostname'),
|
||||
PORT: config.get<number>('smtp.port'),
|
||||
USERNAME: config.get<string>('smtp.username'),
|
||||
PASSWORD: config.get<string>('smtp.password'),
|
||||
TLS: config.get<boolean>('smtp.tls'),
|
||||
DISABLE_STARTTLS: config.get<boolean>('smtp.disable_starttls'),
|
||||
CA_FILE: config.get<string>('smtp.ca_file'),
|
||||
FROM_ADDRESS: config.get<string>('smtp.from_address')
|
||||
},
|
||||
STORAGE: {
|
||||
TMP_DIR: buildPath(config.get<string>('storage.tmp')),
|
||||
AVATARS_DIR: buildPath(config.get<string>('storage.avatars')),
|
||||
LOG_DIR: buildPath(config.get<string>('storage.logs')),
|
||||
VIDEOS_DIR: buildPath(config.get<string>('storage.videos')),
|
||||
STREAMING_PLAYLISTS_DIR: buildPath(config.get<string>('storage.streaming_playlists')),
|
||||
REDUNDANCY_DIR: buildPath(config.get<string>('storage.redundancy')),
|
||||
THUMBNAILS_DIR: buildPath(config.get<string>('storage.thumbnails')),
|
||||
PREVIEWS_DIR: buildPath(config.get<string>('storage.previews')),
|
||||
CAPTIONS_DIR: buildPath(config.get<string>('storage.captions')),
|
||||
TORRENTS_DIR: buildPath(config.get<string>('storage.torrents')),
|
||||
CACHE_DIR: buildPath(config.get<string>('storage.cache'))
|
||||
},
|
||||
WEBSERVER: {
|
||||
SCHEME: config.get<boolean>('webserver.https') === true ? 'https' : 'http',
|
||||
WS: config.get<boolean>('webserver.https') === true ? 'wss' : 'ws',
|
||||
HOSTNAME: config.get<string>('webserver.hostname'),
|
||||
PORT: config.get<number>('webserver.port')
|
||||
},
|
||||
TRUST_PROXY: config.get<string[]>('trust_proxy'),
|
||||
LOG: {
|
||||
LEVEL: config.get<string>('log.level')
|
||||
},
|
||||
SEARCH: {
|
||||
REMOTE_URI: {
|
||||
USERS: config.get<boolean>('search.remote_uri.users'),
|
||||
ANONYMOUS: config.get<boolean>('search.remote_uri.anonymous')
|
||||
}
|
||||
},
|
||||
TRENDING: {
|
||||
VIDEOS: {
|
||||
INTERVAL_DAYS: config.get<number>('trending.videos.interval_days')
|
||||
}
|
||||
},
|
||||
REDUNDANCY: {
|
||||
VIDEOS: {
|
||||
CHECK_INTERVAL: parseDuration(config.get<string>('redundancy.videos.check_interval')),
|
||||
STRATEGIES: buildVideosRedundancy(config.get<any[]>('redundancy.videos.strategies'))
|
||||
}
|
||||
},
|
||||
CSP: {
|
||||
ENABLED: config.get<boolean>('csp.enabled'),
|
||||
REPORT_ONLY: config.get<boolean>('csp.report_only'),
|
||||
REPORT_URI: config.get<boolean>('csp.report_uri')
|
||||
},
|
||||
TRACKER: {
|
||||
ENABLED: config.get<boolean>('tracker.enabled'),
|
||||
PRIVATE: config.get<boolean>('tracker.private'),
|
||||
REJECT_TOO_MANY_ANNOUNCES: config.get<boolean>('tracker.reject_too_many_announces')
|
||||
},
|
||||
ADMIN: {
|
||||
get EMAIL () { return config.get<string>('admin.email') }
|
||||
},
|
||||
CONTACT_FORM: {
|
||||
get ENABLED () { return config.get<boolean>('contact_form.enabled') }
|
||||
},
|
||||
SIGNUP: {
|
||||
get ENABLED () { return config.get<boolean>('signup.enabled') },
|
||||
get LIMIT () { return config.get<number>('signup.limit') },
|
||||
get REQUIRES_EMAIL_VERIFICATION () { return config.get<boolean>('signup.requires_email_verification') },
|
||||
FILTERS: {
|
||||
CIDR: {
|
||||
get WHITELIST () { return config.get<string[]>('signup.filters.cidr.whitelist') },
|
||||
get BLACKLIST () { return config.get<string[]>('signup.filters.cidr.blacklist') }
|
||||
}
|
||||
}
|
||||
},
|
||||
USER: {
|
||||
get VIDEO_QUOTA () { return parseBytes(config.get<number>('user.video_quota')) },
|
||||
get VIDEO_QUOTA_DAILY () { return parseBytes(config.get<number>('user.video_quota_daily')) }
|
||||
},
|
||||
TRANSCODING: {
|
||||
get ENABLED () { return config.get<boolean>('transcoding.enabled') },
|
||||
get ALLOW_ADDITIONAL_EXTENSIONS () { return config.get<boolean>('transcoding.allow_additional_extensions') },
|
||||
get THREADS () { return config.get<number>('transcoding.threads') },
|
||||
RESOLUTIONS: {
|
||||
get '240p' () { return config.get<boolean>('transcoding.resolutions.240p') },
|
||||
get '360p' () { return config.get<boolean>('transcoding.resolutions.360p') },
|
||||
get '480p' () { return config.get<boolean>('transcoding.resolutions.480p') },
|
||||
get '720p' () { return config.get<boolean>('transcoding.resolutions.720p') },
|
||||
get '1080p' () { return config.get<boolean>('transcoding.resolutions.1080p') }
|
||||
},
|
||||
HLS: {
|
||||
get ENABLED () { return config.get<boolean>('transcoding.hls.enabled') }
|
||||
}
|
||||
},
|
||||
IMPORT: {
|
||||
VIDEOS: {
|
||||
HTTP: {
|
||||
get ENABLED () { return config.get<boolean>('import.videos.http.enabled') }
|
||||
},
|
||||
TORRENT: {
|
||||
get ENABLED () { return config.get<boolean>('import.videos.torrent.enabled') }
|
||||
}
|
||||
}
|
||||
},
|
||||
AUTO_BLACKLIST: {
|
||||
VIDEOS: {
|
||||
OF_USERS: {
|
||||
get ENABLED () { return config.get<boolean>('auto_blacklist.videos.of_users.enabled') }
|
||||
}
|
||||
}
|
||||
},
|
||||
CACHE: {
|
||||
PREVIEWS: {
|
||||
get SIZE () { return config.get<number>('cache.previews.size') }
|
||||
},
|
||||
VIDEO_CAPTIONS: {
|
||||
get SIZE () { return config.get<number>('cache.captions.size') }
|
||||
}
|
||||
},
|
||||
INSTANCE: {
|
||||
get NAME () { return config.get<string>('instance.name') },
|
||||
get SHORT_DESCRIPTION () { return config.get<string>('instance.short_description') },
|
||||
get DESCRIPTION () { return config.get<string>('instance.description') },
|
||||
get TERMS () { return config.get<string>('instance.terms') },
|
||||
get IS_NSFW () { return config.get<boolean>('instance.is_nsfw') },
|
||||
get DEFAULT_CLIENT_ROUTE () { return config.get<string>('instance.default_client_route') },
|
||||
get DEFAULT_NSFW_POLICY () { return config.get<NSFWPolicyType>('instance.default_nsfw_policy') },
|
||||
CUSTOMIZATIONS: {
|
||||
get JAVASCRIPT () { return config.get<string>('instance.customizations.javascript') },
|
||||
get CSS () { return config.get<string>('instance.customizations.css') }
|
||||
},
|
||||
get ROBOTS () { return config.get<string>('instance.robots') },
|
||||
get SECURITYTXT () { return config.get<string>('instance.securitytxt') },
|
||||
get SECURITYTXT_CONTACT () { return config.get<string>('admin.email') }
|
||||
},
|
||||
SERVICES: {
|
||||
TWITTER: {
|
||||
get USERNAME () { return config.get<string>('services.twitter.username') },
|
||||
get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') }
|
||||
}
|
||||
},
|
||||
FOLLOWERS: {
|
||||
INSTANCE: {
|
||||
get ENABLED () { return config.get<boolean>('followers.instance.enabled') },
|
||||
get MANUAL_APPROVAL () { return config.get<boolean>('followers.instance.manual_approval') }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function registerConfigChangedHandler (fun: Function) {
|
||||
configChangedHandlers.push(fun)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
CONFIG,
|
||||
registerConfigChangedHandler
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function getLocalConfigFilePath () {
|
||||
const configSources = config.util.getConfigSources()
|
||||
if (configSources.length === 0) throw new Error('Invalid config source.')
|
||||
|
||||
let filename = 'local'
|
||||
if (process.env.NODE_ENV) filename += `-${process.env.NODE_ENV}`
|
||||
if (process.env.NODE_APP_INSTANCE) filename += `-${process.env.NODE_APP_INSTANCE}`
|
||||
|
||||
return join(dirname(configSources[ 0 ].name), filename + '.json')
|
||||
}
|
||||
|
||||
function buildVideosRedundancy (objs: any[]): VideosRedundancy[] {
|
||||
if (!objs) return []
|
||||
|
||||
if (!Array.isArray(objs)) return objs
|
||||
|
||||
return objs.map(obj => {
|
||||
return Object.assign({}, obj, {
|
||||
minLifetime: parseDuration(obj.min_lifetime),
|
||||
size: bytes.parse(obj.size),
|
||||
minViews: obj.min_views
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function reloadConfig () {
|
||||
|
||||
function directory () {
|
||||
if (process.env.NODE_CONFIG_DIR) {
|
||||
return process.env.NODE_CONFIG_DIR
|
||||
}
|
||||
|
||||
return join(root(), 'config')
|
||||
}
|
||||
|
||||
function purge () {
|
||||
for (const fileName in require.cache) {
|
||||
if (-1 === fileName.indexOf(directory())) {
|
||||
continue
|
||||
}
|
||||
|
||||
delete require.cache[fileName]
|
||||
}
|
||||
|
||||
delete require.cache[require.resolve('config')]
|
||||
}
|
||||
|
||||
purge()
|
||||
|
||||
config = require('config')
|
||||
|
||||
for (const configChangedHandler of configChangedHandlers) {
|
||||
configChangedHandler()
|
||||
}
|
||||
}
|
|
@ -1,20 +1,16 @@
|
|||
import { IConfig } from 'config'
|
||||
import { dirname, join } from 'path'
|
||||
import { JobType, VideoRateType, VideoState, VideosRedundancy } from '../../shared/models'
|
||||
import { join } from 'path'
|
||||
import { JobType, VideoRateType, VideoState } from '../../shared/models'
|
||||
import { ActivityPubActorType } from '../../shared/models/activitypub'
|
||||
import { FollowState } from '../../shared/models/actors'
|
||||
import { VideoAbuseState, VideoImportState, VideoPrivacy, VideoTranscodingFPS } from '../../shared/models/videos'
|
||||
// Do not use barrels, remain constants as independent as possible
|
||||
import { buildPath, isTestInstance, parseDuration, parseBytes, root, sanitizeHost, sanitizeUrl } from '../helpers/core-utils'
|
||||
import { isTestInstance, sanitizeHost, sanitizeUrl } from '../helpers/core-utils'
|
||||
import { NSFWPolicyType } from '../../shared/models/videos/nsfw-policy.type'
|
||||
import { invert } from 'lodash'
|
||||
import { CronRepeatOptions, EveryRepeatOptions } from 'bull'
|
||||
import * as bytes from 'bytes'
|
||||
import { VideoPlaylistPrivacy } from '../../shared/models/videos/playlist/video-playlist-privacy.model'
|
||||
import { VideoPlaylistType } from '../../shared/models/videos/playlist/video-playlist-type.model'
|
||||
|
||||
// Use a variable to reload the configuration if we need
|
||||
let config: IConfig = require('config')
|
||||
import { CONFIG, registerConfigChangedHandler } from './config'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
@ -32,6 +28,15 @@ const PAGINATION = {
|
|||
}
|
||||
}
|
||||
|
||||
const WEBSERVER = {
|
||||
URL: '',
|
||||
HOST: '',
|
||||
SCHEME: '',
|
||||
WS: '',
|
||||
HOSTNAME: '',
|
||||
PORT: 0
|
||||
}
|
||||
|
||||
// Sortable columns per schema
|
||||
const SORTABLE_COLUMNS = {
|
||||
USERS: [ 'id', 'username', 'createdAt' ],
|
||||
|
@ -102,7 +107,7 @@ const REMOTE_SCHEME = {
|
|||
}
|
||||
|
||||
// TODO: remove 'video-file'
|
||||
const JOB_ATTEMPTS: { [ id in (JobType | 'video-file') ]: number } = {
|
||||
const JOB_ATTEMPTS: { [id in (JobType | 'video-file')]: number } = {
|
||||
'activitypub-http-broadcast': 5,
|
||||
'activitypub-http-unicast': 5,
|
||||
'activitypub-http-fetcher': 5,
|
||||
|
@ -115,7 +120,7 @@ const JOB_ATTEMPTS: { [ id in (JobType | 'video-file') ]: number } = {
|
|||
'videos-views': 1,
|
||||
'activitypub-refresher': 1
|
||||
}
|
||||
const JOB_CONCURRENCY: { [ id in (JobType | 'video-file') ]: number } = {
|
||||
const JOB_CONCURRENCY: { [id in (JobType | 'video-file')]: number } = {
|
||||
'activitypub-http-broadcast': 1,
|
||||
'activitypub-http-unicast': 5,
|
||||
'activitypub-http-fetcher': 1,
|
||||
|
@ -128,7 +133,7 @@ const JOB_CONCURRENCY: { [ id in (JobType | 'video-file') ]: number } = {
|
|||
'videos-views': 1,
|
||||
'activitypub-refresher': 1
|
||||
}
|
||||
const JOB_TTL: { [ id in (JobType | 'video-file') ]: number } = {
|
||||
const JOB_TTL: { [id in (JobType | 'video-file')]: number } = {
|
||||
'activitypub-http-broadcast': 60000 * 10, // 10 minutes
|
||||
'activitypub-http-unicast': 60000 * 10, // 10 minutes
|
||||
'activitypub-http-fetcher': 60000 * 10, // 10 minutes
|
||||
|
@ -163,184 +168,6 @@ let SCHEDULER_INTERVALS_MS = {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const CONFIG = {
|
||||
CUSTOM_FILE: getLocalConfigFilePath(),
|
||||
LISTEN: {
|
||||
PORT: config.get<number>('listen.port'),
|
||||
HOSTNAME: config.get<string>('listen.hostname')
|
||||
},
|
||||
DATABASE: {
|
||||
DBNAME: 'peertube' + config.get<string>('database.suffix'),
|
||||
HOSTNAME: config.get<string>('database.hostname'),
|
||||
PORT: config.get<number>('database.port'),
|
||||
USERNAME: config.get<string>('database.username'),
|
||||
PASSWORD: config.get<string>('database.password'),
|
||||
POOL: {
|
||||
MAX: config.get<number>('database.pool.max')
|
||||
}
|
||||
},
|
||||
REDIS: {
|
||||
HOSTNAME: config.has('redis.hostname') ? config.get<string>('redis.hostname') : null,
|
||||
PORT: config.has('redis.port') ? config.get<number>('redis.port') : null,
|
||||
SOCKET: config.has('redis.socket') ? config.get<string>('redis.socket') : null,
|
||||
AUTH: config.has('redis.auth') ? config.get<string>('redis.auth') : null,
|
||||
DB: config.has('redis.db') ? config.get<number>('redis.db') : null
|
||||
},
|
||||
SMTP: {
|
||||
HOSTNAME: config.get<string>('smtp.hostname'),
|
||||
PORT: config.get<number>('smtp.port'),
|
||||
USERNAME: config.get<string>('smtp.username'),
|
||||
PASSWORD: config.get<string>('smtp.password'),
|
||||
TLS: config.get<boolean>('smtp.tls'),
|
||||
DISABLE_STARTTLS: config.get<boolean>('smtp.disable_starttls'),
|
||||
CA_FILE: config.get<string>('smtp.ca_file'),
|
||||
FROM_ADDRESS: config.get<string>('smtp.from_address')
|
||||
},
|
||||
STORAGE: {
|
||||
TMP_DIR: buildPath(config.get<string>('storage.tmp')),
|
||||
AVATARS_DIR: buildPath(config.get<string>('storage.avatars')),
|
||||
LOG_DIR: buildPath(config.get<string>('storage.logs')),
|
||||
VIDEOS_DIR: buildPath(config.get<string>('storage.videos')),
|
||||
STREAMING_PLAYLISTS_DIR: buildPath(config.get<string>('storage.streaming_playlists')),
|
||||
REDUNDANCY_DIR: buildPath(config.get<string>('storage.redundancy')),
|
||||
THUMBNAILS_DIR: buildPath(config.get<string>('storage.thumbnails')),
|
||||
PREVIEWS_DIR: buildPath(config.get<string>('storage.previews')),
|
||||
CAPTIONS_DIR: buildPath(config.get<string>('storage.captions')),
|
||||
TORRENTS_DIR: buildPath(config.get<string>('storage.torrents')),
|
||||
CACHE_DIR: buildPath(config.get<string>('storage.cache'))
|
||||
},
|
||||
WEBSERVER: {
|
||||
SCHEME: config.get<boolean>('webserver.https') === true ? 'https' : 'http',
|
||||
WS: config.get<boolean>('webserver.https') === true ? 'wss' : 'ws',
|
||||
HOSTNAME: config.get<string>('webserver.hostname'),
|
||||
PORT: config.get<number>('webserver.port'),
|
||||
URL: '',
|
||||
HOST: ''
|
||||
},
|
||||
TRUST_PROXY: config.get<string[]>('trust_proxy'),
|
||||
LOG: {
|
||||
LEVEL: config.get<string>('log.level')
|
||||
},
|
||||
SEARCH: {
|
||||
REMOTE_URI: {
|
||||
USERS: config.get<boolean>('search.remote_uri.users'),
|
||||
ANONYMOUS: config.get<boolean>('search.remote_uri.anonymous')
|
||||
}
|
||||
},
|
||||
TRENDING: {
|
||||
VIDEOS: {
|
||||
INTERVAL_DAYS: config.get<number>('trending.videos.interval_days')
|
||||
}
|
||||
},
|
||||
REDUNDANCY: {
|
||||
VIDEOS: {
|
||||
CHECK_INTERVAL: parseDuration(config.get<string>('redundancy.videos.check_interval')),
|
||||
STRATEGIES: buildVideosRedundancy(config.get<any[]>('redundancy.videos.strategies'))
|
||||
}
|
||||
},
|
||||
CSP: {
|
||||
ENABLED: config.get<boolean>('csp.enabled'),
|
||||
REPORT_ONLY: config.get<boolean>('csp.report_only'),
|
||||
REPORT_URI: config.get<boolean>('csp.report_uri')
|
||||
},
|
||||
TRACKER: {
|
||||
ENABLED: config.get<boolean>('tracker.enabled'),
|
||||
PRIVATE: config.get<boolean>('tracker.private'),
|
||||
REJECT_TOO_MANY_ANNOUNCES: config.get<boolean>('tracker.reject_too_many_announces')
|
||||
},
|
||||
ADMIN: {
|
||||
get EMAIL () { return config.get<string>('admin.email') }
|
||||
},
|
||||
CONTACT_FORM: {
|
||||
get ENABLED () { return config.get<boolean>('contact_form.enabled') }
|
||||
},
|
||||
SIGNUP: {
|
||||
get ENABLED () { return config.get<boolean>('signup.enabled') },
|
||||
get LIMIT () { return config.get<number>('signup.limit') },
|
||||
get REQUIRES_EMAIL_VERIFICATION () { return config.get<boolean>('signup.requires_email_verification') },
|
||||
FILTERS: {
|
||||
CIDR: {
|
||||
get WHITELIST () { return config.get<string[]>('signup.filters.cidr.whitelist') },
|
||||
get BLACKLIST () { return config.get<string[]>('signup.filters.cidr.blacklist') }
|
||||
}
|
||||
}
|
||||
},
|
||||
USER: {
|
||||
get VIDEO_QUOTA () { return parseBytes(config.get<number>('user.video_quota')) },
|
||||
get VIDEO_QUOTA_DAILY () { return parseBytes(config.get<number>('user.video_quota_daily')) }
|
||||
},
|
||||
TRANSCODING: {
|
||||
get ENABLED () { return config.get<boolean>('transcoding.enabled') },
|
||||
get ALLOW_ADDITIONAL_EXTENSIONS () { return config.get<boolean>('transcoding.allow_additional_extensions') },
|
||||
get THREADS () { return config.get<number>('transcoding.threads') },
|
||||
RESOLUTIONS: {
|
||||
get '240p' () { return config.get<boolean>('transcoding.resolutions.240p') },
|
||||
get '360p' () { return config.get<boolean>('transcoding.resolutions.360p') },
|
||||
get '480p' () { return config.get<boolean>('transcoding.resolutions.480p') },
|
||||
get '720p' () { return config.get<boolean>('transcoding.resolutions.720p') },
|
||||
get '1080p' () { return config.get<boolean>('transcoding.resolutions.1080p') }
|
||||
},
|
||||
HLS: {
|
||||
get ENABLED () { return config.get<boolean>('transcoding.hls.enabled') }
|
||||
}
|
||||
},
|
||||
IMPORT: {
|
||||
VIDEOS: {
|
||||
HTTP: {
|
||||
get ENABLED () { return config.get<boolean>('import.videos.http.enabled') }
|
||||
},
|
||||
TORRENT: {
|
||||
get ENABLED () { return config.get<boolean>('import.videos.torrent.enabled') }
|
||||
}
|
||||
}
|
||||
},
|
||||
AUTO_BLACKLIST: {
|
||||
VIDEOS: {
|
||||
OF_USERS: {
|
||||
get ENABLED () { return config.get<boolean>('auto_blacklist.videos.of_users.enabled') }
|
||||
}
|
||||
}
|
||||
},
|
||||
CACHE: {
|
||||
PREVIEWS: {
|
||||
get SIZE () { return config.get<number>('cache.previews.size') }
|
||||
},
|
||||
VIDEO_CAPTIONS: {
|
||||
get SIZE () { return config.get<number>('cache.captions.size') }
|
||||
}
|
||||
},
|
||||
INSTANCE: {
|
||||
get NAME () { return config.get<string>('instance.name') },
|
||||
get SHORT_DESCRIPTION () { return config.get<string>('instance.short_description') },
|
||||
get DESCRIPTION () { return config.get<string>('instance.description') },
|
||||
get TERMS () { return config.get<string>('instance.terms') },
|
||||
get IS_NSFW () { return config.get<boolean>('instance.is_nsfw') },
|
||||
get DEFAULT_CLIENT_ROUTE () { return config.get<string>('instance.default_client_route') },
|
||||
get DEFAULT_NSFW_POLICY () { return config.get<NSFWPolicyType>('instance.default_nsfw_policy') },
|
||||
CUSTOMIZATIONS: {
|
||||
get JAVASCRIPT () { return config.get<string>('instance.customizations.javascript') },
|
||||
get CSS () { return config.get<string>('instance.customizations.css') }
|
||||
},
|
||||
get ROBOTS () { return config.get<string>('instance.robots') },
|
||||
get SECURITYTXT () { return config.get<string>('instance.securitytxt') },
|
||||
get SECURITYTXT_CONTACT () { return config.get<string>('admin.email') }
|
||||
},
|
||||
SERVICES: {
|
||||
TWITTER: {
|
||||
get USERNAME () { return config.get<string>('services.twitter.username') },
|
||||
get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') }
|
||||
}
|
||||
},
|
||||
FOLLOWERS: {
|
||||
INSTANCE: {
|
||||
get ENABLED () { return config.get<boolean>('followers.instance.enabled') },
|
||||
get MANUAL_APPROVAL () { return config.get<boolean>('followers.instance.manual_approval') }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
let CONSTRAINTS_FIELDS = {
|
||||
USERS: {
|
||||
NAME: { min: 1, max: 120 }, // Length
|
||||
|
@ -517,38 +344,38 @@ const VIDEO_LICENCES = {
|
|||
const VIDEO_LANGUAGES = buildLanguages()
|
||||
|
||||
const VIDEO_PRIVACIES = {
|
||||
[VideoPrivacy.PUBLIC]: 'Public',
|
||||
[VideoPrivacy.UNLISTED]: 'Unlisted',
|
||||
[VideoPrivacy.PRIVATE]: 'Private'
|
||||
[ VideoPrivacy.PUBLIC ]: 'Public',
|
||||
[ VideoPrivacy.UNLISTED ]: 'Unlisted',
|
||||
[ VideoPrivacy.PRIVATE ]: 'Private'
|
||||
}
|
||||
|
||||
const VIDEO_STATES = {
|
||||
[VideoState.PUBLISHED]: 'Published',
|
||||
[VideoState.TO_TRANSCODE]: 'To transcode',
|
||||
[VideoState.TO_IMPORT]: 'To import'
|
||||
[ VideoState.PUBLISHED ]: 'Published',
|
||||
[ VideoState.TO_TRANSCODE ]: 'To transcode',
|
||||
[ VideoState.TO_IMPORT ]: 'To import'
|
||||
}
|
||||
|
||||
const VIDEO_IMPORT_STATES = {
|
||||
[VideoImportState.FAILED]: 'Failed',
|
||||
[VideoImportState.PENDING]: 'Pending',
|
||||
[VideoImportState.SUCCESS]: 'Success'
|
||||
[ VideoImportState.FAILED ]: 'Failed',
|
||||
[ VideoImportState.PENDING ]: 'Pending',
|
||||
[ VideoImportState.SUCCESS ]: 'Success'
|
||||
}
|
||||
|
||||
const VIDEO_ABUSE_STATES = {
|
||||
[VideoAbuseState.PENDING]: 'Pending',
|
||||
[VideoAbuseState.REJECTED]: 'Rejected',
|
||||
[VideoAbuseState.ACCEPTED]: 'Accepted'
|
||||
[ VideoAbuseState.PENDING ]: 'Pending',
|
||||
[ VideoAbuseState.REJECTED ]: 'Rejected',
|
||||
[ VideoAbuseState.ACCEPTED ]: 'Accepted'
|
||||
}
|
||||
|
||||
const VIDEO_PLAYLIST_PRIVACIES = {
|
||||
[VideoPlaylistPrivacy.PUBLIC]: 'Public',
|
||||
[VideoPlaylistPrivacy.UNLISTED]: 'Unlisted',
|
||||
[VideoPlaylistPrivacy.PRIVATE]: 'Private'
|
||||
[ VideoPlaylistPrivacy.PUBLIC ]: 'Public',
|
||||
[ VideoPlaylistPrivacy.UNLISTED ]: 'Unlisted',
|
||||
[ VideoPlaylistPrivacy.PRIVATE ]: 'Private'
|
||||
}
|
||||
|
||||
const VIDEO_PLAYLIST_TYPES = {
|
||||
[VideoPlaylistType.REGULAR]: 'Regular',
|
||||
[VideoPlaylistType.WATCH_LATER]: 'Watch later'
|
||||
[ VideoPlaylistType.REGULAR ]: 'Regular',
|
||||
[ VideoPlaylistType.WATCH_LATER ]: 'Watch later'
|
||||
}
|
||||
|
||||
const MIMETYPES = {
|
||||
|
@ -634,7 +461,7 @@ const USER_PASSWORD_RESET_LIFETIME = 60000 * 5 // 5 minutes
|
|||
|
||||
const USER_EMAIL_VERIFY_LIFETIME = 60000 * 60 // 60 minutes
|
||||
|
||||
const NSFW_POLICY_TYPES: { [ id: string]: NSFWPolicyType } = {
|
||||
const NSFW_POLICY_TYPES: { [ id: string ]: NSFWPolicyType } = {
|
||||
DO_NOT_LIST: 'do_not_list',
|
||||
BLUR: 'blur',
|
||||
DISPLAY: 'display'
|
||||
|
@ -765,14 +592,14 @@ if (isTestInstance() === true) {
|
|||
SCHEDULER_INTERVALS_MS.actorFollowScores = 1000
|
||||
SCHEDULER_INTERVALS_MS.removeOldJobs = 10000
|
||||
SCHEDULER_INTERVALS_MS.updateVideos = 5000
|
||||
REPEAT_JOBS['videos-views'] = { every: 5000 }
|
||||
REPEAT_JOBS[ 'videos-views' ] = { every: 5000 }
|
||||
|
||||
REDUNDANCY.VIDEOS.RANDOMIZED_FACTOR = 1
|
||||
|
||||
VIDEO_VIEW_LIFETIME = 1000 // 1 second
|
||||
CONTACT_FORM_LIFETIME = 1000 // 1 second
|
||||
|
||||
JOB_ATTEMPTS['email'] = 1
|
||||
JOB_ATTEMPTS[ 'email' ] = 1
|
||||
|
||||
FILES_CACHE.VIDEO_CAPTIONS.MAX_AGE = 3000
|
||||
MEMOIZE_TTL.OVERVIEWS_SAMPLE = 1
|
||||
|
@ -783,9 +610,15 @@ if (isTestInstance() === true) {
|
|||
|
||||
updateWebserverUrls()
|
||||
|
||||
registerConfigChangedHandler(() => {
|
||||
updateWebserverUrls()
|
||||
updateWebserverConfig()
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
WEBSERVER,
|
||||
API_VERSION,
|
||||
HLS_REDUNDANCY_DIRECTORY,
|
||||
P2P_MEDIA_LOADER_PEER_VERSION,
|
||||
|
@ -794,7 +627,6 @@ export {
|
|||
BCRYPT_SALT_SIZE,
|
||||
TRACKER_RATE_LIMITS,
|
||||
FILES_CACHE,
|
||||
CONFIG,
|
||||
CONSTRAINTS_FIELDS,
|
||||
EMBED_SIZE,
|
||||
REDUNDANCY,
|
||||
|
@ -857,17 +689,6 @@ export {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function getLocalConfigFilePath () {
|
||||
const configSources = config.util.getConfigSources()
|
||||
if (configSources.length === 0) throw new Error('Invalid config source.')
|
||||
|
||||
let filename = 'local'
|
||||
if (process.env.NODE_ENV) filename += `-${process.env.NODE_ENV}`
|
||||
if (process.env.NODE_APP_INSTANCE) filename += `-${process.env.NODE_APP_INSTANCE}`
|
||||
|
||||
return join(dirname(configSources[ 0 ].name), filename + '.json')
|
||||
}
|
||||
|
||||
function buildVideoMimetypeExt () {
|
||||
const data = {
|
||||
'video/webm': '.webm',
|
||||
|
@ -890,8 +711,12 @@ function buildVideoMimetypeExt () {
|
|||
}
|
||||
|
||||
function updateWebserverUrls () {
|
||||
CONFIG.WEBSERVER.URL = sanitizeUrl(CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT)
|
||||
CONFIG.WEBSERVER.HOST = sanitizeHost(CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT, REMOTE_SCHEME.HTTP)
|
||||
WEBSERVER.URL = sanitizeUrl(CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT)
|
||||
WEBSERVER.HOST = sanitizeHost(CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT, REMOTE_SCHEME.HTTP)
|
||||
WEBSERVER.SCHEME = CONFIG.WEBSERVER.SCHEME
|
||||
WEBSERVER.WS = CONFIG.WEBSERVER.WS
|
||||
WEBSERVER.HOSTNAME = CONFIG.WEBSERVER.HOSTNAME
|
||||
WEBSERVER.PORT = CONFIG.WEBSERVER.PORT
|
||||
}
|
||||
|
||||
function updateWebserverConfig () {
|
||||
|
@ -907,20 +732,6 @@ function buildVideosExtname () {
|
|||
: [ '.mp4', '.ogv', '.webm' ]
|
||||
}
|
||||
|
||||
function buildVideosRedundancy (objs: any[]): VideosRedundancy[] {
|
||||
if (!objs) return []
|
||||
|
||||
if (!Array.isArray(objs)) return objs
|
||||
|
||||
return objs.map(obj => {
|
||||
return Object.assign({}, obj, {
|
||||
minLifetime: parseDuration(obj.min_lifetime),
|
||||
size: bytes.parse(obj.size),
|
||||
minViews: obj.min_views
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function buildLanguages () {
|
||||
const iso639 = require('iso-639-3')
|
||||
|
||||
|
@ -953,42 +764,12 @@ function buildLanguages () {
|
|||
iso639
|
||||
.filter(l => {
|
||||
return (l.iso6391 !== null && l.type === 'living') ||
|
||||
additionalLanguages[l.iso6393] === true
|
||||
additionalLanguages[ l.iso6393 ] === true
|
||||
})
|
||||
.forEach(l => languages[l.iso6391 || l.iso6393] = l.name)
|
||||
.forEach(l => languages[ l.iso6391 || l.iso6393 ] = l.name)
|
||||
|
||||
// Override Occitan label
|
||||
languages['oc'] = 'Occitan'
|
||||
languages[ 'oc' ] = 'Occitan'
|
||||
|
||||
return languages
|
||||
}
|
||||
|
||||
export function reloadConfig () {
|
||||
|
||||
function directory () {
|
||||
if (process.env.NODE_CONFIG_DIR) {
|
||||
return process.env.NODE_CONFIG_DIR
|
||||
}
|
||||
|
||||
return join(root(), 'config')
|
||||
}
|
||||
|
||||
function purge () {
|
||||
for (const fileName in require.cache) {
|
||||
if (-1 === fileName.indexOf(directory())) {
|
||||
continue
|
||||
}
|
||||
|
||||
delete require.cache[fileName]
|
||||
}
|
||||
|
||||
delete require.cache[require.resolve('config')]
|
||||
}
|
||||
|
||||
purge()
|
||||
|
||||
config = require('config')
|
||||
|
||||
updateWebserverConfig()
|
||||
updateWebserverUrls()
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import { VideoCommentModel } from '../models/video/video-comment'
|
|||
import { VideoFileModel } from '../models/video/video-file'
|
||||
import { VideoShareModel } from '../models/video/video-share'
|
||||
import { VideoTagModel } from '../models/video/video-tag'
|
||||
import { CONFIG } from './constants'
|
||||
import { CONFIG } from './config'
|
||||
import { ScheduleVideoUpdateModel } from '../models/video/schedule-video-update'
|
||||
import { VideoCaptionModel } from '../models/video/video-caption'
|
||||
import { VideoImportModel } from '../models/video/video-import'
|
||||
|
|
|
@ -6,9 +6,10 @@ import { UserModel } from '../models/account/user'
|
|||
import { ApplicationModel } from '../models/application/application'
|
||||
import { OAuthClientModel } from '../models/oauth/oauth-client'
|
||||
import { applicationExist, clientsExist, usersExist } from './checker-after-init'
|
||||
import { FILES_CACHE, CONFIG, HLS_STREAMING_PLAYLIST_DIRECTORY, LAST_MIGRATION_VERSION } from './constants'
|
||||
import { FILES_CACHE, HLS_STREAMING_PLAYLIST_DIRECTORY, LAST_MIGRATION_VERSION } from './constants'
|
||||
import { sequelizeTypescript } from './database'
|
||||
import { remove, ensureDir } from 'fs-extra'
|
||||
import { ensureDir, remove } from 'fs-extra'
|
||||
import { CONFIG } from './config'
|
||||
|
||||
async function installApplication () {
|
||||
try {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
import { join } from 'path'
|
||||
import { CONFIG } from '../../initializers/constants'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
import { getVideoFileResolution } from '../../helpers/ffmpeg-utils'
|
||||
import { readdir, rename } from 'fs-extra'
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
import { CONFIG } from '../constants'
|
||||
import { WEBSERVER } from '../constants'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction,
|
||||
queryInterface: Sequelize.QueryInterface,
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
const toReplace = CONFIG.WEBSERVER.HOSTNAME + ':443'
|
||||
const by = CONFIG.WEBSERVER.HOST
|
||||
const toReplace = WEBSERVER.HOSTNAME + ':443'
|
||||
const by = WEBSERVER.HOST
|
||||
const replacer = column => `replace("${column}", '${toReplace}', '${by}')`
|
||||
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
import { createClient } from 'redis'
|
||||
import { CONFIG } from '../constants'
|
||||
import { JobQueue } from '../../lib/job-queue'
|
||||
import { initDatabaseModels } from '../database'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
import { createClient } from 'redis'
|
||||
import { CONFIG } from '../constants'
|
||||
import { JobQueue } from '../../lib/job-queue'
|
||||
import { initDatabaseModels } from '../database'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
import { CONFIG } from '../constants'
|
||||
import { VideoPlaylistPrivacy, VideoPlaylistType } from '../../../shared/models/videos'
|
||||
import * as uuidv4 from 'uuid/v4'
|
||||
import { WEBSERVER } from '../constants'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction,
|
||||
|
@ -57,7 +57,7 @@ CREATE TABLE IF NOT EXISTS "videoPlaylistElement"
|
|||
for (const username of usernames) {
|
||||
const uuid = uuidv4()
|
||||
|
||||
const baseUrl = CONFIG.WEBSERVER.URL + '/video-playlists/' + uuid
|
||||
const baseUrl = WEBSERVER.URL + '/video-playlists/' + uuid
|
||||
const query = `
|
||||
INSERT INTO "videoPlaylist" ("url", "uuid", "name", "privacy", "type", "ownerAccountId", "createdAt", "updatedAt")
|
||||
SELECT '${baseUrl}' AS "url",
|
||||
|
|
|
@ -12,7 +12,7 @@ import { logger } from '../../helpers/logger'
|
|||
import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto'
|
||||
import { doRequest, downloadImage } from '../../helpers/requests'
|
||||
import { getUrlFromWebfinger } from '../../helpers/webfinger'
|
||||
import { AVATARS_SIZE, CONFIG, MIMETYPES, sequelizeTypescript } from '../../initializers'
|
||||
import { AVATARS_SIZE, MIMETYPES, sequelizeTypescript, WEBSERVER } from '../../initializers'
|
||||
import { AccountModel } from '../../models/account/account'
|
||||
import { ActorModel } from '../../models/activitypub/actor'
|
||||
import { AvatarModel } from '../../models/avatar/avatar'
|
||||
|
@ -21,6 +21,7 @@ import { VideoChannelModel } from '../../models/video/video-channel'
|
|||
import { JobQueue } from '../job-queue'
|
||||
import { getServerActor } from '../../helpers/utils'
|
||||
import { ActorFetchByUrlType, fetchActorByUrl } from '../../helpers/actor'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
// Set account keys, this could be long so process after the account creation and do not block the client
|
||||
function setAsyncActorKeys (actor: ActorModel) {
|
||||
|
@ -116,7 +117,7 @@ function buildActorInstance (type: ActivityPubActorType, url: string, preferredU
|
|||
followingCount: 0,
|
||||
inboxUrl: url + '/inbox',
|
||||
outboxUrl: url + '/outbox',
|
||||
sharedInboxUrl: CONFIG.WEBSERVER.URL + '/inbox',
|
||||
sharedInboxUrl: WEBSERVER.URL + '/inbox',
|
||||
followersUrl: url + '/followers',
|
||||
followingUrl: url + '/following'
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object'
|
||||
import { crawlCollectionPage } from './crawl'
|
||||
import { ACTIVITY_PUB, CONFIG, CRAWL_REQUEST_CONCURRENCY, sequelizeTypescript, THUMBNAILS_SIZE } from '../../initializers'
|
||||
import { ACTIVITY_PUB, CRAWL_REQUEST_CONCURRENCY, sequelizeTypescript, THUMBNAILS_SIZE } from '../../initializers'
|
||||
import { AccountModel } from '../../models/account/account'
|
||||
import { isArray } from '../../helpers/custom-validators/misc'
|
||||
import { getOrCreateActorAndServerAndModel } from './actor'
|
||||
|
@ -17,6 +17,7 @@ import { VideoModel } from '../../models/video/video'
|
|||
import { FilteredModelAttributes } from 'sequelize-typescript/lib/models/Model'
|
||||
import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
|
||||
import { ActivityIconObject } from '../../../shared/models/activitypub/objects'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: AccountModel, to: string[]) {
|
||||
const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPlaylistPrivacy.PUBLIC : VideoPlaylistPrivacy.UNLISTED
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import { ActivityFollow } from '../../../../shared/models/activitypub'
|
||||
import { retryTransactionWrapper } from '../../../helpers/database-utils'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { sequelizeTypescript, CONFIG } from '../../../initializers'
|
||||
import { sequelizeTypescript } from '../../../initializers'
|
||||
import { ActorModel } from '../../../models/activitypub/actor'
|
||||
import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
|
||||
import { sendAccept, sendReject } from '../send'
|
||||
import { Notifier } from '../../notifier'
|
||||
import { getAPId } from '../../../helpers/activitypub'
|
||||
import { getServerActor } from '../../../helpers/utils'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
async function processFollowActivity (activity: ActivityFollow, byActor: ActorModel) {
|
||||
const activityObject = getAPId(activity.object)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { CONFIG } from '../../initializers'
|
||||
import { WEBSERVER } from '../../initializers'
|
||||
import { ActorModel } from '../../models/activitypub/actor'
|
||||
import { ActorFollowModel } from '../../models/activitypub/actor-follow'
|
||||
import { VideoModel } from '../../models/video/video'
|
||||
|
@ -9,41 +9,41 @@ import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-
|
|||
import { VideoPlaylistModel } from '../../models/video/video-playlist'
|
||||
|
||||
function getVideoActivityPubUrl (video: VideoModel) {
|
||||
return CONFIG.WEBSERVER.URL + '/videos/watch/' + video.uuid
|
||||
return WEBSERVER.URL + '/videos/watch/' + video.uuid
|
||||
}
|
||||
|
||||
function getVideoPlaylistActivityPubUrl (videoPlaylist: VideoPlaylistModel) {
|
||||
return CONFIG.WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid
|
||||
return WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid
|
||||
}
|
||||
|
||||
function getVideoPlaylistElementActivityPubUrl (videoPlaylist: VideoPlaylistModel, video: VideoModel) {
|
||||
return CONFIG.WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid + '/' + video.uuid
|
||||
return WEBSERVER.URL + '/video-playlists/' + videoPlaylist.uuid + '/' + video.uuid
|
||||
}
|
||||
|
||||
function getVideoCacheFileActivityPubUrl (videoFile: VideoFileModel) {
|
||||
const suffixFPS = videoFile.fps && videoFile.fps !== -1 ? '-' + videoFile.fps : ''
|
||||
|
||||
return `${CONFIG.WEBSERVER.URL}/redundancy/videos/${videoFile.Video.uuid}/${videoFile.resolution}${suffixFPS}`
|
||||
return `${WEBSERVER.URL}/redundancy/videos/${videoFile.Video.uuid}/${videoFile.resolution}${suffixFPS}`
|
||||
}
|
||||
|
||||
function getVideoCacheStreamingPlaylistActivityPubUrl (video: VideoModel, playlist: VideoStreamingPlaylistModel) {
|
||||
return `${CONFIG.WEBSERVER.URL}/redundancy/streaming-playlists/${playlist.getStringType()}/${video.uuid}`
|
||||
return `${WEBSERVER.URL}/redundancy/streaming-playlists/${playlist.getStringType()}/${video.uuid}`
|
||||
}
|
||||
|
||||
function getVideoCommentActivityPubUrl (video: VideoModel, videoComment: VideoCommentModel) {
|
||||
return CONFIG.WEBSERVER.URL + '/videos/watch/' + video.uuid + '/comments/' + videoComment.id
|
||||
return WEBSERVER.URL + '/videos/watch/' + video.uuid + '/comments/' + videoComment.id
|
||||
}
|
||||
|
||||
function getVideoChannelActivityPubUrl (videoChannelName: string) {
|
||||
return CONFIG.WEBSERVER.URL + '/video-channels/' + videoChannelName
|
||||
return WEBSERVER.URL + '/video-channels/' + videoChannelName
|
||||
}
|
||||
|
||||
function getAccountActivityPubUrl (accountName: string) {
|
||||
return CONFIG.WEBSERVER.URL + '/accounts/' + accountName
|
||||
return WEBSERVER.URL + '/accounts/' + accountName
|
||||
}
|
||||
|
||||
function getVideoAbuseActivityPubUrl (videoAbuse: VideoAbuseModel) {
|
||||
return CONFIG.WEBSERVER.URL + '/admin/video-abuses/' + videoAbuse.id
|
||||
return WEBSERVER.URL + '/admin/video-abuses/' + videoAbuse.id
|
||||
}
|
||||
|
||||
function getVideoViewActivityPubUrl (byActor: ActorModel, video: VideoModel) {
|
||||
|
|
|
@ -19,7 +19,6 @@ import { logger } from '../../helpers/logger'
|
|||
import { doRequest, downloadImage } from '../../helpers/requests'
|
||||
import {
|
||||
ACTIVITY_PUB,
|
||||
CONFIG,
|
||||
MIMETYPES,
|
||||
P2P_MEDIA_LOADER_PEER_VERSION,
|
||||
REMOTE_SCHEME,
|
||||
|
@ -51,6 +50,7 @@ import { FilteredModelAttributes } from 'sequelize-typescript/lib/models/Model'
|
|||
import { AccountVideoRateModel } from '../../models/account/account-video-rate'
|
||||
import { VideoShareModel } from '../../models/video/video-share'
|
||||
import { VideoCommentModel } from '../../models/video/video-comment'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) {
|
||||
// If the video is not private and is published, we federate it
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import 'multer'
|
||||
import { sendUpdateActor } from './activitypub/send'
|
||||
import { AVATARS_SIZE, CONFIG, sequelizeTypescript } from '../initializers'
|
||||
import { AVATARS_SIZE, sequelizeTypescript } from '../initializers'
|
||||
import { updateActorAvatarInstance } from './activitypub'
|
||||
import { processImage } from '../helpers/image-utils'
|
||||
import { AccountModel } from '../models/account/account'
|
||||
|
@ -8,6 +8,7 @@ import { VideoChannelModel } from '../models/video/video-channel'
|
|||
import { extname, join } from 'path'
|
||||
import { retryTransactionWrapper } from '../helpers/database-utils'
|
||||
import * as uuidv4 from 'uuid/v4'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
async function updateActorAvatarFile (avatarPhysicalFile: Express.Multer.File, accountOrChannel: AccountModel | VideoChannelModel) {
|
||||
const extension = extname(avatarPhysicalFile.filename)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as express from 'express'
|
||||
import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/models/i18n/i18n'
|
||||
import { CONFIG, CUSTOM_HTML_TAG_COMMENTS, EMBED_SIZE } from '../initializers'
|
||||
import { CUSTOM_HTML_TAG_COMMENTS, EMBED_SIZE, WEBSERVER } from '../initializers'
|
||||
import { join } from 'path'
|
||||
import { escapeHTML } from '../helpers/core-utils'
|
||||
import { VideoModel } from '../models/video/video'
|
||||
|
@ -11,6 +11,7 @@ import { getActivityStreamDuration } from '../models/video/video-format-utils'
|
|||
import { AccountModel } from '../models/account/account'
|
||||
import { VideoChannelModel } from '../models/video/video-channel'
|
||||
import * as Bluebird from 'bluebird'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
export class ClientHtml {
|
||||
|
||||
|
@ -106,7 +107,7 @@ export class ClientHtml {
|
|||
|
||||
// Save locale in cookies
|
||||
res.cookie('clientLanguage', lang, {
|
||||
secure: CONFIG.WEBSERVER.SCHEME === 'https',
|
||||
secure: WEBSERVER.SCHEME === 'https',
|
||||
sameSite: true,
|
||||
maxAge: 1000 * 3600 * 24 * 90 // 3 months
|
||||
})
|
||||
|
@ -143,12 +144,12 @@ export class ClientHtml {
|
|||
}
|
||||
|
||||
private static addVideoOpenGraphAndOEmbedTags (htmlStringPage: string, video: VideoModel) {
|
||||
const previewUrl = CONFIG.WEBSERVER.URL + video.getPreviewStaticPath()
|
||||
const videoUrl = CONFIG.WEBSERVER.URL + video.getWatchStaticPath()
|
||||
const previewUrl = WEBSERVER.URL + video.getPreviewStaticPath()
|
||||
const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
|
||||
|
||||
const videoNameEscaped = escapeHTML(video.name)
|
||||
const videoDescriptionEscaped = escapeHTML(video.description)
|
||||
const embedUrl = CONFIG.WEBSERVER.URL + video.getEmbedStaticPath()
|
||||
const embedUrl = WEBSERVER.URL + video.getEmbedStaticPath()
|
||||
|
||||
const openGraphMetaTags = {
|
||||
'og:type': 'video',
|
||||
|
@ -180,7 +181,7 @@ export class ClientHtml {
|
|||
const oembedLinkTags = [
|
||||
{
|
||||
type: 'application/json+oembed',
|
||||
href: CONFIG.WEBSERVER.URL + '/services/oembed?url=' + encodeURIComponent(videoUrl),
|
||||
href: WEBSERVER.URL + '/services/oembed?url=' + encodeURIComponent(videoUrl),
|
||||
title: videoNameEscaped
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { createTransport, Transporter } from 'nodemailer'
|
||||
import { isTestInstance } from '../helpers/core-utils'
|
||||
import { bunyanLogger, logger } from '../helpers/logger'
|
||||
import { CONFIG } from '../initializers'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
import { UserModel } from '../models/account/user'
|
||||
import { VideoModel } from '../models/video/video'
|
||||
import { JobQueue } from './job-queue'
|
||||
|
@ -12,6 +12,7 @@ import { VideoAbuseModel } from '../models/video/video-abuse'
|
|||
import { VideoBlacklistModel } from '../models/video/video-blacklist'
|
||||
import { VideoImportModel } from '../models/video/video-import'
|
||||
import { ActorFollowModel } from '../models/activitypub/actor-follow'
|
||||
import { WEBSERVER } from '../initializers/constants'
|
||||
|
||||
type SendEmailOptions = {
|
||||
to: string[]
|
||||
|
@ -91,7 +92,7 @@ class Emailer {
|
|||
|
||||
addNewVideoFromSubscriberNotification (to: string[], video: VideoModel) {
|
||||
const channelName = video.VideoChannel.getDisplayName()
|
||||
const videoUrl = CONFIG.WEBSERVER.URL + video.getWatchStaticPath()
|
||||
const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
|
||||
|
||||
const text = `Hi dear user,\n\n` +
|
||||
`Your subscription ${channelName} just published a new video: ${video.name}` +
|
||||
|
@ -148,7 +149,7 @@ class Emailer {
|
|||
}
|
||||
|
||||
myVideoPublishedNotification (to: string[], video: VideoModel) {
|
||||
const videoUrl = CONFIG.WEBSERVER.URL + video.getWatchStaticPath()
|
||||
const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
|
||||
|
||||
const text = `Hi dear user,\n\n` +
|
||||
`Your video ${video.name} has been published.` +
|
||||
|
@ -168,7 +169,7 @@ class Emailer {
|
|||
}
|
||||
|
||||
myVideoImportSuccessNotification (to: string[], videoImport: VideoImportModel) {
|
||||
const videoUrl = CONFIG.WEBSERVER.URL + videoImport.Video.getWatchStaticPath()
|
||||
const videoUrl = WEBSERVER.URL + videoImport.Video.getWatchStaticPath()
|
||||
|
||||
const text = `Hi dear user,\n\n` +
|
||||
`Your video import ${videoImport.getTargetIdentifier()} is finished.` +
|
||||
|
@ -188,7 +189,7 @@ class Emailer {
|
|||
}
|
||||
|
||||
myVideoImportErrorNotification (to: string[], videoImport: VideoImportModel) {
|
||||
const importUrl = CONFIG.WEBSERVER.URL + '/my-account/video-imports'
|
||||
const importUrl = WEBSERVER.URL + '/my-account/video-imports'
|
||||
|
||||
const text = `Hi dear user,\n\n` +
|
||||
`Your video import ${videoImport.getTargetIdentifier()} encountered an error.` +
|
||||
|
@ -210,7 +211,7 @@ class Emailer {
|
|||
addNewCommentOnMyVideoNotification (to: string[], comment: VideoCommentModel) {
|
||||
const accountName = comment.Account.getDisplayName()
|
||||
const video = comment.Video
|
||||
const commentUrl = CONFIG.WEBSERVER.URL + comment.getCommentStaticPath()
|
||||
const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath()
|
||||
|
||||
const text = `Hi dear user,\n\n` +
|
||||
`A new comment has been posted by ${accountName} on your video ${video.name}` +
|
||||
|
@ -232,7 +233,7 @@ class Emailer {
|
|||
addNewCommentMentionNotification (to: string[], comment: VideoCommentModel) {
|
||||
const accountName = comment.Account.getDisplayName()
|
||||
const video = comment.Video
|
||||
const commentUrl = CONFIG.WEBSERVER.URL + comment.getCommentStaticPath()
|
||||
const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath()
|
||||
|
||||
const text = `Hi dear user,\n\n` +
|
||||
`${accountName} mentioned you on video ${video.name}` +
|
||||
|
@ -252,10 +253,10 @@ class Emailer {
|
|||
}
|
||||
|
||||
addVideoAbuseModeratorsNotification (to: string[], videoAbuse: VideoAbuseModel) {
|
||||
const videoUrl = CONFIG.WEBSERVER.URL + videoAbuse.Video.getWatchStaticPath()
|
||||
const videoUrl = WEBSERVER.URL + videoAbuse.Video.getWatchStaticPath()
|
||||
|
||||
const text = `Hi,\n\n` +
|
||||
`${CONFIG.WEBSERVER.HOST} received an abuse for the following video ${videoUrl}\n\n` +
|
||||
`${WEBSERVER.HOST} received an abuse for the following video ${videoUrl}\n\n` +
|
||||
`Cheers,\n` +
|
||||
`PeerTube.`
|
||||
|
||||
|
@ -269,8 +270,8 @@ class Emailer {
|
|||
}
|
||||
|
||||
addVideoAutoBlacklistModeratorsNotification (to: string[], video: VideoModel) {
|
||||
const VIDEO_AUTO_BLACKLIST_URL = CONFIG.WEBSERVER.URL + '/admin/moderation/video-auto-blacklist/list'
|
||||
const videoUrl = CONFIG.WEBSERVER.URL + video.getWatchStaticPath()
|
||||
const VIDEO_AUTO_BLACKLIST_URL = WEBSERVER.URL + '/admin/moderation/video-auto-blacklist/list'
|
||||
const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
|
||||
|
||||
const text = `Hi,\n\n` +
|
||||
`A recently added video was auto-blacklisted and requires moderator review before publishing.` +
|
||||
|
@ -293,13 +294,13 @@ class Emailer {
|
|||
|
||||
addNewUserRegistrationNotification (to: string[], user: UserModel) {
|
||||
const text = `Hi,\n\n` +
|
||||
`User ${user.username} just registered on ${CONFIG.WEBSERVER.HOST} PeerTube instance.\n\n` +
|
||||
`User ${user.username} just registered on ${WEBSERVER.HOST} PeerTube instance.\n\n` +
|
||||
`Cheers,\n` +
|
||||
`PeerTube.`
|
||||
|
||||
const emailPayload: EmailPayload = {
|
||||
to,
|
||||
subject: '[PeerTube] New user registration on ' + CONFIG.WEBSERVER.HOST,
|
||||
subject: '[PeerTube] New user registration on ' + WEBSERVER.HOST,
|
||||
text
|
||||
}
|
||||
|
||||
|
@ -308,10 +309,10 @@ class Emailer {
|
|||
|
||||
addVideoBlacklistNotification (to: string[], videoBlacklist: VideoBlacklistModel) {
|
||||
const videoName = videoBlacklist.Video.name
|
||||
const videoUrl = CONFIG.WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath()
|
||||
const videoUrl = WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath()
|
||||
|
||||
const reasonString = videoBlacklist.reason ? ` for the following reason: ${videoBlacklist.reason}` : ''
|
||||
const blockedString = `Your video ${videoName} (${videoUrl} on ${CONFIG.WEBSERVER.HOST} has been blacklisted${reasonString}.`
|
||||
const blockedString = `Your video ${videoName} (${videoUrl} on ${WEBSERVER.HOST} has been blacklisted${reasonString}.`
|
||||
|
||||
const text = 'Hi,\n\n' +
|
||||
blockedString +
|
||||
|
@ -329,10 +330,10 @@ class Emailer {
|
|||
}
|
||||
|
||||
addVideoUnblacklistNotification (to: string[], video: VideoModel) {
|
||||
const videoUrl = CONFIG.WEBSERVER.URL + video.getWatchStaticPath()
|
||||
const videoUrl = WEBSERVER.URL + video.getWatchStaticPath()
|
||||
|
||||
const text = 'Hi,\n\n' +
|
||||
`Your video ${video.name} (${videoUrl}) on ${CONFIG.WEBSERVER.HOST} has been unblacklisted.` +
|
||||
`Your video ${video.name} (${videoUrl}) on ${WEBSERVER.HOST} has been unblacklisted.` +
|
||||
'\n\n' +
|
||||
'Cheers,\n' +
|
||||
`PeerTube.`
|
||||
|
@ -348,7 +349,7 @@ class Emailer {
|
|||
|
||||
addPasswordResetEmailJob (to: string, resetPasswordUrl: string) {
|
||||
const text = `Hi dear user,\n\n` +
|
||||
`A reset password procedure for your account ${to} has been requested on ${CONFIG.WEBSERVER.HOST} ` +
|
||||
`A reset password procedure for your account ${to} has been requested on ${WEBSERVER.HOST} ` +
|
||||
`Please follow this link to reset it: ${resetPasswordUrl}\n\n` +
|
||||
`If you are not the person who initiated this request, please ignore this email.\n\n` +
|
||||
`Cheers,\n` +
|
||||
|
@ -365,7 +366,7 @@ class Emailer {
|
|||
|
||||
addVerifyEmailJob (to: string, verifyEmailUrl: string) {
|
||||
const text = `Welcome to PeerTube,\n\n` +
|
||||
`To start using PeerTube on ${CONFIG.WEBSERVER.HOST} you must verify your email! ` +
|
||||
`To start using PeerTube on ${WEBSERVER.HOST} you must verify your email! ` +
|
||||
`Please follow this link to verify this email belongs to you: ${verifyEmailUrl}\n\n` +
|
||||
`If you are not the person who initiated this request, please ignore this email.\n\n` +
|
||||
`Cheers,\n` +
|
||||
|
@ -383,7 +384,7 @@ class Emailer {
|
|||
addUserBlockJob (user: UserModel, blocked: boolean, reason?: string) {
|
||||
const reasonString = reason ? ` for the following reason: ${reason}` : ''
|
||||
const blockedWord = blocked ? 'blocked' : 'unblocked'
|
||||
const blockedString = `Your account ${user.username} on ${CONFIG.WEBSERVER.HOST} has been ${blockedWord}${reasonString}.`
|
||||
const blockedString = `Your account ${user.username} on ${WEBSERVER.HOST} has been ${blockedWord}${reasonString}.`
|
||||
|
||||
const text = 'Hi,\n\n' +
|
||||
blockedString +
|
||||
|
@ -428,7 +429,7 @@ class Emailer {
|
|||
|
||||
const fromDisplayName = options.fromDisplayName
|
||||
? options.fromDisplayName
|
||||
: CONFIG.WEBSERVER.HOST
|
||||
: WEBSERVER.HOST
|
||||
|
||||
return this.transporter.sendMail({
|
||||
from: `"${fromDisplayName}" <${CONFIG.SMTP.FROM_ADDRESS}>`,
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { join } from 'path'
|
||||
import { FILES_CACHE, CONFIG } from '../../initializers'
|
||||
import { FILES_CACHE } from '../../initializers'
|
||||
import { VideoModel } from '../../models/video/video'
|
||||
import { VideoCaptionModel } from '../../models/video/video-caption'
|
||||
import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
type GetPathParam = { videoId: string, language: string }
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { join } from 'path'
|
||||
import { FILES_CACHE, CONFIG, STATIC_PATHS } from '../../initializers'
|
||||
import { FILES_CACHE, STATIC_PATHS } from '../../initializers'
|
||||
import { VideoModel } from '../../models/video/video'
|
||||
import { AbstractVideoStaticFileCache } from './abstract-video-static-file-cache'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
class VideosPreviewCache extends AbstractVideoStaticFileCache <string> {
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { VideoModel } from '../models/video/video'
|
||||
import { basename, dirname, join } from 'path'
|
||||
import { CONFIG, HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, sequelizeTypescript } from '../initializers'
|
||||
import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, sequelizeTypescript } from '../initializers'
|
||||
import { close, ensureDir, move, open, outputJSON, pathExists, read, readFile, remove, writeFile } from 'fs-extra'
|
||||
import { getVideoFileSize } from '../helpers/ffmpeg-utils'
|
||||
import { sha256 } from '../helpers/core-utils'
|
||||
|
@ -10,6 +10,7 @@ import { doRequest, doRequestAndSaveToFile } from '../helpers/requests'
|
|||
import { generateRandomString } from '../helpers/utils'
|
||||
import { flatten, uniq } from 'lodash'
|
||||
import { VideoFileModel } from '../models/video/video-file'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
async function updateStreamingPlaylistsInfohashesIfNeeded () {
|
||||
const playlistsToUpdate = await VideoStreamingPlaylistModel.listByIncorrectPeerVersion()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as Bull from 'bull'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { CONFIG, REMOTE_SCHEME, sequelizeTypescript } from '../../../initializers'
|
||||
import { REMOTE_SCHEME, sequelizeTypescript, WEBSERVER } from '../../../initializers'
|
||||
import { sendFollow } from '../../activitypub/send'
|
||||
import { sanitizeHost } from '../../../helpers/core-utils'
|
||||
import { loadActorUrlOrGetFromWebfinger } from '../../../helpers/webfinger'
|
||||
|
@ -23,7 +23,7 @@ async function processActivityPubFollow (job: Bull.Job) {
|
|||
logger.info('Processing ActivityPub follow in job %d.', job.id)
|
||||
|
||||
let targetActor: ActorModel
|
||||
if (!host || host === CONFIG.WEBSERVER.HOST) {
|
||||
if (!host || host === WEBSERVER.HOST) {
|
||||
targetActor = await ActorModel.loadLocalByName(payload.name)
|
||||
} else {
|
||||
const sanitizedHost = sanitizeHost(host, REMOTE_SCHEME.HTTP)
|
||||
|
|
|
@ -6,7 +6,7 @@ import { VideoImportState } from '../../../../shared/models/videos'
|
|||
import { getDurationFromVideoFile, getVideoFileFPS, getVideoFileResolution } from '../../../helpers/ffmpeg-utils'
|
||||
import { extname, join } from 'path'
|
||||
import { VideoFileModel } from '../../../models/video/video-file'
|
||||
import { CONFIG, PREVIEWS_SIZE, sequelizeTypescript, THUMBNAILS_SIZE, VIDEO_IMPORT_TIMEOUT } from '../../../initializers'
|
||||
import { PREVIEWS_SIZE, sequelizeTypescript, THUMBNAILS_SIZE, VIDEO_IMPORT_TIMEOUT } from '../../../initializers'
|
||||
import { downloadImage } from '../../../helpers/requests'
|
||||
import { VideoState } from '../../../../shared'
|
||||
import { JobQueue } from '../index'
|
||||
|
@ -14,8 +14,9 @@ import { federateVideoIfNeeded } from '../../activitypub'
|
|||
import { VideoModel } from '../../../models/video/video'
|
||||
import { downloadWebTorrentVideo } from '../../../helpers/webtorrent'
|
||||
import { getSecureTorrentName } from '../../../helpers/utils'
|
||||
import { remove, move, stat } from 'fs-extra'
|
||||
import { move, remove, stat } from 'fs-extra'
|
||||
import { Notifier } from '../../notifier'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
type VideoImportYoutubeDLPayload = {
|
||||
type: 'youtube-dl'
|
||||
|
|
|
@ -5,11 +5,12 @@ import { VideoModel } from '../../../models/video/video'
|
|||
import { JobQueue } from '../job-queue'
|
||||
import { federateVideoIfNeeded } from '../../activitypub'
|
||||
import { retryTransactionWrapper } from '../../../helpers/database-utils'
|
||||
import { CONFIG, sequelizeTypescript } from '../../../initializers'
|
||||
import { sequelizeTypescript } from '../../../initializers'
|
||||
import * as Bluebird from 'bluebird'
|
||||
import { computeResolutionsToTranscode } from '../../../helpers/ffmpeg-utils'
|
||||
import { generateHlsPlaylist, optimizeVideofile, transcodeOriginalVideofile } from '../../video-transcoding'
|
||||
import { Notifier } from '../../notifier'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
export type VideoTranscodingPayload = {
|
||||
videoUUID: string
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as Bull from 'bull'
|
|||
import { JobState, JobType } from '../../../shared/models'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { Redis } from '../redis'
|
||||
import { CONFIG, JOB_ATTEMPTS, JOB_COMPLETED_LIFETIME, JOB_CONCURRENCY, JOB_TTL, REPEAT_JOBS } from '../../initializers'
|
||||
import { JOB_ATTEMPTS, JOB_COMPLETED_LIFETIME, JOB_CONCURRENCY, JOB_TTL, REPEAT_JOBS, WEBSERVER } from '../../initializers'
|
||||
import { ActivitypubHttpBroadcastPayload, processActivityPubHttpBroadcast } from './handlers/activitypub-http-broadcast'
|
||||
import { ActivitypubHttpFetcherPayload, processActivityPubHttpFetcher } from './handlers/activitypub-http-fetcher'
|
||||
import { ActivitypubHttpUnicastPayload, processActivityPubHttpUnicast } from './handlers/activitypub-http-unicast'
|
||||
|
@ -68,7 +68,7 @@ class JobQueue {
|
|||
if (this.initialized === true) return
|
||||
this.initialized = true
|
||||
|
||||
this.jobRedisPrefix = 'bull-' + CONFIG.WEBSERVER.HOST
|
||||
this.jobRedisPrefix = 'bull-' + WEBSERVER.HOST
|
||||
const queueOptions = {
|
||||
prefix: this.jobRedisPrefix,
|
||||
redis: Redis.getRedisClient(),
|
||||
|
|
|
@ -6,7 +6,7 @@ import { UserNotificationModel } from '../models/account/user-notification'
|
|||
import { VideoCommentModel } from '../models/video/video-comment'
|
||||
import { UserModel } from '../models/account/user'
|
||||
import { PeerTubeSocket } from './peertube-socket'
|
||||
import { CONFIG } from '../initializers/constants'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
import { VideoPrivacy, VideoState } from '../../shared/models/videos'
|
||||
import { VideoAbuseModel } from '../models/video/video-abuse'
|
||||
import { VideoBlacklistModel } from '../models/video/video-blacklist'
|
||||
|
|
|
@ -4,8 +4,9 @@ import { logger } from '../helpers/logger'
|
|||
import { UserModel } from '../models/account/user'
|
||||
import { OAuthClientModel } from '../models/oauth/oauth-client'
|
||||
import { OAuthTokenModel } from '../models/oauth/oauth-token'
|
||||
import { CONFIG, CACHE } from '../initializers/constants'
|
||||
import { CACHE } from '../initializers/constants'
|
||||
import { Transaction } from 'sequelize'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
type TokenInfo = { accessToken: string, refreshToken: string, accessTokenExpiresAt: Date, refreshTokenExpiresAt: Date }
|
||||
let accessTokenCache: { [ accessToken: string ]: OAuthTokenModel } = {}
|
||||
|
|
|
@ -3,12 +3,13 @@ import { createClient, RedisClient } from 'redis'
|
|||
import { logger } from '../helpers/logger'
|
||||
import { generateRandomString } from '../helpers/utils'
|
||||
import {
|
||||
CONFIG,
|
||||
CONTACT_FORM_LIFETIME,
|
||||
USER_EMAIL_VERIFY_LIFETIME,
|
||||
USER_PASSWORD_RESET_LIFETIME,
|
||||
VIDEO_VIEW_LIFETIME
|
||||
VIDEO_VIEW_LIFETIME,
|
||||
WEBSERVER
|
||||
} from '../initializers'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
type CachedRoute = {
|
||||
body: string,
|
||||
|
@ -41,7 +42,7 @@ class Redis {
|
|||
this.client.auth(CONFIG.REDIS.AUTH)
|
||||
}
|
||||
|
||||
this.prefix = 'redis-' + CONFIG.WEBSERVER.HOST + '-'
|
||||
this.prefix = 'redis-' + WEBSERVER.HOST + '-'
|
||||
}
|
||||
|
||||
static getRedisClient () {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { AbstractScheduler } from './abstract-scheduler'
|
||||
import { CONFIG, HLS_REDUNDANCY_DIRECTORY, REDUNDANCY, VIDEO_IMPORT_TIMEOUT } from '../../initializers'
|
||||
import { HLS_REDUNDANCY_DIRECTORY, REDUNDANCY, VIDEO_IMPORT_TIMEOUT, WEBSERVER } from '../../initializers'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { VideosRedundancy } from '../../../shared/models/redundancy'
|
||||
import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy'
|
||||
|
@ -15,6 +15,7 @@ import { getOrCreateVideoAndAccountAndChannel } from '../activitypub'
|
|||
import { VideoStreamingPlaylistModel } from '../../models/video/video-streaming-playlist'
|
||||
import { VideoModel } from '../../models/video/video'
|
||||
import { downloadPlaylistSegments } from '../hls'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
type CandidateToDuplicate = {
|
||||
redundancy: VideosRedundancy,
|
||||
|
@ -186,7 +187,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
|
|||
const createdModel = await VideoRedundancyModel.create({
|
||||
expiresOn: this.buildNewExpiration(redundancy.minLifetime),
|
||||
url: getVideoCacheFileActivityPubUrl(file),
|
||||
fileUrl: video.getVideoRedundancyUrl(file, CONFIG.WEBSERVER.URL),
|
||||
fileUrl: video.getVideoRedundancyUrl(file, WEBSERVER.URL),
|
||||
strategy: redundancy.strategy,
|
||||
videoFileId: file.id,
|
||||
actorId: serverActor.id
|
||||
|
@ -212,7 +213,7 @@ export class VideosRedundancyScheduler extends AbstractScheduler {
|
|||
const createdModel = await VideoRedundancyModel.create({
|
||||
expiresOn: this.buildNewExpiration(redundancy.minLifetime),
|
||||
url: getVideoCacheStreamingPlaylistActivityPubUrl(video, playlist),
|
||||
fileUrl: playlist.getVideoRedundancyUrl(CONFIG.WEBSERVER.URL),
|
||||
fileUrl: playlist.getVideoRedundancyUrl(WEBSERVER.URL),
|
||||
strategy: redundancy.strategy,
|
||||
videoStreamingPlaylistId: playlist.id,
|
||||
actorId: serverActor.id
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as sequelize from 'sequelize'
|
||||
import { CONFIG } from '../initializers/constants'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
import { VideoBlacklistType, UserRight } from '../../shared/models'
|
||||
import { VideoBlacklistModel } from '../models/video/video-blacklist'
|
||||
import { UserModel } from '../models/account/user'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { CONFIG, HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION } from '../initializers'
|
||||
import { HLS_STREAMING_PLAYLIST_DIRECTORY, P2P_MEDIA_LOADER_PEER_VERSION, WEBSERVER } from '../initializers'
|
||||
import { join } from 'path'
|
||||
import { getVideoFileFPS, transcode } from '../helpers/ffmpeg-utils'
|
||||
import { ensureDir, move, remove, stat } from 'fs-extra'
|
||||
|
@ -9,6 +9,7 @@ import { VideoModel } from '../models/video/video'
|
|||
import { updateMasterHLSPlaylist, updateSha256Segments } from './hls'
|
||||
import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist'
|
||||
import { VideoStreamingPlaylistType } from '../../shared/models/videos/video-streaming-playlist.type'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
async function optimizeVideofile (video: VideoModel, inputVideoFileArg?: VideoFileModel) {
|
||||
const videosDirectory = CONFIG.STORAGE.VIDEOS_DIR
|
||||
|
@ -111,12 +112,12 @@ async function generateHlsPlaylist (video: VideoModel, resolution: VideoResoluti
|
|||
await updateMasterHLSPlaylist(video)
|
||||
await updateSha256Segments(video)
|
||||
|
||||
const playlistUrl = CONFIG.WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsMasterPlaylistStaticPath(video.uuid)
|
||||
const playlistUrl = WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsMasterPlaylistStaticPath(video.uuid)
|
||||
|
||||
await VideoStreamingPlaylistModel.upsert({
|
||||
videoId: video.id,
|
||||
playlistUrl,
|
||||
segmentsSha256Url: CONFIG.WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsSha256SegmentsStaticPath(video.uuid),
|
||||
segmentsSha256Url: WEBSERVER.URL + VideoStreamingPlaylistModel.getHlsSha256SegmentsStaticPath(video.uuid),
|
||||
p2pMediaLoaderInfohashes: VideoStreamingPlaylistModel.buildP2PMediaLoaderInfoHashes(playlistUrl, video.VideoFiles),
|
||||
p2pMediaLoaderPeerVersion: P2P_MEDIA_LOADER_PEER_VERSION,
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as helmet from 'helmet'
|
||||
import { CONFIG } from '../initializers/constants'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
||||
const baseDirectives = Object.assign({},
|
||||
{
|
||||
|
|
|
@ -3,13 +3,12 @@ import * as express from 'express'
|
|||
import { logger } from '../../helpers/logger'
|
||||
import { areValidationErrors } from './utils'
|
||||
import { doesAccountNameWithHostExist } from '../../helpers/custom-validators/accounts'
|
||||
import { UserModel } from '../../models/account/user'
|
||||
import { AccountBlocklistModel } from '../../models/account/account-blocklist'
|
||||
import { isHostValid } from '../../helpers/custom-validators/servers'
|
||||
import { ServerBlocklistModel } from '../../models/server/server-blocklist'
|
||||
import { ServerModel } from '../../models/server/server'
|
||||
import { CONFIG } from '../../initializers'
|
||||
import { getServerActor } from '../../helpers/utils'
|
||||
import { WEBSERVER } from '../../initializers/constants'
|
||||
|
||||
const blockAccountValidator = [
|
||||
body('accountName').exists().withMessage('Should have an account name with host'),
|
||||
|
@ -79,7 +78,7 @@ const blockServerValidator = [
|
|||
|
||||
const host: string = req.body.host
|
||||
|
||||
if (host === CONFIG.WEBSERVER.HOST) {
|
||||
if (host === WEBSERVER.HOST) {
|
||||
return res.status(409)
|
||||
.send({ error: 'You cannot block your own server.' })
|
||||
.end()
|
||||
|
|
|
@ -4,7 +4,7 @@ import { isTestInstance } from '../../helpers/core-utils'
|
|||
import { isEachUniqueHostValid, isHostValid } from '../../helpers/custom-validators/servers'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { getServerActor } from '../../helpers/utils'
|
||||
import { CONFIG, SERVER_ACTOR_NAME } from '../../initializers'
|
||||
import { SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers'
|
||||
import { ActorFollowModel } from '../../models/activitypub/actor-follow'
|
||||
import { areValidationErrors } from './utils'
|
||||
import { ActorModel } from '../../models/activitypub/actor'
|
||||
|
@ -16,7 +16,7 @@ const followValidator = [
|
|||
|
||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
// Force https if the administrator wants to make friends
|
||||
if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') {
|
||||
if (isTestInstance() === false && WEBSERVER.SCHEME === 'http') {
|
||||
return res.status(500)
|
||||
.json({
|
||||
error: 'Cannot follow on a non HTTPS web server.'
|
||||
|
|
|
@ -5,10 +5,10 @@ import { isTestInstance } from '../../helpers/core-utils'
|
|||
import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc'
|
||||
import { doesVideoExist } from '../../helpers/custom-validators/videos'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { CONFIG } from '../../initializers'
|
||||
import { areValidationErrors } from './utils'
|
||||
import { WEBSERVER } from '../../initializers/constants'
|
||||
|
||||
const urlShouldStartWith = CONFIG.WEBSERVER.SCHEME + '://' + join(CONFIG.WEBSERVER.HOST, 'videos', 'watch') + '/'
|
||||
const urlShouldStartWith = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch') + '/'
|
||||
const videoWatchRegex = new RegExp('([^/]+)$')
|
||||
const isURLOptions = {
|
||||
require_host: true,
|
||||
|
|
|
@ -7,7 +7,7 @@ import { body } from 'express-validator/check'
|
|||
import { isUserDisplayNameValid } from '../../helpers/custom-validators/users'
|
||||
import { Emailer } from '../../lib/emailer'
|
||||
import { Redis } from '../../lib/redis'
|
||||
import { CONFIG } from '../../initializers/constants'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
const serverGetValidator = [
|
||||
body('host').custom(isHostValid).withMessage('Should have a valid host'),
|
||||
|
|
|
@ -5,8 +5,8 @@ import { logger } from '../../helpers/logger'
|
|||
import { areValidationErrors } from './utils'
|
||||
import { ActorFollowModel } from '../../models/activitypub/actor-follow'
|
||||
import { areValidActorHandles, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor'
|
||||
import { CONFIG } from '../../initializers'
|
||||
import { toArray } from '../../helpers/custom-validators/misc'
|
||||
import { WEBSERVER } from '../../initializers/constants'
|
||||
|
||||
const userSubscriptionAddValidator = [
|
||||
body('uri').custom(isValidActorHandle).withMessage('Should have a valid URI to follow (username@domain)'),
|
||||
|
@ -43,7 +43,7 @@ const userSubscriptionGetValidator = [
|
|||
if (areValidationErrors(req, res)) return
|
||||
|
||||
let [ name, host ] = req.params.uri.split('@')
|
||||
if (host === CONFIG.WEBSERVER.HOST) host = null
|
||||
if (host === WEBSERVER.HOST) host = null
|
||||
|
||||
const user = res.locals.oauth.token.User
|
||||
const subscription = await ActorFollowModel.loadByActorAndTargetNameAndHostForAPI(user.Account.Actor.id, name, host)
|
||||
|
|
|
@ -7,7 +7,7 @@ import { getCommonVideoEditAttributes } from './videos'
|
|||
import { isVideoImportTargetUrlValid, isVideoImportTorrentFile } from '../../../helpers/custom-validators/video-imports'
|
||||
import { cleanUpReqFiles } from '../../../helpers/express-utils'
|
||||
import { doesVideoChannelOfAccountExist, isVideoMagnetUriValid, isVideoNameValid } from '../../../helpers/custom-validators/videos'
|
||||
import { CONFIG } from '../../../initializers/constants'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
import { CONSTRAINTS_FIELDS } from '../../../initializers'
|
||||
|
||||
const videoImportAddValidator = getCommonVideoEditAttributes().concat([
|
||||
|
|
|
@ -32,7 +32,7 @@ import {
|
|||
} from '../../../helpers/custom-validators/videos'
|
||||
import { getDurationFromVideoFile } from '../../../helpers/ffmpeg-utils'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { CONFIG, CONSTRAINTS_FIELDS } from '../../../initializers'
|
||||
import { CONSTRAINTS_FIELDS } from '../../../initializers'
|
||||
import { authenticatePromiseIfNeeded } from '../../oauth'
|
||||
import { areValidationErrors } from '../utils'
|
||||
import { cleanUpReqFiles } from '../../../helpers/express-utils'
|
||||
|
@ -43,6 +43,7 @@ import { AccountModel } from '../../../models/account/account'
|
|||
import { VideoFetchType } from '../../../helpers/video'
|
||||
import { isNSFWQueryValid, isNumberArray, isStringArray } from '../../../helpers/custom-validators/search'
|
||||
import { getServerActor } from '../../../helpers/utils'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
|
||||
const videosAddValidator = getCommonVideoEditAttributes().concat([
|
||||
body('videofile')
|
||||
|
|
|
@ -25,9 +25,9 @@ import { getSort, throwIfNotValid } from '../utils'
|
|||
import { VideoChannelModel } from '../video/video-channel'
|
||||
import { VideoCommentModel } from '../video/video-comment'
|
||||
import { UserModel } from './user'
|
||||
import { CONFIG } from '../../initializers'
|
||||
import { AvatarModel } from '../avatar/avatar'
|
||||
import { VideoPlaylistModel } from '../video/video-playlist'
|
||||
import { WEBSERVER } from '../../initializers/constants'
|
||||
|
||||
export enum ScopeNames {
|
||||
SUMMARY = 'SUMMARY'
|
||||
|
@ -199,7 +199,7 @@ export class AccountModel extends Model<AccountModel> {
|
|||
static loadByNameWithHost (nameWithHost: string) {
|
||||
const [ accountName, host ] = nameWithHost.split('@')
|
||||
|
||||
if (!host || host === CONFIG.WEBSERVER.HOST) return AccountModel.loadLocalByName(accountName)
|
||||
if (!host || host === WEBSERVER.HOST) return AccountModel.loadLocalByName(accountName)
|
||||
|
||||
return AccountModel.loadByNameAndHost(accountName, host)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import {
|
|||
isActorPublicKeyValid
|
||||
} from '../../helpers/custom-validators/activitypub/actor'
|
||||
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
|
||||
import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONFIG, CONSTRAINTS_FIELDS } from '../../initializers'
|
||||
import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers'
|
||||
import { AccountModel } from '../account/account'
|
||||
import { AvatarModel } from '../avatar/avatar'
|
||||
import { ServerModel } from '../server/server'
|
||||
|
@ -516,7 +516,7 @@ export class ActorModel extends Model<ActorModel> {
|
|||
}
|
||||
|
||||
getHost () {
|
||||
return this.Server ? this.Server.host : CONFIG.WEBSERVER.HOST
|
||||
return this.Server ? this.Server.host : WEBSERVER.HOST
|
||||
}
|
||||
|
||||
getRedundancyAllowed () {
|
||||
|
@ -526,7 +526,7 @@ export class ActorModel extends Model<ActorModel> {
|
|||
getAvatarUrl () {
|
||||
if (!this.avatarId) return undefined
|
||||
|
||||
return CONFIG.WEBSERVER.URL + this.Avatar.getWebserverPath()
|
||||
return WEBSERVER.URL + this.Avatar.getWebserverPath()
|
||||
}
|
||||
|
||||
isOutdated () {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { join } from 'path'
|
||||
import { AfterDestroy, AllowNull, Column, CreatedAt, Model, Table, UpdatedAt } from 'sequelize-typescript'
|
||||
import { Avatar } from '../../../shared/models/avatars/avatar.model'
|
||||
import { CONFIG, STATIC_PATHS } from '../../initializers'
|
||||
import { STATIC_PATHS } from '../../initializers'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { remove } from 'fs-extra'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
@Table({
|
||||
tableName: 'avatar'
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
import { ActorModel } from '../activitypub/actor'
|
||||
import { getVideoSort, throwIfNotValid } from '../utils'
|
||||
import { isActivityPubUrlValid, isUrlValid } from '../../helpers/custom-validators/activitypub/misc'
|
||||
import { CONFIG, CONSTRAINTS_FIELDS, MIMETYPES } from '../../initializers'
|
||||
import { CONSTRAINTS_FIELDS, MIMETYPES } from '../../initializers'
|
||||
import { VideoFileModel } from '../video/video-file'
|
||||
import { getServerActor } from '../../helpers/utils'
|
||||
import { VideoModel } from '../video/video'
|
||||
|
@ -29,6 +29,7 @@ import { isTestInstance } from '../../helpers/core-utils'
|
|||
import * as Bluebird from 'bluebird'
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { VideoStreamingPlaylistModel } from '../video/video-streaming-playlist'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
export enum ScopeNames {
|
||||
WITH_VIDEO = 'WITH_VIDEO'
|
||||
|
|
|
@ -16,10 +16,11 @@ import { throwIfNotValid } from '../utils'
|
|||
import { VideoModel } from './video'
|
||||
import { isVideoCaptionLanguageValid } from '../../helpers/custom-validators/video-captions'
|
||||
import { VideoCaption } from '../../../shared/models/videos/caption/video-caption.model'
|
||||
import { CONFIG, STATIC_PATHS, VIDEO_LANGUAGES } from '../../initializers'
|
||||
import { STATIC_PATHS, VIDEO_LANGUAGES } from '../../initializers'
|
||||
import { join } from 'path'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { remove } from 'fs-extra'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
export enum ScopeNames {
|
||||
WITH_VIDEO_UUID_AND_REMOTE = 'WITH_VIDEO_UUID_AND_REMOTE'
|
||||
|
|
|
@ -8,7 +8,8 @@ import {
|
|||
Default,
|
||||
DefaultScope,
|
||||
ForeignKey,
|
||||
HasMany, IFindOptions,
|
||||
HasMany,
|
||||
IFindOptions,
|
||||
Is,
|
||||
Model,
|
||||
Scopes,
|
||||
|
@ -28,7 +29,7 @@ import { AccountModel, ScopeNames as AccountModelScopeNames } from '../account/a
|
|||
import { ActorModel, unusedActorAttributesForAPI } from '../activitypub/actor'
|
||||
import { buildServerIdsFollowedBy, buildTrigramSearchIndex, createSimilarityAttribute, getSort, throwIfNotValid } from '../utils'
|
||||
import { VideoModel } from './video'
|
||||
import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers'
|
||||
import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers'
|
||||
import { ServerModel } from '../server/server'
|
||||
import { DefineIndexesOptions } from 'sequelize'
|
||||
import { AvatarModel } from '../avatar/avatar'
|
||||
|
@ -419,7 +420,7 @@ export class VideoChannelModel extends Model<VideoChannelModel> {
|
|||
static loadByNameWithHostAndPopulateAccount (nameWithHost: string) {
|
||||
const [ name, host ] = nameWithHost.split('@')
|
||||
|
||||
if (!host || host === CONFIG.WEBSERVER.HOST) return VideoChannelModel.loadLocalByNameAndPopulateAccount(name)
|
||||
if (!host || host === WEBSERVER.HOST) return VideoChannelModel.loadLocalByNameAndPopulateAccount(name)
|
||||
|
||||
return VideoChannelModel.loadByNameAndHostAndPopulateAccount(name, host)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import { ActivityTagObject } from '../../../shared/models/activitypub/objects/co
|
|||
import { VideoCommentObject } from '../../../shared/models/activitypub/objects/video-comment-object'
|
||||
import { VideoComment } from '../../../shared/models/videos/video-comment.model'
|
||||
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
|
||||
import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers'
|
||||
import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers'
|
||||
import { sendDeleteVideoComment } from '../../lib/activitypub/send'
|
||||
import { AccountModel } from '../account/account'
|
||||
import { ActorModel } from '../activitypub/actor'
|
||||
|
@ -482,7 +482,7 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
|
|||
let result: string[] = []
|
||||
|
||||
const localMention = `@(${actorNameAlphabet}+)`
|
||||
const remoteMention = `${localMention}@${CONFIG.WEBSERVER.HOST}`
|
||||
const remoteMention = `${localMention}@${WEBSERVER.HOST}`
|
||||
|
||||
const mentionRegex = this.isOwned()
|
||||
? '(?:(?:' + remoteMention + ')|(?:' + localMention + '))' // Include local mentions?
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
ActivityUrlObject,
|
||||
VideoTorrentObject
|
||||
} from '../../../shared/models/activitypub/objects'
|
||||
import { CONFIG, MIMETYPES, THUMBNAILS_SIZE } from '../../initializers'
|
||||
import { MIMETYPES, THUMBNAILS_SIZE, WEBSERVER } from '../../initializers'
|
||||
import { VideoCaptionModel } from './video-caption'
|
||||
import {
|
||||
getVideoCommentsActivityPubUrl,
|
||||
|
@ -290,7 +290,7 @@ function videoModelToActivityPubObject (video: VideoModel): VideoTorrentObject {
|
|||
type: 'Link',
|
||||
mimeType: 'text/html',
|
||||
mediaType: 'text/html',
|
||||
href: CONFIG.WEBSERVER.URL + '/videos/watch/' + video.uuid
|
||||
href: WEBSERVER.URL + '/videos/watch/' + video.uuid
|
||||
})
|
||||
|
||||
const subtitleLanguage = []
|
||||
|
|
|
@ -26,12 +26,12 @@ import {
|
|||
import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc'
|
||||
import {
|
||||
ACTIVITY_PUB,
|
||||
CONFIG,
|
||||
CONSTRAINTS_FIELDS,
|
||||
STATIC_PATHS,
|
||||
THUMBNAILS_SIZE,
|
||||
VIDEO_PLAYLIST_PRIVACIES,
|
||||
VIDEO_PLAYLIST_TYPES
|
||||
VIDEO_PLAYLIST_TYPES,
|
||||
WEBSERVER
|
||||
} from '../../initializers'
|
||||
import { VideoPlaylist } from '../../../shared/models/videos/playlist/video-playlist.model'
|
||||
import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account'
|
||||
|
@ -43,6 +43,7 @@ import { activityPubCollectionPagination } from '../../helpers/activitypub'
|
|||
import { remove } from 'fs-extra'
|
||||
import { logger } from '../../helpers/logger'
|
||||
import { VideoPlaylistType } from '../../../shared/models/videos/playlist/video-playlist-type.model'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
enum ScopeNames {
|
||||
AVAILABLE_FOR_LIST = 'AVAILABLE_FOR_LIST',
|
||||
|
@ -417,7 +418,7 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
|
|||
}
|
||||
|
||||
getThumbnailUrl () {
|
||||
return CONFIG.WEBSERVER.URL + STATIC_PATHS.THUMBNAILS + this.getThumbnailName()
|
||||
return WEBSERVER.URL + STATIC_PATHS.THUMBNAILS + this.getThumbnailName()
|
||||
}
|
||||
|
||||
getThumbnailStaticPath () {
|
||||
|
|
|
@ -51,10 +51,9 @@ import { getServerActor } from '../../helpers/utils'
|
|||
import {
|
||||
ACTIVITY_PUB,
|
||||
API_VERSION,
|
||||
CONFIG,
|
||||
CONSTRAINTS_FIELDS,
|
||||
HLS_STREAMING_PLAYLIST_DIRECTORY,
|
||||
HLS_REDUNDANCY_DIRECTORY,
|
||||
HLS_STREAMING_PLAYLIST_DIRECTORY,
|
||||
PREVIEWS_SIZE,
|
||||
REMOTE_SCHEME,
|
||||
STATIC_DOWNLOAD_PATHS,
|
||||
|
@ -64,7 +63,8 @@ import {
|
|||
VIDEO_LANGUAGES,
|
||||
VIDEO_LICENCES,
|
||||
VIDEO_PRIVACIES,
|
||||
VIDEO_STATES
|
||||
VIDEO_STATES,
|
||||
WEBSERVER
|
||||
} from '../../initializers'
|
||||
import { sendDeleteVideo } from '../../lib/activitypub/send'
|
||||
import { AccountModel } from '../account/account'
|
||||
|
@ -77,12 +77,13 @@ import {
|
|||
buildTrigramSearchIndex,
|
||||
buildWhereIdOrUUID,
|
||||
createSimilarityAttribute,
|
||||
getVideoSort, isOutdated,
|
||||
getVideoSort,
|
||||
isOutdated,
|
||||
throwIfNotValid
|
||||
} from '../utils'
|
||||
import { TagModel } from './tag'
|
||||
import { VideoAbuseModel } from './video-abuse'
|
||||
import { VideoChannelModel, ScopeNames as VideoChannelScopeNames } from './video-channel'
|
||||
import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel'
|
||||
import { VideoCommentModel } from './video-comment'
|
||||
import { VideoFileModel } from './video-file'
|
||||
import { VideoShareModel } from './video-share'
|
||||
|
@ -105,6 +106,7 @@ import { UserModel } from '../account/user'
|
|||
import { VideoImportModel } from './video-import'
|
||||
import { VideoStreamingPlaylistModel } from './video-streaming-playlist'
|
||||
import { VideoPlaylistElementModel } from './video-playlist-element'
|
||||
import { CONFIG } from '../../initializers/config'
|
||||
|
||||
// FIXME: Define indexes here because there is an issue with TS and Sequelize.literal when called directly in the annotation
|
||||
const indexes: Sequelize.DefineIndexesOptions[] = [
|
||||
|
@ -1664,10 +1666,10 @@ export class VideoModel extends Model<VideoModel> {
|
|||
name: `${this.name} ${videoFile.resolution}p${videoFile.extname}`,
|
||||
createdBy: 'PeerTube',
|
||||
announceList: [
|
||||
[ CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT + '/tracker/socket' ],
|
||||
[ CONFIG.WEBSERVER.URL + '/tracker/announce' ]
|
||||
[ WEBSERVER.WS + '://' + WEBSERVER.HOSTNAME + ':' + WEBSERVER.PORT + '/tracker/socket' ],
|
||||
[ WEBSERVER.URL + '/tracker/announce' ]
|
||||
],
|
||||
urlList: [ CONFIG.WEBSERVER.URL + STATIC_PATHS.WEBSEED + this.getVideoFilename(videoFile) ]
|
||||
urlList: [ WEBSERVER.URL + STATIC_PATHS.WEBSEED + this.getVideoFilename(videoFile) ]
|
||||
}
|
||||
|
||||
const torrent = await createTorrentPromise(this.getVideoFilePath(videoFile), options)
|
||||
|
@ -1781,8 +1783,8 @@ export class VideoModel extends Model<VideoModel> {
|
|||
let baseUrlWs
|
||||
|
||||
if (this.isOwned()) {
|
||||
baseUrlHttp = CONFIG.WEBSERVER.URL
|
||||
baseUrlWs = CONFIG.WEBSERVER.WS + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
|
||||
baseUrlHttp = WEBSERVER.URL
|
||||
baseUrlWs = WEBSERVER.WS + '://' + WEBSERVER.HOSTNAME + ':' + WEBSERVER.PORT
|
||||
} else {
|
||||
baseUrlHttp = REMOTE_SCHEME.HTTP + '://' + this.VideoChannel.Account.Actor.Server.host
|
||||
baseUrlWs = REMOTE_SCHEME.WS + '://' + this.VideoChannel.Account.Actor.Server.host
|
||||
|
|
Loading…
Reference in a new issue