Merge branch 'develop' of https://github.com/sct/overseerr into jellyfin-support
This commit is contained in:
@@ -1,19 +1,23 @@
|
||||
import { randomUUID } from 'crypto';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { merge } from 'lodash';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { Permission } from './permissions';
|
||||
import path from 'path';
|
||||
import webpush from 'web-push';
|
||||
import { MediaServerType } from '../constants/server';
|
||||
import { Permission } from './permissions';
|
||||
|
||||
export interface Library {
|
||||
id: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
type: 'show' | 'movie';
|
||||
lastScan?: number;
|
||||
}
|
||||
|
||||
export interface Region {
|
||||
iso_3166_1: string;
|
||||
english_name: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface Language {
|
||||
@@ -29,6 +33,7 @@ export interface PlexSettings {
|
||||
port: number;
|
||||
useSsl?: boolean;
|
||||
libraries: Library[];
|
||||
webAppUrl?: string;
|
||||
}
|
||||
|
||||
export interface JellyfinSettings {
|
||||
@@ -38,7 +43,7 @@ export interface JellyfinSettings {
|
||||
serverId: string;
|
||||
}
|
||||
|
||||
interface DVRSettings {
|
||||
export interface DVRSettings {
|
||||
id: number;
|
||||
name: string;
|
||||
hostname: string;
|
||||
@@ -49,6 +54,7 @@ interface DVRSettings {
|
||||
activeProfileId: number;
|
||||
activeProfileName: string;
|
||||
activeDirectory: string;
|
||||
tags: number[];
|
||||
is4k: boolean;
|
||||
isDefault: boolean;
|
||||
externalUrl?: string;
|
||||
@@ -66,21 +72,35 @@ export interface SonarrSettings extends DVRSettings {
|
||||
activeAnimeDirectory?: string;
|
||||
activeAnimeLanguageProfileId?: number;
|
||||
activeLanguageProfileId?: number;
|
||||
animeTags?: number[];
|
||||
enableSeasonFolders: boolean;
|
||||
}
|
||||
|
||||
interface Quota {
|
||||
quotaLimit?: number;
|
||||
quotaDays?: number;
|
||||
}
|
||||
|
||||
export interface MainSettings {
|
||||
apiKey: string;
|
||||
applicationTitle: string;
|
||||
applicationUrl: string;
|
||||
csrfProtection: boolean;
|
||||
cacheImages: boolean;
|
||||
defaultPermissions: number;
|
||||
defaultQuotas: {
|
||||
movie: Quota;
|
||||
tv: Quota;
|
||||
};
|
||||
hideAvailable: boolean;
|
||||
localLogin: boolean;
|
||||
newPlexLogin: boolean;
|
||||
region: string;
|
||||
originalLanguage: string;
|
||||
trustProxy: boolean;
|
||||
mediaServerType: number;
|
||||
partialRequestsEnabled: boolean;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
interface PublicSettings {
|
||||
@@ -89,6 +109,7 @@ interface PublicSettings {
|
||||
|
||||
interface FullPublicSettings extends PublicSettings {
|
||||
applicationTitle: string;
|
||||
applicationUrl: string;
|
||||
hideAvailable: boolean;
|
||||
localLogin: boolean;
|
||||
movie4kEnabled: boolean;
|
||||
@@ -98,15 +119,23 @@ interface FullPublicSettings extends PublicSettings {
|
||||
mediaServerType: number;
|
||||
jellyfinHost?: string;
|
||||
jellyfinServerName?: string;
|
||||
partialRequestsEnabled: boolean;
|
||||
cacheImages: boolean;
|
||||
vapidPublic: string;
|
||||
enablePushRegistration: boolean;
|
||||
locale: string;
|
||||
emailEnabled: boolean;
|
||||
}
|
||||
|
||||
export interface NotificationAgentConfig {
|
||||
enabled: boolean;
|
||||
types: number;
|
||||
types?: number;
|
||||
options: Record<string, unknown>;
|
||||
}
|
||||
export interface NotificationAgentDiscord extends NotificationAgentConfig {
|
||||
options: {
|
||||
botUsername?: string;
|
||||
botAvatarUrl?: string;
|
||||
webhookUrl: string;
|
||||
};
|
||||
}
|
||||
@@ -123,15 +152,27 @@ export interface NotificationAgentEmail extends NotificationAgentConfig {
|
||||
smtpHost: string;
|
||||
smtpPort: number;
|
||||
secure: boolean;
|
||||
ignoreTls: boolean;
|
||||
requireTls: boolean;
|
||||
authUser?: string;
|
||||
authPass?: string;
|
||||
allowSelfSigned: boolean;
|
||||
senderName: string;
|
||||
pgpPrivateKey?: string;
|
||||
pgpPassword?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface NotificationAgentLunaSea extends NotificationAgentConfig {
|
||||
options: {
|
||||
webhookUrl: string;
|
||||
profileName?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface NotificationAgentTelegram extends NotificationAgentConfig {
|
||||
options: {
|
||||
botUsername?: string;
|
||||
botAPI: string;
|
||||
chatId: string;
|
||||
sendSilently: boolean;
|
||||
@@ -148,7 +189,6 @@ export interface NotificationAgentPushover extends NotificationAgentConfig {
|
||||
options: {
|
||||
accessToken: string;
|
||||
userToken: string;
|
||||
priority: number;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -156,28 +196,41 @@ export interface NotificationAgentWebhook extends NotificationAgentConfig {
|
||||
options: {
|
||||
webhookUrl: string;
|
||||
jsonPayload: string;
|
||||
authHeader: string;
|
||||
authHeader?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export enum NotificationAgentKey {
|
||||
DISCORD = 'discord',
|
||||
EMAIL = 'email',
|
||||
PUSHBULLET = 'pushbullet',
|
||||
PUSHOVER = 'pushover',
|
||||
SLACK = 'slack',
|
||||
TELEGRAM = 'telegram',
|
||||
WEBHOOK = 'webhook',
|
||||
WEBPUSH = 'webpush',
|
||||
}
|
||||
|
||||
interface NotificationAgents {
|
||||
discord: NotificationAgentDiscord;
|
||||
email: NotificationAgentEmail;
|
||||
lunasea: NotificationAgentLunaSea;
|
||||
pushbullet: NotificationAgentPushbullet;
|
||||
pushover: NotificationAgentPushover;
|
||||
slack: NotificationAgentSlack;
|
||||
telegram: NotificationAgentTelegram;
|
||||
webhook: NotificationAgentWebhook;
|
||||
webpush: NotificationAgentConfig;
|
||||
}
|
||||
|
||||
interface NotificationSettings {
|
||||
enabled: boolean;
|
||||
autoapprovalEnabled: boolean;
|
||||
agents: NotificationAgents;
|
||||
}
|
||||
|
||||
interface AllSettings {
|
||||
clientId: string;
|
||||
vapidPublic: string;
|
||||
vapidPrivate: string;
|
||||
main: MainSettings;
|
||||
plex: PlexSettings;
|
||||
jellyfin: JellyfinSettings;
|
||||
@@ -196,23 +249,33 @@ class Settings {
|
||||
|
||||
constructor(initialSettings?: AllSettings) {
|
||||
this.data = {
|
||||
clientId: uuidv4(),
|
||||
clientId: randomUUID(),
|
||||
vapidPrivate: '',
|
||||
vapidPublic: '',
|
||||
main: {
|
||||
apiKey: '',
|
||||
applicationTitle: 'Overseerr',
|
||||
applicationUrl: '',
|
||||
csrfProtection: false,
|
||||
cacheImages: false,
|
||||
defaultPermissions: Permission.REQUEST,
|
||||
defaultQuotas: {
|
||||
movie: {},
|
||||
tv: {},
|
||||
},
|
||||
hideAvailable: false,
|
||||
localLogin: true,
|
||||
newPlexLogin: true,
|
||||
region: '',
|
||||
originalLanguage: '',
|
||||
trustProxy: false,
|
||||
mediaServerType: MediaServerType.NOT_CONFIGURED,
|
||||
partialRequestsEnabled: true,
|
||||
locale: 'en',
|
||||
},
|
||||
plex: {
|
||||
name: '',
|
||||
ip: '127.0.0.1',
|
||||
ip: '',
|
||||
port: 32400,
|
||||
useSsl: false,
|
||||
libraries: [],
|
||||
@@ -229,17 +292,16 @@ class Settings {
|
||||
initialized: false,
|
||||
},
|
||||
notifications: {
|
||||
enabled: true,
|
||||
autoapprovalEnabled: false,
|
||||
agents: {
|
||||
email: {
|
||||
enabled: false,
|
||||
types: 0,
|
||||
options: {
|
||||
emailFrom: '',
|
||||
smtpHost: '127.0.0.1',
|
||||
smtpHost: '',
|
||||
smtpPort: 587,
|
||||
secure: false,
|
||||
ignoreTls: false,
|
||||
requireTls: false,
|
||||
allowSelfSigned: false,
|
||||
senderName: 'Overseerr',
|
||||
},
|
||||
@@ -251,6 +313,13 @@ class Settings {
|
||||
webhookUrl: '',
|
||||
},
|
||||
},
|
||||
lunasea: {
|
||||
enabled: false,
|
||||
types: 0,
|
||||
options: {
|
||||
webhookUrl: '',
|
||||
},
|
||||
},
|
||||
slack: {
|
||||
enabled: false,
|
||||
types: 0,
|
||||
@@ -280,7 +349,6 @@ class Settings {
|
||||
options: {
|
||||
accessToken: '',
|
||||
userToken: '',
|
||||
priority: 0,
|
||||
},
|
||||
},
|
||||
webhook: {
|
||||
@@ -288,11 +356,14 @@ class Settings {
|
||||
types: 0,
|
||||
options: {
|
||||
webhookUrl: '',
|
||||
authHeader: '',
|
||||
jsonPayload:
|
||||
'IntcbiAgICBcIm5vdGlmaWNhdGlvbl90eXBlXCI6IFwie3tub3RpZmljYXRpb25fdHlwZX19XCIsXG4gICAgXCJzdWJqZWN0XCI6IFwie3tzdWJqZWN0fX1cIixcbiAgICBcIm1lc3NhZ2VcIjogXCJ7e21lc3NhZ2V9fVwiLFxuICAgIFwiaW1hZ2VcIjogXCJ7e2ltYWdlfX1cIixcbiAgICBcImVtYWlsXCI6IFwie3tub3RpZnl1c2VyX2VtYWlsfX1cIixcbiAgICBcInVzZXJuYW1lXCI6IFwie3tub3RpZnl1c2VyX3VzZXJuYW1lfX1cIixcbiAgICBcImF2YXRhclwiOiBcInt7bm90aWZ5dXNlcl9hdmF0YXJ9fVwiLFxuICAgIFwie3ttZWRpYX19XCI6IHtcbiAgICAgICAgXCJtZWRpYV90eXBlXCI6IFwie3ttZWRpYV90eXBlfX1cIixcbiAgICAgICAgXCJ0bWRiSWRcIjogXCJ7e21lZGlhX3RtZGJpZH19XCIsXG4gICAgICAgIFwiaW1kYklkXCI6IFwie3ttZWRpYV9pbWRiaWR9fVwiLFxuICAgICAgICBcInR2ZGJJZFwiOiBcInt7bWVkaWFfdHZkYmlkfX1cIixcbiAgICAgICAgXCJzdGF0dXNcIjogXCJ7e21lZGlhX3N0YXR1c319XCIsXG4gICAgICAgIFwic3RhdHVzNGtcIjogXCJ7e21lZGlhX3N0YXR1czRrfX1cIlxuICAgIH0sXG4gICAgXCJ7e2V4dHJhfX1cIjogW11cbn0i',
|
||||
'IntcbiAgICBcIm5vdGlmaWNhdGlvbl90eXBlXCI6IFwie3tub3RpZmljYXRpb25fdHlwZX19XCIsXG4gICAgXCJzdWJqZWN0XCI6IFwie3tzdWJqZWN0fX1cIixcbiAgICBcIm1lc3NhZ2VcIjogXCJ7e21lc3NhZ2V9fVwiLFxuICAgIFwiaW1hZ2VcIjogXCJ7e2ltYWdlfX1cIixcbiAgICBcImVtYWlsXCI6IFwie3tub3RpZnl1c2VyX2VtYWlsfX1cIixcbiAgICBcInVzZXJuYW1lXCI6IFwie3tub3RpZnl1c2VyX3VzZXJuYW1lfX1cIixcbiAgICBcImF2YXRhclwiOiBcInt7bm90aWZ5dXNlcl9hdmF0YXJ9fVwiLFxuICAgIFwie3ttZWRpYX19XCI6IHtcbiAgICAgICAgXCJtZWRpYV90eXBlXCI6IFwie3ttZWRpYV90eXBlfX1cIixcbiAgICAgICAgXCJ0bWRiSWRcIjogXCJ7e21lZGlhX3RtZGJpZH19XCIsXG4gICAgICAgIFwiaW1kYklkXCI6IFwie3ttZWRpYV9pbWRiaWR9fVwiLFxuICAgICAgICBcInR2ZGJJZFwiOiBcInt7bWVkaWFfdHZkYmlkfX1cIixcbiAgICAgICAgXCJzdGF0dXNcIjogXCJ7e21lZGlhX3N0YXR1c319XCIsXG4gICAgICAgIFwic3RhdHVzNGtcIjogXCJ7e21lZGlhX3N0YXR1czRrfX1cIlxuICAgIH0sXG4gICAgXCJ7e2V4dHJhfX1cIjogW10sXG4gICAgXCJ7e3JlcXVlc3R9fVwiOiB7XG4gICAgICAgIFwicmVxdWVzdF9pZFwiOiBcInt7cmVxdWVzdF9pZH19XCIsXG4gICAgICAgIFwicmVxdWVzdGVkQnlfZW1haWxcIjogXCJ7e3JlcXVlc3RlZEJ5X2VtYWlsfX1cIixcbiAgICAgICAgXCJyZXF1ZXN0ZWRCeV91c2VybmFtZVwiOiBcInt7cmVxdWVzdGVkQnlfdXNlcm5hbWV9fVwiLFxuICAgICAgICBcInJlcXVlc3RlZEJ5X2F2YXRhclwiOiBcInt7cmVxdWVzdGVkQnlfYXZhdGFyfX1cIlxuICAgIH1cbn0i',
|
||||
},
|
||||
},
|
||||
webpush: {
|
||||
enabled: false,
|
||||
options: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -357,6 +428,7 @@ class Settings {
|
||||
return {
|
||||
...this.data.public,
|
||||
applicationTitle: this.data.main.applicationTitle,
|
||||
applicationUrl: this.data.main.applicationUrl,
|
||||
hideAvailable: this.data.main.hideAvailable,
|
||||
localLogin: this.data.main.localLogin,
|
||||
movie4kEnabled: this.data.radarr.some(
|
||||
@@ -369,6 +441,12 @@ class Settings {
|
||||
originalLanguage: this.data.main.originalLanguage,
|
||||
mediaServerType: this.main.mediaServerType,
|
||||
jellyfinHost: this.jellyfin.hostname,
|
||||
partialRequestsEnabled: this.data.main.partialRequestsEnabled,
|
||||
cacheImages: this.data.main.cacheImages,
|
||||
vapidPublic: this.vapidPublic,
|
||||
enablePushRegistration: this.data.notifications.agents.webpush.enabled,
|
||||
locale: this.data.main.locale,
|
||||
emailEnabled: this.data.notifications.agents.email.enabled,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -382,13 +460,25 @@ class Settings {
|
||||
|
||||
get clientId(): string {
|
||||
if (!this.data.clientId) {
|
||||
this.data.clientId = uuidv4();
|
||||
this.data.clientId = randomUUID();
|
||||
this.save();
|
||||
}
|
||||
|
||||
return this.data.clientId;
|
||||
}
|
||||
|
||||
get vapidPublic(): string {
|
||||
this.generateVapidKeys();
|
||||
|
||||
return this.data.vapidPublic;
|
||||
}
|
||||
|
||||
get vapidPrivate(): string {
|
||||
this.generateVapidKeys();
|
||||
|
||||
return this.data.vapidPrivate;
|
||||
}
|
||||
|
||||
public regenerateApiKey(): MainSettings {
|
||||
this.main.apiKey = this.generateApiKey();
|
||||
this.save();
|
||||
@@ -396,7 +486,16 @@ class Settings {
|
||||
}
|
||||
|
||||
private generateApiKey(): string {
|
||||
return Buffer.from(`${Date.now()}${uuidv4()})`).toString('base64');
|
||||
return Buffer.from(`${Date.now()}${randomUUID()})`).toString('base64');
|
||||
}
|
||||
|
||||
private generateVapidKeys(force = false): void {
|
||||
if (!this.data.vapidPublic || !this.data.vapidPrivate || force) {
|
||||
const vapidKeys = webpush.generateVAPIDKeys();
|
||||
this.data.vapidPrivate = vapidKeys.privateKey;
|
||||
this.data.vapidPublic = vapidKeys.publicKey;
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user