From 3a4992633ee62d5edfbb484d9c6bcb3cf158489d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 31 Jul 2023 14:34:36 +0200 Subject: Migrate server to ESM Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports) --- packages/models/src/server/about.model.ts | 20 ++ .../src/server/broadcast-message-level.type.ts | 1 + .../models/src/server/client-log-create.model.ts | 11 + .../models/src/server/client-log-level.type.ts | 1 + packages/models/src/server/contact-form.model.ts | 6 + packages/models/src/server/custom-config.model.ts | 259 +++++++++++++++++ packages/models/src/server/debug.model.ts | 12 + packages/models/src/server/emailer.model.ts | 49 ++++ packages/models/src/server/index.ts | 16 ++ packages/models/src/server/job.model.ts | 303 ++++++++++++++++++++ .../src/server/peertube-problem-document.model.ts | 32 +++ packages/models/src/server/server-config.model.ts | 305 +++++++++++++++++++++ packages/models/src/server/server-debug.model.ts | 4 + .../models/src/server/server-error-code.enum.ts | 92 +++++++ .../src/server/server-follow-create.model.ts | 4 + .../models/src/server/server-log-level.type.ts | 1 + packages/models/src/server/server-stats.model.ts | 47 ++++ 17 files changed, 1163 insertions(+) create mode 100644 packages/models/src/server/about.model.ts create mode 100644 packages/models/src/server/broadcast-message-level.type.ts create mode 100644 packages/models/src/server/client-log-create.model.ts create mode 100644 packages/models/src/server/client-log-level.type.ts create mode 100644 packages/models/src/server/contact-form.model.ts create mode 100644 packages/models/src/server/custom-config.model.ts create mode 100644 packages/models/src/server/debug.model.ts create mode 100644 packages/models/src/server/emailer.model.ts create mode 100644 packages/models/src/server/index.ts create mode 100644 packages/models/src/server/job.model.ts create mode 100644 packages/models/src/server/peertube-problem-document.model.ts create mode 100644 packages/models/src/server/server-config.model.ts create mode 100644 packages/models/src/server/server-debug.model.ts create mode 100644 packages/models/src/server/server-error-code.enum.ts create mode 100644 packages/models/src/server/server-follow-create.model.ts create mode 100644 packages/models/src/server/server-log-level.type.ts create mode 100644 packages/models/src/server/server-stats.model.ts (limited to 'packages/models/src/server') diff --git a/packages/models/src/server/about.model.ts b/packages/models/src/server/about.model.ts new file mode 100644 index 000000000..6d4ba63c4 --- /dev/null +++ b/packages/models/src/server/about.model.ts @@ -0,0 +1,20 @@ +export interface About { + instance: { + name: string + shortDescription: string + description: string + terms: string + + codeOfConduct: string + hardwareInformation: string + + creationReason: string + moderationInformation: string + administrator: string + maintenanceLifetime: string + businessModel: string + + languages: string[] + categories: number[] + } +} diff --git a/packages/models/src/server/broadcast-message-level.type.ts b/packages/models/src/server/broadcast-message-level.type.ts new file mode 100644 index 000000000..bf43e18b5 --- /dev/null +++ b/packages/models/src/server/broadcast-message-level.type.ts @@ -0,0 +1 @@ +export type BroadcastMessageLevel = 'info' | 'warning' | 'error' diff --git a/packages/models/src/server/client-log-create.model.ts b/packages/models/src/server/client-log-create.model.ts new file mode 100644 index 000000000..543af0d3d --- /dev/null +++ b/packages/models/src/server/client-log-create.model.ts @@ -0,0 +1,11 @@ +import { ClientLogLevel } from './client-log-level.type.js' + +export interface ClientLogCreate { + message: string + url: string + level: ClientLogLevel + + stackTrace?: string + userAgent?: string + meta?: string +} diff --git a/packages/models/src/server/client-log-level.type.ts b/packages/models/src/server/client-log-level.type.ts new file mode 100644 index 000000000..18dea2751 --- /dev/null +++ b/packages/models/src/server/client-log-level.type.ts @@ -0,0 +1 @@ +export type ClientLogLevel = 'warn' | 'error' diff --git a/packages/models/src/server/contact-form.model.ts b/packages/models/src/server/contact-form.model.ts new file mode 100644 index 000000000..c23e6d1ba --- /dev/null +++ b/packages/models/src/server/contact-form.model.ts @@ -0,0 +1,6 @@ +export interface ContactForm { + fromEmail: string + fromName: string + subject: string + body: string +} diff --git a/packages/models/src/server/custom-config.model.ts b/packages/models/src/server/custom-config.model.ts new file mode 100644 index 000000000..df4176ba7 --- /dev/null +++ b/packages/models/src/server/custom-config.model.ts @@ -0,0 +1,259 @@ +import { NSFWPolicyType } from '../videos/nsfw-policy.type.js' +import { BroadcastMessageLevel } from './broadcast-message-level.type.js' + +export type ConfigResolutions = { + '144p': boolean + '240p': boolean + '360p': boolean + '480p': boolean + '720p': boolean + '1080p': boolean + '1440p': boolean + '2160p': boolean +} + +export interface CustomConfig { + instance: { + name: string + shortDescription: string + description: string + terms: string + codeOfConduct: string + + creationReason: string + moderationInformation: string + administrator: string + maintenanceLifetime: string + businessModel: string + hardwareInformation: string + + languages: string[] + categories: number[] + + isNSFW: boolean + defaultNSFWPolicy: NSFWPolicyType + + defaultClientRoute: string + + customizations: { + javascript?: string + css?: string + } + } + + theme: { + default: string + } + + services: { + twitter: { + username: string + whitelisted: boolean + } + } + + client: { + videos: { + miniature: { + preferAuthorDisplayName: boolean + } + } + + menu: { + login: { + redirectOnSingleExternalAuth: boolean + } + } + } + + cache: { + previews: { + size: number + } + + captions: { + size: number + } + + torrents: { + size: number + } + + storyboards: { + size: number + } + } + + signup: { + enabled: boolean + limit: number + requiresApproval: boolean + requiresEmailVerification: boolean + minimumAge: number + } + + admin: { + email: string + } + + contactForm: { + enabled: boolean + } + + user: { + history: { + videos: { + enabled: boolean + } + } + videoQuota: number + videoQuotaDaily: number + } + + videoChannels: { + maxPerUser: number + } + + transcoding: { + enabled: boolean + + allowAdditionalExtensions: boolean + allowAudioFiles: boolean + + remoteRunners: { + enabled: boolean + } + + threads: number + concurrency: number + + profile: string + + resolutions: ConfigResolutions & { '0p': boolean } + + alwaysTranscodeOriginalResolution: boolean + + webVideos: { + enabled: boolean + } + + hls: { + enabled: boolean + } + } + + live: { + enabled: boolean + + allowReplay: boolean + + latencySetting: { + enabled: boolean + } + + maxDuration: number + maxInstanceLives: number + maxUserLives: number + + transcoding: { + enabled: boolean + remoteRunners: { + enabled: boolean + } + threads: number + profile: string + resolutions: ConfigResolutions + alwaysTranscodeOriginalResolution: boolean + } + } + + videoStudio: { + enabled: boolean + + remoteRunners: { + enabled: boolean + } + } + + videoFile: { + update: { + enabled: boolean + } + } + + import: { + videos: { + concurrency: number + + http: { + enabled: boolean + } + torrent: { + enabled: boolean + } + } + videoChannelSynchronization: { + enabled: boolean + maxPerUser: number + } + } + + trending: { + videos: { + algorithms: { + enabled: string[] + default: string + } + } + } + + autoBlacklist: { + videos: { + ofUsers: { + enabled: boolean + } + } + } + + followers: { + instance: { + enabled: boolean + manualApproval: boolean + } + } + + followings: { + instance: { + autoFollowBack: { + enabled: boolean + } + + autoFollowIndex: { + enabled: boolean + indexUrl: string + } + } + } + + broadcastMessage: { + enabled: boolean + message: string + level: BroadcastMessageLevel + dismissable: boolean + } + + search: { + remoteUri: { + users: boolean + anonymous: boolean + } + + searchIndex: { + enabled: boolean + url: string + disableLocalSearch: boolean + isDefaultSearch: boolean + } + } + +} diff --git a/packages/models/src/server/debug.model.ts b/packages/models/src/server/debug.model.ts new file mode 100644 index 000000000..41f2109af --- /dev/null +++ b/packages/models/src/server/debug.model.ts @@ -0,0 +1,12 @@ +export interface Debug { + ip: string + activityPubMessagesWaiting: number +} + +export interface SendDebugCommand { + command: 'remove-dandling-resumable-uploads' + | 'process-video-views-buffer' + | 'process-video-viewers' + | 'process-video-channel-sync-latest' + | 'process-update-videos-scheduler' +} diff --git a/packages/models/src/server/emailer.model.ts b/packages/models/src/server/emailer.model.ts new file mode 100644 index 000000000..39512d306 --- /dev/null +++ b/packages/models/src/server/emailer.model.ts @@ -0,0 +1,49 @@ +type From = string | { name?: string, address: string } + +interface Base extends Partial { + to: string[] | string +} + +interface MailTemplate extends Base { + template: string + locals?: { [key: string]: any } + text?: undefined +} + +interface MailText extends Base { + text: string + + locals?: Partial & { + title?: string + action?: { + url: string + text: string + } + } +} + +interface SendEmailDefaultLocalsOptions { + instanceName: string + text: string + subject: string +} + +interface SendEmailDefaultMessageOptions { + to: string[] | string + from: From + subject: string + replyTo: string +} + +export type SendEmailDefaultOptions = { + template: 'common' + + message: SendEmailDefaultMessageOptions + + locals: SendEmailDefaultLocalsOptions & { + WEBSERVER: any + EMAIL: any + } +} + +export type SendEmailOptions = MailTemplate | MailText diff --git a/packages/models/src/server/index.ts b/packages/models/src/server/index.ts new file mode 100644 index 000000000..ba6af8f6f --- /dev/null +++ b/packages/models/src/server/index.ts @@ -0,0 +1,16 @@ +export * from './about.model.js' +export * from './broadcast-message-level.type.js' +export * from './client-log-create.model.js' +export * from './client-log-level.type.js' +export * from './contact-form.model.js' +export * from './custom-config.model.js' +export * from './debug.model.js' +export * from './emailer.model.js' +export * from './job.model.js' +export * from './peertube-problem-document.model.js' +export * from './server-config.model.js' +export * from './server-debug.model.js' +export * from './server-error-code.enum.js' +export * from './server-follow-create.model.js' +export * from './server-log-level.type.js' +export * from './server-stats.model.js' diff --git a/packages/models/src/server/job.model.ts b/packages/models/src/server/job.model.ts new file mode 100644 index 000000000..f86a20e28 --- /dev/null +++ b/packages/models/src/server/job.model.ts @@ -0,0 +1,303 @@ +import { ContextType } from '../activitypub/context.js' +import { VideoStateType } from '../videos/index.js' +import { VideoStudioTaskCut } from '../videos/studio/index.js' +import { SendEmailOptions } from './emailer.model.js' + +export type JobState = 'active' | 'completed' | 'failed' | 'waiting' | 'delayed' | 'paused' | 'waiting-children' + +export type JobType = + | 'activitypub-cleaner' + | 'activitypub-follow' + | 'activitypub-http-broadcast-parallel' + | 'activitypub-http-broadcast' + | 'activitypub-http-fetcher' + | 'activitypub-http-unicast' + | 'activitypub-refresher' + | 'actor-keys' + | 'after-video-channel-import' + | 'email' + | 'federate-video' + | 'transcoding-job-builder' + | 'manage-video-torrent' + | 'move-to-object-storage' + | 'notify' + | 'video-channel-import' + | 'video-file-import' + | 'video-import' + | 'video-live-ending' + | 'video-redundancy' + | 'video-studio-edition' + | 'video-transcoding' + | 'videos-views-stats' + | 'generate-video-storyboard' + +export interface Job { + id: number | string + state: JobState | 'unknown' + type: JobType + data: any + priority: number + progress: number + error: any + createdAt: Date | string + finishedOn: Date | string + processedOn: Date | string + + parent?: { + id: string + } +} + +export type ActivitypubHttpBroadcastPayload = { + uris: string[] + contextType: ContextType + body: any + signatureActorId?: number +} + +export type ActivitypubFollowPayload = { + followerActorId: number + name: string + host: string + isAutoFollow?: boolean + assertIsChannel?: boolean +} + +export type FetchType = 'activity' | 'video-shares' | 'video-comments' | 'account-playlists' +export type ActivitypubHttpFetcherPayload = { + uri: string + type: FetchType + videoId?: number +} + +export type ActivitypubHttpUnicastPayload = { + uri: string + contextType: ContextType + signatureActorId?: number + body: object +} + +export type RefreshPayload = { + type: 'video' | 'video-playlist' | 'actor' + url: string +} + +export type EmailPayload = SendEmailOptions + +export type VideoFileImportPayload = { + videoUUID: string + filePath: string +} + +// --------------------------------------------------------------------------- + +export type VideoImportTorrentPayloadType = 'magnet-uri' | 'torrent-file' +export type VideoImportYoutubeDLPayloadType = 'youtube-dl' + +export interface VideoImportYoutubeDLPayload { + type: VideoImportYoutubeDLPayloadType + videoImportId: number + + fileExt?: string +} + +export interface VideoImportTorrentPayload { + type: VideoImportTorrentPayloadType + videoImportId: number +} + +export type VideoImportPayload = (VideoImportYoutubeDLPayload | VideoImportTorrentPayload) & { + preventException: boolean +} + +export interface VideoImportPreventExceptionResult { + resultType: 'success' | 'error' +} + +// --------------------------------------------------------------------------- + +export type VideoRedundancyPayload = { + videoId: number +} + +export type ManageVideoTorrentPayload = + { + action: 'create' + videoId: number + videoFileId: number + } | { + action: 'update-metadata' + + videoId?: number + streamingPlaylistId?: number + + videoFileId: number + } + +// Video transcoding payloads + +interface BaseTranscodingPayload { + videoUUID: string + isNewVideo?: boolean +} + +export interface HLSTranscodingPayload extends BaseTranscodingPayload { + type: 'new-resolution-to-hls' + resolution: number + fps: number + copyCodecs: boolean + + deleteWebVideoFiles: boolean +} + +export interface NewWebVideoResolutionTranscodingPayload extends BaseTranscodingPayload { + type: 'new-resolution-to-web-video' + resolution: number + fps: number +} + +export interface MergeAudioTranscodingPayload extends BaseTranscodingPayload { + type: 'merge-audio-to-web-video' + + resolution: number + fps: number + + hasChildren: boolean +} + +export interface OptimizeTranscodingPayload extends BaseTranscodingPayload { + type: 'optimize-to-web-video' + + quickTranscode: boolean + + hasChildren: boolean +} + +export type VideoTranscodingPayload = + HLSTranscodingPayload + | NewWebVideoResolutionTranscodingPayload + | OptimizeTranscodingPayload + | MergeAudioTranscodingPayload + +export interface VideoLiveEndingPayload { + videoId: number + publishedAt: string + liveSessionId: number + streamingPlaylistId: number + + replayDirectory?: string +} + +export interface ActorKeysPayload { + actorId: number +} + +export interface DeleteResumableUploadMetaFilePayload { + filepath: string +} + +export interface MoveObjectStoragePayload { + videoUUID: string + isNewVideo: boolean + previousVideoState: VideoStateType +} + +export type VideoStudioTaskCutPayload = VideoStudioTaskCut + +export type VideoStudioTaskIntroPayload = { + name: 'add-intro' + + options: { + file: string + } +} + +export type VideoStudioTaskOutroPayload = { + name: 'add-outro' + + options: { + file: string + } +} + +export type VideoStudioTaskWatermarkPayload = { + name: 'add-watermark' + + options: { + file: string + + watermarkSizeRatio: number + horitonzalMarginRatio: number + verticalMarginRatio: number + } +} + +export type VideoStudioTaskPayload = + VideoStudioTaskCutPayload | + VideoStudioTaskIntroPayload | + VideoStudioTaskOutroPayload | + VideoStudioTaskWatermarkPayload + +export interface VideoStudioEditionPayload { + videoUUID: string + tasks: VideoStudioTaskPayload[] +} + +// --------------------------------------------------------------------------- + +export interface VideoChannelImportPayload { + externalChannelUrl: string + videoChannelId: number + + partOfChannelSyncId?: number +} + +export interface AfterVideoChannelImportPayload { + channelSyncId: number +} + +// --------------------------------------------------------------------------- + +export type NotifyPayload = + { + action: 'new-video' + videoUUID: string + } + +// --------------------------------------------------------------------------- + +export interface FederateVideoPayload { + videoUUID: string + isNewVideo: boolean +} + +// --------------------------------------------------------------------------- + +export interface TranscodingJobBuilderPayload { + videoUUID: string + + optimizeJob?: { + isNewVideo: boolean + } + + // Array of jobs to create + jobs?: { + type: 'video-transcoding' + payload: VideoTranscodingPayload + priority?: number + }[] + + // Array of sequential jobs to create + sequentialJobs?: { + type: 'video-transcoding' + payload: VideoTranscodingPayload + priority?: number + }[][] +} + +// --------------------------------------------------------------------------- + +export interface GenerateStoryboardPayload { + videoUUID: string + federate: boolean +} diff --git a/packages/models/src/server/peertube-problem-document.model.ts b/packages/models/src/server/peertube-problem-document.model.ts new file mode 100644 index 000000000..c717fc152 --- /dev/null +++ b/packages/models/src/server/peertube-problem-document.model.ts @@ -0,0 +1,32 @@ +import { HttpStatusCodeType } from '../http/http-status-codes.js' +import { OAuth2ErrorCodeType, ServerErrorCodeType } from './server-error-code.enum.js' + +export interface PeerTubeProblemDocumentData { + 'invalid-params'?: Record + + originUrl?: string + + keyId?: string + + targetUrl?: string + + actorUrl?: string + + // Feeds + format?: string + url?: string +} + +export interface PeerTubeProblemDocument extends PeerTubeProblemDocumentData { + type: string + title: string + + detail: string + // FIXME: Compat PeerTube <= 3.2 + error: string + + status: HttpStatusCodeType + + docs?: string + code?: OAuth2ErrorCodeType | ServerErrorCodeType +} diff --git a/packages/models/src/server/server-config.model.ts b/packages/models/src/server/server-config.model.ts new file mode 100644 index 000000000..a2a2bd5aa --- /dev/null +++ b/packages/models/src/server/server-config.model.ts @@ -0,0 +1,305 @@ +import { ClientScriptJSON } from '../plugins/plugin-package-json.model.js' +import { NSFWPolicyType } from '../videos/nsfw-policy.type.js' +import { VideoPrivacyType } from '../videos/video-privacy.enum.js' +import { BroadcastMessageLevel } from './broadcast-message-level.type.js' + +export interface ServerConfigPlugin { + name: string + npmName: string + version: string + description: string + clientScripts: { [name: string]: ClientScriptJSON } +} + +export interface ServerConfigTheme extends ServerConfigPlugin { + css: string[] +} + +export interface RegisteredExternalAuthConfig { + npmName: string + name: string + version: string + authName: string + authDisplayName: string +} + +export interface RegisteredIdAndPassAuthConfig { + npmName: string + name: string + version: string + authName: string + weight: number +} + +export interface ServerConfig { + serverVersion: string + serverCommit?: string + + client: { + videos: { + miniature: { + displayAuthorAvatar: boolean + preferAuthorDisplayName: boolean + } + resumableUpload: { + maxChunkSize: number + } + } + + menu: { + login: { + redirectOnSingleExternalAuth: boolean + } + } + } + + defaults: { + publish: { + downloadEnabled: boolean + commentsEnabled: boolean + privacy: VideoPrivacyType + licence: number + } + + p2p: { + webapp: { + enabled: boolean + } + + embed: { + enabled: boolean + } + } + } + + webadmin: { + configuration: { + edition: { + allowed: boolean + } + } + } + + instance: { + name: string + shortDescription: string + isNSFW: boolean + defaultNSFWPolicy: NSFWPolicyType + defaultClientRoute: string + customizations: { + javascript: string + css: string + } + } + + search: { + remoteUri: { + users: boolean + anonymous: boolean + } + + searchIndex: { + enabled: boolean + url: string + disableLocalSearch: boolean + isDefaultSearch: boolean + } + } + + plugin: { + registered: ServerConfigPlugin[] + + registeredExternalAuths: RegisteredExternalAuthConfig[] + + registeredIdAndPassAuths: RegisteredIdAndPassAuthConfig[] + } + + theme: { + registered: ServerConfigTheme[] + default: string + } + + email: { + enabled: boolean + } + + contactForm: { + enabled: boolean + } + + signup: { + allowed: boolean + allowedForCurrentIP: boolean + requiresEmailVerification: boolean + requiresApproval: boolean + minimumAge: number + } + + transcoding: { + hls: { + enabled: boolean + } + + web_videos: { + enabled: boolean + } + + enabledResolutions: number[] + + profile: string + availableProfiles: string[] + + remoteRunners: { + enabled: boolean + } + } + + live: { + enabled: boolean + + allowReplay: boolean + latencySetting: { + enabled: boolean + } + + maxDuration: number + maxInstanceLives: number + maxUserLives: number + + transcoding: { + enabled: boolean + + remoteRunners: { + enabled: boolean + } + + enabledResolutions: number[] + + profile: string + availableProfiles: string[] + } + + rtmp: { + port: number + } + } + + videoStudio: { + enabled: boolean + + remoteRunners: { + enabled: boolean + } + } + + videoFile: { + update: { + enabled: boolean + } + } + + import: { + videos: { + http: { + enabled: boolean + } + torrent: { + enabled: boolean + } + } + videoChannelSynchronization: { + enabled: boolean + } + } + + autoBlacklist: { + videos: { + ofUsers: { + enabled: boolean + } + } + } + + avatar: { + file: { + size: { + max: number + } + extensions: string[] + } + } + + banner: { + file: { + size: { + max: number + } + extensions: string[] + } + } + + video: { + image: { + size: { + max: number + } + extensions: string[] + } + file: { + extensions: string[] + } + } + + videoCaption: { + file: { + size: { + max: number + } + extensions: string[] + } + } + + user: { + videoQuota: number + videoQuotaDaily: number + } + + videoChannels: { + maxPerUser: number + } + + trending: { + videos: { + intervalDays: number + algorithms: { + enabled: string[] + default: string + } + } + } + + tracker: { + enabled: boolean + } + + followings: { + instance: { + autoFollowIndex: { + indexUrl: string + } + } + } + + broadcastMessage: { + enabled: boolean + message: string + level: BroadcastMessageLevel + dismissable: boolean + } + + homepage: { + enabled: boolean + } +} + +export type HTMLServerConfig = Omit diff --git a/packages/models/src/server/server-debug.model.ts b/packages/models/src/server/server-debug.model.ts new file mode 100644 index 000000000..4b731bb90 --- /dev/null +++ b/packages/models/src/server/server-debug.model.ts @@ -0,0 +1,4 @@ +export interface ServerDebug { + ip: string + activityPubMessagesWaiting: number +} diff --git a/packages/models/src/server/server-error-code.enum.ts b/packages/models/src/server/server-error-code.enum.ts new file mode 100644 index 000000000..dc200c1ea --- /dev/null +++ b/packages/models/src/server/server-error-code.enum.ts @@ -0,0 +1,92 @@ +export const ServerErrorCode = { + /** + * The simplest form of payload too large: when the file size is over the + * global file size limit + */ + MAX_FILE_SIZE_REACHED:'max_file_size_reached', + + /** + * The payload is too large for the user quota set + */ + QUOTA_REACHED:'quota_reached', + + /** + * Error yielded upon trying to access a video that is not federated, nor can + * be. This may be due to: remote videos on instances that are not followed by + * yours, and with your instance disallowing unknown instances being accessed. + */ + DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS:'does_not_respect_follow_constraints', + + LIVE_NOT_ENABLED:'live_not_enabled', + LIVE_NOT_ALLOWING_REPLAY:'live_not_allowing_replay', + LIVE_CONFLICTING_PERMANENT_AND_SAVE_REPLAY:'live_conflicting_permanent_and_save_replay', + /** + * Pretty self-explanatory: the set maximum number of simultaneous lives was + * reached, and this error is typically there to inform the user trying to + * broadcast one. + */ + MAX_INSTANCE_LIVES_LIMIT_REACHED:'max_instance_lives_limit_reached', + /** + * Pretty self-explanatory: the set maximum number of simultaneous lives FOR + * THIS USER was reached, and this error is typically there to inform the user + * trying to broadcast one. + */ + MAX_USER_LIVES_LIMIT_REACHED:'max_user_lives_limit_reached', + + /** + * A torrent should have at most one correct video file. Any more and we will + * not be able to choose automatically. + */ + INCORRECT_FILES_IN_TORRENT:'incorrect_files_in_torrent', + + COMMENT_NOT_ASSOCIATED_TO_VIDEO:'comment_not_associated_to_video', + + MISSING_TWO_FACTOR:'missing_two_factor', + INVALID_TWO_FACTOR:'invalid_two_factor', + + ACCOUNT_WAITING_FOR_APPROVAL:'account_waiting_for_approval', + ACCOUNT_APPROVAL_REJECTED:'account_approval_rejected', + + RUNNER_JOB_NOT_IN_PROCESSING_STATE:'runner_job_not_in_processing_state', + RUNNER_JOB_NOT_IN_PENDING_STATE:'runner_job_not_in_pending_state', + UNKNOWN_RUNNER_TOKEN:'unknown_runner_token', + + VIDEO_REQUIRES_PASSWORD:'video_requires_password', + INCORRECT_VIDEO_PASSWORD:'incorrect_video_password', + + VIDEO_ALREADY_BEING_TRANSCODED:'video_already_being_transcoded' +} as const + +/** + * oauthjs/oauth2-server error codes + * @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 + **/ +export const OAuth2ErrorCode = { + /** + * The provided authorization grant (e.g., authorization code, resource owner + * credentials) or refresh token is invalid, expired, revoked, does not match + * the redirection URI used in the authorization request, or was issued to + * another client. + * + * @see https://github.com/oauthjs/node-oauth2-server/blob/master/lib/errors/invalid-grant-error.js + */ + INVALID_GRANT: 'invalid_grant', + + /** + * Client authentication failed (e.g., unknown client, no client authentication + * included, or unsupported authentication method). + * + * @see https://github.com/oauthjs/node-oauth2-server/blob/master/lib/errors/invalid-client-error.js + */ + INVALID_CLIENT: 'invalid_client', + + /** + * The access token provided is expired, revoked, malformed, or invalid for other reasons + * + * @see https://github.com/oauthjs/node-oauth2-server/blob/master/lib/errors/invalid-token-error.js + */ + INVALID_TOKEN: 'invalid_token' +} as const + +export type OAuth2ErrorCodeType = typeof OAuth2ErrorCode[keyof typeof OAuth2ErrorCode] +export type ServerErrorCodeType = typeof ServerErrorCode[keyof typeof ServerErrorCode] diff --git a/packages/models/src/server/server-follow-create.model.ts b/packages/models/src/server/server-follow-create.model.ts new file mode 100644 index 000000000..3f90c7d6f --- /dev/null +++ b/packages/models/src/server/server-follow-create.model.ts @@ -0,0 +1,4 @@ +export interface ServerFollowCreate { + hosts?: string[] + handles?: string[] +} diff --git a/packages/models/src/server/server-log-level.type.ts b/packages/models/src/server/server-log-level.type.ts new file mode 100644 index 000000000..f0f31a4ae --- /dev/null +++ b/packages/models/src/server/server-log-level.type.ts @@ -0,0 +1 @@ +export type ServerLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'audit' diff --git a/packages/models/src/server/server-stats.model.ts b/packages/models/src/server/server-stats.model.ts new file mode 100644 index 000000000..5870ee73d --- /dev/null +++ b/packages/models/src/server/server-stats.model.ts @@ -0,0 +1,47 @@ +import { ActivityType } from '../activitypub/index.js' +import { VideoRedundancyStrategyWithManual } from '../redundancy/index.js' + +type ActivityPubMessagesSuccess = Record<`totalActivityPub${ActivityType}MessagesSuccesses`, number> +type ActivityPubMessagesErrors = Record<`totalActivityPub${ActivityType}MessagesErrors`, number> + +export interface ServerStats extends ActivityPubMessagesSuccess, ActivityPubMessagesErrors { + totalUsers: number + totalDailyActiveUsers: number + totalWeeklyActiveUsers: number + totalMonthlyActiveUsers: number + + totalLocalVideos: number + totalLocalVideoViews: number + totalLocalVideoComments: number + totalLocalVideoFilesSize: number + + totalVideos: number + totalVideoComments: number + + totalLocalVideoChannels: number + totalLocalDailyActiveVideoChannels: number + totalLocalWeeklyActiveVideoChannels: number + totalLocalMonthlyActiveVideoChannels: number + + totalLocalPlaylists: number + + totalInstanceFollowers: number + totalInstanceFollowing: number + + videosRedundancy: VideosRedundancyStats[] + + totalActivityPubMessagesProcessed: number + totalActivityPubMessagesSuccesses: number + totalActivityPubMessagesErrors: number + + activityPubMessagesProcessedPerSecond: number + totalActivityPubMessagesWaiting: number +} + +export interface VideosRedundancyStats { + strategy: VideoRedundancyStrategyWithManual + totalSize: number + totalUsed: number + totalVideoFiles: number + totalVideos: number +} -- cgit v1.2.3