"@types/async": "^3.0.0",
"@types/async-lock": "^1.1.0",
"@types/bcrypt": "^5.0.0",
+ "@types/bencode": "^2.0.0",
"@types/bluebird": "^3.5.33",
"@types/body-parser": "^1.16.3",
"@types/bull": "^3.15.0",
"@types/chai-json-schema": "^1.4.3",
"@types/chai-xml": "^0.3.1",
"@types/config": "^0.0.39",
+ "@types/create-torrent": "^5.0.0",
"@types/express": "4.17.9",
"@types/express-rate-limit": "^5.0.0",
"@types/fluent-ffmpeg": "^2.1.16",
import { pathExists, stat, writeFile } from 'fs-extra'
import { createTorrentPromise } from '@server/helpers/webtorrent'
import { CONFIG } from '@server/initializers/config'
-import * as parseTorrent from 'parse-torrent'
+import parseTorrent from 'parse-torrent'
import { logger } from '@server/helpers/logger'
run()
registerTSPaths()
import { program } from 'commander'
-import * as ffmpeg from 'fluent-ffmpeg'
+import ffmpeg from 'fluent-ffmpeg'
import { buildx264VODCommand, runCommand, TranscodeOptions } from '@server/helpers/ffmpeg-utils'
import { exit } from 'process'
import { VideoTranscodingProfilesManager } from '@server/lib/transcoding/video-transcoding-profiles'
import { registerTSPaths } from '../server/helpers/register-ts-paths'
registerTSPaths()
-import * as prompt from 'prompt'
+import { start, get } from 'prompt'
import { join, basename } from 'path'
import { CONFIG } from '../server/initializers/config'
import { VideoModel } from '../server/models/video/video'
import { initDatabaseModels } from '../server/initializers/database'
import { readdir, remove, stat } from 'fs-extra'
import { VideoRedundancyModel } from '../server/models/redundancy/video-redundancy'
-import * as Bluebird from 'bluebird'
+import { map } from 'bluebird'
import { getUUIDFromFilename } from '../server/helpers/utils'
import { ThumbnailModel } from '../server/models/video/thumbnail'
import { ActorImageModel } from '../server/models/actor/actor-image'
const files = await readdir(directory)
const toDelete: string[] = []
- await Bluebird.map(files, async file => {
+ await map(files, async file => {
const filePath = join(directory, file)
if (await existFun(filePath) !== true) {
async function askConfirmation () {
return new Promise((res, rej) => {
- prompt.start()
+ start()
const schema = {
properties: {
confirm: {
}
}
}
- prompt.get(schema, function (err, result) {
+ get(schema, function (err, result) {
if (err) return rej(err)
return res(result.confirm?.match(/y/) !== null)
import { registerTSPaths } from '../server/helpers/register-ts-paths'
registerTSPaths()
-import * as Bluebird from 'bluebird'
+import { map } from 'bluebird'
import { program } from 'commander'
import { pathExists, remove } from 'fs-extra'
import { generateImageFilename, processImage } from '@server/helpers/image-utils'
const videos = await VideoModel.listLocal()
- await Bluebird.map(videos, v => {
+ await map(videos, v => {
return processVideo(v)
.catch(err => console.error('Cannot process video %s.', v.url, err))
}, { concurrency: 20 })
}
// ----------- Node modules -----------
-import * as express from 'express'
-import * as morgan from 'morgan'
-import * as cors from 'cors'
-import * as cookieParser from 'cookie-parser'
-import * as helmet from 'helmet'
-import * as useragent from 'useragent'
-import * as anonymize from 'ip-anonymize'
+import express from 'express'
+import morgan, { token } from 'morgan'
+import cors from 'cors'
+import cookieParser from 'cookie-parser'
+import { frameguard } from 'helmet'
+import { parse } from 'useragent'
+import anonymize from 'ip-anonymize'
import { program as cli } from 'commander'
process.title = 'peertube'
}
if (CONFIG.SECURITY.FRAMEGUARD.ENABLED) {
- app.use(helmet.frameguard({
+ app.use(frameguard({
action: 'deny' // we only allow it for /videos/embed, see server/controllers/client.ts
}))
}
}
// For the logger
-morgan.token('remote-addr', (req: express.Request) => {
+token('remote-addr', (req: express.Request) => {
if (CONFIG.LOG.ANONYMIZE_IP === true || req.get('DNT') === '1') {
return anonymize(req.ip, 16, 16)
}
return req.ip
})
-morgan.token('user-agent', (req: express.Request) => {
+token('user-agent', (req: express.Request) => {
if (req.get('DNT') === '1') {
- return useragent.parse(req.get('user-agent')).family
+ return parse(req.get('user-agent')).family
}
return req.get('user-agent')
-import * as cors from 'cors'
-import * as express from 'express'
+import cors from 'cors'
+import express from 'express'
import { getServerActor } from '@server/models/application/application'
import { MAccountId, MActorId, MChannelId, MVideoId } from '@server/types/models'
import { VideoPrivacy, VideoRateType } from '../../../shared/models/videos'
-import * as express from 'express'
+import express from 'express'
import { InboxManager } from '@server/lib/activitypub/inbox-manager'
import { Activity, ActivityPubCollection, ActivityPubOrderedCollection, RootActivity } from '../../../shared'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
-import * as express from 'express'
+import express from 'express'
import { activityPubClientRouter } from './client'
import { inboxRouter } from './inbox'
import { outboxRouter } from './outbox'
-import * as express from 'express'
+import express from 'express'
import { Activity } from '../../../shared/models/activitypub/activity'
import { VideoPrivacy } from '../../../shared/models/videos'
import { activityPubCollectionPagination, activityPubContextify } from '../../helpers/activitypub'
-import * as express from 'express'
+import express from 'express'
function activityPubResponse (data: any, res: express.Response) {
return res.type('application/activity+json; charset=utf-8')
-import * as express from 'express'
+import express from 'express'
import { logger } from '@server/helpers/logger'
import { createAccountAbuse, createVideoAbuse, createVideoCommentAbuse } from '@server/lib/moderation'
import { Notifier } from '@server/lib/notifier'
-import * as express from 'express'
+import express from 'express'
import { pickCommonVideoQuery } from '@server/helpers/query'
import { getServerActor } from '@server/models/application/application'
import { buildNSFWFilter, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
-import * as express from 'express'
+import express from 'express'
import { removeComment } from '@server/lib/video-comment'
import { bulkRemoveCommentsOfValidator } from '@server/middlewares/validators/bulk'
import { VideoCommentModel } from '@server/models/video/video-comment'
-import * as express from 'express'
+import express from 'express'
import { remove, writeJSON } from 'fs-extra'
import { snakeCase } from 'lodash'
import validator from 'validator'
-import * as express from 'express'
+import express from 'express'
import { ServerConfigManager } from '@server/lib/server-config-manager'
import { ActorCustomPageModel } from '@server/models/account/actor-custom-page'
import { HttpStatusCode, UserRight } from '@shared/models'
-import * as cors from 'cors'
-import * as express from 'express'
-import * as RateLimit from 'express-rate-limit'
+import cors from 'cors'
+import express from 'express'
+import RateLimit from 'express-rate-limit'
import { HttpStatusCode } from '../../../shared/models'
import { badRequest } from '../../helpers/express-utils'
import { CONFIG } from '../../initializers/config'
-import * as express from 'express'
+import express from 'express'
import { ResultList } from '../../../shared'
import { Job, JobState, JobType } from '../../../shared/models'
import { UserRight } from '../../../shared/models/users'
-import * as express from 'express'
+import express from 'express'
import { OAuthClientLocal } from '../../../shared'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { logger } from '../../helpers/logger'
-import * as express from 'express'
-import * as memoizee from 'memoizee'
+import express from 'express'
+import memoizee from 'memoizee'
import { logger } from '@server/helpers/logger'
import { Hooks } from '@server/lib/plugins/hooks'
import { VideoModel } from '@server/models/video/video'
-import * as express from 'express'
+import express from 'express'
import { logger } from '@server/helpers/logger'
import { getFormattedObjects } from '@server/helpers/utils'
import { listAvailablePluginsFromIndex } from '@server/lib/plugins/plugin-index'
-import * as express from 'express'
+import express from 'express'
import { searchChannelsRouter } from './search-video-channels'
import { searchPlaylistsRouter } from './search-video-playlists'
import { searchVideosRouter } from './search-videos'
-import * as express from 'express'
+import express from 'express'
import { sanitizeUrl } from '@server/helpers/core-utils'
import { pickSearchChannelQuery } from '@server/helpers/query'
import { doJSONRequest } from '@server/helpers/requests'
-import * as express from 'express'
+import express from 'express'
import { sanitizeUrl } from '@server/helpers/core-utils'
import { isUserAbleToSearchRemoteURI } from '@server/helpers/express-utils'
import { logger } from '@server/helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { sanitizeUrl } from '@server/helpers/core-utils'
import { pickSearchVideoQuery } from '@server/helpers/query'
import { doJSONRequest } from '@server/helpers/requests'
-import * as express from 'express'
+import express from 'express'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { ContactForm } from '../../../../shared/models/server'
import { Emailer } from '../../../lib/emailer'
-import * as express from 'express'
+import express from 'express'
import { InboxManager } from '@server/lib/activitypub/inbox-manager'
import { RemoveDanglingResumableUploadsScheduler } from '@server/lib/schedulers/remove-dangling-resumable-uploads-scheduler'
import { Debug, SendDebugCommand } from '@shared/models'
-import * as express from 'express'
+import express from 'express'
import { getServerActor } from '@server/models/application/application'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserRight } from '../../../../shared/models/users'
-import * as express from 'express'
+import express from 'express'
import { contactRouter } from './contact'
import { debugRouter } from './debug'
import { serverFollowsRouter } from './follows'
-import * as express from 'express'
+import express from 'express'
import { readdir, readFile } from 'fs-extra'
import { join } from 'path'
import { logger, mtimeSortFilesDesc } from '@server/helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { JobQueue } from '@server/lib/job-queue'
import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import 'multer'
-import * as express from 'express'
+import express from 'express'
import { logger } from '@server/helpers/logger'
import { getServerActor } from '@server/models/application/application'
import { UserNotificationModel } from '@server/models/user/user-notification'
-import * as express from 'express'
+import express from 'express'
import { StatsManager } from '@server/lib/stat-manager'
import { ROUTE_CACHE_LIFETIME } from '../../../initializers/constants'
import { asyncMiddleware } from '../../../middlewares'
-import * as express from 'express'
-import * as RateLimit from 'express-rate-limit'
+import express from 'express'
+import RateLimit from 'express-rate-limit'
import { tokensRouter } from '@server/controllers/api/users/token'
import { Hooks } from '@server/lib/plugins/hooks'
import { OAuthTokenModel } from '@server/models/oauth/oauth-token'
import 'multer'
-import * as express from 'express'
+import express from 'express'
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '@server/helpers/audit-logger'
import { Hooks } from '@server/lib/plugins/hooks'
import { AttributesOnly } from '@shared/core-utils'
-import * as express from 'express'
+import express from 'express'
import { AbuseModel } from '@server/models/abuse/abuse'
import {
abuseListForUserValidator,
import 'multer'
-import * as express from 'express'
+import express from 'express'
import { logger } from '@server/helpers/logger'
import { UserNotificationModel } from '@server/models/user/user-notification'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
-import * as express from 'express'
+import express from 'express'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { getFormattedObjects } from '../../../helpers/utils'
import { sequelizeTypescript } from '../../../initializers/database'
import 'multer'
-import * as express from 'express'
+import express from 'express'
import { UserNotificationModel } from '@server/models/user/user-notification'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { UserNotificationSetting } from '../../../../shared/models/users'
import 'multer'
-import * as express from 'express'
+import express from 'express'
import { pickCommonVideoQuery } from '@server/helpers/query'
import { sendUndoFollow } from '@server/lib/activitypub/send'
import { VideoChannelModel } from '@server/models/video/video-channel'
-import * as express from 'express'
+import express from 'express'
import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
import { asyncMiddleware, authenticate } from '../../../middlewares'
import { doVideosInPlaylistExistValidator } from '../../../middlewares/validators/videos/video-playlists'
-import * as express from 'express'
-import * as RateLimit from 'express-rate-limit'
+import express from 'express'
+import RateLimit from 'express-rate-limit'
import { logger } from '@server/helpers/logger'
import { buildUUID } from '@server/helpers/uuid'
import { CONFIG } from '@server/initializers/config'
-import * as express from 'express'
+import express from 'express'
import { pickCommonVideoQuery } from '@server/helpers/query'
import { Hooks } from '@server/lib/plugins/hooks'
import { getServerActor } from '@server/models/application/application'
-import * as express from 'express'
+import express from 'express'
import { join } from 'path'
import { uuidToShort } from '@server/helpers/uuid'
import { scheduleRefreshIfNeeded } from '@server/lib/activitypub/playlists'
-import * as express from 'express'
+import express from 'express'
import { blacklistVideo, unblacklistVideo } from '@server/lib/video-blacklist'
import { UserRight, VideoBlacklistCreate } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
-import * as express from 'express'
+import express from 'express'
import { MVideoCaption } from '@server/types/models'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { moveAndProcessCaptionFile } from '../../../helpers/captions-utils'
-import * as express from 'express'
+import express from 'express'
import { ResultList, ThreadsResultList, UserRight, VideoCommentCreate } from '../../../../shared/models'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { VideoCommentThreads } from '../../../../shared/models/videos/comment/video-comment.model'
-import * as express from 'express'
+import express from 'express'
import { move, readFile } from 'fs-extra'
-import * as magnetUtil from 'magnet-uri'
-import * as parseTorrent from 'parse-torrent'
+import { decode } from 'magnet-uri'
+import parseTorrent, { Instance } from 'parse-torrent'
import { join } from 'path'
import { ServerConfigManager } from '@server/lib/server-config-manager'
import { setVideoTags } from '@server/lib/video'
torrentfile.path = newTorrentPath
const buf = await readFile(torrentfile.path)
- const parsedTorrent = parseTorrent(buf) as parseTorrent.Instance
+ const parsedTorrent = parseTorrent(buf) as Instance
if (parsedTorrent.files.length !== 1) {
cleanUpReqFiles(req)
function processMagnetURI (body: VideoImportCreate) {
const magnetUri = body.magnetUri
- const parsed = magnetUtil.decode(magnetUri)
+ const parsed = decode(magnetUri)
return {
name: extractNameFromArray(parsed.name),
-import * as express from 'express'
+import express from 'express'
import toInt from 'validator/lib/toInt'
import { pickCommonVideoQuery } from '@server/helpers/query'
import { doJSONRequest } from '@server/helpers/requests'
-import * as express from 'express'
+import express from 'express'
import { createReqFiles } from '@server/helpers/express-utils'
import { buildUUID, uuidToShort } from '@server/helpers/uuid'
import { CONFIG } from '@server/initializers/config'
-import * as express from 'express'
+import express from 'express'
import { MVideoFullLight } from '@server/types/models'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { VideoChangeOwnershipStatus, VideoState } from '../../../../shared/models/videos'
-import * as express from 'express'
+import express from 'express'
import { UserVideoRateUpdate } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { logger } from '../../../helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { Transaction } from 'sequelize/types'
import { changeVideoChannelShare } from '@server/lib/activitypub/share'
import { buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video'
-import * as express from 'express'
+import express from 'express'
import { move } from 'fs-extra'
import { basename } from 'path'
import { getLowercaseExtension } from '@server/helpers/core-utils'
-import * as express from 'express'
+import express from 'express'
import { UserWatchingVideo } from '../../../../shared'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import {
-import * as express from 'express'
+import express from 'express'
import { truncate } from 'lodash'
import { SitemapStream, streamToPromise } from 'sitemap'
import { buildNSFWFilter } from '../helpers/express-utils'
-import * as express from 'express'
+import express from 'express'
import { constants, promises as fs } from 'fs'
import { readFile } from 'fs-extra'
import { join } from 'path'
-import * as cors from 'cors'
-import * as express from 'express'
+import cors from 'cors'
+import express from 'express'
import { logger } from '@server/helpers/logger'
import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
import { Hooks } from '@server/lib/plugins/hooks'
-import * as express from 'express'
-import * as Feed from 'pfeed'
+import express from 'express'
+import Feed from 'pfeed'
import { getCategoryLabel } from '@server/models/video/formatter/video-format-utils'
import { VideoFilter } from '../../shared/models/videos/video-query.type'
import { buildNSFWFilter } from '../helpers/express-utils'
-import * as cors from 'cors'
-import * as express from 'express'
+import cors from 'cors'
+import express from 'express'
import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { logger } from '../helpers/logger'
-import * as cors from 'cors'
-import * as express from 'express'
+import cors from 'cors'
+import express from 'express'
import { mapToJSON } from '@server/helpers/core-utils'
import { LiveSegmentShaStore } from '@server/lib/live'
import { HttpStatusCode } from '@shared/models'
-import * as express from 'express'
+import express from 'express'
import { join } from 'path'
import { logger } from '@server/helpers/logger'
import { optionalAuthenticate } from '@server/middlewares/auth'
-import * as express from 'express'
+import express from 'express'
import { EMBED_SIZE, PREVIEWS_SIZE, WEBSERVER, THUMBNAILS_SIZE } from '../initializers/constants'
import { asyncMiddleware, oembedValidator } from '../middlewares'
import { accountNameWithHostGetValidator } from '../middlewares/validators'
-import * as cors from 'cors'
-import * as express from 'express'
+import cors from 'cors'
+import express from 'express'
import { join } from 'path'
import { serveIndexHTML } from '@server/lib/client-html'
import { ServerConfigManager } from '@server/lib/server-config-manager'
-import * as bitTorrentTracker from 'bittorrent-tracker'
-import * as express from 'express'
-import * as http from 'http'
-import * as proxyAddr from 'proxy-addr'
+import { Server as TrackerServer } from 'bittorrent-tracker'
+import express from 'express'
+import { createServer } from 'http'
+import proxyAddr from 'proxy-addr'
import { Server as WebSocketServer } from 'ws'
import { Redis } from '@server/lib/redis'
import { logger } from '../helpers/logger'
import { VideoFileModel } from '../models/video/video-file'
import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist'
-const TrackerServer = bitTorrentTracker.Server
-
const trackerRouter = express.Router()
let peersIps = {}
trackerRouter.get('/tracker/scrape', (req, res) => onHttpRequest(req, res, { action: 'scrape' }))
function createWebsocketTrackerServer (app: express.Application) {
- const server = http.createServer(app)
+ const server = createServer(app)
const wss = new WebSocketServer({ noServer: true })
wss.on('connection', function (ws, req) {
-import * as cors from 'cors'
-import * as express from 'express'
+import cors from 'cors'
+import express from 'express'
import { WEBSERVER } from '@server/initializers/constants'
import { asyncMiddleware } from '../middlewares'
import { webfingerValidator } from '../middlewares/validators'
-import * as Bluebird from 'bluebird'
+import Bluebird from 'bluebird'
import { URL } from 'url'
import validator from 'validator'
import { ContextType } from '@shared/models/activitypub/context'
import { diff } from 'deep-object-diff'
-import * as express from 'express'
-import * as flatten from 'flat'
+import express from 'express'
+import flatten from 'flat'
import { chain } from 'lodash'
-import * as path from 'path'
-import * as winston from 'winston'
+import { join } from 'path'
+import { addColors, config, createLogger, format, transports } from 'winston'
import { AUDIT_LOG_FILENAME } from '@server/initializers/constants'
import { AdminAbuse, User, VideoChannel, VideoDetails, VideoImport } from '../../shared'
import { CustomConfig } from '../../shared/models/server/custom-config.model'
DELETE = 'delete'
}
-const colors = winston.config.npm.colors
-colors.audit = winston.config.npm.colors.info
+const colors = config.npm.colors
+colors.audit = config.npm.colors.info
-winston.addColors(colors)
+addColors(colors)
-const auditLogger = winston.createLogger({
+const auditLogger = createLogger({
levels: { audit: 0 },
transports: [
- new winston.transports.File({
- filename: path.join(CONFIG.STORAGE.LOG_DIR, AUDIT_LOG_FILENAME),
+ new transports.File({
+ filename: join(CONFIG.STORAGE.LOG_DIR, AUDIT_LOG_FILENAME),
level: 'audit',
maxsize: 5242880,
maxFiles: 5,
- format: winston.format.combine(
- winston.format.timestamp(),
+ format: format.combine(
+ format.timestamp(),
labelFormatter(),
- winston.format.splat(),
+ format.splat(),
jsonLoggerFormat
)
})
constructor (private readonly keysToKeep: string[], private readonly prefix: string, private readonly entityInfos: object) { }
toLogKeys (): object {
- return chain(flatten(this.entityInfos, { delimiter: '-', safe: true }))
+ return chain(flatten<object, any>(this.entityInfos, { delimiter: '-', safe: true }))
.pick(this.keysToKeep)
- .mapKeys((value, key) => `${this.prefix}-${key}`)
+ .mapKeys((_value, key) => `${this.prefix}-${key}`)
.value()
}
}
import { createReadStream, createWriteStream, move, remove } from 'fs-extra'
import { join } from 'path'
-import * as srt2vtt from 'srt-to-vtt'
+import srt2vtt from 'srt-to-vtt'
+import { Transform } from 'stream'
import { MVideoCaption } from '@server/types/models'
import { CONFIG } from '../initializers/config'
import { pipelinePromise } from './core-utils'
-import { Transform } from 'stream'
async function moveAndProcessCaptionFile (physicalFile: { filename: string, path: string }, videoCaption: MVideoCaption) {
const videoCaptionsDir = CONFIG.STORAGE.CAPTIONS_DIR
import { BinaryToTextEncoding, createHash, randomBytes } from 'crypto'
import { truncate } from 'lodash'
import { basename, extname, isAbsolute, join, resolve } from 'path'
-import * as pem from 'pem'
+import { createPrivateKey as createPrivateKey_1, getPublicKey as getPublicKey_1 } from 'pem'
import { pipeline } from 'stream'
import { URL } from 'url'
import { promisify } from 'util'
}
const randomBytesPromise = promisify1<number, Buffer>(randomBytes)
-const createPrivateKey = promisify1<number, { key: string }>(pem.createPrivateKey)
-const getPublicKey = promisify1<string, { publicKey: string }>(pem.getPublicKey)
+const createPrivateKey = promisify1<number, { key: string }>(createPrivateKey_1)
+const getPublicKey = promisify1<string, { publicKey: string }>(getPublicKey_1)
const execPromise2 = promisify2<string, any, string>(exec)
const execPromise = promisify1<string, string>(exec)
const pipelinePromise = promisify(pipeline)
-import * as AsyncLRU from 'async-lru'
-import * as jsonld from 'jsonld'
+import AsyncLRU from 'async-lru'
import { logger } from './logger'
+import jsonld = require('jsonld')
+
const CACHE = {
'https://w3id.org/security/v1': {
'@context': {
import { UploadFilesForCheck } from 'express'
import { values } from 'lodash'
-import * as magnetUtil from 'magnet-uri'
+import magnetUtil from 'magnet-uri'
import validator from 'validator'
import { VideoFilter, VideoPrivacy, VideoRateType } from '../../../shared'
import {
-import * as retry from 'async/retry'
-import * as Bluebird from 'bluebird'
+import retry from 'async/retry'
+import Bluebird from 'bluebird'
import { Transaction } from 'sequelize'
import { Model } from 'sequelize-typescript'
import { sequelizeTypescript } from '@server/initializers/database'
-import * as express from 'express'
-import * as multer from 'multer'
+import express from 'express'
+import multer, { diskStorage } from 'multer'
import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { CONFIG } from '../initializers/config'
import { REMOTE_SCHEME } from '../initializers/constants'
mimeTypes: { [id: string]: string | string[] },
destinations: { [fieldName: string]: string }
) {
- const storage = multer.diskStorage({
+ const storage = diskStorage({
destination: (req, file, cb) => {
cb(null, destinations[file.fieldname])
},
import { Job } from 'bull'
-import * as ffmpeg from 'fluent-ffmpeg'
+import ffmpeg, { FfmpegCommand, FilterSpecification, getAvailableEncoders } from 'fluent-ffmpeg'
import { readFile, remove, writeFile } from 'fs-extra'
import { dirname, join } from 'path'
import { FFMPEG_NICE, VIDEO_LIVE } from '@server/initializers/constants'
return supportedEncoders
}
- const getAvailableEncodersPromise = promisify0(ffmpeg.getAvailableEncoders)
+ const getAvailableEncodersPromise = promisify0(getAvailableEncoders)
const availableFFmpegEncoders = await getAvailableEncodersPromise()
const searchEncoders = new Set<string>()
| QuickTranscodeOptions
const builders: {
- [ type in TranscodeOptionsType ]: (c: ffmpeg.FfmpegCommand, o?: TranscodeOptions) => Promise<ffmpeg.FfmpegCommand> | ffmpeg.FfmpegCommand
+ [ type in TranscodeOptionsType ]: (c: FfmpegCommand, o?: TranscodeOptions) => Promise<FfmpegCommand> | FfmpegCommand
} = {
'quick-transcode': buildQuickTranscodeCommand,
'hls': buildHLSVODCommand,
const varStreamMap: string[] = []
- const complexFilter: ffmpeg.FilterSpecification[] = [
+ const complexFilter: FilterSpecification[] = [
{
inputs: '[v:0]',
filter: 'split',
// ---------------------------------------------------------------------------
function addDefaultEncoderGlobalParams (options: {
- command: ffmpeg.FfmpegCommand
+ command: FfmpegCommand
}) {
const { command } = options
}
function addDefaultEncoderParams (options: {
- command: ffmpeg.FfmpegCommand
+ command: FfmpegCommand
encoder: 'libx264' | string
streamNum?: number
fps?: number
}
}
-function addDefaultLiveHLSParams (command: ffmpeg.FfmpegCommand, outPath: string, masterPlaylistName: string) {
+function addDefaultLiveHLSParams (command: FfmpegCommand, outPath: string, masterPlaylistName: string) {
command.outputOption('-hls_time ' + VIDEO_LIVE.SEGMENT_TIME_SECONDS)
command.outputOption('-hls_list_size ' + VIDEO_LIVE.SEGMENTS_LIST_SIZE)
command.outputOption('-hls_flags delete_segments+independent_segments')
// Transcode VOD command builders
// ---------------------------------------------------------------------------
-async function buildx264VODCommand (command: ffmpeg.FfmpegCommand, options: TranscodeOptions) {
+async function buildx264VODCommand (command: FfmpegCommand, options: TranscodeOptions) {
let fps = await getVideoFileFPS(options.inputPath)
fps = computeFPS(fps, options.resolution)
return command
}
-async function buildAudioMergeCommand (command: ffmpeg.FfmpegCommand, options: MergeAudioTranscodeOptions) {
+async function buildAudioMergeCommand (command: FfmpegCommand, options: MergeAudioTranscodeOptions) {
command = command.loop(undefined)
const scaleFilterValue = getScaleCleanerValue()
return command
}
-function buildOnlyAudioCommand (command: ffmpeg.FfmpegCommand, _options: OnlyAudioTranscodeOptions) {
+function buildOnlyAudioCommand (command: FfmpegCommand, _options: OnlyAudioTranscodeOptions) {
command = presetOnlyAudio(command)
return command
}
-function buildQuickTranscodeCommand (command: ffmpeg.FfmpegCommand) {
+function buildQuickTranscodeCommand (command: FfmpegCommand) {
command = presetCopy(command)
command = command.outputOption('-map_metadata -1') // strip all metadata
return command
}
-function addCommonHLSVODCommandOptions (command: ffmpeg.FfmpegCommand, outputPath: string) {
+function addCommonHLSVODCommandOptions (command: FfmpegCommand, outputPath: string) {
return command.outputOption('-hls_time 4')
.outputOption('-hls_list_size 0')
.outputOption('-hls_playlist_type vod')
.outputOption('-hls_flags single_file')
}
-async function buildHLSVODCommand (command: ffmpeg.FfmpegCommand, options: HLSTranscodeOptions) {
+async function buildHLSVODCommand (command: FfmpegCommand, options: HLSTranscodeOptions) {
const videoPath = getHLSVideoPath(options)
if (options.copyCodecs) command = presetCopy(command)
return command
}
-function buildHLSVODFromTSCommand (command: ffmpeg.FfmpegCommand, options: HLSFromTSTranscodeOptions) {
+function buildHLSVODFromTSCommand (command: FfmpegCommand, options: HLSFromTSTranscodeOptions) {
const videoPath = getHLSVideoPath(options)
command.outputOption('-c copy')
}
async function presetVideo (options: {
- command: ffmpeg.FfmpegCommand
+ command: FfmpegCommand
input: string
transcodeOptions: TranscodeOptions
fps?: number
return localCommand
}
-function presetCopy (command: ffmpeg.FfmpegCommand): ffmpeg.FfmpegCommand {
+function presetCopy (command: FfmpegCommand): FfmpegCommand {
return command
.format('mp4')
.videoCodec('copy')
.audioCodec('copy')
}
-function presetOnlyAudio (command: ffmpeg.FfmpegCommand): ffmpeg.FfmpegCommand {
+function presetOnlyAudio (command: FfmpegCommand): FfmpegCommand {
return command
.format('mp4')
.audioCodec('copy')
.noVideo()
}
-function applyEncoderOptions (command: ffmpeg.FfmpegCommand, options: EncoderOptions): ffmpeg.FfmpegCommand {
+function applyEncoderOptions (command: FfmpegCommand, options: EncoderOptions): FfmpegCommand {
return command
.inputOptions(options.inputOptions ?? [])
.outputOptions(options.outputOptions ?? [])
}
async function runCommand (options: {
- command: ffmpeg.FfmpegCommand
+ command: FfmpegCommand
silent?: boolean // false
job?: Job
}) {
-import * as ffmpeg from 'fluent-ffmpeg'
+import { ffprobe, FfprobeData } from 'fluent-ffmpeg'
import { getMaxBitrate } from '@shared/core-utils'
import { VideoFileMetadata, VideoResolution, VideoTranscodingFPS } from '../../shared/models/videos'
import { CONFIG } from '../initializers/config'
*/
function ffprobePromise (path: string) {
- return new Promise<ffmpeg.FfprobeData>((res, rej) => {
- ffmpeg.ffprobe(path, (err, data) => {
+ return new Promise<FfprobeData>((res, rej) => {
+ ffprobe(path, (err, data) => {
if (err) return rej(err)
return res(data)
})
}
-async function getAudioStream (videoPath: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getAudioStream (videoPath: string, existingProbe?: FfprobeData) {
// without position, ffprobe considers the last input only
// we make it consider the first input only
// if you pass a file path to pos, then ffprobe acts on that file directly
}
}
-async function getVideoStreamSize (path: string, existingProbe?: ffmpeg.FfprobeData): Promise<{ width: number, height: number }> {
+async function getVideoStreamSize (path: string, existingProbe?: FfprobeData): Promise<{ width: number, height: number }> {
const videoStream = await getVideoStreamFromFile(path, existingProbe)
return videoStream === null
return `${videoCodec}.${baseProfile}${level}`
}
-async function getAudioStreamCodec (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getAudioStreamCodec (path: string, existingProbe?: FfprobeData) {
const { audioStream } = await getAudioStream(path, existingProbe)
if (!audioStream) return ''
return 'mp4a.40.2' // Fallback
}
-async function getVideoFileResolution (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getVideoFileResolution (path: string, existingProbe?: FfprobeData) {
const size = await getVideoStreamSize(path, existingProbe)
return {
}
}
-async function getVideoFileFPS (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getVideoFileFPS (path: string, existingProbe?: FfprobeData) {
const videoStream = await getVideoStreamFromFile(path, existingProbe)
if (videoStream === null) return 0
return 0
}
-async function getMetadataFromFile (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getMetadataFromFile (path: string, existingProbe?: FfprobeData) {
const metadata = existingProbe || await ffprobePromise(path)
return new VideoFileMetadata(metadata)
}
-async function getVideoFileBitrate (path: string, existingProbe?: ffmpeg.FfprobeData): Promise<number> {
+async function getVideoFileBitrate (path: string, existingProbe?: FfprobeData): Promise<number> {
const metadata = await getMetadataFromFile(path, existingProbe)
let bitrate = metadata.format.bit_rate as number
return undefined
}
-async function getDurationFromVideoFile (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getDurationFromVideoFile (path: string, existingProbe?: FfprobeData) {
const metadata = await getMetadataFromFile(path, existingProbe)
return Math.round(metadata.format.duration)
}
-async function getVideoStreamFromFile (path: string, existingProbe?: ffmpeg.FfprobeData) {
+async function getVideoStreamFromFile (path: string, existingProbe?: FfprobeData) {
const metadata = await getMetadataFromFile(path, existingProbe)
return metadata.streams.find(s => s.codec_type === 'video') || null
await canDoQuickAudioTranscode(path, probe)
}
-async function canDoQuickVideoTranscode (path: string, probe?: ffmpeg.FfprobeData): Promise<boolean> {
+async function canDoQuickVideoTranscode (path: string, probe?: FfprobeData): Promise<boolean> {
const videoStream = await getVideoStreamFromFile(path, probe)
const fps = await getVideoFileFPS(path, probe)
const bitRate = await getVideoFileBitrate(path, probe)
return true
}
-async function canDoQuickAudioTranscode (path: string, probe?: ffmpeg.FfprobeData): Promise<boolean> {
+async function canDoQuickAudioTranscode (path: string, probe?: FfprobeData): Promise<boolean> {
const parsedAudio = await getAudioStream(path, probe)
if (!parsedAudio.audioStream) return true
import { copy, readFile, remove, rename } from 'fs-extra'
-import * as Jimp from 'jimp'
+import Jimp, { read } from 'jimp'
import { getLowercaseExtension } from './core-utils'
import { convertWebPToJPG, processGIF } from './ffmpeg-utils'
import { logger } from './logger'
const inputBuffer = await readFile(path)
try {
- jimpInstance = await Jimp.read(inputBuffer)
+ jimpInstance = await read(inputBuffer)
} catch (err) {
logger.debug('Cannot read %s with jimp. Try to convert the image using ffmpeg first.', path, { err })
await convertWebPToJPG(path, newName)
await rename(newName, path)
- jimpInstance = await Jimp.read(path)
+ jimpInstance = await read(path)
}
await remove(destination)
// Thanks http://tostring.it/2014/06/23/advanced-logging-with-nodejs/
import { mkdirpSync, stat } from 'fs-extra'
import { omit } from 'lodash'
-import * as path from 'path'
+import { join } from 'path'
import { format as sqlFormat } from 'sql-formatter'
-import * as winston from 'winston'
+import { createLogger, format, transports } from 'winston'
import { FileTransportOptions } from 'winston/lib/winston/transports'
import { CONFIG } from '../initializers/config'
import { LOG_FILENAME } from '../initializers/constants'
}
}
-const consoleLoggerFormat = winston.format.printf(info => {
+const consoleLoggerFormat = format.printf(info => {
const toOmit = [ 'label', 'timestamp', 'level', 'message', 'sql', 'tags' ]
const obj = omit(info, ...toOmit)
return `[${info.label}] ${info.timestamp} ${info.level}: ${info.message}${additionalInfos}`
})
-const jsonLoggerFormat = winston.format.printf(info => {
+const jsonLoggerFormat = format.printf(info => {
return JSON.stringify(info, getLoggerReplacer())
})
-const timestampFormatter = winston.format.timestamp({
+const timestampFormatter = format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss.SSS'
})
const labelFormatter = (suffix?: string) => {
- return winston.format.label({
+ return format.label({
label: suffix ? `${label} ${suffix}` : label
})
}
const fileLoggerOptions: FileTransportOptions = {
- filename: path.join(CONFIG.STORAGE.LOG_DIR, LOG_FILENAME),
+ filename: join(CONFIG.STORAGE.LOG_DIR, LOG_FILENAME),
handleExceptions: true,
- format: winston.format.combine(
- winston.format.timestamp(),
+ format: format.combine(
+ format.timestamp(),
jsonLoggerFormat
)
}
const logger = buildLogger()
function buildLogger (labelSuffix?: string) {
- return winston.createLogger({
+ return createLogger({
level: CONFIG.LOG.LEVEL,
- format: winston.format.combine(
+ format: format.combine(
labelFormatter(labelSuffix),
- winston.format.splat()
+ format.splat()
),
transports: [
- new winston.transports.File(fileLoggerOptions),
- new winston.transports.Console({
+ new transports.File(fileLoggerOptions),
+ new transports.Console({
handleExceptions: true,
- format: winston.format.combine(
+ format: format.combine(
timestampFormatter,
- winston.format.colorize(),
+ format.colorize(),
consoleLoggerFormat
)
})
+import { compare, genSalt, hash } from 'bcrypt'
+import { createSign, createVerify } from 'crypto'
import { Request } from 'express'
+import { cloneDeep } from 'lodash'
import { BCRYPT_SALT_SIZE, HTTP_SIGNATURE, PRIVATE_RSA_KEY_SIZE } from '../initializers/constants'
+import { MActor } from '../types/models'
import { createPrivateKey, getPublicKey, promisify1, promisify2, sha256 } from './core-utils'
import { jsonld } from './custom-jsonld-signature'
import { logger } from './logger'
-import { cloneDeep } from 'lodash'
-import { createSign, createVerify } from 'crypto'
-import * as bcrypt from 'bcrypt'
-import { MActor } from '../types/models'
-const bcryptComparePromise = promisify2<any, string, boolean>(bcrypt.compare)
-const bcryptGenSaltPromise = promisify1<number, string>(bcrypt.genSalt)
-const bcryptHashPromise = promisify2<any, string | number, string>(bcrypt.hash)
+const bcryptComparePromise = promisify2<any, string, boolean>(compare)
+const bcryptGenSaltPromise = promisify1<number, string>(genSalt)
+const bcryptHashPromise = promisify2<any, string | number, string>(hash)
const httpSignature = require('http-signature')
// ---------------------------------------------------------------------------
-function hash (obj: any): Promise<any> {
+function hashObject (obj: any): Promise<any> {
return jsonld.promises
.normalize(obj, {
algorithm: 'URDNA2015',
delete signatureCopy.id
delete signatureCopy.signatureValue
- return hash(signatureCopy)
+ return hashObject(signatureCopy)
}
function createDocWithoutSignatureHash (doc: any) {
const docWithoutSignature = cloneDeep(doc)
delete docWithoutSignature.signature
- return hash(docWithoutSignature)
+ return hashObject(docWithoutSignature)
}
-import * as short from 'short-uuid'
+import short, { uuid } from 'short-uuid'
const translator = short()
function buildUUID () {
- return short.uuid()
+ return uuid()
}
function uuidToShort (uuid: string) {
-import * as bencode from 'bencode'
-import * as createTorrent from 'create-torrent'
+import { decode, encode } from 'bencode'
+import createTorrent from 'create-torrent'
import { createWriteStream, ensureDir, readFile, remove, writeFile } from 'fs-extra'
-import * as magnetUtil from 'magnet-uri'
-import * as parseTorrent from 'parse-torrent'
+import magnetUtil from 'magnet-uri'
+import parseTorrent from 'parse-torrent'
import { dirname, join } from 'path'
-import * as WebTorrent from 'webtorrent'
+import { pipeline } from 'stream'
+import WebTorrent, { Instance, TorrentFile } from 'webtorrent'
import { isArray } from '@server/helpers/custom-validators/misc'
import { WEBSERVER } from '@server/initializers/constants'
import { generateTorrentFileName } from '@server/lib/paths'
import { logger } from './logger'
import { generateVideoImportTmpPath } from './utils'
import { extractVideo } from './video'
-import { pipeline } from 'stream'
const createTorrentPromise = promisify2<string, any, any>(createTorrent)
return new Promise<string>((res, rej) => {
const webtorrent = new WebTorrent()
- let file: WebTorrent.TorrentFile
+ let file: TorrentFile
const torrentId = target.magnetUri || join(CONFIG.STORAGE.TORRENTS_DIR, target.torrentName)
const oldTorrentPath = join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename)
const torrentContent = await readFile(oldTorrentPath)
- const decoded = bencode.decode(torrentContent)
+ const decoded = decode(torrentContent)
decoded['announce-list'] = buildAnnounceList()
decoded.announce = decoded['announce-list'][0][0]
logger.info('Updating torrent URLs %s -> %s.', oldTorrentPath, newTorrentPath)
- await writeFile(newTorrentPath, bencode.encode(decoded))
+ await writeFile(newTorrentPath, encode(decoded))
await remove(join(CONFIG.STORAGE.TORRENTS_DIR, videoFile.torrentFilename))
videoFile.torrentFilename = newTorrentFilename
// ---------------------------------------------------------------------------
function safeWebtorrentDestroy (
- webtorrent: WebTorrent.Instance,
+ webtorrent: Instance,
torrentId: string,
downloadedFile?: { directoryPath: string, filepath: string },
torrentName?: string
-import * as config from 'config'
+import { util, has, get } from 'config'
import { uniq } from 'lodash'
import { URL } from 'url'
import { getFFmpegVersion } from '@server/helpers/ffmpeg-utils'
const parsed = new URL(actor.url)
if (WEBSERVER.HOST !== parsed.host) {
- const NODE_ENV = config.util.getEnv('NODE_ENV')
- const NODE_CONFIG_DIR = config.util.getEnv('NODE_CONFIG_DIR')
+ const NODE_ENV = util.getEnv('NODE_ENV')
+ const NODE_CONFIG_DIR = util.getEnv('NODE_CONFIG_DIR')
logger.warn(
'It seems PeerTube was started (and created some data) with another domain name. ' +
function checkConfig () {
// Moved configuration keys
- if (config.has('services.csp-logger')) {
+ if (has('services.csp-logger')) {
logger.warn('services.csp-logger configuration has been renamed to csp.report_uri. Please update your configuration file.')
}
// Check storage directory locations
if (isProdInstance()) {
- const configStorage = config.get('storage')
+ const configStorage = get('storage')
for (const key of Object.keys(configStorage)) {
if (configStorage[key].startsWith('storage/')) {
logger.warn(
-import * as config from 'config'
+import { IConfig } from 'config'
import { parseSemVersion, promisify0 } from '../helpers/core-utils'
import { logger } from '../helpers/logger'
+// Special behaviour for config because we can reload it
+const config: IConfig = require('config')
+
// ONLY USE CORE MODULES IN THIS FILE!
// Check the config files
-import * as bytes from 'bytes'
+import bytes from 'bytes'
import { IConfig } from 'config'
import decache from 'decache'
import { dirname, join } from 'path'
-import * as passwordGenerator from 'password-generator'
+import { ensureDir, remove } from 'fs-extra'
+import passwordGenerator from 'password-generator'
import { UserRole } from '../../shared'
import { logger } from '../helpers/logger'
import { createApplicationActor, createUserAccountAndChannelAndPlaylist } from '../lib/user'
-import { UserModel } from '../models/user/user'
import { ApplicationModel } from '../models/application/application'
import { OAuthClientModel } from '../models/oauth/oauth-client'
+import { UserModel } from '../models/user/user'
import { applicationExist, clientsExist, usersExist } from './checker-after-init'
+import { CONFIG } from './config'
import { FILES_CACHE, HLS_STREAMING_PLAYLIST_DIRECTORY, LAST_MIGRATION_VERSION, RESUMABLE_UPLOAD_DIRECTORY } from './constants'
import { sequelizeTypescript } from './database'
-import { ensureDir, remove } from 'fs-extra'
-import { CONFIG } from './config'
async function installApplication () {
try {
-import * as path from 'path'
+import { readdir } from 'fs-extra'
+import { join } from 'path'
+import { QueryTypes } from 'sequelize'
import { logger } from '../helpers/logger'
import { LAST_MIGRATION_VERSION } from './constants'
import { sequelizeTypescript } from './database'
-import { readdir } from 'fs-extra'
-import { QueryTypes } from 'sequelize'
async function migrate () {
const tables = await sequelizeTypescript.getQueryInterface().showAllTables()
// ---------------------------------------------------------------------------
async function getMigrationScripts () {
- const files = await readdir(path.join(__dirname, 'migrations'))
+ const files = await readdir(join(__dirname, 'migrations'))
const filesToMigrate: {
version: string
script: string
const migrationScriptName = entity.script
logger.info('Executing %s migration script.', migrationScriptName)
- const migrationScript = require(path.join(__dirname, 'migrations', migrationScriptName))
+ const migrationScript = require(join(__dirname, 'migrations', migrationScriptName))
return sequelizeTypescript.transaction(async t => {
const options = {
-import * as WebFinger from 'webfinger.js'
+import WebFinger from 'webfinger.js'
import { isProdInstance } from '@server/helpers/core-utils'
import { isActivityPubUrlValid } from '@server/helpers/custom-validators/activitypub/misc'
import { REQUEST_TIMEOUT, WEBSERVER } from '@server/initializers/constants'
-import { retryTransactionWrapper } from '@server/helpers/database-utils'
-import * as Bluebird from 'bluebird'
+import Bluebird from 'bluebird'
import { URL } from 'url'
+import { retryTransactionWrapper } from '@server/helpers/database-utils'
import { ActivityPubOrderedCollection } from '../../../shared/models/activitypub'
import { logger } from '../../helpers/logger'
import { doJSONRequest } from '../../helpers/requests'
import { ACTIVITY_PUB, WEBSERVER } from '../../initializers/constants'
type HandlerFunction<T> = (items: T[]) => (Promise<any> | Bluebird<any>)
-type CleanerFunction = (startedDate: Date) => (Promise<any> | Bluebird<any>)
+type CleanerFunction = (startedDate: Date) => Promise<any>
async function crawlCollectionPage <T> (argUrl: string, handler: HandlerFunction<T>, cleaner?: CleanerFunction) {
let url = argUrl
-import * as Bluebird from 'bluebird'
+import { map } from 'bluebird'
import { getAPId } from '@server/helpers/activitypub'
import { isArray } from '@server/helpers/custom-validators/misc'
import { logger, loggerTagsFactory } from '@server/helpers/logger'
const lTags = loggerTagsFactory('ap', 'video-playlist')
async function createAccountPlaylists (playlistUrls: string[]) {
- await Bluebird.map(playlistUrls, async playlistUrl => {
+ await map(playlistUrls, async playlistUrl => {
try {
const exists = await VideoPlaylistModel.doesPlaylistExist(playlistUrl)
if (exists === true) return
async function buildElementsDBAttributes (elementUrls: string[], playlist: MVideoPlaylist) {
const elementsToCreate: FilteredModelAttributes<VideoPlaylistElementModel>[] = []
- await Bluebird.map(elementUrls, async elementUrl => {
+ await map(elementUrls, async elementUrl => {
try {
const { elementObject } = await fetchRemotePlaylistElement(elementUrl)
-import * as Bluebird from 'bluebird'
+import { map } from 'bluebird'
import { Transaction } from 'sequelize'
import { getServerActor } from '@server/models/application/application'
import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub'
}
async function addVideoShares (shareUrls: string[], video: MVideoId) {
- await Bluebird.map(shareUrls, async shareUrl => {
+ await map(shareUrls, async shareUrl => {
try {
await addVideoShare(shareUrl, video)
} catch (err) {
-import * as Bluebird from 'bluebird'
+import { map } from 'bluebird'
import { checkUrlsSameHost } from '../../helpers/activitypub'
import { sanitizeAndCheckVideoCommentObject } from '../../helpers/custom-validators/activitypub/video-comments'
import { logger } from '../../helpers/logger'
type ResolveThreadResult = Promise<{ video: MVideoAccountLightBlacklistAllFiles, comment: MCommentOwnerVideo, commentCreated: boolean }>
async function addVideoComments (commentUrls: string[]) {
- return Bluebird.map(commentUrls, async commentUrl => {
+ return map(commentUrls, async commentUrl => {
try {
await resolveThread({ url: commentUrl, isVideo: false })
} catch (err) {
-import * as Bluebird from 'bluebird'
+import { map } from 'bluebird'
import { Transaction } from 'sequelize'
import { doJSONRequest } from '@server/helpers/requests'
import { VideoRateType } from '../../../shared/models/videos'
const lTags = loggerTagsFactory('ap', 'video-rate', 'create')
async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateType) {
- await Bluebird.map(ratesUrl, async rateUrl => {
+ await map(ratesUrl, async rateUrl => {
try {
await createRate(rateUrl, video, rate)
} catch (err) {
import { maxBy, minBy } from 'lodash'
-import * as magnetUtil from 'magnet-uri'
+import magnetUtil from 'magnet-uri'
import { basename } from 'path'
import { isAPVideoFileUrlMetadataObject } from '@server/helpers/custom-validators/activitypub/videos'
import { isVideoFileInfoHashValid } from '@server/helpers/custom-validators/videos'
-import * as express from 'express'
+import express from 'express'
import { AccessDeniedError } from 'oauth2-server'
import { PluginManager } from '@server/lib/plugins/plugin-manager'
import { ActorModel } from '@server/models/actor/actor'
-import * as express from 'express'
+import express from 'express'
import {
InvalidClientError,
InvalidGrantError,
-import * as LRUCache from 'lru-cache'
+import LRUCache from 'lru-cache'
import { MOAuthTokenUser } from '@server/types/models'
import { LRU_CACHE } from '../../initializers/constants'
-import * as express from 'express'
+import express from 'express'
import { readFile } from 'fs-extra'
import { join } from 'path'
import validator from 'validator'
import { remove } from 'fs-extra'
import { logger } from '../../helpers/logger'
-import * as memoizee from 'memoizee'
+import memoizee from 'memoizee'
type GetFilePathResult = { isOwned: boolean, path: string, downloadName?: string } | undefined
-import * as Bluebird from 'bluebird'
-import * as Bull from 'bull'
+import { map } from 'bluebird'
+import { Job } from 'bull'
import { checkUrlsSameHost } from '@server/helpers/activitypub'
import {
isAnnounceActivityValid,
// Job to clean remote interactions off local videos
-async function processActivityPubCleaner (_job: Bull.Job) {
+async function processActivityPubCleaner (_job: Job) {
logger.info('Processing ActivityPub cleaner.')
{
const rateUrls = await AccountVideoRateModel.listRemoteRateUrlsOfLocalVideos()
const { bodyValidator, deleter, updater } = rateOptionsFactory()
- await Bluebird.map(rateUrls, async rateUrl => {
+ await map(rateUrls, async rateUrl => {
try {
const result = await updateObjectIfNeeded(rateUrl, bodyValidator, updater, deleter)
const shareUrls = await VideoShareModel.listRemoteShareUrlsOfLocalVideos()
const { bodyValidator, deleter, updater } = shareOptionsFactory()
- await Bluebird.map(shareUrls, async shareUrl => {
+ await map(shareUrls, async shareUrl => {
try {
await updateObjectIfNeeded(shareUrl, bodyValidator, updater, deleter)
} catch (err) {
const commentUrls = await VideoCommentModel.listRemoteCommentUrlsOfLocalVideos()
const { bodyValidator, deleter, updater } = commentOptionsFactory()
- await Bluebird.map(commentUrls, async commentUrl => {
+ await map(commentUrls, async commentUrl => {
try {
await updateObjectIfNeeded(commentUrl, bodyValidator, updater, deleter)
} catch (err) {
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { getLocalActorFollowActivityPubUrl } from '@server/lib/activitypub/url'
import { ActivitypubFollowPayload } from '@shared/models'
import { sanitizeHost } from '../../../helpers/core-utils'
import { sendFollow } from '../../activitypub/send'
import { Notifier } from '../../notifier'
-async function processActivityPubFollow (job: Bull.Job) {
+async function processActivityPubFollow (job: Job) {
const payload = job.data as ActivitypubFollowPayload
const host = payload.host
-import * as Bluebird from 'bluebird'
-import * as Bull from 'bull'
+import { map } from 'bluebird'
+import { Job } from 'bull'
import { ActivitypubHttpBroadcastPayload } from '@shared/models'
import { logger } from '../../../helpers/logger'
import { doRequest } from '../../../helpers/requests'
import { ActorFollowScoreCache } from '../../files-cache'
import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from './utils/activitypub-http-utils'
-async function processActivityPubHttpBroadcast (job: Bull.Job) {
+async function processActivityPubHttpBroadcast (job: Job) {
logger.info('Processing ActivityPub broadcast in job %d.', job.id)
const payload = job.data as ActivitypubHttpBroadcastPayload
const badUrls: string[] = []
const goodUrls: string[] = []
- await Bluebird.map(payload.uris, uri => {
+ await map(payload.uris, uri => {
return doRequest(uri, options)
.then(() => goodUrls.push(uri))
.catch(() => badUrls.push(uri))
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { ActivitypubHttpFetcherPayload, FetchType } from '@shared/models'
import { logger } from '../../../helpers/logger'
import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
import { addVideoComments } from '../../activitypub/video-comments'
import { createRates } from '../../activitypub/video-rates'
-async function processActivityPubHttpFetcher (job: Bull.Job) {
+async function processActivityPubHttpFetcher (job: Job) {
logger.info('Processing ActivityPub fetcher in job %d.', job.id)
const payload = job.data as ActivitypubHttpFetcherPayload
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { ActivitypubHttpUnicastPayload } from '@shared/models'
import { logger } from '../../../helpers/logger'
import { doRequest } from '../../../helpers/requests'
import { ActorFollowScoreCache } from '../../files-cache'
import { buildGlobalHeaders, buildSignedRequestOptions, computeBody } from './utils/activitypub-http-utils'
-async function processActivityPubHttpUnicast (job: Bull.Job) {
+async function processActivityPubHttpUnicast (job: Job) {
logger.info('Processing ActivityPub unicast in job %d.', job.id)
const payload = job.data as ActivitypubHttpUnicastPayload
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { refreshVideoPlaylistIfNeeded } from '@server/lib/activitypub/playlists'
import { refreshVideoIfNeeded } from '@server/lib/activitypub/videos'
import { loadVideoByUrl } from '@server/lib/model-loaders'
import { VideoPlaylistModel } from '../../../models/video/video-playlist'
import { refreshActorIfNeeded } from '../../activitypub/actors'
-async function refreshAPObject (job: Bull.Job) {
+async function refreshAPObject (job: Job) {
const payload = job.data as RefreshPayload
logger.info('Processing AP refresher in job %d for %s.', job.id, payload.url)
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { generateAndSaveActorKeys } from '@server/lib/activitypub/actors'
import { ActorModel } from '@server/models/actor/actor'
import { ActorKeysPayload } from '@shared/models'
import { logger } from '../../../helpers/logger'
-async function processActorKeys (job: Bull.Job) {
+async function processActorKeys (job: Job) {
const payload = job.data as ActorKeysPayload
logger.info('Processing actor keys in job %d.', job.id)
-import * as Bull from 'bull'
+import { Job } from 'bull'
+import { EmailPayload } from '@shared/models'
import { logger } from '../../../helpers/logger'
import { Emailer } from '../../emailer'
-import { EmailPayload } from '@shared/models'
-async function processEmail (job: Bull.Job) {
+async function processEmail (job: Job) {
const payload = job.data as EmailPayload
logger.info('Processing email in job %d.', job.id)
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { remove } from 'fs-extra'
import { join } from 'path'
import { logger } from '@server/helpers/logger'
import { MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoWithAllFiles } from '@server/types/models'
import { MoveObjectStoragePayload, VideoStorage } from '../../../../shared'
-export async function processMoveToObjectStorage (job: Bull.Job) {
+export async function processMoveToObjectStorage (job: Job) {
const payload = job.data as MoveObjectStoragePayload
logger.info('Moving video %s in job %d.', payload.videoUUID, job.id)
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { copy, stat } from 'fs-extra'
import { getLowercaseExtension } from '@server/helpers/core-utils'
import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent'
import { VideoFileModel } from '../../../models/video/video-file'
import { createHlsJobIfEnabled } from './video-transcoding'
-async function processVideoFileImport (job: Bull.Job) {
+async function processVideoFileImport (job: Job) {
const payload = job.data as VideoFileImportPayload
logger.info('Processing video file import in job %d.', job.id)
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { move, remove, stat } from 'fs-extra'
import { getLowercaseExtension } from '@server/helpers/core-utils'
import { retryTransactionWrapper } from '@server/helpers/database-utils'
import { Notifier } from '../../notifier'
import { generateVideoMiniature } from '../../thumbnail'
-async function processVideoImport (job: Bull.Job) {
+async function processVideoImport (job: Job) {
const payload = job.data as VideoImportPayload
if (payload.type === 'youtube-dl') return processYoutubeDLImport(job, payload)
// ---------------------------------------------------------------------------
-async function processTorrentImport (job: Bull.Job, payload: VideoImportTorrentPayload) {
+async function processTorrentImport (job: Job, payload: VideoImportTorrentPayload) {
logger.info('Processing torrent video import in job %d.', job.id)
const videoImport = await getVideoImportOrDie(payload.videoImportId)
return processFile(() => downloadWebTorrentVideo(target, VIDEO_IMPORT_TIMEOUT), videoImport, options)
}
-async function processYoutubeDLImport (job: Bull.Job, payload: VideoImportYoutubeDLPayload) {
+async function processYoutubeDLImport (job: Job, payload: VideoImportYoutubeDLPayload) {
logger.info('Processing youtubeDL video import in job %d.', job.id)
const videoImport = await getVideoImportOrDie(payload.videoImportId)
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { pathExists, readdir, remove } from 'fs-extra'
import { join } from 'path'
import { ffprobePromise, getAudioStream, getDurationFromVideoFile, getVideoFileResolution } from '@server/helpers/ffprobe-utils'
import { ThumbnailType, VideoLiveEndingPayload, VideoState } from '@shared/models'
import { logger } from '../../../helpers/logger'
-async function processVideoLiveEnding (job: Bull.Job) {
+async function processVideoLiveEnding (job: Job) {
const payload = job.data as VideoLiveEndingPayload
function logError () {
-import * as Bull from 'bull'
-import { logger } from '../../../helpers/logger'
+import { Job } from 'bull'
import { VideosRedundancyScheduler } from '@server/lib/schedulers/videos-redundancy-scheduler'
import { VideoRedundancyPayload } from '@shared/models'
+import { logger } from '../../../helpers/logger'
-async function processVideoRedundancy (job: Bull.Job) {
+async function processVideoRedundancy (job: Job) {
const payload = job.data as VideoRedundancyPayload
logger.info('Processing video redundancy in job %d.', job.id)
-import * as Bull from 'bull'
+import { Job } from 'bull'
import { TranscodeOptionsType } from '@server/helpers/ffmpeg-utils'
import { addTranscodingJob, getTranscodingJobPriority } from '@server/lib/video'
import { VideoPathManager } from '@server/lib/video-path-manager'
transcodeNewWebTorrentResolution
} from '../../transcoding/video-transcoding'
-type HandlerFunction = (job: Bull.Job, payload: VideoTranscodingPayload, video: MVideoFullLight, user: MUser) => Promise<void>
+type HandlerFunction = (job: Job, payload: VideoTranscodingPayload, video: MVideoFullLight, user: MUser) => Promise<void>
const handlers: { [ id in VideoTranscodingPayload['type'] ]: HandlerFunction } = {
'new-resolution-to-hls': handleHLSJob,
const lTags = loggerTagsFactory('transcoding')
-async function processVideoTranscoding (job: Bull.Job) {
+async function processVideoTranscoding (job: Job) {
const payload = job.data as VideoTranscodingPayload
logger.info('Processing transcoding job %d.', job.id, lTags(payload.videoUUID))
// Job handlers
// ---------------------------------------------------------------------------
-async function handleHLSJob (job: Bull.Job, payload: HLSTranscodingPayload, video: MVideoFullLight, user: MUser) {
+async function handleHLSJob (job: Job, payload: HLSTranscodingPayload, video: MVideoFullLight, user: MUser) {
logger.info('Handling HLS transcoding job for %s.', video.uuid, lTags(video.uuid))
const videoFileInput = payload.copyCodecs
}
async function handleNewWebTorrentResolutionJob (
- job: Bull.Job,
+ job: Job,
payload: NewResolutionTranscodingPayload,
video: MVideoFullLight,
user: MUserId
await retryTransactionWrapper(onNewWebTorrentFileResolution, video, user, payload)
}
-async function handleWebTorrentMergeAudioJob (job: Bull.Job, payload: MergeAudioTranscodingPayload, video: MVideoFullLight, user: MUserId) {
+async function handleWebTorrentMergeAudioJob (job: Job, payload: MergeAudioTranscodingPayload, video: MVideoFullLight, user: MUserId) {
logger.info('Handling merge audio transcoding job for %s.', video.uuid, lTags(video.uuid))
await mergeAudioVideofile(video, payload.resolution, job)
await retryTransactionWrapper(onVideoFileOptimizer, video, payload, 'video', user)
}
-async function handleWebTorrentOptimizeJob (job: Bull.Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) {
+async function handleWebTorrentOptimizeJob (job: Job, payload: OptimizeTranscodingPayload, video: MVideoFullLight, user: MUserId) {
logger.info('Handling optimize transcoding job for %s.', video.uuid, lTags(video.uuid))
const { transcodeType } = await optimizeOriginalVideofile(video, video.getMaxQualityFile(), job)
-import * as Bull from 'bull'
+import Bull, { Job, JobOptions, Queue } from 'bull'
import { jobStates } from '@server/helpers/custom-validators/jobs'
import { CONFIG } from '@server/initializers/config'
import { processVideoRedundancy } from '@server/lib/job-queue/handlers/video-redundancy'
import { refreshAPObject } from './handlers/activitypub-refresher'
import { processActorKeys } from './handlers/actor-keys'
import { processEmail } from './handlers/email'
+import { processMoveToObjectStorage } from './handlers/move-to-object-storage'
import { processVideoFileImport } from './handlers/video-file-import'
import { processVideoImport } from './handlers/video-import'
import { processVideoLiveEnding } from './handlers/video-live-ending'
import { processVideoTranscoding } from './handlers/video-transcoding'
import { processVideosViews } from './handlers/video-views'
-import { processMoveToObjectStorage } from './handlers/move-to-object-storage'
type CreateJobArgument =
{ type: 'activitypub-http-broadcast', payload: ActivitypubHttpBroadcastPayload } |
priority?: number
}
-const handlers: { [id in JobType]: (job: Bull.Job) => Promise<any> } = {
+const handlers: { [id in JobType]: (job: Job) => Promise<any> } = {
'activitypub-http-broadcast': processActivityPubHttpBroadcast,
'activitypub-http-unicast': processActivityPubHttpUnicast,
'activitypub-http-fetcher': processActivityPubHttpFetcher,
private static instance: JobQueue
- private queues: { [id in JobType]?: Bull.Queue } = {}
+ private queues: { [id in JobType]?: Queue } = {}
private initialized = false
private jobRedisPrefix: string
return
}
- const jobArgs: Bull.JobOptions = {
+ const jobArgs: JobOptions = {
backoff: { delay: 60 * 1000, type: 'exponential' },
attempts: JOB_ATTEMPTS[obj.type],
timeout: JOB_TTL[obj.type],
count: number
asc?: boolean
jobType: JobType
- }): Promise<Bull.Job[]> {
+ }): Promise<Job[]> {
const { state, start, count, asc, jobType } = options
const states = state ? [ state ] : jobStates
- let results: Bull.Job[] = []
+ let results: Job[] = []
const filteredJobTypes = this.filterJobTypes(jobType)
-import * as Bluebird from 'bluebird'
-import * as chokidar from 'chokidar'
+import { mapSeries } from 'bluebird'
+import { FSWatcher, watch } from 'chokidar'
import { FfmpegCommand } from 'fluent-ffmpeg'
import { appendFile, ensureDir, readFile, stat } from 'fs-extra'
import { basename, join } from 'path'
private segmentsToProcessPerPlaylist: { [playlistId: string]: string[] } = {}
- private tsWatcher: chokidar.FSWatcher
- private masterWatcher: chokidar.FSWatcher
+ private tsWatcher: FSWatcher
+ private masterWatcher: FSWatcher
private readonly isAbleToUploadVideoWithCache = memoizee((userId: number) => {
return isAbleToUploadVideo(userId, 1000)
}
private watchMasterFile (outPath: string) {
- this.masterWatcher = chokidar.watch(outPath + '/' + this.streamingPlaylist.playlistFilename)
+ this.masterWatcher = watch(outPath + '/' + this.streamingPlaylist.playlistFilename)
this.masterWatcher.on('add', () => {
this.emit('master-playlist-created', { videoId: this.videoId })
private watchTSFiles (outPath: string) {
const startStreamDateTime = new Date().getTime()
- this.tsWatcher = chokidar.watch(outPath + '/*.ts')
+ this.tsWatcher = watch(outPath + '/*.ts')
const playlistIdMatcher = /^([\d+])-/
}
private processSegments (hlsVideoPath: string, segmentPaths: string[]) {
- Bluebird.mapSeries(segmentPaths, async previousSegment => {
+ mapSeries(segmentPaths, async previousSegment => {
// Add sha hash of previous segments, because ffmpeg should have finished generating them
await LiveSegmentShaStore.Instance.addSegmentSha(this.videoUUID, previousSegment)
import 'multer'
import { queue } from 'async'
-import * as LRUCache from 'lru-cache'
+import LRUCache from 'lru-cache'
import { join } from 'path'
import { getLowercaseExtension } from '@server/helpers/core-utils'
import { buildUUID } from '@server/helpers/uuid'
-import { Server } from 'http'
-import * as SocketIO from 'socket.io'
+import { Server as HTTPServer } from 'http'
+import { Namespace, Server as SocketServer, Socket } from 'socket.io'
+import { isIdValid } from '@server/helpers/custom-validators/misc'
import { MVideo } from '@server/types/models'
import { UserNotificationModelForApi } from '@server/types/models/user'
import { LiveVideoEventPayload, LiveVideoEventType } from '@shared/models'
import { logger } from '../helpers/logger'
import { authenticateSocket } from '../middlewares'
-import { isIdValid } from '@server/helpers/custom-validators/misc'
class PeerTubeSocket {
private static instance: PeerTubeSocket
- private userNotificationSockets: { [ userId: number ]: SocketIO.Socket[] } = {}
- private liveVideosNamespace: SocketIO.Namespace
+ private userNotificationSockets: { [ userId: number ]: Socket[] } = {}
+ private liveVideosNamespace: Namespace
private constructor () {}
- init (server: Server) {
- const io = new SocketIO.Server(server)
+ init (server: HTTPServer) {
+ const io = new SocketServer(server)
io.of('/user-notifications')
.use(authenticateSocket)
-import * as Bluebird from 'bluebird'
+import Bluebird from 'bluebird'
import { ServerActionHookName, ServerFilterHookName } from '../../../shared/models'
import { logger } from '../../helpers/logger'
import { PluginManager } from './plugin-manager'
-import * as express from 'express'
+import express from 'express'
import { join } from 'path'
import { buildLogger } from '@server/helpers/logger'
import { CONFIG } from '@server/initializers/config'
import decache from 'decache'
-import * as express from 'express'
+import express from 'express'
import { createReadStream, createWriteStream } from 'fs'
import { ensureDir, outputFile, readJSON } from 'fs-extra'
import { basename, join } from 'path'
-import * as express from 'express'
+import express from 'express'
import { logger } from '@server/helpers/logger'
import { onExternalUserAuthenticated } from '@server/lib/auth/external-auth'
import { VideoConstantManagerFactory } from '@server/lib/plugins/video-constant-manager-factory'
-import * as express from 'express'
+import express from 'express'
import { createClient, RedisClient } from 'redis'
import { logger } from '../helpers/logger'
import { generateRandomString } from '../helpers/utils'
+import Bluebird from 'bluebird'
import { logger } from '../../helpers/logger'
-import * as Bluebird from 'bluebird'
export abstract class AbstractScheduler {
-import * as bluebird from 'bluebird'
+import { map } from 'bluebird'
import { readdir, remove, stat } from 'fs-extra'
import { logger, loggerTagsFactory } from '@server/helpers/logger'
import { getResumableUploadPath } from '@server/helpers/upload'
logger.debug('Reading resumable video upload folder %s with %d files', path, metafiles.length, lTags())
try {
- await bluebird.map(metafiles, metafile => {
+ await map(metafiles, metafile => {
return this.deleteIfOlderThan(metafile, this.lastExecutionTimeMs)
}, { concurrency: 5 })
} catch (error) {
-import * as express from 'express'
+import express from 'express'
import { CONFIG } from '@server/initializers/config'
import { AccountBlocklistModel } from '@server/models/account/account-blocklist'
import { getServerActor } from '@server/models/application/application'
-import { UserModel } from '../models/user/user'
-import * as ipaddr from 'ipaddr.js'
+import { IPv4, IPv6, parse, subnetMatch } from 'ipaddr.js'
import { CONFIG } from '../initializers/config'
+import { UserModel } from '../models/user/user'
const isCidr = require('is-cidr')
function isSignupAllowedForCurrentIP (ip: string) {
if (!ip) return false
- const addr = ipaddr.parse(ip)
+ const addr = parse(ip)
const excludeList = [ 'blacklist' ]
let matched = ''
}
if (addr.kind() === 'ipv4') {
- const addrV4 = ipaddr.IPv4.parse(ip)
+ const addrV4 = IPv4.parse(ip)
const rangeList = {
whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v4(cidr))
- .map(cidr => ipaddr.IPv4.parseCIDR(cidr)),
+ .map(cidr => IPv4.parseCIDR(cidr)),
blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v4(cidr))
- .map(cidr => ipaddr.IPv4.parseCIDR(cidr))
+ .map(cidr => IPv4.parseCIDR(cidr))
}
- matched = ipaddr.subnetMatch(addrV4, rangeList, 'unknown')
+ matched = subnetMatch(addrV4, rangeList, 'unknown')
} else if (addr.kind() === 'ipv6') {
- const addrV6 = ipaddr.IPv6.parse(ip)
+ const addrV6 = IPv6.parse(ip)
const rangeList = {
whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v6(cidr))
- .map(cidr => ipaddr.IPv6.parseCIDR(cidr)),
+ .map(cidr => IPv6.parseCIDR(cidr)),
blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v6(cidr))
- .map(cidr => ipaddr.IPv6.parseCIDR(cidr))
+ .map(cidr => IPv6.parseCIDR(cidr))
}
- matched = ipaddr.subnetMatch(addrV6, rangeList, 'unknown')
+ matched = subnetMatch(addrV6, rangeList, 'unknown')
}
return !excludeList.includes(matched)
+import { mapSeries } from 'bluebird'
import { CONFIG } from '@server/initializers/config'
-import { UserModel } from '@server/models/user/user'
import { ActorFollowModel } from '@server/models/actor/actor-follow'
import { VideoRedundancyModel } from '@server/models/redundancy/video-redundancy'
+import { UserModel } from '@server/models/user/user'
import { VideoModel } from '@server/models/video/video'
import { VideoChannelModel } from '@server/models/video/video-channel'
import { VideoCommentModel } from '@server/models/video/video-comment'
import { VideoFileModel } from '@server/models/video/video-file'
import { VideoPlaylistModel } from '@server/models/video/video-playlist'
import { ActivityType, ServerStats, VideoRedundancyStrategyWithManual } from '@shared/models'
-import * as Bluebird from 'bluebird'
class StatsManager {
strategies.push({ strategy: 'manual', size: null })
- return Bluebird.mapSeries(strategies, r => {
+ return mapSeries(strategies, r => {
return VideoRedundancyModel.getStats(r.strategy)
.then(stats => Object.assign(stats, { strategy: r.strategy, totalSize: r.size }))
})
-import * as express from 'express'
+import express from 'express'
import { Socket } from 'socket.io'
import { getAccessToken } from '@server/lib/auth/oauth-model'
import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
// Thanks: https://github.com/kwhitley/apicache
// We duplicated the library because it is unmaintened and prevent us to upgrade to recent NodeJS versions
-import * as express from 'express'
+import express from 'express'
import { OutgoingHttpHeaders } from 'http'
import { isTestInstance, parseDurationToMs } from '@server/helpers/core-utils'
import { logger } from '@server/helpers/logger'
-import * as helmet from 'helmet'
+import { contentSecurityPolicy } from 'helmet'
import { CONFIG } from '../initializers/config'
const baseDirectives = Object.assign({},
CONFIG.WEBSERVER.SCHEME === 'https' ? { upgradeInsecureRequests: [] } : {}
)
-const baseCSP = helmet.contentSecurityPolicy({
+const baseCSP = contentSecurityPolicy({
directives: baseDirectives,
reportOnly: CONFIG.CSP.REPORT_ONLY
})
-const embedCSP = helmet.contentSecurityPolicy({
+const embedCSP = contentSecurityPolicy({
directives: Object.assign({}, baseDirectives, { frameAncestors: [ '*' ] }),
reportOnly: CONFIG.CSP.REPORT_ONLY
})
-import * as express from 'express'
+import express from 'express'
function openapiOperationDoc (options: {
url?: string
-import * as express from 'express'
+import express from 'express'
import { ProblemDocument, ProblemDocumentExtension } from 'http-problem-details'
import { HttpStatusCode } from '@shared/models'
-import * as express from 'express'
+import express from 'express'
import { PAGINATION } from '../initializers/constants'
function setDefaultPagination (req: express.Request, res: express.Response, next: express.NextFunction) {
-import * as express from 'express'
+import express from 'express'
import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { getHostWithPort } from '../helpers/express-utils'
-import * as express from 'express'
+import express from 'express'
import { SortType } from '../models/utils'
const setDefaultSort = setDefaultSortFactory('-createdAt')
-import * as express from 'express'
+import express from 'express'
import { UserRight } from '../../shared'
import { HttpStatusCode } from '../../shared/models/http/http-error-codes'
import { logger } from '../helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { body, param, query } from 'express-validator'
import {
areAbusePredefinedReasonsValid,
-import * as express from 'express'
+import express from 'express'
import { param } from 'express-validator'
import { isAccountNameValid } from '../../helpers/custom-validators/accounts'
import { logger } from '../../helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { getServerActor } from '@server/models/application/application'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { isRootActivityValid } from '../../../helpers/custom-validators/activitypub/activity'
-import * as express from 'express'
+import express from 'express'
import { query } from 'express-validator'
import { PAGINATION } from '@server/initializers/constants'
import { logger } from '../../../helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { body } from 'express-validator'
import {
isSignatureCreatorValid,
-import * as express from 'express'
+import express from 'express'
import { body } from 'express-validator'
import { isActorImageFile } from '@server/helpers/custom-validators/actor-images'
import { cleanUpReqFiles } from '../../helpers/express-utils'
-import * as express from 'express'
+import express from 'express'
import { body, param } from 'express-validator'
import { getServerActor } from '@server/models/application/application'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
-import * as express from 'express'
+import express from 'express'
import { body } from 'express-validator'
import { isBulkRemoveCommentsOfScopeValid } from '@server/helpers/custom-validators/bulk'
import { HttpStatusCode, UserRight } from '@shared/models'
-import * as express from 'express'
+import express from 'express'
import { body } from 'express-validator'
import { isIntOrNull } from '@server/helpers/custom-validators/misc'
import { isEmailEnabled } from '@server/initializers/config'
-import * as express from 'express'
+import express from 'express'
import { param, query } from 'express-validator'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isValidRSSFeed } from '../../helpers/custom-validators/feeds'
-import * as express from 'express'
+import express from 'express'
import { body, param, query } from 'express-validator'
import { isEachUniqueHandleValid, isFollowStateValid, isRemoteHandleValid } from '@server/helpers/custom-validators/follows'
import { loadActorUrlOrGetFromWebfinger } from '@server/lib/activitypub/actors'
-import * as express from 'express'
+import express from 'express'
import { param, query } from 'express-validator'
import { isValidJobState, isValidJobType } from '../../helpers/custom-validators/jobs'
import { logger, loggerTagsFactory } from '../../helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { query } from 'express-validator'
import { isValidLogLevel } from '../../helpers/custom-validators/logs'
import { isDateValid } from '../../helpers/custom-validators/misc'
-import * as express from 'express'
+import express from 'express'
import { query } from 'express-validator'
import { join } from 'path'
import { loadVideo } from '@server/lib/model-loaders'
-import * as express from 'express'
+import express from 'express'
import { query } from 'express-validator'
import { PAGINATION } from '@server/initializers/constants'
import { logger } from '../../helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { body, param, query, ValidationChain } from 'express-validator'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { PluginType } from '../../../shared/models/plugins/plugin.type'
-import * as express from 'express'
+import express from 'express'
import { body, param, query } from 'express-validator'
import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
-import * as express from 'express'
+import express from 'express'
import { query } from 'express-validator'
import { isSearchTargetValid } from '@server/helpers/custom-validators/search'
import { isHostValid } from '@server/helpers/custom-validators/servers'
-import * as express from 'express'
+import express from 'express'
import { body } from 'express-validator'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isHostValid, isValidContactBody } from '../../helpers/custom-validators/servers'
-import * as express from 'express'
+import express from 'express'
import { param, query, validationResult } from 'express-validator'
import { isIdOrUUIDValid, toCompleteUUID } from '@server/helpers/custom-validators/misc'
import { logger } from '../../../helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { VideoChannelModel } from '@server/models/video/video-channel'
import { MChannelBannerAccountDefault } from '@server/types/models'
import { HttpStatusCode } from '@shared/models'
-import * as express from 'express'
+import express from 'express'
import { VideoCommentModel } from '@server/models/video/video-comment'
import { MVideoId } from '@server/types/models'
import { HttpStatusCode } from '@shared/models'
-import * as express from 'express'
+import express from 'express'
import { VideoImportModel } from '@server/models/video/video-import'
import { HttpStatusCode } from '@shared/models'
-import * as express from 'express'
+import express from 'express'
import { VideoChangeOwnershipModel } from '@server/models/video/video-change-ownership'
import { HttpStatusCode } from '@shared/models'
-import * as express from 'express'
+import express from 'express'
import { VideoPlaylistModel } from '@server/models/video/video-playlist'
import { MVideoPlaylist } from '@server/types/models'
import { HttpStatusCode } from '@shared/models'
-import * as express from 'express'
+import express from 'express'
import { param } from 'express-validator'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isSafePath } from '../../helpers/custom-validators/misc'
-import * as express from 'express'
+import express from 'express'
import { body, query } from 'express-validator'
import { exists, isDateValid } from '../../helpers/custom-validators/misc'
import { logger } from '../../helpers/logger'
-import * as express from 'express'
+import express from 'express'
import { body, query } from 'express-validator'
import { isNotEmptyIntArray, toBooleanOrNull } from '../../helpers/custom-validators/misc'
import { isUserNotificationSettingValid } from '../../helpers/custom-validators/user-notifications'
-import * as express from 'express'
+import express from 'express'
import { body, param, query } from 'express-validator'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { areValidActorHandles, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor'
-import * as express from 'express'
+import express from 'express'
import { body, param, query } from 'express-validator'
import { omit } from 'lodash'
import { Hooks } from '@server/lib/plugins/hooks'
-import * as express from 'express'
+import express from 'express'
import { body, query } from 'express-validator'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { isBooleanValid, toBooleanOrNull, toIntOrNull } from '../../../helpers/custom-validators/misc'
-import * as express from 'express'
+import express from 'express'
import { body, param } from 'express-validator'
import { UserRight } from '../../../../shared'
import { isVideoCaptionFile, isVideoCaptionLanguageValid } from '../../../helpers/custom-validators/video-captions'
-import * as express from 'express'
+import express from 'express'
import { body, param, query } from 'express-validator'
import { VIDEO_CHANNELS } from '@server/initializers/constants'
import { MChannelAccountDefault, MUser } from '@server/types/models'
-import * as express from 'express'
+import express from 'express'
import { body, param, query } from 'express-validator'
import { MUserAccountUrl } from '@server/types/models'
import { UserRight } from '../../../../shared'
-import * as express from 'express'
+import express from 'express'
import { body } from 'express-validator'
import { isPreImportVideoAccepted } from '@server/lib/moderation'
import { Hooks } from '@server/lib/plugins/hooks'
-import * as express from 'express'
+import express from 'express'
import { body } from 'express-validator'
import { CONSTRAINTS_FIELDS } from '@server/initializers/constants'
import { isLocalLiveVideoAccepted } from '@server/lib/moderation'
-import * as express from 'express'
+import express from 'express'
import { param } from 'express-validator'
import { isIdValid } from '@server/helpers/custom-validators/misc'
import { checkUserCanTerminateOwnershipChange } from '@server/helpers/custom-validators/video-ownership'
-import * as express from 'express'
+import express from 'express'
import { body, param, query, ValidationChain } from 'express-validator'
import { ExpressPromiseHandler } from '@server/types/express'
import { MUserAccountId } from '@server/types/models'
-import * as express from 'express'
+import express from 'express'
import { body, param, query } from 'express-validator'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { VideoRateType } from '../../../../shared/models/videos'
-import * as express from 'express'
+import express from 'express'
import { param } from 'express-validator'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { isIdValid } from '../../../helpers/custom-validators/misc'
-import * as express from 'express'
+import express from 'express'
import { body } from 'express-validator'
import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes'
import { toIntOrNull } from '../../../helpers/custom-validators/misc'
-import * as express from 'express'
+import express from 'express'
import { body, header, param, query, ValidationChain } from 'express-validator'
import { getResumableUploadPath } from '@server/helpers/upload'
import { isAbleToUploadVideo } from '@server/lib/user'
-import * as express from 'express'
+import express from 'express'
import { query } from 'express-validator'
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { isWebfingerLocalResourceValid } from '../../helpers/custom-validators/webfinger'
-import * as memoizee from 'memoizee'
+import memoizee from 'memoizee'
import { AllowNull, Column, Default, DefaultScope, HasOne, IsInt, Model, Table } from 'sequelize-typescript'
import { AttributesOnly } from '@shared/core-utils'
import { AccountModel } from '../account/account'
import { Model } from 'sequelize-typescript'
-import * as Bluebird from 'bluebird'
import { logger } from '@server/helpers/logger'
type ModelCacheType =
if (cache.has(key)) {
logger.debug('Model cache hit for %s -> %s.', cacheType, key)
- return Bluebird.resolve<T>(cache.get(key))
+ return Promise.resolve<T>(cache.get(key))
}
return fun().then(m => {
if (accountId) {
whereAnd.push({
- [Op.eq]: accountId
+ accountId
})
}
import { remove } from 'fs-extra'
-import * as memoizee from 'memoizee'
+import memoizee from 'memoizee'
import { join } from 'path'
import { FindOptions, Op, Transaction } from 'sequelize'
import {
-import * as memoizee from 'memoizee'
+import memoizee from 'memoizee'
import { join } from 'path'
import { Op } from 'sequelize'
import {
-import * as Sequelize from 'sequelize'
-import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Table } from 'sequelize-typescript'
+import { literal, Op } from 'sequelize'
+import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Model, Table } from 'sequelize-typescript'
import { AttributesOnly } from '@shared/core-utils'
import { VideoModel } from './video'
createdAt: Date
@AllowNull(false)
- @Column(Sequelize.DATE)
+ @Column(DataType.DATE)
startDate: Date
@AllowNull(false)
- @Column(Sequelize.DATE)
+ @Column(DataType.DATE)
endDate: Date
@AllowNull(false)
const query = {
where: {
startDate: {
- [Sequelize.Op.lt]: beforeDate
+ [Op.lt]: beforeDate
},
videoId: {
- [Sequelize.Op.in]: Sequelize.literal('(SELECT "id" FROM "video" WHERE "remote" IS TRUE)')
+ [Op.in]: literal('(SELECT "id" FROM "video" WHERE "remote" IS TRUE)')
}
}
}
-import * as Bluebird from 'bluebird'
+import Bluebird from 'bluebird'
import { remove } from 'fs-extra'
import { maxBy, minBy } from 'lodash'
import { join } from 'path'
import 'mocha'
import * as chai from 'chai'
import { readdir } from 'fs-extra'
-import * as magnetUtil from 'magnet-uri'
+import magnetUtil from 'magnet-uri'
import { basename, join } from 'path'
import {
checkSegmentHash,
import 'mocha'
-import * as request from 'supertest'
+import request from 'supertest'
import { cleanupTests, createSingleServer, PeerTubeServer } from '@shared/extra-utils'
import { HttpStatusCode } from '@shared/models'
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await,@typescript-eslint/no-floating-promises */
import 'mocha'
-import * as magnetUtil from 'magnet-uri'
-import * as WebTorrent from 'webtorrent'
+import magnetUtil from 'magnet-uri'
+import WebTorrent from 'webtorrent'
import { cleanupTests, createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
describe('Test tracker', function () {
import 'mocha'
import * as chai from 'chai'
-import * as request from 'supertest'
+import request from 'supertest'
import {
buildAbsoluteFixturePath,
checkTmpIsEmpty,
import 'mocha'
import * as chai from 'chai'
-import * as xmlParser from 'fast-xml-parser'
+import { parse, validate } from 'fast-xml-parser'
import {
cleanupTests,
createMultipleServers,
it('Should contain a valid enclosure (covers RSS 2.0 endpoint)', async function () {
for (const server of servers) {
const rss = await server.feed.getXML({ feed: 'videos' })
- expect(xmlParser.validate(rss)).to.be.true
+ expect(validate(rss)).to.be.true
- const xmlDoc = xmlParser.parse(rss, { parseAttributeValue: true, ignoreAttributes: false })
+ const xmlDoc = parse(rss, { parseAttributeValue: true, ignoreAttributes: false })
const enclosure = xmlDoc.rss.channel.item[0].enclosure
expect(enclosure).to.exist
registerTSPaths()
import { OptionValues, program } from 'commander'
-import * as prompt from 'prompt'
import { assignToken, buildServer, getNetrc, getSettings, writeSettings } from './cli'
import { isUserUsernameValid } from '../helpers/custom-validators/users'
-import * as CliTable3 from 'cli-table3'
+import CliTable3 from 'cli-table3'
+
+import prompt = require('prompt')
async function delInstance (url: string) {
const [ settings, netrc ] = await Promise.all([ getSettings(), getNetrc() ])
import { remove } from 'fs-extra'
import { truncate } from 'lodash'
import { join } from 'path'
-import * as prompt from 'prompt'
import { promisify } from 'util'
import { YoutubeDL } from '@server/helpers/youtube-dl'
import { sha256 } from '../helpers/core-utils'
} from './cli'
import { PeerTubeServer } from '@shared/extra-utils'
+import prompt = require('prompt')
+
const processOptions = {
maxBuffer: Infinity
}
import { assignToken, buildServer, getServerCredentials } from './cli'
import { PluginType } from '../../shared/models'
import { isAbsolute } from 'path'
-import * as CliTable3 from 'cli-table3'
+import CliTable3 from 'cli-table3'
program
.name('plugins')
import { registerTSPaths } from '../helpers/register-ts-paths'
registerTSPaths()
-import * as CliTable3 from 'cli-table3'
+import CliTable3 from 'cli-table3'
import { Command, program } from 'commander'
import { uniq } from 'lodash'
import { URL } from 'url'
-import * as express from 'express'
+import express from 'express'
import { UserRole } from '@shared/models'
import { MOAuthToken, MUser } from '../models'
import { expect } from 'chai'
-import * as ffmpeg from 'fluent-ffmpeg'
+import ffmpeg from 'fluent-ffmpeg'
import { ensureDir, pathExists } from 'fs-extra'
import { dirname } from 'path'
import { getVideoFileBitrate, getVideoFileFPS, getVideoFileResolution } from '@server/helpers/ffprobe-utils'
import { readFile } from 'fs-extra'
-import * as parseTorrent from 'parse-torrent'
+import parseTorrent from 'parse-torrent'
import { basename, join } from 'path'
import * as WebTorrent from 'webtorrent'
import { VideoFile } from '@shared/models'
import { ChildProcess } from 'child_process'
+import MailDev from 'maildev'
import { randomInt } from '@shared/core-utils'
import { parallelTests } from '../miscs'
-const MailDev = require('maildev')
-
class MockSmtpServer {
private static instance: MockSmtpServer
-import * as express from 'express'
+import express from 'express'
import { randomInt } from '@shared/core-utils'
export class MockInstancesIndex {
-import * as express from 'express'
+import express from 'express'
import { randomInt } from '@shared/core-utils'
export class MockJoinPeerTubeVersions {
-import * as express from 'express'
+import express from 'express'
import got, { RequestError } from 'got'
import { Server } from 'http'
import { pipeline } from 'stream'
-import * as express from 'express'
+import express, { Request, Response } from 'express'
import { Server } from 'http'
import { randomInt } from '@shared/core-utils'
return new Promise<number>(res => {
const app = express()
- app.get('/blocklist', (req: express.Request, res: express.Response) => {
+ app.get('/blocklist', (req: Request, res: Response) => {
return res.json(this.body)
})
import { createServer, Server } from 'http'
-import * as proxy from 'proxy'
+import proxy from 'proxy'
import { randomInt } from '@shared/core-utils'
class MockProxy {
/* eslint-disable @typescript-eslint/no-floating-promises */
import { decode } from 'querystring'
-import * as request from 'supertest'
+import request from 'supertest'
import { URL } from 'url'
import { HttpStatusCode } from '@shared/models'
import { buildAbsoluteFixturePath } from '../miscs/tests'
import { expect } from 'chai'
-import * as request from 'supertest'
+import request from 'supertest'
import { HttpStatusCode } from '@shared/models'
async function testCaptionFile (url: string, captionPath: string, containsString: string) {
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
import { expect } from 'chai'
-import * as ffmpeg from 'fluent-ffmpeg'
+import ffmpeg, { FfmpegCommand } from 'fluent-ffmpeg'
import { pathExists, readdir } from 'fs-extra'
import { join } from 'path'
import { buildAbsoluteFixturePath, wait } from '../miscs'
return command
}
-function waitFfmpegUntilError (command: ffmpeg.FfmpegCommand, successAfterMS = 10000) {
+function waitFfmpegUntilError (command: FfmpegCommand, successAfterMS = 10000) {
return new Promise<void>((res, rej) => {
command.on('error', err => {
return rej(err)
})
}
-async function testFfmpegStreamError (command: ffmpeg.FfmpegCommand, shouldHaveError: boolean) {
+async function testFfmpegStreamError (command: FfmpegCommand, shouldHaveError: boolean) {
let error: Error
try {
if (!shouldHaveError && error) throw error
}
-async function stopFfmpeg (command: ffmpeg.FfmpegCommand) {
+async function stopFfmpeg (command: FfmpegCommand) {
command.kill('SIGINT')
await wait(500)
"importHelpers": true,
"removeComments": true,
"strictBindCallApply": true,
+ "esModuleInterop": true,
"outDir": "./dist",
"lib": [
"dom",
dependencies:
"@types/node" "*"
+"@types/bencode@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@types/bencode/-/bencode-2.0.0.tgz#75161d132f15a912aa49ea0c861c53ddb8539a76"
+ integrity sha512-ntDggX576d+MULpy9ApOy3OI9GqO86H+T9zEwYk3fdVaLi85M/1l+GVR/UWfITg9czcOO2SxZJyzyTOrI8UsFA==
+ dependencies:
+ "@types/node" "*"
+
"@types/bittorrent-protocol@*":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@types/bittorrent-protocol/-/bittorrent-protocol-3.1.1.tgz#76bfd5903d0f7c7b23289763f39aca9337b3b723"
resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
+"@types/create-torrent@^5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@types/create-torrent/-/create-torrent-5.0.0.tgz#bd3def0e133390049113c09b0c263a6d6cca2852"
+ integrity sha512-mZbaThIOP3NQru6/oi7I3hcWSu8/d0/4os13JVWGAU5hoAZIUc6MbeloHAX5nnnIZgn7YIp5PpNRf9Im/QvAvA==
+ dependencies:
+ "@types/node" "*"
+
"@types/express-rate-limit@^5.0.0":
version "5.1.3"
resolved "https://registry.yarnpkg.com/@types/express-rate-limit/-/express-rate-limit-5.1.3.tgz#79f2ca40d90455a5798da6f8e06d8a3d35f4a1d6"