From ba5a8d89bbf049e4afc41543bcc072cccdb02669 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 3 Feb 2021 09:33:05 +0100 Subject: Update server dependencies --- server/helpers/captions-utils.ts | 2 +- server/helpers/core-utils.ts | 10 +-- server/helpers/custom-jsonld-signature.ts | 1 + server/helpers/logger.ts | 2 +- server/helpers/webtorrent.ts | 2 +- server/helpers/youtube-dl.ts | 2 +- server/lib/activitypub/inbox-manager.ts | 1 + server/lib/avatar.ts | 2 +- server/lib/hls.ts | 2 +- server/lib/redis.ts | 2 +- server/middlewares/async.ts | 5 +- server/middlewares/oauth.ts | 2 +- server/middlewares/validators/oembed.ts | 2 +- .../validators/videos/video-playlists.ts | 23 +++--- server/middlewares/validators/videos/videos.ts | 5 +- server/models/account/user-notification.ts | 94 ++++++++++++---------- server/models/video/video-format-utils.ts | 6 +- server/tools/cli.ts | 52 ++++++------ server/tools/peertube-auth.ts | 20 +++-- server/tools/peertube-get-access-token.ts | 22 ++--- server/tools/peertube-import-videos.ts | 44 +++++----- server/tools/peertube-plugins.ts | 45 ++++++----- server/tools/peertube-redundancy.ts | 25 +++--- server/tools/peertube-repl.ts | 1 - server/tools/peertube-upload.ts | 22 ++--- server/tools/peertube-watch.ts | 38 ++++----- server/tools/peertube.ts | 17 ++-- server/types/express.ts | 3 + 28 files changed, 233 insertions(+), 219 deletions(-) create mode 100644 server/types/express.ts (limited to 'server') diff --git a/server/helpers/captions-utils.ts b/server/helpers/captions-utils.ts index 0dad23759..7cbfb3561 100644 --- a/server/helpers/captions-utils.ts +++ b/server/helpers/captions-utils.ts @@ -30,7 +30,7 @@ export { // --------------------------------------------------------------------------- function convertSrtToVtt (source: string, destination: string) { - return new Promise((res, rej) => { + return new Promise((res, rej) => { const file = createReadStream(source) const converter = srt2vtt() const writer = createWriteStream(destination) diff --git a/server/helpers/core-utils.ts b/server/helpers/core-utils.ts index e1c15a6eb..935fd22d9 100644 --- a/server/helpers/core-utils.ts +++ b/server/helpers/core-utils.ts @@ -5,12 +5,12 @@ Useful to avoid circular dependencies. */ -import { createHash, HexBase64Latin1Encoding, randomBytes } from 'crypto' +import { exec, ExecOptions } from 'child_process' +import { BinaryToTextEncoding, createHash, randomBytes } from 'crypto' +import { truncate } from 'lodash' import { basename, isAbsolute, join, resolve } from 'path' import * as pem from 'pem' import { URL } from 'url' -import { truncate } from 'lodash' -import { exec, ExecOptions } from 'child_process' const objectConverter = (oldObject: any, keyConverter: (e: string) => string, valueConverter: (e: any) => any) => { if (!oldObject || typeof oldObject !== 'object') { @@ -205,11 +205,11 @@ function peertubeTruncate (str: string, options: { length: number, separator?: R return truncate(str, options) } -function sha256 (str: string | Buffer, encoding: HexBase64Latin1Encoding = 'hex') { +function sha256 (str: string | Buffer, encoding: BinaryToTextEncoding = 'hex') { return createHash('sha256').update(str).digest(encoding) } -function sha1 (str: string | Buffer, encoding: HexBase64Latin1Encoding = 'hex') { +function sha1 (str: string | Buffer, encoding: BinaryToTextEncoding = 'hex') { return createHash('sha1').update(str).digest(encoding) } diff --git a/server/helpers/custom-jsonld-signature.ts b/server/helpers/custom-jsonld-signature.ts index 749c50cb3..56f10086c 100644 --- a/server/helpers/custom-jsonld-signature.ts +++ b/server/helpers/custom-jsonld-signature.ts @@ -76,6 +76,7 @@ const lru = new AsyncLRU({ } }) +/* eslint-disable no-import-assign */ jsonld.documentLoader = (url) => { return new Promise((res, rej) => { lru.get(url, (err, value) => { diff --git a/server/helpers/logger.ts b/server/helpers/logger.ts index 746b2e0a6..6917a64d9 100644 --- a/server/helpers/logger.ts +++ b/server/helpers/logger.ts @@ -61,7 +61,7 @@ const consoleLoggerFormat = winston.format.printf(info => { if (CONFIG.LOG.PRETTIFY_SQL) { additionalInfos += '\n' + sqlFormat(info.sql, { language: 'sql', - ident: ' ' + indent: ' ' }) } else { additionalInfos += ' - ' + info.sql diff --git a/server/helpers/webtorrent.ts b/server/helpers/webtorrent.ts index 089954e32..9c5df2083 100644 --- a/server/helpers/webtorrent.ts +++ b/server/helpers/webtorrent.ts @@ -149,7 +149,7 @@ function safeWebtorrentDestroy ( downloadedFile?: { directoryPath: string, filepath: string }, torrentName?: string ) { - return new Promise(res => { + return new Promise(res => { webtorrent.destroy(err => { // Delete torrent file if (torrentName) { diff --git a/server/helpers/youtube-dl.ts b/server/helpers/youtube-dl.ts index 3a9e57561..8537a5772 100644 --- a/server/helpers/youtube-dl.ts +++ b/server/helpers/youtube-dl.ts @@ -195,7 +195,7 @@ async function updateYoutubeDLBinary () { await ensureDir(binDirectory) - return new Promise(res => { + return new Promise(res => { request.get(url, { followRedirect: false }, (err, result) => { if (err) { logger.error('Cannot update youtube-dl.', { err }) diff --git a/server/lib/activitypub/inbox-manager.ts b/server/lib/activitypub/inbox-manager.ts index 19e112f91..6d9bf7cf0 100644 --- a/server/lib/activitypub/inbox-manager.ts +++ b/server/lib/activitypub/inbox-manager.ts @@ -41,6 +41,7 @@ class InboxManager { addInboxMessage (options: QueueParam) { this.inboxQueue.push(options) + .catch(err => logger.error('Cannot add options in inbox queue.', { options, err })) } static get Instance () { diff --git a/server/lib/avatar.ts b/server/lib/avatar.ts index e79cd1546..86f1e7bdb 100644 --- a/server/lib/avatar.ts +++ b/server/lib/avatar.ts @@ -65,7 +65,7 @@ const downloadImageQueue = queue((task, cb) => { }, QUEUE_CONCURRENCY.AVATAR_PROCESS_IMAGE) function pushAvatarProcessInQueue (task: DownloadImageQueueTask) { - return new Promise((res, rej) => { + return new Promise((res, rej) => { downloadImageQueue.push(task, err => { if (err) return rej(err) diff --git a/server/lib/hls.ts b/server/lib/hls.ts index 9ea83f337..ef489097a 100644 --- a/server/lib/hls.ts +++ b/server/lib/hls.ts @@ -111,7 +111,7 @@ function downloadPlaylistSegments (playlistUrl: string, destinationDir: string, logger.info('Importing HLS playlist %s', playlistUrl) - return new Promise(async (res, rej) => { + return new Promise(async (res, rej) => { const tmpDirectory = join(CONFIG.STORAGE.TMP_DIR, await generateRandomString(10)) await ensureDir(tmpDirectory) diff --git a/server/lib/redis.ts b/server/lib/redis.ts index 257cce141..62641e313 100644 --- a/server/lib/redis.ts +++ b/server/lib/redis.ts @@ -263,7 +263,7 @@ class Redis { } private addToSet (key: string, value: string) { - return new Promise((res, rej) => { + return new Promise((res, rej) => { this.client.sadd(this.prefix + key, value, err => err ? rej(err) : res()) }) } diff --git a/server/middlewares/async.ts b/server/middlewares/async.ts index 25b22596c..3a1bdabb8 100644 --- a/server/middlewares/async.ts +++ b/server/middlewares/async.ts @@ -1,12 +1,13 @@ import { eachSeries } from 'async' import { NextFunction, Request, RequestHandler, Response } from 'express' -import { retryTransactionWrapper } from '../helpers/database-utils' import { ValidationChain } from 'express-validator' +import { ExpressPromiseHandler } from '@server/types/express' +import { retryTransactionWrapper } from '../helpers/database-utils' // Syntactic sugar to avoid try/catch in express controllers // Thanks: https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016 -export type RequestPromiseHandler = ValidationChain | ((req: Request, res: Response, next: NextFunction) => Promise) +export type RequestPromiseHandler = ValidationChain | ExpressPromiseHandler function asyncMiddleware (fun: RequestPromiseHandler | RequestPromiseHandler[]) { return (req: Request, res: Response, next: NextFunction) => { diff --git a/server/middlewares/oauth.ts b/server/middlewares/oauth.ts index ffc1b7ca9..47799153a 100644 --- a/server/middlewares/oauth.ts +++ b/server/middlewares/oauth.ts @@ -49,7 +49,7 @@ function authenticateSocket (socket: Socket, next: (err?: any) => void) { } function authenticatePromiseIfNeeded (req: express.Request, res: express.Response, authenticateInQuery = false) { - return new Promise(resolve => { + return new Promise(resolve => { // Already authenticated? (or tried to) if (res.locals.oauth?.token.User) return resolve() diff --git a/server/middlewares/validators/oembed.ts b/server/middlewares/validators/oembed.ts index 86623efcd..2a7dc257b 100644 --- a/server/middlewares/validators/oembed.ts +++ b/server/middlewares/validators/oembed.ts @@ -14,7 +14,7 @@ import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-code const startVideoPlaylistsURL = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch', 'playlist') + '/' const startVideosURL = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch') + '/' -const watchRegex = new RegExp('([^/]+)$') +const watchRegex = /([^/]+)$/ const isURLOptions = { require_host: true, require_tld: true diff --git a/server/middlewares/validators/videos/video-playlists.ts b/server/middlewares/validators/videos/video-playlists.ts index c7a6f68e3..0fba4f5fd 100644 --- a/server/middlewares/validators/videos/video-playlists.ts +++ b/server/middlewares/validators/videos/video-playlists.ts @@ -1,10 +1,11 @@ import * as express from 'express' import { body, param, query, ValidationChain } from 'express-validator' +import { ExpressPromiseHandler } from '@server/types/express' +import { MUserAccountId } from '@server/types/models' import { UserRight, VideoPlaylistCreate, VideoPlaylistUpdate } from '../../../../shared' -import { logger } from '../../../helpers/logger' -import { areValidationErrors } from '../utils' -import { isVideoImage } from '../../../helpers/custom-validators/videos' -import { CONSTRAINTS_FIELDS } from '../../../initializers/constants' +import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' +import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model' +import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model' import { isArrayOf, isIdOrUUIDValid, @@ -21,15 +22,15 @@ import { isVideoPlaylistTimestampValid, isVideoPlaylistTypeValid } from '../../../helpers/custom-validators/video-playlists' +import { isVideoImage } from '../../../helpers/custom-validators/videos' import { cleanUpReqFiles } from '../../../helpers/express-utils' -import { VideoPlaylistElementModel } from '../../../models/video/video-playlist-element' -import { authenticatePromiseIfNeeded } from '../../oauth' -import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/video-playlist-privacy.model' -import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/video-playlist-type.model' +import { logger } from '../../../helpers/logger' import { doesVideoChannelIdExist, doesVideoExist, doesVideoPlaylistExist, VideoPlaylistFetchType } from '../../../helpers/middlewares' +import { CONSTRAINTS_FIELDS } from '../../../initializers/constants' +import { VideoPlaylistElementModel } from '../../../models/video/video-playlist-element' import { MVideoPlaylist } from '../../../types/models/video/video-playlist' -import { MUserAccountId } from '@server/types/models' -import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' +import { authenticatePromiseIfNeeded } from '../../oauth' +import { areValidationErrors } from '../utils' const videoPlaylistsAddValidator = getCommonPlaylistEditAttributes().concat([ body('displayName') @@ -395,7 +396,7 @@ function getCommonPlaylistEditAttributes () { body('videoChannelId') .optional() .customSanitizer(toIntOrNull) - ] as (ValidationChain | express.Handler)[] + ] as (ValidationChain | ExpressPromiseHandler)[] } function checkUserCanManageVideoPlaylist (user: MUserAccountId, videoPlaylist: MVideoPlaylist, right: UserRight, res: express.Response) { diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts index 84e309bec..26a671a1e 100644 --- a/server/middlewares/validators/videos/videos.ts +++ b/server/middlewares/validators/videos/videos.ts @@ -2,8 +2,10 @@ import * as express from 'express' import { body, param, query, ValidationChain } from 'express-validator' import { isAbleToUploadVideo } from '@server/lib/user' import { getServerActor } from '@server/models/application/application' +import { ExpressPromiseHandler } from '@server/types/express' import { MVideoFullLight } from '@server/types/models' import { ServerErrorCode, UserRight, VideoChangeOwnershipStatus, VideoPrivacy } from '../../../../shared' +import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/video-change-ownership-accept.model' import { exists, @@ -54,7 +56,6 @@ import { AccountModel } from '../../../models/account/account' import { VideoModel } from '../../../models/video/video' import { authenticatePromiseIfNeeded } from '../../oauth' import { areValidationErrors } from '../utils' -import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes' const videosAddValidator = getCommonVideoEditAttributes().concat([ body('videofile') @@ -411,7 +412,7 @@ function getCommonVideoEditAttributes () { .optional() .customSanitizer(toIntOrNull) .custom(isScheduleVideoUpdatePrivacyValid).withMessage('Should have correct schedule update privacy') - ] as (ValidationChain | express.Handler)[] + ] as (ValidationChain | ExpressPromiseHandler)[] } const commonVideosFiltersValidator = [ diff --git a/server/models/account/user-notification.ts b/server/models/account/user-notification.ts index 52b792a5b..add129644 100644 --- a/server/models/account/user-notification.ts +++ b/server/models/account/user-notification.ts @@ -469,27 +469,33 @@ export class UserNotificationModel extends Model { ? Object.assign(this.formatVideo(this.Video), { channel: this.formatActor(this.Video.VideoChannel) }) : undefined - const videoImport = this.VideoImport ? { - id: this.VideoImport.id, - video: this.VideoImport.Video ? this.formatVideo(this.VideoImport.Video) : undefined, - torrentName: this.VideoImport.torrentName, - magnetUri: this.VideoImport.magnetUri, - targetUrl: this.VideoImport.targetUrl - } : undefined - - const comment = this.Comment ? { - id: this.Comment.id, - threadId: this.Comment.getThreadId(), - account: this.formatActor(this.Comment.Account), - video: this.formatVideo(this.Comment.Video) - } : undefined + const videoImport = this.VideoImport + ? { + id: this.VideoImport.id, + video: this.VideoImport.Video ? this.formatVideo(this.VideoImport.Video) : undefined, + torrentName: this.VideoImport.torrentName, + magnetUri: this.VideoImport.magnetUri, + targetUrl: this.VideoImport.targetUrl + } + : undefined + + const comment = this.Comment + ? { + id: this.Comment.id, + threadId: this.Comment.getThreadId(), + account: this.formatActor(this.Comment.Account), + video: this.formatVideo(this.Comment.Video) + } + : undefined const abuse = this.Abuse ? this.formatAbuse(this.Abuse) : undefined - const videoBlacklist = this.VideoBlacklist ? { - id: this.VideoBlacklist.id, - video: this.formatVideo(this.VideoBlacklist.Video) - } : undefined + const videoBlacklist = this.VideoBlacklist + ? { + id: this.VideoBlacklist.id, + video: this.formatVideo(this.VideoBlacklist.Video) + } + : undefined const account = this.Account ? this.formatActor(this.Account) : undefined @@ -498,23 +504,25 @@ export class UserNotificationModel extends Model { Group: 'channel' as 'channel', Person: 'account' as 'account' } - const actorFollow = this.ActorFollow ? { - id: this.ActorFollow.id, - state: this.ActorFollow.state, - follower: { - id: this.ActorFollow.ActorFollower.Account.id, - displayName: this.ActorFollow.ActorFollower.Account.getDisplayName(), - name: this.ActorFollow.ActorFollower.preferredUsername, - avatar: this.ActorFollow.ActorFollower.Avatar ? { path: this.ActorFollow.ActorFollower.Avatar.getStaticPath() } : undefined, - host: this.ActorFollow.ActorFollower.getHost() - }, - following: { - type: actorFollowingType[this.ActorFollow.ActorFollowing.type], - displayName: (this.ActorFollow.ActorFollowing.VideoChannel || this.ActorFollow.ActorFollowing.Account).getDisplayName(), - name: this.ActorFollow.ActorFollowing.preferredUsername, - host: this.ActorFollow.ActorFollowing.getHost() + const actorFollow = this.ActorFollow + ? { + id: this.ActorFollow.id, + state: this.ActorFollow.state, + follower: { + id: this.ActorFollow.ActorFollower.Account.id, + displayName: this.ActorFollow.ActorFollower.Account.getDisplayName(), + name: this.ActorFollow.ActorFollower.preferredUsername, + avatar: this.ActorFollow.ActorFollower.Avatar ? { path: this.ActorFollow.ActorFollower.Avatar.getStaticPath() } : undefined, + host: this.ActorFollow.ActorFollower.getHost() + }, + following: { + type: actorFollowingType[this.ActorFollow.ActorFollowing.type], + displayName: (this.ActorFollow.ActorFollowing.VideoChannel || this.ActorFollow.ActorFollowing.Account).getDisplayName(), + name: this.ActorFollow.ActorFollowing.preferredUsername, + host: this.ActorFollow.ActorFollowing.getHost() + } } - } : undefined + : undefined return { id: this.id, @@ -541,15 +549,17 @@ export class UserNotificationModel extends Model { } formatAbuse (this: UserNotificationModelForApi, abuse: UserNotificationIncludes.AbuseInclude) { - const commentAbuse = abuse.VideoCommentAbuse?.VideoComment ? { - threadId: abuse.VideoCommentAbuse.VideoComment.getThreadId(), - - video: { - id: abuse.VideoCommentAbuse.VideoComment.Video.id, - name: abuse.VideoCommentAbuse.VideoComment.Video.name, - uuid: abuse.VideoCommentAbuse.VideoComment.Video.uuid + const commentAbuse = abuse.VideoCommentAbuse?.VideoComment + ? { + threadId: abuse.VideoCommentAbuse.VideoComment.getThreadId(), + + video: { + id: abuse.VideoCommentAbuse.VideoComment.Video.id, + name: abuse.VideoCommentAbuse.VideoComment.Video.name, + uuid: abuse.VideoCommentAbuse.VideoComment.Video.uuid + } } - } : undefined + : undefined const videoAbuse = abuse.VideoAbuse?.Video ? this.formatVideo(abuse.VideoAbuse.Video) : undefined diff --git a/server/models/video/video-format-utils.ts b/server/models/video/video-format-utils.ts index a1f022fb4..77b8bcfe3 100644 --- a/server/models/video/video-format-utils.ts +++ b/server/models/video/video-format-utils.ts @@ -82,9 +82,9 @@ function videoModelToFormattedJSON (video: MVideoFormattable, options?: VideoFor account: video.VideoChannel.Account.toFormattedSummaryJSON(), channel: video.VideoChannel.toFormattedSummaryJSON(), - userHistory: userHistory ? { - currentTime: userHistory.currentTime - } : undefined, + userHistory: userHistory + ? { currentTime: userHistory.currentTime } + : undefined, // Can be added by external plugins pluginData: (video as any).pluginData diff --git a/server/tools/cli.ts b/server/tools/cli.ts index d5416fc38..cc89fe46e 100644 --- a/server/tools/cli.ts +++ b/server/tools/cli.ts @@ -69,23 +69,25 @@ function deleteSettings () { } function getRemoteObjectOrDie ( - program: any, + program: CommanderStatic, settings: Settings, netrc: Netrc ): { url: string, username: string, password: string } { - if (!program['url'] || !program['username'] || !program['password']) { + const options = program.opts() + + if (!options.url || !options.username || !options.password) { // No remote and we don't have program parameters: quit if (settings.remotes.length === 0 || Object.keys(netrc.machines).length === 0) { - if (!program['url']) console.error('--url field is required.') - if (!program['username']) console.error('--username field is required.') - if (!program['password']) console.error('--password field is required.') + if (!options.url) console.error('--url field is required.') + if (!options.username) console.error('--username field is required.') + if (!options.password) console.error('--password field is required.') return process.exit(-1) } - let url: string = program['url'] - let username: string = program['username'] - let password: string = program['password'] + let url: string = options.url + let username: string = options.username + let password: string = options.password if (!url && settings.default !== -1) url = settings.remotes[settings.default] @@ -98,9 +100,9 @@ function getRemoteObjectOrDie ( } return { - url: program['url'], - username: program['username'], - password: program['password'] + url: options.url, + username: options.username, + password: options.password } } @@ -127,6 +129,8 @@ function buildCommonVideoOptions (command: CommanderStatic) { } async function buildVideoAttributesFromCommander (url: string, command: CommanderStatic, defaultAttributes: any = {}) { + const options = command.opts() + const defaultBooleanAttributes = { nsfw: false, commentsEnabled: true, @@ -137,8 +141,8 @@ async function buildVideoAttributesFromCommander (url: string, command: Commande const booleanAttributes: { [id in keyof typeof defaultBooleanAttributes]: boolean } | {} = {} for (const key of Object.keys(defaultBooleanAttributes)) { - if (command[key] !== undefined) { - booleanAttributes[key] = command[key] + if (options[key] !== undefined) { + booleanAttributes[key] = options[key] } else if (defaultAttributes[key] !== undefined) { booleanAttributes[key] = defaultAttributes[key] } else { @@ -147,20 +151,20 @@ async function buildVideoAttributesFromCommander (url: string, command: Commande } const videoAttributes = { - name: command['videoName'] || defaultAttributes.name, - category: command['category'] || defaultAttributes.category || undefined, - licence: command['licence'] || defaultAttributes.licence || undefined, - language: command['language'] || defaultAttributes.language || undefined, - privacy: command['privacy'] || defaultAttributes.privacy || VideoPrivacy.PUBLIC, - support: command['support'] || defaultAttributes.support || undefined, - description: command['videoDescription'] || defaultAttributes.description || undefined, - tags: command['tags'] || defaultAttributes.tags || undefined + name: options.videoName || defaultAttributes.name, + category: options.category || defaultAttributes.category || undefined, + licence: options.licence || defaultAttributes.licence || undefined, + language: options.language || defaultAttributes.language || undefined, + privacy: options.privacy || defaultAttributes.privacy || VideoPrivacy.PUBLIC, + support: options.support || defaultAttributes.support || undefined, + description: options.videoDescription || defaultAttributes.description || undefined, + tags: options.tags || defaultAttributes.tags || undefined } Object.assign(videoAttributes, booleanAttributes) - if (command['channelName']) { - const res = await getVideoChannel(url, command['channelName']) + if (options.channelName) { + const res = await getVideoChannel(url, options.channelName) const videoChannel: VideoChannel = res.body Object.assign(videoAttributes, { channelId: videoChannel.id }) @@ -173,7 +177,7 @@ async function buildVideoAttributesFromCommander (url: string, command: Commande return videoAttributes } -function getServerCredentials (program: any) { +function getServerCredentials (program: CommanderStatic) { return Promise.all([ getSettings(), getNetrc() ]) .then(([ settings, netrc ]) => { return getRemoteObjectOrDie(program, settings, netrc) diff --git a/server/tools/peertube-auth.ts b/server/tools/peertube-auth.ts index 6a0b89fe2..e54649002 100644 --- a/server/tools/peertube-auth.ts +++ b/server/tools/peertube-auth.ts @@ -66,7 +66,8 @@ program .option('-U, --username ', 'Username') .option('-p, --password ', 'Password') .option('--default', 'add the entry as the new default') - .action(options => { + .action((options: program.OptionValues) => { + /* eslint-disable no-import-assign */ prompt.override = options prompt.start() prompt.get({ @@ -102,7 +103,7 @@ program process.exit(-1) } - await setInstance(result.url, result.username, result.password, program['default']) + await setInstance(result.url, result.username, result.password, options.default) process.exit(0) }) @@ -160,15 +161,12 @@ program } }) -program.on('--help', function () { - console.log(' Examples:') - console.log() - console.log(' $ peertube auth add -u https://peertube.cpy.re -U "PEERTUBE_USER" --password "PEERTUBE_PASSWORD"') - console.log(' $ peertube auth add -u https://peertube.cpy.re -U root') - console.log(' $ peertube auth list') - console.log(' $ peertube auth del https://peertube.cpy.re') - console.log() -}) +program.addHelpText('after', '\n\n Examples:\n\n' + + ' $ peertube auth add -u https://peertube.cpy.re -U "PEERTUBE_USER" --password "PEERTUBE_PASSWORD"\n' + + ' $ peertube auth add -u https://peertube.cpy.re -U root\n' + + ' $ peertube auth list\n' + + ' $ peertube auth del https://peertube.cpy.re\n' +) if (!process.argv.slice(2).length) { program.outputHelp() diff --git a/server/tools/peertube-get-access-token.ts b/server/tools/peertube-get-access-token.ts index 6d47d8922..b2c278c48 100644 --- a/server/tools/peertube-get-access-token.ts +++ b/server/tools/peertube-get-access-token.ts @@ -10,25 +10,27 @@ program .option('-p, --password ', 'Password') .parse(process.argv) +const options = program.opts() + if ( - !program['url'] || - !program['username'] || - !program['password'] + !options.url || + !options.username || + !options.password ) { - if (!program['url']) console.error('--url field is required.') - if (!program['username']) console.error('--username field is required.') - if (!program['password']) console.error('--password field is required.') + if (!options.url) console.error('--url field is required.') + if (!options.username) console.error('--username field is required.') + if (!options.password) console.error('--password field is required.') process.exit(-1) } -getClient(program.url) +getClient(options.url) .then(res => { const server = { - url: program['url'], + url: options.url, user: { - username: program['username'], - password: program['password'] + username: options.username, + password: options.password }, client: { id: res.body.client_id, diff --git a/server/tools/peertube-import-videos.ts b/server/tools/peertube-import-videos.ts index 65798adb4..d91767c29 100644 --- a/server/tools/peertube-import-videos.ts +++ b/server/tools/peertube-import-videos.ts @@ -45,22 +45,24 @@ command .usage("[global options] [ -- youtube-dl options]") .parse(process.argv) -const log = getLogger(program['verbose']) +const options = command.opts() + +const log = getLogger(options.verbose) getServerCredentials(command) .then(({ url, username, password }) => { - if (!program['targetUrl']) { + if (!options.targetUrl) { exitError('--target-url field is required.') } try { - accessSync(program['tmpdir'], constants.R_OK | constants.W_OK) + accessSync(options.tmpdir, constants.R_OK | constants.W_OK) } catch (e) { - exitError('--tmpdir %s: directory does not exist or is not accessible', program['tmpdir']) + exitError('--tmpdir %s: directory does not exist or is not accessible', options.tmpdir) } url = normalizeTargetUrl(url) - program['targetUrl'] = normalizeTargetUrl(program['targetUrl']) + options.targetUrl = normalizeTargetUrl(options.targetUrl) const user = { username, password } @@ -76,7 +78,7 @@ async function run (url: string, user: UserInfo) { const youtubeDL = await safeGetYoutubeDL() - let info = await getYoutubeDLInfo(youtubeDL, program['targetUrl'], command.args) + let info = await getYoutubeDLInfo(youtubeDL, options.targetUrl, command.args) if (!Array.isArray(info)) info = [ info ] @@ -92,10 +94,10 @@ async function run (url: string, user: UserInfo) { let infoArray: any[] infoArray = [].concat(info) - if (program['first']) { - infoArray = infoArray.slice(0, program['first']) - } else if (program['last']) { - infoArray = infoArray.slice(-program['last']) + if (options.first) { + infoArray = infoArray.slice(0, options.first) + } else if (options.last) { + infoArray = infoArray.slice(-options.last) } // Normalize utf8 fields infoArray = infoArray.map(i => normalizeObject(i)) @@ -104,12 +106,12 @@ async function run (url: string, user: UserInfo) { for (const [ index, info ] of infoArray.entries()) { try { - if (index > 0 && program['waitInterval']) { - log.info("Wait for %d seconds before continuing.", program['waitInterval'] / 1000) - await new Promise(res => setTimeout(res, program['waitInterval'])) + if (index > 0 && options.waitInterval) { + log.info("Wait for %d seconds before continuing.", options.waitInterval / 1000) + await new Promise(res => setTimeout(res, options.waitInterval)) } await processVideo({ - cwd: program['tmpdir'], + cwd: options.tmpdir, url, user, youtubeInfo: info @@ -119,7 +121,7 @@ async function run (url: string, user: UserInfo) { } } - log.info('Video/s for user %s imported: %s', user.username, program['targetUrl']) + log.info('Video/s for user %s imported: %s', user.username, options.targetUrl) process.exit(0) } @@ -137,14 +139,14 @@ async function processVideo (parameters: { log.debug('Fetched object.', videoInfo) const originallyPublishedAt = buildOriginallyPublishedAt(videoInfo) - if (program['since'] && originallyPublishedAt && originallyPublishedAt.getTime() < program['since'].getTime()) { + if (options.since && originallyPublishedAt && originallyPublishedAt.getTime() < options.since.getTime()) { log.info('Video "%s" has been published before "%s", don\'t upload it.\n', - videoInfo.title, formatDate(program['since'])) + videoInfo.title, formatDate(options.since)) return } - if (program['until'] && originallyPublishedAt && originallyPublishedAt.getTime() > program['until'].getTime()) { + if (options.until && originallyPublishedAt && originallyPublishedAt.getTime() > options.until.getTime()) { log.info('Video "%s" has been published after "%s", don\'t upload it.\n', - videoInfo.title, formatDate(program['until'])) + videoInfo.title, formatDate(options.until)) return } @@ -161,11 +163,11 @@ async function processVideo (parameters: { log.info('Downloading video "%s"...', videoInfo.title) - const options = [ '-f', getYoutubeDLVideoFormat(), ...command.args, '-o', path ] + const youtubeDLOptions = [ '-f', getYoutubeDLVideoFormat(), ...command.args, '-o', path ] try { const youtubeDL = await safeGetYoutubeDL() const youtubeDLExec = promisify(youtubeDL.exec).bind(youtubeDL) - const output = await youtubeDLExec(videoInfo.url, options, processOptions) + const output = await youtubeDLExec(videoInfo.url, youtubeDLOptions, processOptions) log.info(output.join('\n')) await uploadVideoOnPeerTube({ cwd, diff --git a/server/tools/peertube-plugins.ts b/server/tools/peertube-plugins.ts index 05b75fab2..08e8cd713 100644 --- a/server/tools/peertube-plugins.ts +++ b/server/tools/peertube-plugins.ts @@ -10,6 +10,7 @@ import { getAdminTokenOrDie, getServerCredentials } from './cli' import { PeerTubePlugin } from '../../shared/models/plugins/peertube-plugin.model' import { isAbsolute } from 'path' import * as CliTable3 from 'cli-table3' +import commander = require('commander') program .name('plugins') @@ -33,7 +34,7 @@ program .option('-p, --password ', 'Password') .option('-P --path ', 'Install from a path') .option('-n, --npm-name ', 'Install from npm') - .action((options) => installPluginCLI(options)) + .action((options, command) => installPluginCLI(command, options)) program .command('update') @@ -43,7 +44,7 @@ program .option('-p, --password ', 'Password') .option('-P --path ', 'Update from a path') .option('-n, --npm-name ', 'Update from npm') - .action((options) => updatePluginCLI(options)) + .action((options, command) => updatePluginCLI(command, options)) program .command('uninstall') @@ -52,7 +53,7 @@ program .option('-U, --username ', 'Username') .option('-p, --password ', 'Password') .option('-n, --npm-name ', 'NPM plugin/theme name') - .action(options => uninstallPluginCLI(options)) + .action((options, command) => uninstallPluginCLI(command, options)) if (!process.argv.slice(2).length) { program.outputHelp() @@ -60,6 +61,8 @@ if (!process.argv.slice(2).length) { program.parse(process.argv) +const options = program.opts() + // ---------------------------------------------------------------------------- async function pluginsListCLI () { @@ -67,8 +70,8 @@ async function pluginsListCLI () { const accessToken = await getAdminTokenOrDie(url, username, password) let pluginType: PluginType - if (program['onlyThemes']) pluginType = PluginType.THEME - if (program['onlyPlugins']) pluginType = PluginType.PLUGIN + if (options.onlyThemes) pluginType = PluginType.THEME + if (options.onlyPlugins) pluginType = PluginType.PLUGIN const res = await listPlugins({ url, @@ -101,27 +104,27 @@ async function pluginsListCLI () { process.exit(0) } -async function installPluginCLI (options: any) { - if (!options['path'] && !options['npmName']) { +async function installPluginCLI (command: commander.CommanderStatic, options: commander.OptionValues) { + if (!options.path && !options.npmName) { console.error('You need to specify the npm name or the path of the plugin you want to install.\n') program.outputHelp() process.exit(-1) } - if (options['path'] && !isAbsolute(options['path'])) { + if (options.path && !isAbsolute(options.path)) { console.error('Path should be absolute.') process.exit(-1) } - const { url, username, password } = await getServerCredentials(options) + const { url, username, password } = await getServerCredentials(command) const accessToken = await getAdminTokenOrDie(url, username, password) try { await installPlugin({ url, accessToken, - npmName: options['npmName'], - path: options['path'] + npmName: options.npmName, + path: options.path }) } catch (err) { console.error('Cannot install plugin.', err) @@ -132,27 +135,27 @@ async function installPluginCLI (options: any) { process.exit(0) } -async function updatePluginCLI (options: any) { - if (!options['path'] && !options['npmName']) { +async function updatePluginCLI (command: commander.CommanderStatic, options: commander.OptionValues) { + if (!options.path && !options.npmName) { console.error('You need to specify the npm name or the path of the plugin you want to update.\n') program.outputHelp() process.exit(-1) } - if (options['path'] && !isAbsolute(options['path'])) { + if (options.path && !isAbsolute(options.path)) { console.error('Path should be absolute.') process.exit(-1) } - const { url, username, password } = await getServerCredentials(options) + const { url, username, password } = await getServerCredentials(command) const accessToken = await getAdminTokenOrDie(url, username, password) try { await updatePlugin({ url, accessToken, - npmName: options['npmName'], - path: options['path'] + npmName: options.npmName, + path: options.path }) } catch (err) { console.error('Cannot update plugin.', err) @@ -163,21 +166,21 @@ async function updatePluginCLI (options: any) { process.exit(0) } -async function uninstallPluginCLI (options: any) { - if (!options['npmName']) { +async function uninstallPluginCLI (command: commander.CommanderStatic, options: commander.OptionValues) { + if (!options.npmName) { console.error('You need to specify the npm name of the plugin/theme you want to uninstall.\n') program.outputHelp() process.exit(-1) } - const { url, username, password } = await getServerCredentials(options) + const { url, username, password } = await getServerCredentials(command) const accessToken = await getAdminTokenOrDie(url, username, password) try { await uninstallPlugin({ url, accessToken, - npmName: options['npmName'] + npmName: options.npmName }) } catch (err) { console.error('Cannot uninstall plugin.', err) diff --git a/server/tools/peertube-redundancy.ts b/server/tools/peertube-redundancy.ts index fe482daf4..5bc80ddb9 100644 --- a/server/tools/peertube-redundancy.ts +++ b/server/tools/peertube-redundancy.ts @@ -14,6 +14,7 @@ import { URL } from 'url' import { uniq } from 'lodash' import bytes = require('bytes') +import commander = require('commander') program .name('plugins') @@ -42,7 +43,7 @@ program .option('-U, --username ', 'Username') .option('-p, --password ', 'Password') .option('-v, --video ', 'Video id to duplicate') - .action((options) => addRedundancyCLI(options)) + .action((options, command) => addRedundancyCLI(options, command)) program .command('remove') @@ -51,7 +52,7 @@ program .option('-U, --username ', 'Username') .option('-p, --password ', 'Password') .option('-v, --video ', 'Video id to remove from redundancies') - .action((options) => removeRedundancyCLI(options)) + .action((options, command) => removeRedundancyCLI(options, command)) if (!process.argv.slice(2).length) { program.outputHelp() @@ -104,13 +105,13 @@ async function listRedundanciesCLI (target: VideoRedundanciesTarget) { process.exit(0) } -async function addRedundancyCLI (options: { videoId: number }) { - const { url, username, password } = await getServerCredentials(program) +async function addRedundancyCLI (options: { video: number }, command: commander.CommanderStatic) { + const { url, username, password } = await getServerCredentials(command) const accessToken = await getAdminTokenOrDie(url, username, password) - if (!options['video'] || validator.isInt('' + options['video']) === false) { + if (!options.video || validator.isInt('' + options.video) === false) { console.error('You need to specify the video id to duplicate and it should be a number.\n') - program.outputHelp() + command.outputHelp() process.exit(-1) } @@ -118,7 +119,7 @@ async function addRedundancyCLI (options: { videoId: number }) { await addVideoRedundancy({ url, accessToken, - videoId: options['video'] + videoId: options.video }) console.log('Video will be duplicated by your instance!') @@ -137,17 +138,17 @@ async function addRedundancyCLI (options: { videoId: number }) { } } -async function removeRedundancyCLI (options: { videoId: number }) { - const { url, username, password } = await getServerCredentials(program) +async function removeRedundancyCLI (options: { video: number }, command: commander.CommanderStatic) { + const { url, username, password } = await getServerCredentials(command) const accessToken = await getAdminTokenOrDie(url, username, password) - if (!options['video'] || validator.isInt('' + options['video']) === false) { + if (!options.video || validator.isInt('' + options.video) === false) { console.error('You need to specify the video id to remove from your redundancies.\n') - program.outputHelp() + command.outputHelp() process.exit(-1) } - const videoId = parseInt(options['video'] + '', 10) + const videoId = parseInt(options.video + '', 10) let redundancies = await listVideoRedundanciesData(url, accessToken, 'my-videos') let videoRedundancy = redundancies.find(r => videoId === r.id) diff --git a/server/tools/peertube-repl.ts b/server/tools/peertube-repl.ts index a5c35e9ea..a38d51801 100644 --- a/server/tools/peertube-repl.ts +++ b/server/tools/peertube-repl.ts @@ -82,7 +82,6 @@ const start = async () => { } replServer.defineCommand('reset', resetCommand) replServer.defineCommand('r', resetCommand) - } start() diff --git a/server/tools/peertube-upload.ts b/server/tools/peertube-upload.ts index 8de952e7b..86c7f3d91 100644 --- a/server/tools/peertube-upload.ts +++ b/server/tools/peertube-upload.ts @@ -22,16 +22,18 @@ command .option('-f, --file ', 'Video absolute file path') .parse(process.argv) +const options = command.opts() + getServerCredentials(command) .then(({ url, username, password }) => { - if (!program['videoName'] || !program['file']) { - if (!program['videoName']) console.error('--video-name is required.') - if (!program['file']) console.error('--file is required.') + if (!options.videoName || !options.file) { + if (!options.videoName) console.error('--video-name is required.') + if (!options.file) console.error('--file is required.') process.exit(-1) } - if (isAbsolute(program['file']) === false) { + if (isAbsolute(options.file) === false) { console.error('File path should be absolute.') process.exit(-1) } @@ -46,21 +48,21 @@ getServerCredentials(command) async function run (url: string, username: string, password: string) { const accessToken = await getAccessToken(url, username, password) - await access(program['file'], constants.F_OK) + await access(options.file, constants.F_OK) - console.log('Uploading %s video...', program['videoName']) + console.log('Uploading %s video...', options.videoName) const videoAttributes = await buildVideoAttributesFromCommander(url, program) Object.assign(videoAttributes, { - fixture: program['file'], - thumbnailfile: program['thumbnail'], - previewfile: program['preview'] + fixture: options.file, + thumbnailfile: options.thumbnail, + previewfile: options.preview }) try { await uploadVideo(url, accessToken, videoAttributes) - console.log(`Video ${program['videoName']} uploaded.`) + console.log(`Video ${options.videoName} uploaded.`) process.exit(0) } catch (err) { console.error(require('util').inspect(err)) diff --git a/server/tools/peertube-watch.ts b/server/tools/peertube-watch.ts index b8e750a37..6d9cfa3b7 100644 --- a/server/tools/peertube-watch.ts +++ b/server/tools/peertube-watch.ts @@ -8,40 +8,30 @@ import { execSync } from 'child_process' program .name('watch') .arguments('') - .option('-g, --gui ', 'player type', /^(airplay|stdout|chromecast|mpv|vlc|mplayer|xbmc)$/i, 'vlc') + .addOption( + new program.Option('-g, --gui ', 'player type') + .default('vlc') + .choices([ 'airplay', 'stdout', 'chromecast', 'mpv', 'vlc', 'mplayer', 'xbmc' ]) + ) .option('-r, --resolution ', 'video resolution', '480') - .on('--help', function () { - console.log(' Available Players:') - console.log() - console.log(' - mpv') - console.log(' - mplayer') - console.log(' - vlc') - console.log(' - stdout') - console.log(' - xbmc') - console.log(' - airplay') - console.log(' - chromecast') - console.log() - console.log() - console.log(' Examples:') - console.log() - console.log(' $ peertube watch -g mpv https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10') - console.log(' $ peertube watch --gui stdout https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10') - console.log(' $ peertube watch https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10') - console.log() - }) - .action((url, cmd) => run(url, cmd)) + .addHelpText('after', '\n\n Examples:\n\n' + + ' $ peertube watch -g mpv https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10\n' + + ' $ peertube watch --gui stdout https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10\n' + + ' $ peertube watch https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10\n' + ) + .action((url, options) => run(url, options)) .parse(process.argv) -function run (url: string, program: any) { +function run (url: string, options: program.OptionValues) { if (!url) { console.error(' positional argument is required.') process.exit(-1) } const cmd = 'node ' + join(__dirname, 'node_modules', 'webtorrent-hybrid', 'bin', 'cmd.js') - const args = ` --${program.gui} ` + + const args = ` --${options.gui} ` + url.replace('videos/watch', 'download/torrents') + - `-${program.resolution}.torrent` + `-${options.resolution}.torrent` try { execSync(cmd + args) diff --git a/server/tools/peertube.ts b/server/tools/peertube.ts index 88dd5f7f6..655f07f0c 100644 --- a/server/tools/peertube.ts +++ b/server/tools/peertube.ts @@ -69,17 +69,12 @@ getSettings() : 'instance ' + settings.remotes[settings.default] + ' selected' program - .on('--help', function () { - console.log() - console.log(' State: ' + state) - console.log() - console.log(' Examples:') - console.log() - console.log(' $ peertube auth add -u "PEERTUBE_URL" -U "PEERTUBE_USER" --password "PEERTUBE_PASSWORD"') - console.log(' $ peertube up ') - console.log(' $ peertube watch https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10') - console.log() - }) + .addHelpText('after', '\n\n State: ' + state + '\n\n' + + ' Examples:\n\n' + + ' $ peertube auth add -u "PEERTUBE_URL" -U "PEERTUBE_USER" --password "PEERTUBE_PASSWORD"\n' + + ' $ peertube up \n' + + ' $ peertube watch https://peertube.cpy.re/videos/watch/e8a1af4e-414a-4d58-bfe6-2146eed06d10\n' + ) .parse(process.argv) }) .catch(err => console.error(err)) diff --git a/server/types/express.ts b/server/types/express.ts new file mode 100644 index 000000000..e72be36e4 --- /dev/null +++ b/server/types/express.ts @@ -0,0 +1,3 @@ +import { NextFunction, Request, Response } from 'express' + +export type ExpressPromiseHandler = (req: Request, res: Response, next: NextFunction) => Promise -- cgit v1.2.3