1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00
pigallery2/src/common/config/private/PrivateConfig.ts

516 lines
15 KiB
TypeScript
Raw Normal View History

2022-04-04 19:37:31 +02:00
/* eslint-disable @typescript-eslint/no-inferrable-types */
2020-01-28 18:36:52 +01:00
import 'reflect-metadata';
2022-04-04 19:37:31 +02:00
import {
JobScheduleDTO,
JobTrigger,
JobTriggerType,
} from '../../entities/job/JobScheduleDTO';
import {ClientConfig, ClientMetaFileConfig} from '../public/ClientConfig';
import {SubConfigClass} from 'typeconfig/src/decorators/class/SubConfigClass';
import {ConfigProperty} from 'typeconfig/src/decorators/property/ConfigPropoerty';
import {DefaultsJobs} from '../../entities/job/JobDTO';
2022-04-04 19:37:31 +02:00
import {
SearchQueryDTO,
SearchQueryTypes,
TextSearch,
} from '../../entities/SearchQueryDTO';
import {SortingMethods} from '../../entities/SortingMethods';
import {UserRoles} from '../../entities/UserDTO';
2020-01-28 18:36:52 +01:00
export enum DatabaseType {
2022-04-04 19:37:31 +02:00
memory = 1,
mysql = 2,
sqlite = 3,
}
2020-01-28 18:36:52 +01:00
export enum LogLevel {
2022-04-04 19:37:31 +02:00
error = 1,
warn = 2,
info = 3,
verbose = 4,
debug = 5,
silly = 6,
}
2020-01-28 18:36:52 +01:00
export enum SQLLogLevel {
2022-04-04 19:37:31 +02:00
none = 1,
error = 2,
all = 3,
}
2020-01-28 18:36:52 +01:00
export enum ReIndexingSensitivity {
2022-04-04 19:37:31 +02:00
low = 1,
medium = 2,
high = 3,
}
2020-01-28 18:36:52 +01:00
export enum FFmpegPresets {
2022-04-04 19:37:31 +02:00
ultrafast = 1,
superfast = 2,
veryfast = 3,
faster = 4,
fast = 5,
medium = 6,
slow = 7,
slower = 8,
veryslow = 9,
placebo = 10,
}
export type videoCodecType = 'libvpx-vp9' | 'libx264' | 'libvpx' | 'libx265';
2022-04-04 19:37:31 +02:00
export type videoResolutionType =
| 240
| 360
| 480
| 720
| 1080
| 1440
| 2160
| 4320;
export type videoFormatType = 'mp4' | 'webm';
@SubConfigClass()
export class MySQLConfig {
@ConfigProperty({envAlias: 'MYSQL_HOST'})
host: string = 'localhost';
@ConfigProperty({envAlias: 'MYSQL_PORT', min: 0, max: 65535})
port: number = 3306;
@ConfigProperty({envAlias: 'MYSQL_DATABASE'})
database: string = 'pigallery2';
@ConfigProperty({envAlias: 'MYSQL_USERNAME'})
username: string = '';
@ConfigProperty({envAlias: 'MYSQL_PASSWORD', type: 'password'})
password: string = '';
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class SQLiteConfig {
@ConfigProperty()
DBFileName: string = 'sqlite.db';
}
2020-12-28 22:08:57 +01:00
@SubConfigClass()
export class UserConfig {
@ConfigProperty()
name: string;
@ConfigProperty({type: UserRoles})
role: UserRoles;
@ConfigProperty({description: 'Unencrypted, temporary password'})
password: string;
@ConfigProperty({description: 'Encrypted password'})
2022-04-04 19:37:31 +02:00
encryptedPassword: string | undefined;
constructor(name: string, password: string, role: UserRoles) {
this.name = name;
this.role = role;
this.password = password;
}
}
2020-12-28 22:08:57 +01:00
@SubConfigClass()
export class ServerDataBaseConfig {
2022-12-16 23:26:37 +01:00
@ConfigProperty<DatabaseType, IPrivateConfig>({
type: DatabaseType,
onNewValue: (value, config) => {
2022-04-04 19:37:31 +02:00
if (config && value === DatabaseType.memory) {
config.Client.Search.enabled = false;
config.Client.Sharing.enabled = false;
2020-01-28 18:36:52 +01:00
}
2022-04-04 19:37:31 +02:00
},
})
type: DatabaseType = DatabaseType.sqlite;
2020-01-28 18:36:52 +01:00
@ConfigProperty()
dbFolder: string = 'db';
2020-01-28 18:36:52 +01:00
@ConfigProperty()
sqlite?: SQLiteConfig = new SQLiteConfig();
2020-12-28 22:08:57 +01:00
@ConfigProperty()
mysql?: MySQLConfig = new MySQLConfig();
2022-01-14 11:12:53 +01:00
@ConfigProperty({
arrayType: UserConfig,
2022-04-04 19:37:31 +02:00
description:
'Creates these users in the DB if they do not exist. If a user with this name exist, it wont be overwritten, even if the role is different.',
2022-01-14 11:12:53 +01:00
})
enforcedUsers: UserConfig[] = [];
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerThumbnailConfig {
2022-11-21 22:28:13 +01:00
@ConfigProperty({description: 'if true, \'lanczos3\' will used to scale photos, otherwise faster but lowe quality \'nearest\'.'})
useLanczos3: boolean = true;
@ConfigProperty({description: 'Thumbnail image quality', max: 100, min: 1, type: 'unsignedInt'})
quality = 80;
@ConfigProperty({type: 'ratio'})
personFaceMargin: number = 0.6; // in ration [0-1]
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerGPXCompressingConfig {
@ConfigProperty({
description: 'Compresses gpx files on-the-fly, when they are requested.',
})
onTheFly: boolean = true;
@ConfigProperty({type: 'unsignedInt', description: 'Filters out entry that are closer than this in meters.'})
minDistance: number = 5;
@ConfigProperty({type: 'unsignedInt', description: 'Filters out entry that are closer than this in time in milliseconds.'})
minTimeDistance: number = 5000;
}
@SubConfigClass()
export class ServerMetaFileConfig {
@ConfigProperty()
GPXCompressing: ServerGPXCompressingConfig = new ServerGPXCompressingConfig();
}
@SubConfigClass()
export class ServerSharingConfig {
@ConfigProperty()
updateTimeout: number = 1000 * 60 * 5;
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerIndexingConfig {
@ConfigProperty()
cachedFolderTimeout: number = 1000 * 60 * 60; // Do not rescans the folder if seems ok
@ConfigProperty({type: ReIndexingSensitivity})
reIndexingSensitivity: ReIndexingSensitivity = ReIndexingSensitivity.low;
@ConfigProperty({
arrayType: 'string',
2022-04-04 19:37:31 +02:00
description:
'If an entry starts with \'/\' it is treated as an absolute path.' +
' If it doesn\'t start with \'/\' but contains a \'/\', the path is relative to the image directory.' +
' If it doesn\'t contain a \'/\', any folder with this name will be excluded.',
})
excludeFolderList: string[] = ['.Trash-1000', '.dtrash', '$RECYCLE.BIN'];
2022-04-04 19:37:31 +02:00
@ConfigProperty({
arrayType: 'string',
description:
'Any folder that contains a file with this name will be excluded from indexing.',
})
excludeFileList: string[] = [];
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerThreadingConfig {
@ConfigProperty({description: 'App can run on multiple thread'})
enabled: boolean = true;
2022-04-04 19:37:31 +02:00
@ConfigProperty({
description:
'Number of threads that are used to generate thumbnails. If 0, number of \'CPU cores -1\' threads will be used.',
2022-04-04 19:37:31 +02:00
})
thumbnailThreads: number = 0; // if zero-> CPU count -1
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerDuplicatesConfig {
@ConfigProperty()
listingLimit: number = 1000; // maximum number of duplicates to list
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerLogConfig {
@ConfigProperty({type: LogLevel})
level: LogLevel = LogLevel.info;
@ConfigProperty({type: SQLLogLevel})
sqlLevel: SQLLogLevel = SQLLogLevel.error;
@ConfigProperty()
logServerTiming: boolean = false;
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class NeverJobTrigger implements JobTrigger {
@ConfigProperty({type: JobTriggerType})
readonly type = JobTriggerType.never;
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ScheduledJobTrigger implements JobTrigger {
@ConfigProperty({type: JobTriggerType})
readonly type = JobTriggerType.scheduled;
2020-01-28 18:36:52 +01:00
@ConfigProperty({type: 'unsignedInt'})
2022-04-04 19:37:31 +02:00
time: number; // data time
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class PeriodicJobTrigger implements JobTrigger {
@ConfigProperty({type: JobTriggerType})
readonly type = JobTriggerType.periodic;
@ConfigProperty({type: 'unsignedInt', max: 7})
2022-04-04 19:37:31 +02:00
periodicity: number | undefined; // 0-6: week days 7 every day
@ConfigProperty({type: 'unsignedInt', max: 23 * 60 + 59})
2022-04-04 19:37:31 +02:00
atTime: number | undefined; // day time
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class AfterJobTrigger implements JobTrigger {
@ConfigProperty({type: JobTriggerType})
readonly type = JobTriggerType.after;
@ConfigProperty()
2022-04-04 19:37:31 +02:00
afterScheduleName: string | undefined; // runs after schedule
2020-01-28 18:36:52 +01:00
constructor(afterScheduleName?: string) {
this.afterScheduleName = afterScheduleName;
2020-01-28 18:36:52 +01:00
}
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class JobScheduleConfig implements JobScheduleDTO {
@ConfigProperty()
name: string;
@ConfigProperty()
jobName: string;
@ConfigProperty()
config: any = {};
@ConfigProperty()
allowParallelRun: boolean;
@ConfigProperty({
type: NeverJobTrigger,
typeBuilder: (v: JobTrigger) => {
const type = typeof v.type === 'number' ? v.type : JobTriggerType[v.type];
switch (type) {
case JobTriggerType.after:
return AfterJobTrigger;
case JobTriggerType.never:
return NeverJobTrigger;
case JobTriggerType.scheduled:
return ScheduledJobTrigger;
case JobTriggerType.periodic:
return PeriodicJobTrigger;
2020-01-28 18:36:52 +01:00
}
return null;
2022-04-04 19:37:31 +02:00
},
})
2022-04-04 19:37:31 +02:00
trigger:
| AfterJobTrigger
| NeverJobTrigger
| PeriodicJobTrigger
| ScheduledJobTrigger;
constructor(
name: string,
jobName: string,
allowParallelRun: boolean,
trigger:
| AfterJobTrigger
| NeverJobTrigger
| PeriodicJobTrigger
| ScheduledJobTrigger,
config: any
) {
this.name = name;
this.jobName = jobName;
this.config = config;
this.allowParallelRun = allowParallelRun;
this.trigger = trigger;
2020-01-28 18:36:52 +01:00
}
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerJobConfig {
@ConfigProperty({type: 'integer', description: 'Job history size'})
maxSavedProgress: number = 20;
@ConfigProperty({type: 'integer', description: 'Job loads this many photos or videos form the DB for processing'})
mediaProcessingBatchSize: number = 1000;
@ConfigProperty({arrayType: JobScheduleConfig})
scheduled: JobScheduleConfig[] = [
2022-04-04 19:37:31 +02:00
new JobScheduleConfig(
DefaultsJobs[DefaultsJobs.Indexing],
DefaultsJobs[DefaultsJobs.Indexing],
false,
2022-04-04 19:37:31 +02:00
new NeverJobTrigger(),
{indexChangesOnly: true}
),
2022-04-04 19:37:31 +02:00
new JobScheduleConfig(
DefaultsJobs[DefaultsJobs['Preview Filling']],
DefaultsJobs[DefaultsJobs['Preview Filling']],
false,
2022-04-04 19:37:31 +02:00
new NeverJobTrigger(),
{}
),
2022-04-04 19:37:31 +02:00
new JobScheduleConfig(
DefaultsJobs[DefaultsJobs['Thumbnail Generation']],
DefaultsJobs[DefaultsJobs['Thumbnail Generation']],
false,
2022-04-04 19:37:31 +02:00
new AfterJobTrigger(DefaultsJobs[DefaultsJobs['Preview Filling']]),
{sizes: [240], indexedOnly: true}
),
2022-04-04 19:37:31 +02:00
new JobScheduleConfig(
DefaultsJobs[DefaultsJobs['Photo Converting']],
DefaultsJobs[DefaultsJobs['Photo Converting']],
false,
2022-04-04 19:37:31 +02:00
new AfterJobTrigger(DefaultsJobs[DefaultsJobs['Thumbnail Generation']]),
{indexedOnly: true}
),
2022-04-04 19:37:31 +02:00
new JobScheduleConfig(
DefaultsJobs[DefaultsJobs['Video Converting']],
DefaultsJobs[DefaultsJobs['Video Converting']],
false,
2022-04-04 19:37:31 +02:00
new AfterJobTrigger(DefaultsJobs[DefaultsJobs['Photo Converting']]),
{indexedOnly: true}
),
2022-04-04 19:37:31 +02:00
new JobScheduleConfig(
DefaultsJobs[DefaultsJobs['Temp Folder Cleaning']],
DefaultsJobs[DefaultsJobs['Temp Folder Cleaning']],
false,
2022-04-04 19:37:31 +02:00
new AfterJobTrigger(DefaultsJobs[DefaultsJobs['Video Converting']]),
{indexedOnly: true}
),
];
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class VideoTranscodingConfig {
@ConfigProperty({type: 'unsignedInt'})
bitRate: number = 5 * 1024 * 1024;
@ConfigProperty({type: 'unsignedInt'})
resolution: videoResolutionType = 720;
@ConfigProperty({type: 'positiveFloat'})
fps: number = 25;
@ConfigProperty()
codec: videoCodecType = 'libx264';
@ConfigProperty()
format: videoFormatType = 'mp4';
@ConfigProperty({
type: 'unsignedInt',
2022-04-04 19:37:31 +02:00
description:
'Constant Rate Factor. The range of the CRF scale is 051, where 0 is lossless, 23 is the default, and 51 is worst quality possible.',
max: 51,
})
crf: number = 23;
@ConfigProperty({
type: FFmpegPresets,
2022-04-04 19:37:31 +02:00
description:
'A preset is a collection of options that will provide a certain encoding speed to compression ratio',
})
preset: FFmpegPresets = FFmpegPresets.medium;
2022-04-04 19:37:31 +02:00
@ConfigProperty({
arrayType: 'string',
description: 'It will be sent to ffmpeg as it is, as custom options.',
})
customOptions: string[] = [];
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerVideoConfig {
@ConfigProperty()
transcoding: VideoTranscodingConfig = new VideoTranscodingConfig();
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class PhotoConvertingConfig {
2022-04-04 19:37:31 +02:00
@ConfigProperty({
description: 'Converts photos on the fly, when they are requested.',
})
onTheFly: boolean = true;
@ConfigProperty({type: 'unsignedInt'})
resolution: videoResolutionType = 1080;
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerPhotoConfig {
@ConfigProperty()
Converting: PhotoConvertingConfig = new PhotoConvertingConfig();
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerPreviewConfig {
@ConfigProperty({type: 'object'})
2022-04-04 19:37:31 +02:00
SearchQuery: SearchQueryDTO = {
type: SearchQueryTypes.any_text,
text: '',
} as TextSearch;
@ConfigProperty({arrayType: SortingMethods})
Sorting: SortingMethods[] = [
SortingMethods.descRating,
2022-04-04 19:37:31 +02:00
SortingMethods.descDate,
];
}
@SubConfigClass()
export class ServerMediaConfig {
2022-04-04 19:37:31 +02:00
@ConfigProperty({
description:
'Images are loaded from this folder (read permission required)',
})
folder: string = 'demo/images';
2022-04-04 19:37:31 +02:00
@ConfigProperty({
description:
'Thumbnails, converted photos, videos will be stored here (write permission required)',
})
tempFolder: string = 'demo/tmp';
@ConfigProperty()
Video: ServerVideoConfig = new ServerVideoConfig();
@ConfigProperty()
Photo: ServerPhotoConfig = new ServerPhotoConfig();
@ConfigProperty()
Thumbnail: ServerThumbnailConfig = new ServerThumbnailConfig();
}
2020-01-28 18:36:52 +01:00
@SubConfigClass()
export class ServerEnvironmentConfig {
@ConfigProperty({volatile: true})
2022-04-04 19:37:31 +02:00
upTime: string | undefined;
@ConfigProperty({volatile: true})
2022-04-04 19:37:31 +02:00
appVersion: string | undefined;
@ConfigProperty({volatile: true})
2022-04-04 19:37:31 +02:00
buildTime: string | undefined;
@ConfigProperty({volatile: true})
2022-04-04 19:37:31 +02:00
buildCommitHash: string | undefined;
@ConfigProperty({volatile: true})
2022-04-04 19:37:31 +02:00
isDocker: boolean | undefined;
}
2020-02-07 23:32:41 +01:00
@SubConfigClass()
export class ServerConfig {
@ConfigProperty({volatile: true})
Environment: ServerEnvironmentConfig = new ServerEnvironmentConfig();
@ConfigProperty({arrayType: 'string'})
sessionSecret: string[] = [];
@ConfigProperty({type: 'unsignedInt', envAlias: 'PORT', min: 0, max: 65535})
port: number = 80;
@ConfigProperty()
host: string = '0.0.0.0';
@ConfigProperty()
Media: ServerMediaConfig = new ServerMediaConfig();
@ConfigProperty()
Preview: ServerPreviewConfig = new ServerPreviewConfig();
@ConfigProperty()
Threading: ServerThreadingConfig = new ServerThreadingConfig();
@ConfigProperty()
Database: ServerDataBaseConfig = new ServerDataBaseConfig();
@ConfigProperty()
Sharing: ServerSharingConfig = new ServerSharingConfig();
@ConfigProperty({type: 'unsignedInt', description: 'unit: ms'})
sessionTimeout: number = 1000 * 60 * 60 * 24 * 7; // in ms
@ConfigProperty()
Indexing: ServerIndexingConfig = new ServerIndexingConfig();
2022-04-04 19:37:31 +02:00
@ConfigProperty({
type: 'unsignedInt',
description:
'only this many bites will be loaded when scanning photo for metadata',
})
photoMetadataSize: number = 512 * 1024; // only this many bites will be loaded when scanning photo for metadata
@ConfigProperty()
Duplicates: ServerDuplicatesConfig = new ServerDuplicatesConfig();
@ConfigProperty()
Log: ServerLogConfig = new ServerLogConfig();
@ConfigProperty()
Jobs: ServerJobConfig = new ServerJobConfig();
@ConfigProperty()
MetaFile: ServerMetaFileConfig = new ServerMetaFileConfig();
2020-01-28 18:36:52 +01:00
}
export interface IPrivateConfig {
Server: ServerConfig;
Client: ClientConfig;
2020-01-28 18:36:52 +01:00
}