From 7a22a0a56aa75fbb1ba986a5d2c606e1343f30c2 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 5 May 2021 12:10:00 +0200 Subject: Add ability to search live videos --- shared/models/search/boolean-both-query.model.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'shared') diff --git a/shared/models/search/boolean-both-query.model.ts b/shared/models/search/boolean-both-query.model.ts index 57b0e8d44..d6a438249 100644 --- a/shared/models/search/boolean-both-query.model.ts +++ b/shared/models/search/boolean-both-query.model.ts @@ -1 +1,2 @@ export type BooleanBothQuery = 'true' | 'false' | 'both' +export type BooleanQuery = 'true' | 'false' -- cgit v1.2.3 From a66c2e3252d6cca8958959966f42494ded564023 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 7 May 2021 08:59:59 +0200 Subject: Fix remote actor creation date --- shared/models/activitypub/activitypub-actor.ts | 2 ++ 1 file changed, 2 insertions(+) (limited to 'shared') diff --git a/shared/models/activitypub/activitypub-actor.ts b/shared/models/activitypub/activitypub-actor.ts index c59be3f3b..09d4f7402 100644 --- a/shared/models/activitypub/activitypub-actor.ts +++ b/shared/models/activitypub/activitypub-actor.ts @@ -29,4 +29,6 @@ export interface ActivityPubActor { icon?: ActivityIconObject image?: ActivityIconObject + + published?: string } -- cgit v1.2.3 From a1bb73f9b591686b2ddfeb3291f305dae9f7fc6c Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 7 May 2021 11:53:46 +0200 Subject: Refactor a little bit live tests --- shared/extra-utils/server/config.ts | 15 ++++++++++++++- shared/extra-utils/users/users.ts | 23 +++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'shared') diff --git a/shared/extra-utils/server/config.ts b/shared/extra-utils/server/config.ts index 026a5e61c..b70110852 100644 --- a/shared/extra-utils/server/config.ts +++ b/shared/extra-utils/server/config.ts @@ -223,6 +223,18 @@ function updateCustomSubConfig (url: string, token: string, newConfig: DeepParti return updateCustomConfig(url, token, updateParams) } +function getCustomConfigResolutions (enabled: boolean) { + return { + '240p': enabled, + '360p': enabled, + '480p': enabled, + '720p': enabled, + '1080p': enabled, + '1440p': enabled, + '2160p': enabled + } +} + function deleteCustomConfig (url: string, token: string, statusCodeExpected = HttpStatusCode.OK_200) { const path = '/api/v1/config/custom' @@ -242,5 +254,6 @@ export { updateCustomConfig, getAbout, deleteCustomConfig, - updateCustomSubConfig + updateCustomSubConfig, + getCustomConfigResolutions } diff --git a/shared/extra-utils/users/users.ts b/shared/extra-utils/users/users.ts index 6040dd9c0..0f15962ad 100644 --- a/shared/extra-utils/users/users.ts +++ b/shared/extra-utils/users/users.ts @@ -1,5 +1,6 @@ import { omit } from 'lodash' import * as request from 'supertest' +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' import { UserUpdateMe } from '../../models/users' import { UserAdminFlag } from '../../models/users/user-flag.model' import { UserRegister } from '../../models/users/user-register.model' @@ -7,9 +8,8 @@ import { UserRole } from '../../models/users/user-role' import { makeGetRequest, makePostBodyRequest, makePutBodyRequest, updateImageRequest } from '../requests/requests' import { ServerInfo } from '../server/servers' import { userLogin } from './login' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' -type CreateUserArgs = { +function createUser (parameters: { url: string accessToken: string username: string @@ -19,8 +19,7 @@ type CreateUserArgs = { role?: UserRole adminFlags?: UserAdminFlag specialStatus?: number -} -function createUser (parameters: CreateUserArgs) { +}) { const { url, accessToken, @@ -52,6 +51,21 @@ function createUser (parameters: CreateUserArgs) { .expect(specialStatus) } +async function generateUser (server: ServerInfo, username: string) { + const password = 'my super password' + const resCreate = await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password }) + + const token = await userLogin(server, { username, password }) + + const resMe = await getMyUserInformation(server.url, token) + + return { + token, + userId: resCreate.body.user.id, + userChannelId: resMe.body.videoChannels[0].id + } +} + async function generateUserAccessToken (server: ServerInfo, username: string) { const password = 'my super password' await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password }) @@ -393,6 +407,7 @@ export { resetPassword, renewUserScopedTokens, updateMyAvatar, + generateUser, askSendVerifyEmail, generateUserAccessToken, verifyEmail, -- cgit v1.2.3 From 4b91bc1525e89643c575cac6557c86f64e657aa2 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 7 May 2021 14:48:39 +0200 Subject: Reduce pending job waiting --- shared/extra-utils/server/jobs.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared') diff --git a/shared/extra-utils/server/jobs.ts b/shared/extra-utils/server/jobs.ts index 704929bd4..763374e03 100644 --- a/shared/extra-utils/server/jobs.ts +++ b/shared/extra-utils/server/jobs.ts @@ -55,7 +55,7 @@ function getJobsListPaginationAndSort (options: { async function waitJobs (serversArg: ServerInfo[] | ServerInfo) { const pendingJobWait = process.env.NODE_PENDING_JOB_WAIT ? parseInt(process.env.NODE_PENDING_JOB_WAIT, 10) - : 500 + : 250 let servers: ServerInfo[] @@ -115,7 +115,7 @@ async function waitJobs (serversArg: ServerInfo[] | ServerInfo) { } if (pendingRequests) { - await wait(1000) + await wait(pendingJobWait) } } while (pendingRequests) } -- cgit v1.2.3 From e024fd6a7494b37251da1d59470324305cdb4129 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 7 May 2021 17:14:39 +0200 Subject: Update channel updatedAt when uploading a video --- shared/models/actors/account.model.ts | 2 ++ shared/models/actors/actor.model.ts | 1 - shared/models/videos/channel/video-channel.model.ts | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'shared') diff --git a/shared/models/actors/account.model.ts b/shared/models/actors/account.model.ts index 120dec271..f2138077e 100644 --- a/shared/models/actors/account.model.ts +++ b/shared/models/actors/account.model.ts @@ -5,6 +5,8 @@ export interface Account extends Actor { displayName: string description: string + updatedAt: Date | string + userId?: number } diff --git a/shared/models/actors/actor.model.ts b/shared/models/actors/actor.model.ts index 7d9f35b10..fd0662331 100644 --- a/shared/models/actors/actor.model.ts +++ b/shared/models/actors/actor.model.ts @@ -8,6 +8,5 @@ export interface Actor { followingCount: number followersCount: number createdAt: Date | string - updatedAt: Date | string avatar?: ActorImage } diff --git a/shared/models/videos/channel/video-channel.model.ts b/shared/models/videos/channel/video-channel.model.ts index 56517972d..5393f924d 100644 --- a/shared/models/videos/channel/video-channel.model.ts +++ b/shared/models/videos/channel/video-channel.model.ts @@ -11,6 +11,9 @@ export interface VideoChannel extends Actor { description: string support: string isLocal: boolean + + updatedAt: Date | string + ownerAccount?: Account videosCount?: number -- cgit v1.2.3 From f6d6e7f861189a4446f406efb775a29688764b48 Mon Sep 17 00:00:00 2001 From: kontrollanten <6680299+kontrollanten@users.noreply.github.com> Date: Mon, 10 May 2021 11:13:41 +0200 Subject: Resumable video uploads (#3933) * WIP: resumable video uploads relates to #324 * fix review comments * video upload: error handling * fix audio upload * fixes after self review * Update server/controllers/api/videos/index.ts Co-authored-by: Rigel Kent * Update server/middlewares/validators/videos/videos.ts Co-authored-by: Rigel Kent * Update server/controllers/api/videos/index.ts Co-authored-by: Rigel Kent * update after code review * refactor upload route - restore multipart upload route - move resumable to dedicated upload-resumable route - move checks to middleware - do not leak internal fs structure in response * fix yarn.lock upon rebase * factorize addVideo for reuse in both endpoints * add resumable upload API to openapi spec * add initial test and test helper for resumable upload * typings for videoAddResumable middleware * avoid including aws and google packages via node-uploadx, by only including uploadx/core * rename ex-isAudioBg to more explicit name mentioning it is a preview file for audio * add video-upload-tmp-folder-cleaner job * stronger typing of video upload middleware * reduce dependency to @uploadx/core * add audio upload test * refactor resumable uploads cleanup from job to scheduler * refactor resumable uploads scheduler to compare to last execution time * make resumable upload validator to always cleanup on failure * move legacy upload request building outside of uploadVideo test helper * filter upload-resumable middlewares down to POST, PUT, DELETE also begin to type metadata * merge add duration functions * stronger typings and documentation for uploadx behaviour, move init validator up * refactor(client/video-edit): options > uploadxOptions * refactor(client/video-edit): remove obsolete else * scheduler/remove-dangling-resum: rename tag * refactor(server/video): add UploadVideoFiles type * refactor(mw/validators): restructure eslint disable * refactor(mw/validators/videos): rename import * refactor(client/vid-upload): rename html elem id * refactor(sched/remove-dangl): move fn to method * refactor(mw/async): add method typing * refactor(mw/vali/video): double quote > single * refactor(server/upload-resum): express use > all * proper http methud enum server/middlewares/async.ts * properly type http methods * factorize common video upload validation steps * add check for maximum partially uploaded file size * fix audioBg use * fix extname(filename) in addVideo * document parameters for uploadx's resumable protocol * clear META files in scheduler * last audio refactor before cramming preview in the initial POST form data * refactor as mulitpart/form-data initial post request this allows preview/thumbnail uploads alongside the initial request, and cleans up the upload form * Add more tests for resumable uploads * Refactor remove dangling resumable uploads * Prepare changelog * Add more resumable upload tests * Remove user quota check for resumable uploads * Fix upload error handler * Update nginx template for upload-resumable * Cleanup comment * Remove unused express methods * Prefer to use got instead of raw http * Don't retry on error 500 Co-authored-by: Rigel Kent Co-authored-by: Rigel Kent Co-authored-by: Chocobozzz --- shared/core-utils/miscs/http-methods.ts | 21 +++ shared/core-utils/miscs/index.ts | 1 + shared/extra-utils/server/debug.ts | 18 +- shared/extra-utils/server/servers.ts | 2 +- shared/extra-utils/videos/video-channels.ts | 11 +- shared/extra-utils/videos/videos.ts | 258 ++++++++++++++++++++++------ shared/models/server/debug.model.ts | 4 + 7 files changed, 256 insertions(+), 59 deletions(-) create mode 100644 shared/core-utils/miscs/http-methods.ts (limited to 'shared') diff --git a/shared/core-utils/miscs/http-methods.ts b/shared/core-utils/miscs/http-methods.ts new file mode 100644 index 000000000..1cfa458b9 --- /dev/null +++ b/shared/core-utils/miscs/http-methods.ts @@ -0,0 +1,21 @@ +/** HTTP request method to indicate the desired action to be performed for a given resource. */ +export enum HttpMethod { + /** The CONNECT method establishes a tunnel to the server identified by the target resource. */ + CONNECT = 'CONNECT', + /** The DELETE method deletes the specified resource. */ + DELETE = 'DELETE', + /** The GET method requests a representation of the specified resource. Requests using GET should only retrieve data. */ + GET = 'GET', + /** The HEAD method asks for a response identical to that of a GET request, but without the response body. */ + HEAD = 'HEAD', + /** The OPTIONS method is used to describe the communication options for the target resource. */ + OPTIONS = 'OPTIONS', + /** The PATCH method is used to apply partial modifications to a resource. */ + PATCH = 'PATCH', + /** The POST method is used to submit an entity to the specified resource */ + POST = 'POST', + /** The PUT method replaces all current representations of the target resource with the request payload. */ + PUT = 'PUT', + /** The TRACE method performs a message loop-back test along the path to the target resource. */ + TRACE = 'TRACE' +} diff --git a/shared/core-utils/miscs/index.ts b/shared/core-utils/miscs/index.ts index 898fd4791..251df1de2 100644 --- a/shared/core-utils/miscs/index.ts +++ b/shared/core-utils/miscs/index.ts @@ -2,3 +2,4 @@ export * from './date' export * from './miscs' export * from './types' export * from './http-error-codes' +export * from './http-methods' diff --git a/shared/extra-utils/server/debug.ts b/shared/extra-utils/server/debug.ts index 5cf80a5fb..f196812b7 100644 --- a/shared/extra-utils/server/debug.ts +++ b/shared/extra-utils/server/debug.ts @@ -1,5 +1,6 @@ -import { makeGetRequest } from '../requests/requests' +import { makeGetRequest, makePostBodyRequest } from '../requests/requests' import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes' +import { SendDebugCommand } from '@shared/models' function getDebug (url: string, token: string) { const path = '/api/v1/server/debug' @@ -12,8 +13,21 @@ function getDebug (url: string, token: string) { }) } +function sendDebugCommand (url: string, token: string, body: SendDebugCommand) { + const path = '/api/v1/server/debug/run-command' + + return makePostBodyRequest({ + url, + path, + token, + fields: body, + statusCodeExpected: HttpStatusCode.NO_CONTENT_204 + }) +} + // --------------------------------------------------------------------------- export { - getDebug + getDebug, + sendDebugCommand } diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts index 779a3cc36..479f08e12 100644 --- a/shared/extra-utils/server/servers.ts +++ b/shared/extra-utils/server/servers.ts @@ -274,7 +274,7 @@ async function reRunServer (server: ServerInfo, configOverride?: any) { } async function checkTmpIsEmpty (server: ServerInfo) { - await checkDirectoryIsEmpty(server, 'tmp', [ 'plugins-global.css', 'hls' ]) + await checkDirectoryIsEmpty(server, 'tmp', [ 'plugins-global.css', 'hls', 'resumable-uploads' ]) if (await pathExists(join('test' + server.internalServerNumber, 'tmp', 'hls'))) { await checkDirectoryIsEmpty(server, 'tmp/hls') diff --git a/shared/extra-utils/videos/video-channels.ts b/shared/extra-utils/videos/video-channels.ts index d0dfb5856..0aab93e52 100644 --- a/shared/extra-utils/videos/video-channels.ts +++ b/shared/extra-utils/videos/video-channels.ts @@ -5,7 +5,7 @@ import { VideoChannelUpdate } from '../../models/videos/channel/video-channel-up import { VideoChannelCreate } from '../../models/videos/channel/video-channel-create.model' import { makeDeleteRequest, makeGetRequest, updateImageRequest } from '../requests/requests' import { ServerInfo } from '../server/servers' -import { User } from '../../models/users/user.model' +import { MyUser, User } from '../../models/users/user.model' import { getMyUserInformation } from '../users/users' import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' @@ -170,6 +170,12 @@ function setDefaultVideoChannel (servers: ServerInfo[]) { return Promise.all(tasks) } +async function getDefaultVideoChannel (url: string, token: string) { + const res = await getMyUserInformation(url, token) + + return (res.body as MyUser).videoChannels[0].id +} + // --------------------------------------------------------------------------- export { @@ -181,5 +187,6 @@ export { deleteVideoChannel, getVideoChannel, setDefaultVideoChannel, - deleteVideoChannelImage + deleteVideoChannelImage, + getDefaultVideoChannel } diff --git a/shared/extra-utils/videos/videos.ts b/shared/extra-utils/videos/videos.ts index a0143b0ef..e88256ac0 100644 --- a/shared/extra-utils/videos/videos.ts +++ b/shared/extra-utils/videos/videos.ts @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */ import { expect } from 'chai' -import { pathExists, readdir, readFile } from 'fs-extra' +import { createReadStream, pathExists, readdir, readFile, stat } from 'fs-extra' +import got, { Response as GotResponse } from 'got/dist/source' import * as parseTorrent from 'parse-torrent' import { extname, join } from 'path' import * as request from 'supertest' @@ -42,6 +43,7 @@ type VideoAttributes = { channelId?: number privacy?: VideoPrivacy fixture?: string + support?: string thumbnailfile?: string previewfile?: string scheduleUpdate?: { @@ -364,8 +366,13 @@ async function checkVideoFilesWereRemoved ( } } -async function uploadVideo (url: string, accessToken: string, videoAttributesArg: VideoAttributes, specialStatus = HttpStatusCode.OK_200) { - const path = '/api/v1/videos/upload' +async function uploadVideo ( + url: string, + accessToken: string, + videoAttributesArg: VideoAttributes, + specialStatus = HttpStatusCode.OK_200, + mode: 'legacy' | 'resumable' = 'legacy' +) { let defaultChannelId = '1' try { @@ -391,74 +398,170 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg fixture: 'video_short.webm' }, videoAttributesArg) + const res = mode === 'legacy' + ? await buildLegacyUpload(url, accessToken, attributes, specialStatus) + : await buildResumeUpload(url, accessToken, attributes, specialStatus) + + // Wait torrent generation + if (specialStatus === HttpStatusCode.OK_200) { + let video: VideoDetails + do { + const resVideo = await getVideoWithToken(url, accessToken, res.body.video.uuid) + video = resVideo.body + + await wait(50) + } while (!video.files[0].torrentUrl) + } + + return res +} + +function checkUploadVideoParam ( + url: string, + token: string, + attributes: Partial, + specialStatus = HttpStatusCode.OK_200, + mode: 'legacy' | 'resumable' = 'legacy' +) { + return mode === 'legacy' + ? buildLegacyUpload(url, token, attributes, specialStatus) + : buildResumeUpload(url, token, attributes, specialStatus) +} + +async function buildLegacyUpload (url: string, token: string, attributes: VideoAttributes, specialStatus = HttpStatusCode.OK_200) { + const path = '/api/v1/videos/upload' const req = request(url) .post(path) .set('Accept', 'application/json') - .set('Authorization', 'Bearer ' + accessToken) - .field('name', attributes.name) - .field('nsfw', JSON.stringify(attributes.nsfw)) - .field('commentsEnabled', JSON.stringify(attributes.commentsEnabled)) - .field('downloadEnabled', JSON.stringify(attributes.downloadEnabled)) - .field('waitTranscoding', JSON.stringify(attributes.waitTranscoding)) - .field('privacy', attributes.privacy.toString()) - .field('channelId', attributes.channelId) - - if (attributes.support !== undefined) { - req.field('support', attributes.support) - } + .set('Authorization', 'Bearer ' + token) - if (attributes.description !== undefined) { - req.field('description', attributes.description) - } - if (attributes.language !== undefined) { - req.field('language', attributes.language.toString()) - } - if (attributes.category !== undefined) { - req.field('category', attributes.category.toString()) - } - if (attributes.licence !== undefined) { - req.field('licence', attributes.licence.toString()) - } + buildUploadReq(req, attributes) - const tags = attributes.tags || [] - for (let i = 0; i < tags.length; i++) { - req.field('tags[' + i + ']', attributes.tags[i]) + if (attributes.fixture !== undefined) { + req.attach('videofile', buildAbsoluteFixturePath(attributes.fixture)) } - if (attributes.thumbnailfile !== undefined) { - req.attach('thumbnailfile', buildAbsoluteFixturePath(attributes.thumbnailfile)) - } - if (attributes.previewfile !== undefined) { - req.attach('previewfile', buildAbsoluteFixturePath(attributes.previewfile)) - } + return req.expect(specialStatus) +} - if (attributes.scheduleUpdate) { - req.field('scheduleUpdate[updateAt]', attributes.scheduleUpdate.updateAt) +async function buildResumeUpload (url: string, token: string, attributes: VideoAttributes, specialStatus = HttpStatusCode.OK_200) { + let size = 0 + let videoFilePath: string + let mimetype = 'video/mp4' - if (attributes.scheduleUpdate.privacy) { - req.field('scheduleUpdate[privacy]', attributes.scheduleUpdate.privacy) + if (attributes.fixture) { + videoFilePath = buildAbsoluteFixturePath(attributes.fixture) + size = (await stat(videoFilePath)).size + + if (videoFilePath.endsWith('.mkv')) { + mimetype = 'video/x-matroska' + } else if (videoFilePath.endsWith('.webm')) { + mimetype = 'video/webm' } } - if (attributes.originallyPublishedAt !== undefined) { - req.field('originallyPublishedAt', attributes.originallyPublishedAt) + const initializeSessionRes = await prepareResumableUpload({ url, token, attributes, size, mimetype }) + const initStatus = initializeSessionRes.status + + if (videoFilePath && initStatus === HttpStatusCode.CREATED_201) { + const locationHeader = initializeSessionRes.header['location'] + expect(locationHeader).to.not.be.undefined + + const pathUploadId = locationHeader.split('?')[1] + + return sendResumableChunks({ url, token, pathUploadId, videoFilePath, size, specialStatus }) } - const res = await req.attach('videofile', buildAbsoluteFixturePath(attributes.fixture)) - .expect(specialStatus) + const expectedInitStatus = specialStatus === HttpStatusCode.OK_200 + ? HttpStatusCode.CREATED_201 + : specialStatus - // Wait torrent generation - if (specialStatus === HttpStatusCode.OK_200) { - let video: VideoDetails - do { - const resVideo = await getVideoWithToken(url, accessToken, res.body.video.uuid) - video = resVideo.body + expect(initStatus).to.equal(expectedInitStatus) - await wait(50) - } while (!video.files[0].torrentUrl) + return initializeSessionRes +} + +async function prepareResumableUpload (options: { + url: string + token: string + attributes: VideoAttributes + size: number + mimetype: string +}) { + const { url, token, attributes, size, mimetype } = options + + const path = '/api/v1/videos/upload-resumable' + + const req = request(url) + .post(path) + .set('Authorization', 'Bearer ' + token) + .set('X-Upload-Content-Type', mimetype) + .set('X-Upload-Content-Length', size.toString()) + + buildUploadReq(req, attributes) + + if (attributes.fixture) { + req.field('filename', attributes.fixture) } - return res + return req +} + +function sendResumableChunks (options: { + url: string + token: string + pathUploadId: string + videoFilePath: string + size: number + specialStatus?: HttpStatusCode + contentLength?: number + contentRangeBuilder?: (start: number, chunk: any) => string +}) { + const { url, token, pathUploadId, videoFilePath, size, specialStatus, contentLength, contentRangeBuilder } = options + + const expectedStatus = specialStatus || HttpStatusCode.OK_200 + + const path = '/api/v1/videos/upload-resumable' + let start = 0 + + const readable = createReadStream(videoFilePath, { highWaterMark: 8 * 1024 }) + return new Promise((resolve, reject) => { + readable.on('data', async function onData (chunk) { + readable.pause() + + const headers = { + 'Authorization': 'Bearer ' + token, + 'Content-Type': 'application/octet-stream', + 'Content-Range': contentRangeBuilder + ? contentRangeBuilder(start, chunk) + : `bytes ${start}-${start + chunk.length - 1}/${size}`, + 'Content-Length': contentLength ? contentLength + '' : chunk.length + '' + } + + const res = await got({ + url, + method: 'put', + headers, + path: path + '?' + pathUploadId, + body: chunk, + responseType: 'json', + throwHttpErrors: false + }) + + start += chunk.length + + if (res.statusCode === expectedStatus) { + return resolve(res) + } + + if (res.statusCode !== HttpStatusCode.PERMANENT_REDIRECT_308) { + readable.off('data', onData) + return reject(new Error('Incorrect transient behaviour sending intermediary chunks')) + } + + readable.resume() + }) + }) } function updateVideo ( @@ -749,11 +852,13 @@ export { getVideoWithToken, getVideosList, removeAllVideos, + checkUploadVideoParam, getVideosListPagination, getVideosListSort, removeVideo, getVideosListWithToken, uploadVideo, + sendResumableChunks, getVideosWithFilters, uploadRandomVideoOnServers, updateVideo, @@ -767,5 +872,50 @@ export { getMyVideosWithFilter, uploadVideoAndGetId, getLocalIdByUUID, - getVideoIdFromUUID + getVideoIdFromUUID, + prepareResumableUpload +} + +// --------------------------------------------------------------------------- + +function buildUploadReq (req: request.Test, attributes: VideoAttributes) { + + for (const key of [ 'name', 'support', 'channelId', 'description', 'originallyPublishedAt' ]) { + if (attributes[key] !== undefined) { + req.field(key, attributes[key]) + } + } + + for (const key of [ 'nsfw', 'commentsEnabled', 'downloadEnabled', 'waitTranscoding' ]) { + if (attributes[key] !== undefined) { + req.field(key, JSON.stringify(attributes[key])) + } + } + + for (const key of [ 'language', 'privacy', 'category', 'licence' ]) { + if (attributes[key] !== undefined) { + req.field(key, attributes[key].toString()) + } + } + + const tags = attributes.tags || [] + for (let i = 0; i < tags.length; i++) { + req.field('tags[' + i + ']', attributes.tags[i]) + } + + for (const key of [ 'thumbnailfile', 'previewfile' ]) { + if (attributes[key] !== undefined) { + req.attach(key, buildAbsoluteFixturePath(attributes[key])) + } + } + + if (attributes.scheduleUpdate) { + if (attributes.scheduleUpdate.updateAt) { + req.field('scheduleUpdate[updateAt]', attributes.scheduleUpdate.updateAt) + } + + if (attributes.scheduleUpdate.privacy) { + req.field('scheduleUpdate[privacy]', attributes.scheduleUpdate.privacy) + } + } } diff --git a/shared/models/server/debug.model.ts b/shared/models/server/debug.model.ts index 61cba6518..7ceff9137 100644 --- a/shared/models/server/debug.model.ts +++ b/shared/models/server/debug.model.ts @@ -1,3 +1,7 @@ export interface Debug { ip: string } + +export interface SendDebugCommand { + command: 'remove-dandling-resumable-uploads' +} -- cgit v1.2.3 From 2b02c520e66ea452687cab39401b371711caa9ed Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 11 May 2021 11:27:40 +0200 Subject: Cleanup shared models --- shared/extra-utils/index.ts | 16 ++- shared/models/nodeinfo/index.d.ts | 117 --------------------- shared/models/nodeinfo/index.ts | 1 + shared/models/nodeinfo/nodeinfo.model.ts | 117 +++++++++++++++++++++ shared/models/overviews/index.ts | 2 +- shared/models/overviews/videos-overview.model.ts | 24 +++++ shared/models/overviews/videos-overview.ts | 24 ----- shared/models/redundancy/index.ts | 3 +- shared/models/videos/change-ownership/index.ts | 3 + .../video-change-ownership-accept.model.ts | 3 + .../video-change-ownership-create.model.ts | 3 + .../video-change-ownership.model.ts | 17 +++ shared/models/videos/comment/index.ts | 1 + .../models/videos/comment/video-comment.model.ts | 46 ++++++++ shared/models/videos/index.ts | 12 +-- .../videos/video-change-ownership-accept.model.ts | 3 - .../videos/video-change-ownership-create.model.ts | 3 - .../models/videos/video-change-ownership.model.ts | 17 --- shared/models/videos/video-comment.model.ts | 46 -------- shared/models/videos/video-file-metadata.model.ts | 13 +++ shared/models/videos/video-file-metadata.ts | 13 --- shared/models/videos/video-file.model.ts | 2 +- 22 files changed, 251 insertions(+), 235 deletions(-) delete mode 100644 shared/models/nodeinfo/index.d.ts create mode 100644 shared/models/nodeinfo/index.ts create mode 100644 shared/models/nodeinfo/nodeinfo.model.ts create mode 100644 shared/models/overviews/videos-overview.model.ts delete mode 100644 shared/models/overviews/videos-overview.ts create mode 100644 shared/models/videos/change-ownership/index.ts create mode 100644 shared/models/videos/change-ownership/video-change-ownership-accept.model.ts create mode 100644 shared/models/videos/change-ownership/video-change-ownership-create.model.ts create mode 100644 shared/models/videos/change-ownership/video-change-ownership.model.ts create mode 100644 shared/models/videos/comment/index.ts create mode 100644 shared/models/videos/comment/video-comment.model.ts delete mode 100644 shared/models/videos/video-change-ownership-accept.model.ts delete mode 100644 shared/models/videos/video-change-ownership-create.model.ts delete mode 100644 shared/models/videos/video-change-ownership.model.ts delete mode 100644 shared/models/videos/video-comment.model.ts create mode 100644 shared/models/videos/video-file-metadata.model.ts delete mode 100644 shared/models/videos/video-file-metadata.ts (limited to 'shared') diff --git a/shared/extra-utils/index.ts b/shared/extra-utils/index.ts index 898a92d43..720db19cb 100644 --- a/shared/extra-utils/index.ts +++ b/shared/extra-utils/index.ts @@ -1,15 +1,24 @@ export * from './bulk/bulk' + export * from './cli/cli' + export * from './feeds/feeds' + export * from './mock-servers/mock-instances-index' -export * from './miscs/miscs' + +export * from './miscs/email' export * from './miscs/sql' +export * from './miscs/miscs' export * from './miscs/stubs' + export * from './moderation/abuses' export * from './plugins/mock-blocklist' + export * from './requests/check-api-params' export * from './requests/requests' + export * from './search/videos' + export * from './server/activitypub' export * from './server/clients' export * from './server/config' @@ -18,9 +27,14 @@ export * from './server/follows' export * from './server/jobs' export * from './server/plugins' export * from './server/servers' + export * from './users/accounts' +export * from './users/blocklist' export * from './users/login' +export * from './users/user-notifications' +export * from './users/user-subscriptions' export * from './users/users' + export * from './videos/live' export * from './videos/services' export * from './videos/video-blacklist' diff --git a/shared/models/nodeinfo/index.d.ts b/shared/models/nodeinfo/index.d.ts deleted file mode 100644 index 336cb66d2..000000000 --- a/shared/models/nodeinfo/index.d.ts +++ /dev/null @@ -1,117 +0,0 @@ -/** - * NodeInfo schema version 2.0. - */ -export interface HttpNodeinfoDiasporaSoftwareNsSchema20 { - /** - * The schema version, must be 2.0. - */ - version: '2.0' - /** - * Metadata about server software in use. - */ - software: { - /** - * The canonical name of this server software. - */ - name: string - /** - * The version of this server software. - */ - version: string - } - /** - * The protocols supported on this server. - */ - protocols: ( - | 'activitypub' - | 'buddycloud' - | 'dfrn' - | 'diaspora' - | 'libertree' - | 'ostatus' - | 'pumpio' - | 'tent' - | 'xmpp' - | 'zot')[] - /** - * The third party sites this server can connect to via their application API. - */ - services: { - /** - * The third party sites this server can retrieve messages from for combined display with regular traffic. - */ - inbound: ('atom1.0' | 'gnusocial' | 'imap' | 'pnut' | 'pop3' | 'pumpio' | 'rss2.0' | 'twitter')[] - /** - * The third party sites this server can publish messages to on the behalf of a user. - */ - outbound: ( - | 'atom1.0' - | 'blogger' - | 'buddycloud' - | 'diaspora' - | 'dreamwidth' - | 'drupal' - | 'facebook' - | 'friendica' - | 'gnusocial' - | 'google' - | 'insanejournal' - | 'libertree' - | 'linkedin' - | 'livejournal' - | 'mediagoblin' - | 'myspace' - | 'pinterest' - | 'pnut' - | 'posterous' - | 'pumpio' - | 'redmatrix' - | 'rss2.0' - | 'smtp' - | 'tent' - | 'tumblr' - | 'twitter' - | 'wordpress' - | 'xmpp')[] - } - /** - * Whether this server allows open self-registration. - */ - openRegistrations: boolean - /** - * Usage statistics for this server. - */ - usage: { - /** - * statistics about the users of this server. - */ - users: { - /** - * The total amount of on this server registered users. - */ - total?: number - /** - * The amount of users that signed in at least once in the last 180 days. - */ - activeHalfyear?: number - /** - * The amount of users that signed in at least once in the last 30 days. - */ - activeMonth?: number - } - /** - * The amount of posts that were made by users that are registered on this server. - */ - localPosts?: number - /** - * The amount of comments that were made by users that are registered on this server. - */ - localComments?: number - } - /** - * Free form key value pairs for software specific values. Clients should not rely on any specific key present. - */ - metadata: { - [k: string]: any - } -} diff --git a/shared/models/nodeinfo/index.ts b/shared/models/nodeinfo/index.ts new file mode 100644 index 000000000..faa64302a --- /dev/null +++ b/shared/models/nodeinfo/index.ts @@ -0,0 +1 @@ +export * from './nodeinfo.model' diff --git a/shared/models/nodeinfo/nodeinfo.model.ts b/shared/models/nodeinfo/nodeinfo.model.ts new file mode 100644 index 000000000..336cb66d2 --- /dev/null +++ b/shared/models/nodeinfo/nodeinfo.model.ts @@ -0,0 +1,117 @@ +/** + * NodeInfo schema version 2.0. + */ +export interface HttpNodeinfoDiasporaSoftwareNsSchema20 { + /** + * The schema version, must be 2.0. + */ + version: '2.0' + /** + * Metadata about server software in use. + */ + software: { + /** + * The canonical name of this server software. + */ + name: string + /** + * The version of this server software. + */ + version: string + } + /** + * The protocols supported on this server. + */ + protocols: ( + | 'activitypub' + | 'buddycloud' + | 'dfrn' + | 'diaspora' + | 'libertree' + | 'ostatus' + | 'pumpio' + | 'tent' + | 'xmpp' + | 'zot')[] + /** + * The third party sites this server can connect to via their application API. + */ + services: { + /** + * The third party sites this server can retrieve messages from for combined display with regular traffic. + */ + inbound: ('atom1.0' | 'gnusocial' | 'imap' | 'pnut' | 'pop3' | 'pumpio' | 'rss2.0' | 'twitter')[] + /** + * The third party sites this server can publish messages to on the behalf of a user. + */ + outbound: ( + | 'atom1.0' + | 'blogger' + | 'buddycloud' + | 'diaspora' + | 'dreamwidth' + | 'drupal' + | 'facebook' + | 'friendica' + | 'gnusocial' + | 'google' + | 'insanejournal' + | 'libertree' + | 'linkedin' + | 'livejournal' + | 'mediagoblin' + | 'myspace' + | 'pinterest' + | 'pnut' + | 'posterous' + | 'pumpio' + | 'redmatrix' + | 'rss2.0' + | 'smtp' + | 'tent' + | 'tumblr' + | 'twitter' + | 'wordpress' + | 'xmpp')[] + } + /** + * Whether this server allows open self-registration. + */ + openRegistrations: boolean + /** + * Usage statistics for this server. + */ + usage: { + /** + * statistics about the users of this server. + */ + users: { + /** + * The total amount of on this server registered users. + */ + total?: number + /** + * The amount of users that signed in at least once in the last 180 days. + */ + activeHalfyear?: number + /** + * The amount of users that signed in at least once in the last 30 days. + */ + activeMonth?: number + } + /** + * The amount of posts that were made by users that are registered on this server. + */ + localPosts?: number + /** + * The amount of comments that were made by users that are registered on this server. + */ + localComments?: number + } + /** + * Free form key value pairs for software specific values. Clients should not rely on any specific key present. + */ + metadata: { + [k: string]: any + } +} diff --git a/shared/models/overviews/index.ts b/shared/models/overviews/index.ts index 376609efa..468507c6b 100644 --- a/shared/models/overviews/index.ts +++ b/shared/models/overviews/index.ts @@ -1 +1 @@ -export * from './videos-overview' +export * from './videos-overview.model' diff --git a/shared/models/overviews/videos-overview.model.ts b/shared/models/overviews/videos-overview.model.ts new file mode 100644 index 000000000..0f3cb4a52 --- /dev/null +++ b/shared/models/overviews/videos-overview.model.ts @@ -0,0 +1,24 @@ +import { Video, VideoChannelSummary, VideoConstant } from '../videos' + +export interface ChannelOverview { + channel: VideoChannelSummary + videos: Video[] +} + +export interface CategoryOverview { + category: VideoConstant + videos: Video[] +} + +export interface TagOverview { + tag: string + videos: Video[] +} + +export interface VideosOverview { + channels: ChannelOverview[] + + categories: CategoryOverview[] + + tags: TagOverview[] +} diff --git a/shared/models/overviews/videos-overview.ts b/shared/models/overviews/videos-overview.ts deleted file mode 100644 index 0f3cb4a52..000000000 --- a/shared/models/overviews/videos-overview.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Video, VideoChannelSummary, VideoConstant } from '../videos' - -export interface ChannelOverview { - channel: VideoChannelSummary - videos: Video[] -} - -export interface CategoryOverview { - category: VideoConstant - videos: Video[] -} - -export interface TagOverview { - tag: string - videos: Video[] -} - -export interface VideosOverview { - channels: ChannelOverview[] - - categories: CategoryOverview[] - - tags: TagOverview[] -} diff --git a/shared/models/redundancy/index.ts b/shared/models/redundancy/index.ts index 649cc489f..641a5d625 100644 --- a/shared/models/redundancy/index.ts +++ b/shared/models/redundancy/index.ts @@ -1,3 +1,4 @@ -export * from './videos-redundancy-strategy.model' export * from './video-redundancies-filters.model' +export * from './video-redundancy-config-filter.type' export * from './video-redundancy.model' +export * from './videos-redundancy-strategy.model' diff --git a/shared/models/videos/change-ownership/index.ts b/shared/models/videos/change-ownership/index.ts new file mode 100644 index 000000000..a942fb2cd --- /dev/null +++ b/shared/models/videos/change-ownership/index.ts @@ -0,0 +1,3 @@ +export * from './video-change-ownership-accept.model' +export * from './video-change-ownership-create.model' +export * from './video-change-ownership.model' diff --git a/shared/models/videos/change-ownership/video-change-ownership-accept.model.ts b/shared/models/videos/change-ownership/video-change-ownership-accept.model.ts new file mode 100644 index 000000000..f27247633 --- /dev/null +++ b/shared/models/videos/change-ownership/video-change-ownership-accept.model.ts @@ -0,0 +1,3 @@ +export interface VideoChangeOwnershipAccept { + channelId: number +} diff --git a/shared/models/videos/change-ownership/video-change-ownership-create.model.ts b/shared/models/videos/change-ownership/video-change-ownership-create.model.ts new file mode 100644 index 000000000..40fcca285 --- /dev/null +++ b/shared/models/videos/change-ownership/video-change-ownership-create.model.ts @@ -0,0 +1,3 @@ +export interface VideoChangeOwnershipCreate { + username: string +} diff --git a/shared/models/videos/change-ownership/video-change-ownership.model.ts b/shared/models/videos/change-ownership/video-change-ownership.model.ts new file mode 100644 index 000000000..3d31cad0a --- /dev/null +++ b/shared/models/videos/change-ownership/video-change-ownership.model.ts @@ -0,0 +1,17 @@ +import { Account } from '../../actors' +import { Video } from '../video.model' + +export interface VideoChangeOwnership { + id: number + status: VideoChangeOwnershipStatus + initiatorAccount: Account + nextOwnerAccount: Account + video: Video + createdAt: Date +} + +export const enum VideoChangeOwnershipStatus { + WAITING = 'WAITING', + ACCEPTED = 'ACCEPTED', + REFUSED = 'REFUSED' +} diff --git a/shared/models/videos/comment/index.ts b/shared/models/videos/comment/index.ts new file mode 100644 index 000000000..7b9261a36 --- /dev/null +++ b/shared/models/videos/comment/index.ts @@ -0,0 +1 @@ +export * from './video-comment.model' diff --git a/shared/models/videos/comment/video-comment.model.ts b/shared/models/videos/comment/video-comment.model.ts new file mode 100644 index 000000000..79c0e4c0a --- /dev/null +++ b/shared/models/videos/comment/video-comment.model.ts @@ -0,0 +1,46 @@ +import { Account } from '../../actors' + +export interface VideoComment { + id: number + url: string + text: string + threadId: number + inReplyToCommentId: number + videoId: number + createdAt: Date | string + updatedAt: Date | string + deletedAt: Date | string + isDeleted: boolean + totalRepliesFromVideoAuthor: number + totalReplies: number + account: Account +} + +export interface VideoCommentAdmin { + id: number + url: string + text: string + + threadId: number + inReplyToCommentId: number + + createdAt: Date | string + updatedAt: Date | string + + account: Account + + video: { + id: number + uuid: string + name: string + } +} + +export interface VideoCommentThreadTree { + comment: VideoComment + children: VideoCommentThreadTree[] +} + +export interface VideoCommentCreate { + text: string +} diff --git a/shared/models/videos/index.ts b/shared/models/videos/index.ts index fac3e0b2f..64f2c9df6 100644 --- a/shared/models/videos/index.ts +++ b/shared/models/videos/index.ts @@ -1,6 +1,8 @@ export * from './blacklist' export * from './caption' +export * from './change-ownership' export * from './channel' +export * from './comment' export * from './live' export * from './import' export * from './playlist' @@ -10,17 +12,11 @@ export * from './nsfw-policy.type' export * from './thumbnail.type' -export * from './video-change-ownership-accept.model' -export * from './video-change-ownership-create.model' -export * from './video-change-ownership.model' - -export * from './video-comment.model' export * from './video-constant.model' export * from './video-create.model' -export * from './video-file-metadata' -export * from './video-file.model' -export * from './live/live-video.model' +export * from './video-file-metadata.model' +export * from './video-file.model' export * from './video-privacy.enum' export * from './video-query.type' diff --git a/shared/models/videos/video-change-ownership-accept.model.ts b/shared/models/videos/video-change-ownership-accept.model.ts deleted file mode 100644 index f27247633..000000000 --- a/shared/models/videos/video-change-ownership-accept.model.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface VideoChangeOwnershipAccept { - channelId: number -} diff --git a/shared/models/videos/video-change-ownership-create.model.ts b/shared/models/videos/video-change-ownership-create.model.ts deleted file mode 100644 index 40fcca285..000000000 --- a/shared/models/videos/video-change-ownership-create.model.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface VideoChangeOwnershipCreate { - username: string -} diff --git a/shared/models/videos/video-change-ownership.model.ts b/shared/models/videos/video-change-ownership.model.ts deleted file mode 100644 index 669c7f3e7..000000000 --- a/shared/models/videos/video-change-ownership.model.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Account } from '../actors' -import { Video } from './video.model' - -export interface VideoChangeOwnership { - id: number - status: VideoChangeOwnershipStatus - initiatorAccount: Account - nextOwnerAccount: Account - video: Video - createdAt: Date -} - -export const enum VideoChangeOwnershipStatus { - WAITING = 'WAITING', - ACCEPTED = 'ACCEPTED', - REFUSED = 'REFUSED' -} diff --git a/shared/models/videos/video-comment.model.ts b/shared/models/videos/video-comment.model.ts deleted file mode 100644 index 9730a3f76..000000000 --- a/shared/models/videos/video-comment.model.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Account } from '../actors' - -export interface VideoComment { - id: number - url: string - text: string - threadId: number - inReplyToCommentId: number - videoId: number - createdAt: Date | string - updatedAt: Date | string - deletedAt: Date | string - isDeleted: boolean - totalRepliesFromVideoAuthor: number - totalReplies: number - account: Account -} - -export interface VideoCommentAdmin { - id: number - url: string - text: string - - threadId: number - inReplyToCommentId: number - - createdAt: Date | string - updatedAt: Date | string - - account: Account - - video: { - id: number - uuid: string - name: string - } -} - -export interface VideoCommentThreadTree { - comment: VideoComment - children: VideoCommentThreadTree[] -} - -export interface VideoCommentCreate { - text: string -} diff --git a/shared/models/videos/video-file-metadata.model.ts b/shared/models/videos/video-file-metadata.model.ts new file mode 100644 index 000000000..8f527c0a7 --- /dev/null +++ b/shared/models/videos/video-file-metadata.model.ts @@ -0,0 +1,13 @@ +export class VideoFileMetadata { + streams: { [x: string]: any, [x: number]: any }[] + format: { [x: string]: any, [x: number]: any } + chapters: any[] + + constructor (hash: { chapters: any[], format: any, streams: any[] }) { + this.chapters = hash.chapters + this.format = hash.format + this.streams = hash.streams + + delete this.format.filename + } +} diff --git a/shared/models/videos/video-file-metadata.ts b/shared/models/videos/video-file-metadata.ts deleted file mode 100644 index 8f527c0a7..000000000 --- a/shared/models/videos/video-file-metadata.ts +++ /dev/null @@ -1,13 +0,0 @@ -export class VideoFileMetadata { - streams: { [x: string]: any, [x: number]: any }[] - format: { [x: string]: any, [x: number]: any } - chapters: any[] - - constructor (hash: { chapters: any[], format: any, streams: any[] }) { - this.chapters = hash.chapters - this.format = hash.format - this.streams = hash.streams - - delete this.format.filename - } -} diff --git a/shared/models/videos/video-file.model.ts b/shared/models/videos/video-file.model.ts index 1e830b19c..28fce0aaf 100644 --- a/shared/models/videos/video-file.model.ts +++ b/shared/models/videos/video-file.model.ts @@ -1,5 +1,5 @@ import { VideoConstant } from './video-constant.model' -import { VideoFileMetadata } from './video-file-metadata' +import { VideoFileMetadata } from './video-file-metadata.model' import { VideoResolution } from './video-resolution.enum' export interface VideoFile { -- cgit v1.2.3 From 428ccb8b7a44ce60cabb7401a5464cf5fcbd4dba Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 11 May 2021 12:04:47 +0200 Subject: Reorganize plugin models --- shared/extra-utils/server/plugins.ts | 4 +- shared/models/plugins/client-hook.model.ts | 125 --------------------- shared/models/plugins/client/client-hook.model.ts | 125 +++++++++++++++++++++ shared/models/plugins/client/index.ts | 6 + .../plugins/client/plugin-client-scope.type.ts | 9 ++ .../client/plugin-element-placeholder.type.ts | 1 + .../client/register-client-form-field.model.ts | 23 ++++ .../plugins/client/register-client-hook.model.ts | 7 ++ .../register-client-settings-script.model.ts | 8 ++ shared/models/plugins/index.ts | 28 +---- shared/models/plugins/install-plugin.model.ts | 4 - shared/models/plugins/manage-plugin.model.ts | 3 - .../plugins/peertube-plugin-index-list.model.ts | 10 -- .../models/plugins/peertube-plugin-index.model.ts | 14 --- .../peertube-plugin-latest-version.model.ts | 10 -- shared/models/plugins/peertube-plugin.model.ts | 16 --- shared/models/plugins/plugin-client-scope.type.ts | 9 -- .../plugins/plugin-element-placeholder.type.ts | 1 - shared/models/plugins/plugin-index/index.ts | 3 + .../peertube-plugin-index-list.model.ts | 10 ++ .../plugin-index/peertube-plugin-index.model.ts | 14 +++ .../peertube-plugin-latest-version.model.ts | 10 ++ shared/models/plugins/plugin-package-json.model.ts | 2 +- .../plugin-playlist-privacy-manager.model.ts | 8 -- .../plugins/plugin-settings-manager.model.ts | 9 -- .../models/plugins/plugin-storage-manager.model.ts | 5 - .../plugins/plugin-transcoding-manager.model.ts | 13 --- shared/models/plugins/plugin-translation.model.ts | 5 - .../plugins/plugin-video-category-manager.model.ts | 5 - .../plugins/plugin-video-language-manager.model.ts | 5 - .../plugins/plugin-video-licence-manager.model.ts | 5 - .../plugins/plugin-video-privacy-manager.model.ts | 9 -- shared/models/plugins/public-server.setting.ts | 3 - .../plugins/register-client-form-field.model.ts | 23 ---- .../models/plugins/register-client-hook.model.ts | 7 -- .../register-client-settings-script.model.ts | 8 -- .../models/plugins/register-server-hook.model.ts | 7 -- .../plugins/register-server-setting.model.ts | 12 -- shared/models/plugins/server-hook.model.ts | 123 -------------------- shared/models/plugins/server/api/index.ts | 3 + .../plugins/server/api/install-plugin.model.ts | 4 + .../plugins/server/api/manage-plugin.model.ts | 3 + .../plugins/server/api/peertube-plugin.model.ts | 16 +++ shared/models/plugins/server/index.ts | 6 + shared/models/plugins/server/managers/index.ts | 9 ++ .../plugin-playlist-privacy-manager.model.ts | 8 ++ .../managers/plugin-settings-manager.model.ts | 9 ++ .../managers/plugin-storage-manager.model.ts | 5 + .../managers/plugin-transcoding-manager.model.ts | 13 +++ .../plugin-video-category-manager.model.ts | 5 + .../plugin-video-language-manager.model.ts | 5 + .../managers/plugin-video-licence-manager.model.ts | 5 + .../managers/plugin-video-privacy-manager.model.ts | 9 ++ .../plugins/server/plugin-translation.model.ts | 5 + .../plugins/server/register-server-hook.model.ts | 7 ++ shared/models/plugins/server/server-hook.model.ts | 123 ++++++++++++++++++++ shared/models/plugins/server/settings/index.ts | 2 + .../server/settings/public-server.setting.ts | 3 + .../settings/register-server-setting.model.ts | 12 ++ 59 files changed, 474 insertions(+), 467 deletions(-) delete mode 100644 shared/models/plugins/client-hook.model.ts create mode 100644 shared/models/plugins/client/client-hook.model.ts create mode 100644 shared/models/plugins/client/index.ts create mode 100644 shared/models/plugins/client/plugin-client-scope.type.ts create mode 100644 shared/models/plugins/client/plugin-element-placeholder.type.ts create mode 100644 shared/models/plugins/client/register-client-form-field.model.ts create mode 100644 shared/models/plugins/client/register-client-hook.model.ts create mode 100644 shared/models/plugins/client/register-client-settings-script.model.ts delete mode 100644 shared/models/plugins/install-plugin.model.ts delete mode 100644 shared/models/plugins/manage-plugin.model.ts delete mode 100644 shared/models/plugins/peertube-plugin-index-list.model.ts delete mode 100644 shared/models/plugins/peertube-plugin-index.model.ts delete mode 100644 shared/models/plugins/peertube-plugin-latest-version.model.ts delete mode 100644 shared/models/plugins/peertube-plugin.model.ts delete mode 100644 shared/models/plugins/plugin-client-scope.type.ts delete mode 100644 shared/models/plugins/plugin-element-placeholder.type.ts create mode 100644 shared/models/plugins/plugin-index/index.ts create mode 100644 shared/models/plugins/plugin-index/peertube-plugin-index-list.model.ts create mode 100644 shared/models/plugins/plugin-index/peertube-plugin-index.model.ts create mode 100644 shared/models/plugins/plugin-index/peertube-plugin-latest-version.model.ts delete mode 100644 shared/models/plugins/plugin-playlist-privacy-manager.model.ts delete mode 100644 shared/models/plugins/plugin-settings-manager.model.ts delete mode 100644 shared/models/plugins/plugin-storage-manager.model.ts delete mode 100644 shared/models/plugins/plugin-transcoding-manager.model.ts delete mode 100644 shared/models/plugins/plugin-translation.model.ts delete mode 100644 shared/models/plugins/plugin-video-category-manager.model.ts delete mode 100644 shared/models/plugins/plugin-video-language-manager.model.ts delete mode 100644 shared/models/plugins/plugin-video-licence-manager.model.ts delete mode 100644 shared/models/plugins/plugin-video-privacy-manager.model.ts delete mode 100644 shared/models/plugins/public-server.setting.ts delete mode 100644 shared/models/plugins/register-client-form-field.model.ts delete mode 100644 shared/models/plugins/register-client-hook.model.ts delete mode 100644 shared/models/plugins/register-client-settings-script.model.ts delete mode 100644 shared/models/plugins/register-server-hook.model.ts delete mode 100644 shared/models/plugins/register-server-setting.model.ts delete mode 100644 shared/models/plugins/server-hook.model.ts create mode 100644 shared/models/plugins/server/api/index.ts create mode 100644 shared/models/plugins/server/api/install-plugin.model.ts create mode 100644 shared/models/plugins/server/api/manage-plugin.model.ts create mode 100644 shared/models/plugins/server/api/peertube-plugin.model.ts create mode 100644 shared/models/plugins/server/index.ts create mode 100644 shared/models/plugins/server/managers/index.ts create mode 100644 shared/models/plugins/server/managers/plugin-playlist-privacy-manager.model.ts create mode 100644 shared/models/plugins/server/managers/plugin-settings-manager.model.ts create mode 100644 shared/models/plugins/server/managers/plugin-storage-manager.model.ts create mode 100644 shared/models/plugins/server/managers/plugin-transcoding-manager.model.ts create mode 100644 shared/models/plugins/server/managers/plugin-video-category-manager.model.ts create mode 100644 shared/models/plugins/server/managers/plugin-video-language-manager.model.ts create mode 100644 shared/models/plugins/server/managers/plugin-video-licence-manager.model.ts create mode 100644 shared/models/plugins/server/managers/plugin-video-privacy-manager.model.ts create mode 100644 shared/models/plugins/server/plugin-translation.model.ts create mode 100644 shared/models/plugins/server/register-server-hook.model.ts create mode 100644 shared/models/plugins/server/server-hook.model.ts create mode 100644 shared/models/plugins/server/settings/index.ts create mode 100644 shared/models/plugins/server/settings/public-server.setting.ts create mode 100644 shared/models/plugins/server/settings/register-server-setting.model.ts (limited to 'shared') diff --git a/shared/extra-utils/server/plugins.ts b/shared/extra-utils/server/plugins.ts index 864954ee7..d53e5b382 100644 --- a/shared/extra-utils/server/plugins.ts +++ b/shared/extra-utils/server/plugins.ts @@ -4,12 +4,12 @@ import { expect } from 'chai' import { readJSON, writeJSON } from 'fs-extra' import { join } from 'path' import { RegisteredServerSettings } from '@shared/models' -import { PeertubePluginIndexList } from '../../models/plugins/peertube-plugin-index-list.model' +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { PeertubePluginIndexList } from '../../models/plugins/plugin-index/peertube-plugin-index-list.model' import { PluginType } from '../../models/plugins/plugin.type' import { buildServerDirectory, root } from '../miscs/miscs' import { makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests' import { ServerInfo } from './servers' -import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' function listPlugins (parameters: { url: string diff --git a/shared/models/plugins/client-hook.model.ts b/shared/models/plugins/client-hook.model.ts deleted file mode 100644 index 620651051..000000000 --- a/shared/models/plugins/client-hook.model.ts +++ /dev/null @@ -1,125 +0,0 @@ -// Data from API hooks: {hookType}:api.{location}.{elementType}.{actionType}.{target} -// Data in internal functions: {hookType}:{location}.{elementType}.{actionType}.{target} - -export const clientFilterHookObject = { - // Filter params/result of the function that fetch videos of the trending page - 'filter:api.trending-videos.videos.list.params': true, - 'filter:api.trending-videos.videos.list.result': true, - - // Filter params/result of the function that fetch videos of the trending page - 'filter:api.most-liked-videos.videos.list.params': true, - 'filter:api.most-liked-videos.videos.list.result': true, - - // Filter params/result of the function that fetch videos of the local page - 'filter:api.local-videos.videos.list.params': true, - 'filter:api.local-videos.videos.list.result': true, - - // Filter params/result of the function that fetch videos of the recently-added page - 'filter:api.recently-added-videos.videos.list.params': true, - 'filter:api.recently-added-videos.videos.list.result': true, - - // Filter params/result of the function that fetch videos of the user subscription page - 'filter:api.user-subscriptions-videos.videos.list.params': true, - 'filter:api.user-subscriptions-videos.videos.list.result': true, - - // Filter params/result of the function that fetch the video of the video-watch page - 'filter:api.video-watch.video.get.params': true, - 'filter:api.video-watch.video.get.result': true, - - // Filter params/result of the function that fetch the threads of the video-watch page - 'filter:api.video-watch.video-threads.list.params': true, - 'filter:api.video-watch.video-threads.list.result': true, - - // Filter params/result of the function that fetch the replies of a thread in the video-watch page - 'filter:api.video-watch.video-thread-replies.list.params': true, - 'filter:api.video-watch.video-thread-replies.list.result': true, - - // Filter params/result of the function that fetch videos according to the user search - 'filter:api.search.videos.list.params': true, - 'filter:api.search.videos.list.result': true, - // Filter params/result of the function that fetch video-channels according to the user search - 'filter:api.search.video-channels.list.params': true, - 'filter:api.search.video-channels.list.result': true, - - // Filter form - 'filter:api.signup.registration.create.params': true, - - // Filter the options to create our player - 'filter:internal.video-watch.player.build-options.params': true, - 'filter:internal.video-watch.player.build-options.result': true, - - // Filter our SVG icons content - 'filter:internal.common.svg-icons.get-content.params': true, - 'filter:internal.common.svg-icons.get-content.result': true -} - -export type ClientFilterHookName = keyof typeof clientFilterHookObject - -export const clientActionHookObject = { - // Fired when the application is being initialized - 'action:application.init': true, - - // Fired when the video watch page is being initialized - 'action:video-watch.init': true, - // Fired when the video watch page loaded the video - 'action:video-watch.video.loaded': true, - // Fired when the player finished loading - 'action:video-watch.player.loaded': true, - // Fired when the video watch page comments(threads) are loaded and load more comments on scroll - 'action:video-watch.video-threads.loaded': true, - // Fired when a user click on 'View x replies' and they're loaded - 'action:video-watch.video-thread-replies.loaded': true, - - // Fired when the video edit page (upload, URL/torrent import, update) is being initialized - 'action:video-edit.init': true, - - // Fired when the login page is being initialized - 'action:login.init': true, - - // Fired when the search page is being initialized - 'action:search.init': true, - - // Fired every time Angular URL changes - 'action:router.navigation-end': true, - - // Fired when the registration page is being initialized - 'action:signup.register.init': true, - - // PeerTube >= 3.2 - // Fired when the admin plugin settings page is being initialized - 'action:admin-plugin-settings.init': true, - - // Fired when the video upload page is being initalized - 'action:video-upload.init': true, - // Fired when the video import by URL page is being initalized - 'action:video-url-import.init': true, - // Fired when the video import by torrent/magnet URI page is being initalized - 'action:video-torrent-import.init': true, - // Fired when the "Go Live" page is being initalized - 'action:go-live.init': true, - - // Fired when the user explicitely logged in/logged out - 'action:auth-user.logged-in': true, - 'action:auth-user.logged-out': true, - // Fired when the application loaded user information (using tokens from the local storage or after a successful login) - 'action:auth-user.information-loaded': true, - - // Fired when the modal to download a video/caption is shown - 'action:modal.video-download.shown': true, - - // ####### Embed hooks ####### - // /!\ In embed scope, peertube helpers are not available - // ########################### - - // Fired when the embed loaded the player - 'action:embed.player.loaded': true -} - -export type ClientActionHookName = keyof typeof clientActionHookObject - -export const clientHookObject = Object.assign({}, clientFilterHookObject, clientActionHookObject) -export type ClientHookName = keyof typeof clientHookObject - -export interface ClientHook { - runHook (hookName: ClientHookName, result?: T, params?: any): Promise -} diff --git a/shared/models/plugins/client/client-hook.model.ts b/shared/models/plugins/client/client-hook.model.ts new file mode 100644 index 000000000..620651051 --- /dev/null +++ b/shared/models/plugins/client/client-hook.model.ts @@ -0,0 +1,125 @@ +// Data from API hooks: {hookType}:api.{location}.{elementType}.{actionType}.{target} +// Data in internal functions: {hookType}:{location}.{elementType}.{actionType}.{target} + +export const clientFilterHookObject = { + // Filter params/result of the function that fetch videos of the trending page + 'filter:api.trending-videos.videos.list.params': true, + 'filter:api.trending-videos.videos.list.result': true, + + // Filter params/result of the function that fetch videos of the trending page + 'filter:api.most-liked-videos.videos.list.params': true, + 'filter:api.most-liked-videos.videos.list.result': true, + + // Filter params/result of the function that fetch videos of the local page + 'filter:api.local-videos.videos.list.params': true, + 'filter:api.local-videos.videos.list.result': true, + + // Filter params/result of the function that fetch videos of the recently-added page + 'filter:api.recently-added-videos.videos.list.params': true, + 'filter:api.recently-added-videos.videos.list.result': true, + + // Filter params/result of the function that fetch videos of the user subscription page + 'filter:api.user-subscriptions-videos.videos.list.params': true, + 'filter:api.user-subscriptions-videos.videos.list.result': true, + + // Filter params/result of the function that fetch the video of the video-watch page + 'filter:api.video-watch.video.get.params': true, + 'filter:api.video-watch.video.get.result': true, + + // Filter params/result of the function that fetch the threads of the video-watch page + 'filter:api.video-watch.video-threads.list.params': true, + 'filter:api.video-watch.video-threads.list.result': true, + + // Filter params/result of the function that fetch the replies of a thread in the video-watch page + 'filter:api.video-watch.video-thread-replies.list.params': true, + 'filter:api.video-watch.video-thread-replies.list.result': true, + + // Filter params/result of the function that fetch videos according to the user search + 'filter:api.search.videos.list.params': true, + 'filter:api.search.videos.list.result': true, + // Filter params/result of the function that fetch video-channels according to the user search + 'filter:api.search.video-channels.list.params': true, + 'filter:api.search.video-channels.list.result': true, + + // Filter form + 'filter:api.signup.registration.create.params': true, + + // Filter the options to create our player + 'filter:internal.video-watch.player.build-options.params': true, + 'filter:internal.video-watch.player.build-options.result': true, + + // Filter our SVG icons content + 'filter:internal.common.svg-icons.get-content.params': true, + 'filter:internal.common.svg-icons.get-content.result': true +} + +export type ClientFilterHookName = keyof typeof clientFilterHookObject + +export const clientActionHookObject = { + // Fired when the application is being initialized + 'action:application.init': true, + + // Fired when the video watch page is being initialized + 'action:video-watch.init': true, + // Fired when the video watch page loaded the video + 'action:video-watch.video.loaded': true, + // Fired when the player finished loading + 'action:video-watch.player.loaded': true, + // Fired when the video watch page comments(threads) are loaded and load more comments on scroll + 'action:video-watch.video-threads.loaded': true, + // Fired when a user click on 'View x replies' and they're loaded + 'action:video-watch.video-thread-replies.loaded': true, + + // Fired when the video edit page (upload, URL/torrent import, update) is being initialized + 'action:video-edit.init': true, + + // Fired when the login page is being initialized + 'action:login.init': true, + + // Fired when the search page is being initialized + 'action:search.init': true, + + // Fired every time Angular URL changes + 'action:router.navigation-end': true, + + // Fired when the registration page is being initialized + 'action:signup.register.init': true, + + // PeerTube >= 3.2 + // Fired when the admin plugin settings page is being initialized + 'action:admin-plugin-settings.init': true, + + // Fired when the video upload page is being initalized + 'action:video-upload.init': true, + // Fired when the video import by URL page is being initalized + 'action:video-url-import.init': true, + // Fired when the video import by torrent/magnet URI page is being initalized + 'action:video-torrent-import.init': true, + // Fired when the "Go Live" page is being initalized + 'action:go-live.init': true, + + // Fired when the user explicitely logged in/logged out + 'action:auth-user.logged-in': true, + 'action:auth-user.logged-out': true, + // Fired when the application loaded user information (using tokens from the local storage or after a successful login) + 'action:auth-user.information-loaded': true, + + // Fired when the modal to download a video/caption is shown + 'action:modal.video-download.shown': true, + + // ####### Embed hooks ####### + // /!\ In embed scope, peertube helpers are not available + // ########################### + + // Fired when the embed loaded the player + 'action:embed.player.loaded': true +} + +export type ClientActionHookName = keyof typeof clientActionHookObject + +export const clientHookObject = Object.assign({}, clientFilterHookObject, clientActionHookObject) +export type ClientHookName = keyof typeof clientHookObject + +export interface ClientHook { + runHook (hookName: ClientHookName, result?: T, params?: any): Promise +} diff --git a/shared/models/plugins/client/index.ts b/shared/models/plugins/client/index.ts new file mode 100644 index 000000000..6dfc6351f --- /dev/null +++ b/shared/models/plugins/client/index.ts @@ -0,0 +1,6 @@ +export * from './client-hook.model' +export * from './plugin-client-scope.type' +export * from './plugin-element-placeholder.type' +export * from './register-client-form-field.model' +export * from './register-client-hook.model' +export * from './register-client-settings-script.model' diff --git a/shared/models/plugins/client/plugin-client-scope.type.ts b/shared/models/plugins/client/plugin-client-scope.type.ts new file mode 100644 index 000000000..8cc234ff2 --- /dev/null +++ b/shared/models/plugins/client/plugin-client-scope.type.ts @@ -0,0 +1,9 @@ +export type PluginClientScope = + 'common' | + 'video-watch' | + 'search' | + 'signup' | + 'login' | + 'embed' | + 'video-edit' | + 'admin-plugin' diff --git a/shared/models/plugins/client/plugin-element-placeholder.type.ts b/shared/models/plugins/client/plugin-element-placeholder.type.ts new file mode 100644 index 000000000..129099c62 --- /dev/null +++ b/shared/models/plugins/client/plugin-element-placeholder.type.ts @@ -0,0 +1 @@ +export type PluginElementPlaceholder = 'player-next' diff --git a/shared/models/plugins/client/register-client-form-field.model.ts b/shared/models/plugins/client/register-client-form-field.model.ts new file mode 100644 index 000000000..2df071337 --- /dev/null +++ b/shared/models/plugins/client/register-client-form-field.model.ts @@ -0,0 +1,23 @@ +export type RegisterClientFormFieldOptions = { + name?: string + label?: string + type: 'input' | 'input-checkbox' | 'input-password' | 'input-textarea' | 'markdown-text' | 'markdown-enhanced' | 'select' | 'html' + + // For select type + options?: { value: string, label: string }[] + + // For html type + html?: string + + descriptionHTML?: string + + // Default setting value + default?: string | boolean + + // Not supported by plugin setting registration, use registerSettingsScript instead + hidden?: (options: any) => boolean +} + +export interface RegisterClientVideoFieldOptions { + type: 'update' | 'upload' | 'import-url' | 'import-torrent' | 'go-live' +} diff --git a/shared/models/plugins/client/register-client-hook.model.ts b/shared/models/plugins/client/register-client-hook.model.ts new file mode 100644 index 000000000..81047b21d --- /dev/null +++ b/shared/models/plugins/client/register-client-hook.model.ts @@ -0,0 +1,7 @@ +import { ClientHookName } from './client-hook.model' + +export interface RegisterClientHookOptions { + target: ClientHookName + handler: Function + priority?: number +} diff --git a/shared/models/plugins/client/register-client-settings-script.model.ts b/shared/models/plugins/client/register-client-settings-script.model.ts new file mode 100644 index 000000000..481ceef96 --- /dev/null +++ b/shared/models/plugins/client/register-client-settings-script.model.ts @@ -0,0 +1,8 @@ +import { RegisterServerSettingOptions } from '../server' + +export interface RegisterClientSettingsScript { + isSettingHidden (options: { + setting: RegisterServerSettingOptions + formValues: { [name: string]: any } + }): boolean +} diff --git a/shared/models/plugins/index.ts b/shared/models/plugins/index.ts index 03b27f907..cbbe4916e 100644 --- a/shared/models/plugins/index.ts +++ b/shared/models/plugins/index.ts @@ -1,28 +1,6 @@ -export * from './client-hook.model' +export * from './client' +export * from './plugin-index' +export * from './server' export * from './hook-type.enum' -export * from './install-plugin.model' -export * from './manage-plugin.model' -export * from './peertube-plugin-index-list.model' -export * from './peertube-plugin-index.model' -export * from './peertube-plugin-latest-version.model' -export * from './peertube-plugin.model' -export * from './plugin-client-scope.type' -export * from './plugin-element-placeholder.type' export * from './plugin-package-json.model' -export * from './plugin-playlist-privacy-manager.model' -export * from './plugin-settings-manager.model' -export * from './plugin-storage-manager.model' -export * from './plugin-transcoding-manager.model' -export * from './plugin-translation.model' -export * from './plugin-video-category-manager.model' -export * from './plugin-video-language-manager.model' -export * from './plugin-video-licence-manager.model' -export * from './plugin-video-privacy-manager.model' export * from './plugin.type' -export * from './public-server.setting' -export * from './register-client-hook.model' -export * from './register-client-settings-script.model' -export * from './register-client-form-field.model' -export * from './register-server-hook.model' -export * from './register-server-setting.model' -export * from './server-hook.model' diff --git a/shared/models/plugins/install-plugin.model.ts b/shared/models/plugins/install-plugin.model.ts deleted file mode 100644 index 5a268ebe1..000000000 --- a/shared/models/plugins/install-plugin.model.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface InstallOrUpdatePlugin { - npmName?: string - path?: string -} diff --git a/shared/models/plugins/manage-plugin.model.ts b/shared/models/plugins/manage-plugin.model.ts deleted file mode 100644 index 612b3056c..000000000 --- a/shared/models/plugins/manage-plugin.model.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface ManagePlugin { - npmName: string -} diff --git a/shared/models/plugins/peertube-plugin-index-list.model.ts b/shared/models/plugins/peertube-plugin-index-list.model.ts deleted file mode 100644 index 817bac31e..000000000 --- a/shared/models/plugins/peertube-plugin-index-list.model.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { PluginType } from './plugin.type' - -export interface PeertubePluginIndexList { - start: number - count: number - sort: string - pluginType?: PluginType - currentPeerTubeEngine?: string - search?: string -} diff --git a/shared/models/plugins/peertube-plugin-index.model.ts b/shared/models/plugins/peertube-plugin-index.model.ts deleted file mode 100644 index e91c8b4dc..000000000 --- a/shared/models/plugins/peertube-plugin-index.model.ts +++ /dev/null @@ -1,14 +0,0 @@ -export interface PeerTubePluginIndex { - npmName: string - description: string - homepage: string - createdAt: Date - updatedAt: Date - - popularity: number - - latestVersion: string - - name?: string - installed?: boolean -} diff --git a/shared/models/plugins/peertube-plugin-latest-version.model.ts b/shared/models/plugins/peertube-plugin-latest-version.model.ts deleted file mode 100644 index 811a64429..000000000 --- a/shared/models/plugins/peertube-plugin-latest-version.model.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface PeertubePluginLatestVersionRequest { - currentPeerTubeEngine?: string - - npmNames: string[] -} - -export type PeertubePluginLatestVersionResponse = { - npmName: string - latestVersion: string | null -}[] diff --git a/shared/models/plugins/peertube-plugin.model.ts b/shared/models/plugins/peertube-plugin.model.ts deleted file mode 100644 index 2b0bb8cfa..000000000 --- a/shared/models/plugins/peertube-plugin.model.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { PluginType } from './plugin.type' - -export interface PeerTubePlugin { - name: string - type: PluginType - latestVersion: string - version: string - enabled: boolean - uninstalled: boolean - peertubeEngine: string - description: string - homepage: string - settings: { [ name: string ]: string } - createdAt: Date - updatedAt: Date -} diff --git a/shared/models/plugins/plugin-client-scope.type.ts b/shared/models/plugins/plugin-client-scope.type.ts deleted file mode 100644 index 8cc234ff2..000000000 --- a/shared/models/plugins/plugin-client-scope.type.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type PluginClientScope = - 'common' | - 'video-watch' | - 'search' | - 'signup' | - 'login' | - 'embed' | - 'video-edit' | - 'admin-plugin' diff --git a/shared/models/plugins/plugin-element-placeholder.type.ts b/shared/models/plugins/plugin-element-placeholder.type.ts deleted file mode 100644 index 129099c62..000000000 --- a/shared/models/plugins/plugin-element-placeholder.type.ts +++ /dev/null @@ -1 +0,0 @@ -export type PluginElementPlaceholder = 'player-next' diff --git a/shared/models/plugins/plugin-index/index.ts b/shared/models/plugins/plugin-index/index.ts new file mode 100644 index 000000000..913846638 --- /dev/null +++ b/shared/models/plugins/plugin-index/index.ts @@ -0,0 +1,3 @@ +export * from './peertube-plugin-index-list.model' +export * from './peertube-plugin-index.model' +export * from './peertube-plugin-latest-version.model' diff --git a/shared/models/plugins/plugin-index/peertube-plugin-index-list.model.ts b/shared/models/plugins/plugin-index/peertube-plugin-index-list.model.ts new file mode 100644 index 000000000..ecb46482e --- /dev/null +++ b/shared/models/plugins/plugin-index/peertube-plugin-index-list.model.ts @@ -0,0 +1,10 @@ +import { PluginType } from '../plugin.type' + +export interface PeertubePluginIndexList { + start: number + count: number + sort: string + pluginType?: PluginType + currentPeerTubeEngine?: string + search?: string +} diff --git a/shared/models/plugins/plugin-index/peertube-plugin-index.model.ts b/shared/models/plugins/plugin-index/peertube-plugin-index.model.ts new file mode 100644 index 000000000..e91c8b4dc --- /dev/null +++ b/shared/models/plugins/plugin-index/peertube-plugin-index.model.ts @@ -0,0 +1,14 @@ +export interface PeerTubePluginIndex { + npmName: string + description: string + homepage: string + createdAt: Date + updatedAt: Date + + popularity: number + + latestVersion: string + + name?: string + installed?: boolean +} diff --git a/shared/models/plugins/plugin-index/peertube-plugin-latest-version.model.ts b/shared/models/plugins/plugin-index/peertube-plugin-latest-version.model.ts new file mode 100644 index 000000000..811a64429 --- /dev/null +++ b/shared/models/plugins/plugin-index/peertube-plugin-latest-version.model.ts @@ -0,0 +1,10 @@ +export interface PeertubePluginLatestVersionRequest { + currentPeerTubeEngine?: string + + npmNames: string[] +} + +export type PeertubePluginLatestVersionResponse = { + npmName: string + latestVersion: string | null +}[] diff --git a/shared/models/plugins/plugin-package-json.model.ts b/shared/models/plugins/plugin-package-json.model.ts index c26e9ae5b..b2f92af80 100644 --- a/shared/models/plugins/plugin-package-json.model.ts +++ b/shared/models/plugins/plugin-package-json.model.ts @@ -1,4 +1,4 @@ -import { PluginClientScope } from './plugin-client-scope.type' +import { PluginClientScope } from './client/plugin-client-scope.type' export type PluginTranslationPaths = { [ locale: string ]: string diff --git a/shared/models/plugins/plugin-playlist-privacy-manager.model.ts b/shared/models/plugins/plugin-playlist-privacy-manager.model.ts deleted file mode 100644 index d1823ef4e..000000000 --- a/shared/models/plugins/plugin-playlist-privacy-manager.model.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { VideoPlaylistPrivacy } from '../videos/playlist/video-playlist-privacy.model' - -export interface PluginPlaylistPrivacyManager { - // PUBLIC = 1, - // UNLISTED = 2, - // PRIVATE = 3 - deletePlaylistPrivacy: (privacyKey: VideoPlaylistPrivacy) => boolean -} diff --git a/shared/models/plugins/plugin-settings-manager.model.ts b/shared/models/plugins/plugin-settings-manager.model.ts deleted file mode 100644 index 3c28c0565..000000000 --- a/shared/models/plugins/plugin-settings-manager.model.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface PluginSettingsManager { - getSetting: (name: string) => Promise - - getSettings: (names: string[]) => Promise<{ [settingName: string]: string | boolean }> - - setSetting: (name: string, value: string) => Promise - - onSettingsChange: (cb: (names: string[]) => Promise) => void -} diff --git a/shared/models/plugins/plugin-storage-manager.model.ts b/shared/models/plugins/plugin-storage-manager.model.ts deleted file mode 100644 index 51567044a..000000000 --- a/shared/models/plugins/plugin-storage-manager.model.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface PluginStorageManager { - getData: (key: string) => Promise - - storeData: (key: string, data: any) => Promise -} diff --git a/shared/models/plugins/plugin-transcoding-manager.model.ts b/shared/models/plugins/plugin-transcoding-manager.model.ts deleted file mode 100644 index 8babccd4e..000000000 --- a/shared/models/plugins/plugin-transcoding-manager.model.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { EncoderOptionsBuilder } from '../videos/video-transcoding.model' - -export interface PluginTranscodingManager { - addLiveProfile (encoder: string, profile: string, builder: EncoderOptionsBuilder): boolean - - addVODProfile (encoder: string, profile: string, builder: EncoderOptionsBuilder): boolean - - addLiveEncoderPriority (streamType: 'audio' | 'video', encoder: string, priority: number): void - - addVODEncoderPriority (streamType: 'audio' | 'video', encoder: string, priority: number): void - - removeAllProfilesAndEncoderPriorities(): void -} diff --git a/shared/models/plugins/plugin-translation.model.ts b/shared/models/plugins/plugin-translation.model.ts deleted file mode 100644 index a2dd8e560..000000000 --- a/shared/models/plugins/plugin-translation.model.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type PluginTranslation = { - [ npmName: string ]: { - [ key: string ]: string - } -} diff --git a/shared/models/plugins/plugin-video-category-manager.model.ts b/shared/models/plugins/plugin-video-category-manager.model.ts deleted file mode 100644 index 201bfa979..000000000 --- a/shared/models/plugins/plugin-video-category-manager.model.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface PluginVideoCategoryManager { - addCategory: (categoryKey: number, categoryLabel: string) => boolean - - deleteCategory: (categoryKey: number) => boolean -} diff --git a/shared/models/plugins/plugin-video-language-manager.model.ts b/shared/models/plugins/plugin-video-language-manager.model.ts deleted file mode 100644 index 3fd577a79..000000000 --- a/shared/models/plugins/plugin-video-language-manager.model.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface PluginVideoLanguageManager { - addLanguage: (languageKey: string, languageLabel: string) => boolean - - deleteLanguage: (languageKey: string) => boolean -} diff --git a/shared/models/plugins/plugin-video-licence-manager.model.ts b/shared/models/plugins/plugin-video-licence-manager.model.ts deleted file mode 100644 index 82a634d3a..000000000 --- a/shared/models/plugins/plugin-video-licence-manager.model.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface PluginVideoLicenceManager { - addLicence: (licenceKey: number, licenceLabel: string) => boolean - - deleteLicence: (licenceKey: number) => boolean -} diff --git a/shared/models/plugins/plugin-video-privacy-manager.model.ts b/shared/models/plugins/plugin-video-privacy-manager.model.ts deleted file mode 100644 index 3ada99608..000000000 --- a/shared/models/plugins/plugin-video-privacy-manager.model.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { VideoPrivacy } from '../videos/video-privacy.enum' - -export interface PluginVideoPrivacyManager { - // PUBLIC = 1 - // UNLISTED = 2 - // PRIVATE = 3 - // INTERNAL = 4 - deletePrivacy: (privacyKey: VideoPrivacy) => boolean -} diff --git a/shared/models/plugins/public-server.setting.ts b/shared/models/plugins/public-server.setting.ts deleted file mode 100644 index 9802c4d7d..000000000 --- a/shared/models/plugins/public-server.setting.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface PublicServerSetting { - publicSettings: { [ name: string ]: string } -} diff --git a/shared/models/plugins/register-client-form-field.model.ts b/shared/models/plugins/register-client-form-field.model.ts deleted file mode 100644 index 2df071337..000000000 --- a/shared/models/plugins/register-client-form-field.model.ts +++ /dev/null @@ -1,23 +0,0 @@ -export type RegisterClientFormFieldOptions = { - name?: string - label?: string - type: 'input' | 'input-checkbox' | 'input-password' | 'input-textarea' | 'markdown-text' | 'markdown-enhanced' | 'select' | 'html' - - // For select type - options?: { value: string, label: string }[] - - // For html type - html?: string - - descriptionHTML?: string - - // Default setting value - default?: string | boolean - - // Not supported by plugin setting registration, use registerSettingsScript instead - hidden?: (options: any) => boolean -} - -export interface RegisterClientVideoFieldOptions { - type: 'update' | 'upload' | 'import-url' | 'import-torrent' | 'go-live' -} diff --git a/shared/models/plugins/register-client-hook.model.ts b/shared/models/plugins/register-client-hook.model.ts deleted file mode 100644 index 81047b21d..000000000 --- a/shared/models/plugins/register-client-hook.model.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ClientHookName } from './client-hook.model' - -export interface RegisterClientHookOptions { - target: ClientHookName - handler: Function - priority?: number -} diff --git a/shared/models/plugins/register-client-settings-script.model.ts b/shared/models/plugins/register-client-settings-script.model.ts deleted file mode 100644 index ac16af366..000000000 --- a/shared/models/plugins/register-client-settings-script.model.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { RegisterServerSettingOptions } from "./register-server-setting.model" - -export interface RegisterClientSettingsScript { - isSettingHidden (options: { - setting: RegisterServerSettingOptions - formValues: { [name: string]: any } - }): boolean -} diff --git a/shared/models/plugins/register-server-hook.model.ts b/shared/models/plugins/register-server-hook.model.ts deleted file mode 100644 index 746fdc329..000000000 --- a/shared/models/plugins/register-server-hook.model.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ServerHookName } from './server-hook.model' - -export interface RegisterServerHookOptions { - target: ServerHookName - handler: Function - priority?: number -} diff --git a/shared/models/plugins/register-server-setting.model.ts b/shared/models/plugins/register-server-setting.model.ts deleted file mode 100644 index 9f45c3c37..000000000 --- a/shared/models/plugins/register-server-setting.model.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { RegisterClientFormFieldOptions } from './register-client-form-field.model' - -export type RegisterServerSettingOptions = RegisterClientFormFieldOptions & { - // If the setting is not private, anyone can view its value (client code included) - // If the setting is private, only server-side hooks can access it - // Mainly used by the PeerTube client to get admin config - private: boolean -} - -export interface RegisteredServerSettings { - registeredSettings: RegisterServerSettingOptions[] -} diff --git a/shared/models/plugins/server-hook.model.ts b/shared/models/plugins/server-hook.model.ts deleted file mode 100644 index 88277af5a..000000000 --- a/shared/models/plugins/server-hook.model.ts +++ /dev/null @@ -1,123 +0,0 @@ -// {hookType}:{api?}.{location}.{subLocation?}.{actionType}.{target} - -export const serverFilterHookObject = { - // Filter params/result used to list videos for the REST API - // (used by the trending page, recently-added page, local page etc) - 'filter:api.videos.list.params': true, - 'filter:api.videos.list.result': true, - - // Filter params/result used to list account videos for the REST API - 'filter:api.accounts.videos.list.params': true, - 'filter:api.accounts.videos.list.result': true, - - // Filter params/result used to list channel videos for the REST API - 'filter:api.video-channels.videos.list.params': true, - 'filter:api.video-channels.videos.list.result': true, - - // Filter params/result used to list my user videos for the REST API - 'filter:api.user.me.videos.list.params': true, - 'filter:api.user.me.videos.list.result': true, - - // Filter params/results to search videos/channels in the DB or on the remote index - 'filter:api.search.videos.local.list.params': true, - 'filter:api.search.videos.local.list.result': true, - 'filter:api.search.videos.index.list.params': true, - 'filter:api.search.videos.index.list.result': true, - 'filter:api.search.video-channels.local.list.params': true, - 'filter:api.search.video-channels.local.list.result': true, - 'filter:api.search.video-channels.index.list.params': true, - 'filter:api.search.video-channels.index.list.result': true, - - // Filter the result of the get function - // Used to get detailed video information (video watch page for example) - 'filter:api.video.get.result': true, - - // Filter the result of the accept upload/live, import via torrent/url functions - // If this function returns false then the upload is aborted with an error - 'filter:api.video.upload.accept.result': true, - 'filter:api.live-video.create.accept.result': true, - 'filter:api.video.pre-import-url.accept.result': true, - 'filter:api.video.pre-import-torrent.accept.result': true, - 'filter:api.video.post-import-url.accept.result': true, - 'filter:api.video.post-import-torrent.accept.result': true, - // Filter the result of the accept comment (thread or reply) functions - // If the functions return false then the user cannot post its comment - 'filter:api.video-thread.create.accept.result': true, - 'filter:api.video-comment-reply.create.accept.result': true, - - // Filter params/result used to list threads of a specific video - // (used by the video watch page) - 'filter:api.video-threads.list.params': true, - 'filter:api.video-threads.list.result': true, - - // Filter params/result used to list replies of a specific thread - // (used by the video watch page when we click on the "View replies" button) - 'filter:api.video-thread-comments.list.params': true, - 'filter:api.video-thread-comments.list.result': true, - - // Filter result used to check if we need to auto blacklist a video - // (fired when a local or remote video is created or updated) - 'filter:video.auto-blacklist.result': true, - - // Filter result used to check if a user can register on the instance - 'filter:api.user.signup.allowed.result': true, - - // Filter result used to check if video/torrent download is allowed - 'filter:api.download.video.allowed.result': true, - 'filter:api.download.torrent.allowed.result': true, - - // Filter result to check if the embed is allowed for a particular request - 'filter:html.embed.video.allowed.result': true, - 'filter:html.embed.video-playlist.allowed.result': true -} - -export type ServerFilterHookName = keyof typeof serverFilterHookObject - -export const serverActionHookObject = { - // Fired when the application has been loaded and is listening HTTP requests - 'action:application.listening': true, - - // Fired when a local video is updated - 'action:api.video.updated': true, - // Fired when a local video is deleted - 'action:api.video.deleted': true, - // Fired when a local video is uploaded - 'action:api.video.uploaded': true, - // Fired when a local video is viewed - 'action:api.video.viewed': true, - - // Fired when a live video is created - 'action:api.live-video.created': true, - - // Fired when a thread is created - 'action:api.video-thread.created': true, - // Fired when a reply to a thread is created - 'action:api.video-comment-reply.created': true, - // Fired when a comment (thread or reply) is deleted - 'action:api.video-comment.deleted': true, - - // Fired when a user is blocked (banned) - 'action:api.user.blocked': true, - // Fired when a user is unblocked (unbanned) - 'action:api.user.unblocked': true, - // Fired when a user registered on the instance - 'action:api.user.registered': true, - // Fired when an admin/moderator created a user - 'action:api.user.created': true, - // Fired when a user is removed by an admin/moderator - 'action:api.user.deleted': true, - // Fired when a user is updated by an admin/moderator - 'action:api.user.updated': true, - - // Fired when a user got a new oauth2 token - 'action:api.user.oauth2-got-token': true -} - -export type ServerActionHookName = keyof typeof serverActionHookObject - -export const serverHookObject = Object.assign({}, serverFilterHookObject, serverActionHookObject) -export type ServerHookName = keyof typeof serverHookObject - -export interface ServerHook { - runHook (hookName: ServerHookName, result?: T, params?: any): Promise -} diff --git a/shared/models/plugins/server/api/index.ts b/shared/models/plugins/server/api/index.ts new file mode 100644 index 000000000..eb59a03f0 --- /dev/null +++ b/shared/models/plugins/server/api/index.ts @@ -0,0 +1,3 @@ +export * from './install-plugin.model' +export * from './manage-plugin.model' +export * from './peertube-plugin.model' diff --git a/shared/models/plugins/server/api/install-plugin.model.ts b/shared/models/plugins/server/api/install-plugin.model.ts new file mode 100644 index 000000000..5a268ebe1 --- /dev/null +++ b/shared/models/plugins/server/api/install-plugin.model.ts @@ -0,0 +1,4 @@ +export interface InstallOrUpdatePlugin { + npmName?: string + path?: string +} diff --git a/shared/models/plugins/server/api/manage-plugin.model.ts b/shared/models/plugins/server/api/manage-plugin.model.ts new file mode 100644 index 000000000..612b3056c --- /dev/null +++ b/shared/models/plugins/server/api/manage-plugin.model.ts @@ -0,0 +1,3 @@ +export interface ManagePlugin { + npmName: string +} diff --git a/shared/models/plugins/server/api/peertube-plugin.model.ts b/shared/models/plugins/server/api/peertube-plugin.model.ts new file mode 100644 index 000000000..54c383f57 --- /dev/null +++ b/shared/models/plugins/server/api/peertube-plugin.model.ts @@ -0,0 +1,16 @@ +import { PluginType } from '../../plugin.type' + +export interface PeerTubePlugin { + name: string + type: PluginType + latestVersion: string + version: string + enabled: boolean + uninstalled: boolean + peertubeEngine: string + description: string + homepage: string + settings: { [ name: string ]: string } + createdAt: Date + updatedAt: Date +} diff --git a/shared/models/plugins/server/index.ts b/shared/models/plugins/server/index.ts new file mode 100644 index 000000000..d3ff49d3b --- /dev/null +++ b/shared/models/plugins/server/index.ts @@ -0,0 +1,6 @@ +export * from './api' +export * from './managers' +export * from './settings' +export * from './plugin-translation.model' +export * from './register-server-hook.model' +export * from './server-hook.model' diff --git a/shared/models/plugins/server/managers/index.ts b/shared/models/plugins/server/managers/index.ts new file mode 100644 index 000000000..49365a854 --- /dev/null +++ b/shared/models/plugins/server/managers/index.ts @@ -0,0 +1,9 @@ + +export * from './plugin-playlist-privacy-manager.model' +export * from './plugin-settings-manager.model' +export * from './plugin-storage-manager.model' +export * from './plugin-transcoding-manager.model' +export * from './plugin-video-category-manager.model' +export * from './plugin-video-language-manager.model' +export * from './plugin-video-licence-manager.model' +export * from './plugin-video-privacy-manager.model' diff --git a/shared/models/plugins/server/managers/plugin-playlist-privacy-manager.model.ts b/shared/models/plugins/server/managers/plugin-playlist-privacy-manager.model.ts new file mode 100644 index 000000000..4703c0a8b --- /dev/null +++ b/shared/models/plugins/server/managers/plugin-playlist-privacy-manager.model.ts @@ -0,0 +1,8 @@ +import { VideoPlaylistPrivacy } from '../../../videos/playlist/video-playlist-privacy.model' + +export interface PluginPlaylistPrivacyManager { + // PUBLIC = 1, + // UNLISTED = 2, + // PRIVATE = 3 + deletePlaylistPrivacy: (privacyKey: VideoPlaylistPrivacy) => boolean +} diff --git a/shared/models/plugins/server/managers/plugin-settings-manager.model.ts b/shared/models/plugins/server/managers/plugin-settings-manager.model.ts new file mode 100644 index 000000000..3c28c0565 --- /dev/null +++ b/shared/models/plugins/server/managers/plugin-settings-manager.model.ts @@ -0,0 +1,9 @@ +export interface PluginSettingsManager { + getSetting: (name: string) => Promise + + getSettings: (names: string[]) => Promise<{ [settingName: string]: string | boolean }> + + setSetting: (name: string, value: string) => Promise + + onSettingsChange: (cb: (names: string[]) => Promise) => void +} diff --git a/shared/models/plugins/server/managers/plugin-storage-manager.model.ts b/shared/models/plugins/server/managers/plugin-storage-manager.model.ts new file mode 100644 index 000000000..51567044a --- /dev/null +++ b/shared/models/plugins/server/managers/plugin-storage-manager.model.ts @@ -0,0 +1,5 @@ +export interface PluginStorageManager { + getData: (key: string) => Promise + + storeData: (key: string, data: any) => Promise +} diff --git a/shared/models/plugins/server/managers/plugin-transcoding-manager.model.ts b/shared/models/plugins/server/managers/plugin-transcoding-manager.model.ts new file mode 100644 index 000000000..a0422a460 --- /dev/null +++ b/shared/models/plugins/server/managers/plugin-transcoding-manager.model.ts @@ -0,0 +1,13 @@ +import { EncoderOptionsBuilder } from '../../../videos/video-transcoding.model' + +export interface PluginTranscodingManager { + addLiveProfile (encoder: string, profile: string, builder: EncoderOptionsBuilder): boolean + + addVODProfile (encoder: string, profile: string, builder: EncoderOptionsBuilder): boolean + + addLiveEncoderPriority (streamType: 'audio' | 'video', encoder: string, priority: number): void + + addVODEncoderPriority (streamType: 'audio' | 'video', encoder: string, priority: number): void + + removeAllProfilesAndEncoderPriorities(): void +} diff --git a/shared/models/plugins/server/managers/plugin-video-category-manager.model.ts b/shared/models/plugins/server/managers/plugin-video-category-manager.model.ts new file mode 100644 index 000000000..201bfa979 --- /dev/null +++ b/shared/models/plugins/server/managers/plugin-video-category-manager.model.ts @@ -0,0 +1,5 @@ +export interface PluginVideoCategoryManager { + addCategory: (categoryKey: number, categoryLabel: string) => boolean + + deleteCategory: (categoryKey: number) => boolean +} diff --git a/shared/models/plugins/server/managers/plugin-video-language-manager.model.ts b/shared/models/plugins/server/managers/plugin-video-language-manager.model.ts new file mode 100644 index 000000000..3fd577a79 --- /dev/null +++ b/shared/models/plugins/server/managers/plugin-video-language-manager.model.ts @@ -0,0 +1,5 @@ +export interface PluginVideoLanguageManager { + addLanguage: (languageKey: string, languageLabel: string) => boolean + + deleteLanguage: (languageKey: string) => boolean +} diff --git a/shared/models/plugins/server/managers/plugin-video-licence-manager.model.ts b/shared/models/plugins/server/managers/plugin-video-licence-manager.model.ts new file mode 100644 index 000000000..82a634d3a --- /dev/null +++ b/shared/models/plugins/server/managers/plugin-video-licence-manager.model.ts @@ -0,0 +1,5 @@ +export interface PluginVideoLicenceManager { + addLicence: (licenceKey: number, licenceLabel: string) => boolean + + deleteLicence: (licenceKey: number) => boolean +} diff --git a/shared/models/plugins/server/managers/plugin-video-privacy-manager.model.ts b/shared/models/plugins/server/managers/plugin-video-privacy-manager.model.ts new file mode 100644 index 000000000..7717115e3 --- /dev/null +++ b/shared/models/plugins/server/managers/plugin-video-privacy-manager.model.ts @@ -0,0 +1,9 @@ +import { VideoPrivacy } from '../../../videos/video-privacy.enum' + +export interface PluginVideoPrivacyManager { + // PUBLIC = 1 + // UNLISTED = 2 + // PRIVATE = 3 + // INTERNAL = 4 + deletePrivacy: (privacyKey: VideoPrivacy) => boolean +} diff --git a/shared/models/plugins/server/plugin-translation.model.ts b/shared/models/plugins/server/plugin-translation.model.ts new file mode 100644 index 000000000..a2dd8e560 --- /dev/null +++ b/shared/models/plugins/server/plugin-translation.model.ts @@ -0,0 +1,5 @@ +export type PluginTranslation = { + [ npmName: string ]: { + [ key: string ]: string + } +} diff --git a/shared/models/plugins/server/register-server-hook.model.ts b/shared/models/plugins/server/register-server-hook.model.ts new file mode 100644 index 000000000..746fdc329 --- /dev/null +++ b/shared/models/plugins/server/register-server-hook.model.ts @@ -0,0 +1,7 @@ +import { ServerHookName } from './server-hook.model' + +export interface RegisterServerHookOptions { + target: ServerHookName + handler: Function + priority?: number +} diff --git a/shared/models/plugins/server/server-hook.model.ts b/shared/models/plugins/server/server-hook.model.ts new file mode 100644 index 000000000..88277af5a --- /dev/null +++ b/shared/models/plugins/server/server-hook.model.ts @@ -0,0 +1,123 @@ +// {hookType}:{api?}.{location}.{subLocation?}.{actionType}.{target} + +export const serverFilterHookObject = { + // Filter params/result used to list videos for the REST API + // (used by the trending page, recently-added page, local page etc) + 'filter:api.videos.list.params': true, + 'filter:api.videos.list.result': true, + + // Filter params/result used to list account videos for the REST API + 'filter:api.accounts.videos.list.params': true, + 'filter:api.accounts.videos.list.result': true, + + // Filter params/result used to list channel videos for the REST API + 'filter:api.video-channels.videos.list.params': true, + 'filter:api.video-channels.videos.list.result': true, + + // Filter params/result used to list my user videos for the REST API + 'filter:api.user.me.videos.list.params': true, + 'filter:api.user.me.videos.list.result': true, + + // Filter params/results to search videos/channels in the DB or on the remote index + 'filter:api.search.videos.local.list.params': true, + 'filter:api.search.videos.local.list.result': true, + 'filter:api.search.videos.index.list.params': true, + 'filter:api.search.videos.index.list.result': true, + 'filter:api.search.video-channels.local.list.params': true, + 'filter:api.search.video-channels.local.list.result': true, + 'filter:api.search.video-channels.index.list.params': true, + 'filter:api.search.video-channels.index.list.result': true, + + // Filter the result of the get function + // Used to get detailed video information (video watch page for example) + 'filter:api.video.get.result': true, + + // Filter the result of the accept upload/live, import via torrent/url functions + // If this function returns false then the upload is aborted with an error + 'filter:api.video.upload.accept.result': true, + 'filter:api.live-video.create.accept.result': true, + 'filter:api.video.pre-import-url.accept.result': true, + 'filter:api.video.pre-import-torrent.accept.result': true, + 'filter:api.video.post-import-url.accept.result': true, + 'filter:api.video.post-import-torrent.accept.result': true, + // Filter the result of the accept comment (thread or reply) functions + // If the functions return false then the user cannot post its comment + 'filter:api.video-thread.create.accept.result': true, + 'filter:api.video-comment-reply.create.accept.result': true, + + // Filter params/result used to list threads of a specific video + // (used by the video watch page) + 'filter:api.video-threads.list.params': true, + 'filter:api.video-threads.list.result': true, + + // Filter params/result used to list replies of a specific thread + // (used by the video watch page when we click on the "View replies" button) + 'filter:api.video-thread-comments.list.params': true, + 'filter:api.video-thread-comments.list.result': true, + + // Filter result used to check if we need to auto blacklist a video + // (fired when a local or remote video is created or updated) + 'filter:video.auto-blacklist.result': true, + + // Filter result used to check if a user can register on the instance + 'filter:api.user.signup.allowed.result': true, + + // Filter result used to check if video/torrent download is allowed + 'filter:api.download.video.allowed.result': true, + 'filter:api.download.torrent.allowed.result': true, + + // Filter result to check if the embed is allowed for a particular request + 'filter:html.embed.video.allowed.result': true, + 'filter:html.embed.video-playlist.allowed.result': true +} + +export type ServerFilterHookName = keyof typeof serverFilterHookObject + +export const serverActionHookObject = { + // Fired when the application has been loaded and is listening HTTP requests + 'action:application.listening': true, + + // Fired when a local video is updated + 'action:api.video.updated': true, + // Fired when a local video is deleted + 'action:api.video.deleted': true, + // Fired when a local video is uploaded + 'action:api.video.uploaded': true, + // Fired when a local video is viewed + 'action:api.video.viewed': true, + + // Fired when a live video is created + 'action:api.live-video.created': true, + + // Fired when a thread is created + 'action:api.video-thread.created': true, + // Fired when a reply to a thread is created + 'action:api.video-comment-reply.created': true, + // Fired when a comment (thread or reply) is deleted + 'action:api.video-comment.deleted': true, + + // Fired when a user is blocked (banned) + 'action:api.user.blocked': true, + // Fired when a user is unblocked (unbanned) + 'action:api.user.unblocked': true, + // Fired when a user registered on the instance + 'action:api.user.registered': true, + // Fired when an admin/moderator created a user + 'action:api.user.created': true, + // Fired when a user is removed by an admin/moderator + 'action:api.user.deleted': true, + // Fired when a user is updated by an admin/moderator + 'action:api.user.updated': true, + + // Fired when a user got a new oauth2 token + 'action:api.user.oauth2-got-token': true +} + +export type ServerActionHookName = keyof typeof serverActionHookObject + +export const serverHookObject = Object.assign({}, serverFilterHookObject, serverActionHookObject) +export type ServerHookName = keyof typeof serverHookObject + +export interface ServerHook { + runHook (hookName: ServerHookName, result?: T, params?: any): Promise +} diff --git a/shared/models/plugins/server/settings/index.ts b/shared/models/plugins/server/settings/index.ts new file mode 100644 index 000000000..b456de019 --- /dev/null +++ b/shared/models/plugins/server/settings/index.ts @@ -0,0 +1,2 @@ +export * from './public-server.setting' +export * from './register-server-setting.model' diff --git a/shared/models/plugins/server/settings/public-server.setting.ts b/shared/models/plugins/server/settings/public-server.setting.ts new file mode 100644 index 000000000..9802c4d7d --- /dev/null +++ b/shared/models/plugins/server/settings/public-server.setting.ts @@ -0,0 +1,3 @@ +export interface PublicServerSetting { + publicSettings: { [ name: string ]: string } +} diff --git a/shared/models/plugins/server/settings/register-server-setting.model.ts b/shared/models/plugins/server/settings/register-server-setting.model.ts new file mode 100644 index 000000000..d9a798cac --- /dev/null +++ b/shared/models/plugins/server/settings/register-server-setting.model.ts @@ -0,0 +1,12 @@ +import { RegisterClientFormFieldOptions } from '../../client' + +export type RegisterServerSettingOptions = RegisterClientFormFieldOptions & { + // If the setting is not private, anyone can view its value (client code included) + // If the setting is private, only server-side hooks can access it + // Mainly used by the PeerTube client to get admin config + private: boolean +} + +export interface RegisteredServerSettings { + registeredSettings: RegisterServerSettingOptions[] +} -- cgit v1.2.3 From 32985a0a779e0e2100a3990b1f1188645e58dfb1 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 11 May 2021 14:56:00 +0200 Subject: Error if importing a torrent with multiple files --- shared/models/server/server-error-code.enum.ts | 1 + 1 file changed, 1 insertion(+) (limited to 'shared') diff --git a/shared/models/server/server-error-code.enum.ts b/shared/models/server/server-error-code.enum.ts index c02b0e6c7..d17d958be 100644 --- a/shared/models/server/server-error-code.enum.ts +++ b/shared/models/server/server-error-code.enum.ts @@ -2,4 +2,5 @@ export const enum ServerErrorCode { DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS = 1, MAX_INSTANCE_LIVES_LIMIT_REACHED = 2, MAX_USER_LIVES_LIMIT_REACHED = 3, + INCORRECT_FILES_IN_TORRENT = 4 } -- cgit v1.2.3 From 16c016e8b1d5ca46343d3363f9a49e24c5d7c944 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 12 May 2021 14:09:04 +0200 Subject: Stricter models typing --- shared/core-utils/miscs/types.ts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'shared') diff --git a/shared/core-utils/miscs/types.ts b/shared/core-utils/miscs/types.ts index bb64dc830..bd2a97b98 100644 --- a/shared/core-utils/miscs/types.ts +++ b/shared/core-utils/miscs/types.ts @@ -6,6 +6,10 @@ export type FunctionPropertyNames = { export type FunctionProperties = Pick> +export type AttributesOnly = { + [K in keyof T]: T[K] extends Function ? never : T[K] +} + export type PickWith = { [P in KT]: T[P] extends V ? V : never } -- cgit v1.2.3 From aea0b0e7cde7495e60fe07b4444067f53d35ce3f Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 14 May 2021 12:04:44 +0200 Subject: Inject server config in HTML --- shared/extra-utils/server/servers.ts | 3 +++ shared/models/server/server-config.model.ts | 2 ++ 2 files changed, 5 insertions(+) (limited to 'shared') diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts index 479f08e12..d04757470 100644 --- a/shared/extra-utils/server/servers.ts +++ b/shared/extra-utils/server/servers.ts @@ -45,9 +45,12 @@ interface ServerInfo { uuid: string name?: string url?: string + account?: { name: string } + + embedPath?: string } remoteVideo?: { diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts index 85d84af44..2c5026b30 100644 --- a/shared/models/server/server-config.model.ts +++ b/shared/models/server/server-config.model.ts @@ -215,3 +215,5 @@ export interface ServerConfig { dismissable: boolean } } + +export type HTMLServerConfig = Omit -- cgit v1.2.3 From 2539932e16129992a2c0889b4ff527c265a8e2c7 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 27 May 2021 15:59:55 +0200 Subject: Instance homepage support (#4007) * Prepare homepage parsers * Add ability to update instance hompage * Add ability to set homepage as landing page * Add homepage preview in admin * Dynamically update left menu for homepage * Inject home content in homepage * Add videos list and channel miniature custom markup * Remove unused elements in markup service --- shared/core-utils/miscs/miscs.ts | 17 ++++++- shared/core-utils/renderer/html.ts | 52 +++++++++++++++------- shared/extra-utils/custom-pages/custom-pages.ts | 31 +++++++++++++ shared/extra-utils/index.ts | 2 + shared/models/actors/custom-page.model.ts | 3 ++ shared/models/actors/index.ts | 1 + .../custom-markup/custom-markup-data.model.ts | 28 ++++++++++++ shared/models/custom-markup/index.ts | 1 + shared/models/index.ts | 1 + shared/models/server/server-config.model.ts | 4 ++ shared/models/users/user-right.enum.ts | 1 + 11 files changed, 124 insertions(+), 17 deletions(-) create mode 100644 shared/extra-utils/custom-pages/custom-pages.ts create mode 100644 shared/models/actors/custom-page.model.ts create mode 100644 shared/models/custom-markup/custom-markup-data.model.ts create mode 100644 shared/models/custom-markup/index.ts (limited to 'shared') diff --git a/shared/core-utils/miscs/miscs.ts b/shared/core-utils/miscs/miscs.ts index 71703faac..4780ca922 100644 --- a/shared/core-utils/miscs/miscs.ts +++ b/shared/core-utils/miscs/miscs.ts @@ -28,9 +28,24 @@ function isCatchable (value: any) { return value && typeof value.catch === 'function' } +function sortObjectComparator (key: string, order: 'asc' | 'desc') { + return (a: any, b: any) => { + if (a[key] < b[key]) { + return order === 'asc' ? -1 : 1 + } + + if (a[key] > b[key]) { + return order === 'asc' ? 1 : -1 + } + + return 0 + } +} + export { randomInt, compareSemVer, isPromise, - isCatchable + isCatchable, + sortObjectComparator } diff --git a/shared/core-utils/renderer/html.ts b/shared/core-utils/renderer/html.ts index de4ad47ac..bbf8b3fbd 100644 --- a/shared/core-utils/renderer/html.ts +++ b/shared/core-utils/renderer/html.ts @@ -1,25 +1,45 @@ -export const SANITIZE_OPTIONS = { - allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ], - allowedSchemes: [ 'http', 'https' ], - allowedAttributes: { - a: [ 'href', 'class', 'target', 'rel' ] - }, - transformTags: { - a: (tagName: string, attribs: any) => { - let rel = 'noopener noreferrer' - if (attribs.rel === 'me') rel += ' me' +export function getSanitizeOptions () { + return { + allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ], + allowedSchemes: [ 'http', 'https' ], + allowedAttributes: { + 'a': [ 'href', 'class', 'target', 'rel' ], + '*': [ 'data-*' ] + }, + transformTags: { + a: (tagName: string, attribs: any) => { + let rel = 'noopener noreferrer' + if (attribs.rel === 'me') rel += ' me' - return { - tagName, - attribs: Object.assign(attribs, { - target: '_blank', - rel - }) + return { + tagName, + attribs: Object.assign(attribs, { + target: '_blank', + rel + }) + } } } } } +export function getCustomMarkupSanitizeOptions (additionalAllowedTags: string[] = []) { + const base = getSanitizeOptions() + + return { + allowedTags: [ + ...base.allowedTags, + ...additionalAllowedTags, + 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' + ], + allowedSchemes: base.allowedSchemes, + allowedAttributes: { + ...base.allowedAttributes, + '*': [ 'data-*', 'style' ] + } + } +} + // Thanks: https://stackoverflow.com/a/12034334 export function escapeHTML (stringParam: string) { if (!stringParam) return '' diff --git a/shared/extra-utils/custom-pages/custom-pages.ts b/shared/extra-utils/custom-pages/custom-pages.ts new file mode 100644 index 000000000..bf2d16c70 --- /dev/null +++ b/shared/extra-utils/custom-pages/custom-pages.ts @@ -0,0 +1,31 @@ +import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' +import { makeGetRequest, makePutBodyRequest } from '../requests/requests' + +function getInstanceHomepage (url: string, statusCodeExpected = HttpStatusCode.OK_200) { + const path = '/api/v1/custom-pages/homepage/instance' + + return makeGetRequest({ + url, + path, + statusCodeExpected + }) +} + +function updateInstanceHomepage (url: string, token: string, content: string) { + const path = '/api/v1/custom-pages/homepage/instance' + + return makePutBodyRequest({ + url, + path, + token, + fields: { content }, + statusCodeExpected: HttpStatusCode.NO_CONTENT_204 + }) +} + +// --------------------------------------------------------------------------- + +export { + getInstanceHomepage, + updateInstanceHomepage +} diff --git a/shared/extra-utils/index.ts b/shared/extra-utils/index.ts index 720db19cb..3bc09ead5 100644 --- a/shared/extra-utils/index.ts +++ b/shared/extra-utils/index.ts @@ -2,6 +2,8 @@ export * from './bulk/bulk' export * from './cli/cli' +export * from './custom-pages/custom-pages' + export * from './feeds/feeds' export * from './mock-servers/mock-instances-index' diff --git a/shared/models/actors/custom-page.model.ts b/shared/models/actors/custom-page.model.ts new file mode 100644 index 000000000..1e33584c1 --- /dev/null +++ b/shared/models/actors/custom-page.model.ts @@ -0,0 +1,3 @@ +export interface CustomPage { + content: string +} diff --git a/shared/models/actors/index.ts b/shared/models/actors/index.ts index 156f83248..e03f168cd 100644 --- a/shared/models/actors/index.ts +++ b/shared/models/actors/index.ts @@ -2,4 +2,5 @@ export * from './account.model' export * from './actor-image.model' export * from './actor-image.type' export * from './actor.model' +export * from './custom-page.model' export * from './follow.model' diff --git a/shared/models/custom-markup/custom-markup-data.model.ts b/shared/models/custom-markup/custom-markup-data.model.ts new file mode 100644 index 000000000..af697428e --- /dev/null +++ b/shared/models/custom-markup/custom-markup-data.model.ts @@ -0,0 +1,28 @@ +export type EmbedMarkupData = { + // Video or playlist uuid + uuid: string +} + +export type VideoMiniatureMarkupData = { + // Video uuid + uuid: string +} + +export type PlaylistMiniatureMarkupData = { + // Playlist uuid + uuid: string +} + +export type ChannelMiniatureMarkupData = { + // Channel name (username) + name: string +} + +export type VideosListMarkupData = { + title: string + description: string + sort: string + categoryOneOf: string // coma separated values + languageOneOf: string // coma separated values + count: string +} diff --git a/shared/models/custom-markup/index.ts b/shared/models/custom-markup/index.ts new file mode 100644 index 000000000..2898dfa90 --- /dev/null +++ b/shared/models/custom-markup/index.ts @@ -0,0 +1 @@ +export * from './custom-markup-data.model' diff --git a/shared/models/index.ts b/shared/models/index.ts index dff5fdf0e..4db1f234e 100644 --- a/shared/models/index.ts +++ b/shared/models/index.ts @@ -1,6 +1,7 @@ export * from './activitypub' export * from './actors' export * from './moderation' +export * from './custom-markup' export * from './bulk' export * from './redundancy' export * from './users' diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts index 2c5026b30..1667bc0e2 100644 --- a/shared/models/server/server-config.model.ts +++ b/shared/models/server/server-config.model.ts @@ -214,6 +214,10 @@ export interface ServerConfig { level: BroadcastMessageLevel dismissable: boolean } + + homepage: { + enabled: boolean + } } export type HTMLServerConfig = Omit diff --git a/shared/models/users/user-right.enum.ts b/shared/models/users/user-right.enum.ts index bbedc9f00..950b22bad 100644 --- a/shared/models/users/user-right.enum.ts +++ b/shared/models/users/user-right.enum.ts @@ -16,6 +16,7 @@ export const enum UserRight { MANAGE_JOBS, MANAGE_CONFIGURATION, + MANAGE_INSTANCE_CUSTOM_PAGE, MANAGE_ACCOUNTS_BLOCKLIST, MANAGE_SERVERS_BLOCKLIST, -- cgit v1.2.3