@muhammedaksam/easiarr 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/api/arr-api.ts +53 -0
- package/src/api/bazarr-api.ts +83 -0
- package/src/api/jellyseerr-api.ts +82 -8
- package/src/api/naming-config.ts +67 -0
- package/src/api/overseerr-api.ts +24 -0
- package/src/api/qbittorrent-api.ts +58 -0
- package/src/api/quality-profile-api.ts +69 -5
- package/src/apps/registry.ts +71 -1
- package/src/config/homepage-config.ts +28 -8
- package/src/config/schema.ts +2 -0
- package/src/config/slskd-config.ts +85 -0
- package/src/config/soularr-config.ts +105 -0
- package/src/config/trash-quality-definitions.ts +213 -0
- package/src/data/lidarr-custom-formats.ts +127 -0
- package/src/data/trash-profiles.ts +77 -3
- package/src/ui/screens/FullAutoSetup.ts +296 -21
- package/src/ui/screens/TRaSHProfileSetup.ts +39 -20
- package/src/utils/url-utils.ts +38 -0
package/src/apps/registry.ts
CHANGED
|
@@ -248,6 +248,17 @@ export const APPS: Record<AppId, AppDefinition> = {
|
|
|
248
248
|
LOG_HTML: "false",
|
|
249
249
|
CAPTCHA_SOLVER: "none",
|
|
250
250
|
},
|
|
251
|
+
homepage: {
|
|
252
|
+
icon: "flaresolverr.png",
|
|
253
|
+
widget: "customapi",
|
|
254
|
+
widgetFields: {
|
|
255
|
+
url: "http://flaresolverr:8191",
|
|
256
|
+
mappings: JSON.stringify([
|
|
257
|
+
{ field: "msg", label: "Status" },
|
|
258
|
+
{ field: "version", label: "Version" },
|
|
259
|
+
]),
|
|
260
|
+
},
|
|
261
|
+
},
|
|
251
262
|
},
|
|
252
263
|
|
|
253
264
|
// === DOWNLOAD CLIENTS ===
|
|
@@ -302,6 +313,62 @@ export const APPS: Record<AppId, AppDefinition> = {
|
|
|
302
313
|
homepage: { icon: "sabnzbd.png", widget: "sabnzbd" },
|
|
303
314
|
},
|
|
304
315
|
|
|
316
|
+
slskd: {
|
|
317
|
+
id: "slskd",
|
|
318
|
+
name: "Slskd",
|
|
319
|
+
description: "Soulseek client for music downloads",
|
|
320
|
+
category: "downloader",
|
|
321
|
+
defaultPort: 5030,
|
|
322
|
+
image: "slskd/slskd",
|
|
323
|
+
puid: 13016,
|
|
324
|
+
pgid: 13000,
|
|
325
|
+
volumes: (root) => [`${root}/config/slskd:/app`, `${root}/data:/data`],
|
|
326
|
+
secondaryPorts: ["5031:5031", "50300:50300"],
|
|
327
|
+
environment: {
|
|
328
|
+
SLSKD_REMOTE_CONFIGURATION: "true",
|
|
329
|
+
// Web UI authentication (use global credentials)
|
|
330
|
+
SLSKD_USERNAME: "${USERNAME_GLOBAL}",
|
|
331
|
+
SLSKD_PASSWORD: "${PASSWORD_GLOBAL}",
|
|
332
|
+
// Soulseek network credentials (separate account)
|
|
333
|
+
SLSKD_SLSK_USERNAME: "${USERNAME_SOULSEEK}",
|
|
334
|
+
SLSKD_SLSK_PASSWORD: "${PASSWORD_SOULSEEK}",
|
|
335
|
+
},
|
|
336
|
+
secrets: [
|
|
337
|
+
{
|
|
338
|
+
name: "USERNAME_SOULSEEK",
|
|
339
|
+
description: "Soulseek network username (your Soulseek account)",
|
|
340
|
+
required: true,
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
name: "PASSWORD_SOULSEEK",
|
|
344
|
+
description: "Soulseek network password",
|
|
345
|
+
required: true,
|
|
346
|
+
mask: true,
|
|
347
|
+
},
|
|
348
|
+
],
|
|
349
|
+
homepage: { icon: "slskd.png", widget: "slskd" },
|
|
350
|
+
autoSetup: {
|
|
351
|
+
type: "partial",
|
|
352
|
+
description: "Generates slskd.yml with API key for Homepage widget and Soularr integration",
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
|
|
356
|
+
soularr: {
|
|
357
|
+
id: "soularr",
|
|
358
|
+
name: "Soularr",
|
|
359
|
+
description: "Connects Lidarr with Soulseek via Slskd",
|
|
360
|
+
category: "downloader",
|
|
361
|
+
defaultPort: 0, // No web UI
|
|
362
|
+
image: "mrusse08/soularr:latest",
|
|
363
|
+
puid: 13017,
|
|
364
|
+
pgid: 13000,
|
|
365
|
+
volumes: (root) => [`${root}/data/slskd_downloads:/downloads`, `${root}/config/soularr:/data`],
|
|
366
|
+
environment: {
|
|
367
|
+
SCRIPT_INTERVAL: "300",
|
|
368
|
+
},
|
|
369
|
+
dependsOn: ["lidarr", "slskd"],
|
|
370
|
+
},
|
|
371
|
+
|
|
305
372
|
// === MEDIA SERVERS ===
|
|
306
373
|
plex: {
|
|
307
374
|
id: "plex",
|
|
@@ -647,7 +714,10 @@ export const APPS: Record<AppId, AppDefinition> = {
|
|
|
647
714
|
widget: "customapi",
|
|
648
715
|
widgetFields: {
|
|
649
716
|
url: "http://easiarr:8080/config.json",
|
|
650
|
-
mappings: JSON.stringify([
|
|
717
|
+
mappings: JSON.stringify([
|
|
718
|
+
{ field: "version", label: "Version" },
|
|
719
|
+
{ field: "apps.length", label: "Apps" },
|
|
720
|
+
]),
|
|
651
721
|
},
|
|
652
722
|
},
|
|
653
723
|
},
|
|
@@ -24,7 +24,7 @@ export function getHomepageConfigPath(config: EasiarrConfig): string {
|
|
|
24
24
|
* Homepage service entry
|
|
25
25
|
*/
|
|
26
26
|
interface HomepageService {
|
|
27
|
-
href
|
|
27
|
+
href?: string // Optional - cloudflared has no web UI
|
|
28
28
|
icon?: string
|
|
29
29
|
description?: string
|
|
30
30
|
ping?: string
|
|
@@ -55,6 +55,9 @@ export async function generateServicesYaml(config: EasiarrConfig): Promise<strin
|
|
|
55
55
|
// Skip homepage itself
|
|
56
56
|
if (appDef.id === "homepage") continue
|
|
57
57
|
|
|
58
|
+
// Skip apps with no web UI (port 0) and no homepage config
|
|
59
|
+
if (appDef.defaultPort === 0 && !appDef.homepage) continue
|
|
60
|
+
|
|
58
61
|
const port = appConfig.port ?? appDef.defaultPort
|
|
59
62
|
const internalPort = appDef.internalPort ?? port
|
|
60
63
|
// External URL for user browser access (href, ping)
|
|
@@ -63,10 +66,22 @@ export async function generateServicesYaml(config: EasiarrConfig): Promise<strin
|
|
|
63
66
|
const dockerUrl = `http://${appDef.id}:${internalPort}`
|
|
64
67
|
|
|
65
68
|
const service: HomepageService = {
|
|
66
|
-
href: baseUrl,
|
|
67
69
|
description: appDef.description,
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
// Special cases for href/ping
|
|
73
|
+
if (appDef.id === "cloudflared") {
|
|
74
|
+
// Cloudflared has no web UI - skip href/ping
|
|
75
|
+
} else if (appDef.id === "traefik") {
|
|
76
|
+
// Traefik dashboard is on port 8083 (secondary port), not 80 (proxy)
|
|
77
|
+
const dashboardUrl = `http://${localIp}:8083`
|
|
78
|
+
service.href = dashboardUrl
|
|
79
|
+
service.ping = dashboardUrl
|
|
80
|
+
} else {
|
|
81
|
+
service.href = baseUrl
|
|
82
|
+
service.ping = baseUrl
|
|
83
|
+
}
|
|
84
|
+
|
|
70
85
|
// Add icon if defined in homepage meta
|
|
71
86
|
if (appDef.homepage?.icon) {
|
|
72
87
|
service.icon = appDef.homepage.icon
|
|
@@ -75,9 +90,6 @@ export async function generateServicesYaml(config: EasiarrConfig): Promise<strin
|
|
|
75
90
|
service.icon = `${appDef.id}.png`
|
|
76
91
|
}
|
|
77
92
|
|
|
78
|
-
// Add ping for monitoring
|
|
79
|
-
service.ping = baseUrl
|
|
80
|
-
|
|
81
93
|
// Add widget if defined
|
|
82
94
|
if (appDef.homepage?.widget) {
|
|
83
95
|
const apiKey = env[`API_KEY_${appDef.id.toUpperCase()}`]
|
|
@@ -114,7 +126,10 @@ export async function generateServicesYaml(config: EasiarrConfig): Promise<strin
|
|
|
114
126
|
// Skip widget if no API key
|
|
115
127
|
}
|
|
116
128
|
// Most widgets need API key - only add if available
|
|
117
|
-
else if (
|
|
129
|
+
else if (
|
|
130
|
+
apiKey ||
|
|
131
|
+
["qbittorrent", "gluetun", "traefik", "huntarr", "easiarr", "flaresolverr"].includes(appDef.id)
|
|
132
|
+
) {
|
|
118
133
|
service.widget = {
|
|
119
134
|
type: widgetType,
|
|
120
135
|
url: dockerUrl,
|
|
@@ -236,7 +251,10 @@ export async function generateServicesYaml(config: EasiarrConfig): Promise<strin
|
|
|
236
251
|
|
|
237
252
|
for (const { name, service } of services) {
|
|
238
253
|
yaml += ` - ${name}:\n`
|
|
239
|
-
|
|
254
|
+
|
|
255
|
+
if (service.href) {
|
|
256
|
+
yaml += ` href: ${service.href}\n`
|
|
257
|
+
}
|
|
240
258
|
|
|
241
259
|
if (service.icon) {
|
|
242
260
|
yaml += ` icon: ${service.icon}\n`
|
|
@@ -253,7 +271,9 @@ export async function generateServicesYaml(config: EasiarrConfig): Promise<strin
|
|
|
253
271
|
if (service.widget) {
|
|
254
272
|
yaml += ` widget:\n`
|
|
255
273
|
yaml += ` type: ${service.widget.type}\n`
|
|
256
|
-
|
|
274
|
+
if (service.widget.url) {
|
|
275
|
+
yaml += ` url: ${service.widget.url}\n`
|
|
276
|
+
}
|
|
257
277
|
|
|
258
278
|
if (service.widget.key) {
|
|
259
279
|
yaml += ` key: ${service.widget.key}\n`
|
package/src/config/schema.ts
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slskd Config Generator
|
|
3
|
+
* Generates slskd.yml configuration file with API keys and settings
|
|
4
|
+
* Source: https://github.com/slskd/slskd/blob/master/docs/config.md
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { EasiarrConfig } from "./schema"
|
|
8
|
+
import { readEnvSync } from "../utils/env"
|
|
9
|
+
import { randomBytes } from "crypto"
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generate a random API key (base64, 48 bytes = ~64 chars)
|
|
13
|
+
* Equivalent to: openssl rand -base64 48
|
|
14
|
+
*/
|
|
15
|
+
export function generateSlskdApiKey(): string {
|
|
16
|
+
return randomBytes(48).toString("base64")
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Generate slskd.yml content
|
|
21
|
+
* This file should be placed in the slskd config directory (/app/slskd.yml)
|
|
22
|
+
*/
|
|
23
|
+
export function generateSlskdConfig(_config: EasiarrConfig): { yaml: string; apiKey: string } {
|
|
24
|
+
const env = readEnvSync()
|
|
25
|
+
|
|
26
|
+
// Generate or use existing API key
|
|
27
|
+
const apiKey = env.API_KEY_SLSKD || generateSlskdApiKey()
|
|
28
|
+
|
|
29
|
+
const yaml = `# Slskd Configuration
|
|
30
|
+
# Generated by Easiarr
|
|
31
|
+
# Docs: https://github.com/slskd/slskd/blob/master/docs/config.md
|
|
32
|
+
|
|
33
|
+
# Directories for downloads
|
|
34
|
+
directories:
|
|
35
|
+
incomplete: /data/slskd_downloads/incomplete
|
|
36
|
+
downloads: /data/slskd_downloads/complete
|
|
37
|
+
|
|
38
|
+
# Shares - music directory for uploading
|
|
39
|
+
shares:
|
|
40
|
+
directories:
|
|
41
|
+
- /data/media/music
|
|
42
|
+
|
|
43
|
+
# Web UI Configuration
|
|
44
|
+
web:
|
|
45
|
+
port: 5030
|
|
46
|
+
authentication:
|
|
47
|
+
disabled: false
|
|
48
|
+
api_keys:
|
|
49
|
+
# API key for Homepage widget and Soularr
|
|
50
|
+
easiarr:
|
|
51
|
+
key: ${apiKey}
|
|
52
|
+
role: readwrite
|
|
53
|
+
cidr: 0.0.0.0/0,::/0
|
|
54
|
+
|
|
55
|
+
# Soulseek Configuration
|
|
56
|
+
# Credentials are set via environment variables:
|
|
57
|
+
# - SLSKD_SLSK_USERNAME
|
|
58
|
+
# - SLSKD_SLSK_PASSWORD
|
|
59
|
+
soulseek:
|
|
60
|
+
listen_port: 50300
|
|
61
|
+
description: "slskd user via Easiarr"
|
|
62
|
+
|
|
63
|
+
# Global limits
|
|
64
|
+
global:
|
|
65
|
+
upload:
|
|
66
|
+
slots: 10
|
|
67
|
+
speed_limit: 1000
|
|
68
|
+
download:
|
|
69
|
+
slots: 100
|
|
70
|
+
speed_limit: 10000
|
|
71
|
+
|
|
72
|
+
# Logging
|
|
73
|
+
logger:
|
|
74
|
+
disk: false
|
|
75
|
+
`
|
|
76
|
+
|
|
77
|
+
return { yaml, apiKey }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get the path where slskd.yml should be saved
|
|
82
|
+
*/
|
|
83
|
+
export function getSlskdConfigPath(rootDir: string): string {
|
|
84
|
+
return `${rootDir}/config/slskd/slskd.yml`
|
|
85
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soularr Config Generator
|
|
3
|
+
* Generates config.ini for Soularr based on easiarr configuration
|
|
4
|
+
* Source: https://github.com/mrusse/soularr
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { EasiarrConfig } from "./schema"
|
|
8
|
+
import { readEnvSync } from "../utils/env"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate Soularr config.ini content
|
|
12
|
+
* This file should be placed in the Soularr config directory
|
|
13
|
+
*/
|
|
14
|
+
export function generateSoularrConfig(config: EasiarrConfig): string {
|
|
15
|
+
const env = readEnvSync()
|
|
16
|
+
|
|
17
|
+
const lidarrApiKey = env.API_KEY_LIDARR || "yourlidarrapikeygoeshere"
|
|
18
|
+
const slskdApiKey = env.API_KEY_SLSKD || "yourslskdapikeygoeshere"
|
|
19
|
+
|
|
20
|
+
// Find Lidarr and Slskd ports from config
|
|
21
|
+
const lidarrPort = config.apps.find((a) => a.id === "lidarr")?.port || 8686
|
|
22
|
+
const slskdPort = config.apps.find((a) => a.id === "slskd")?.port || 5030
|
|
23
|
+
|
|
24
|
+
return `[Lidarr]
|
|
25
|
+
# Get from Lidarr: Settings > General > Security
|
|
26
|
+
api_key = ${lidarrApiKey}
|
|
27
|
+
# URL Lidarr uses (internal Docker network)
|
|
28
|
+
host_url = http://lidarr:${lidarrPort}
|
|
29
|
+
# Path to slskd downloads inside the Lidarr container
|
|
30
|
+
download_dir = /data/slskd_downloads
|
|
31
|
+
# If true, Lidarr won't auto-import from Slskd (recommended: True to avoid failed_imports issues)
|
|
32
|
+
disable_sync = True
|
|
33
|
+
|
|
34
|
+
[Slskd]
|
|
35
|
+
# Create manually in Slskd web UI
|
|
36
|
+
api_key = ${slskdApiKey}
|
|
37
|
+
# URL Slskd uses (internal Docker network)
|
|
38
|
+
host_url = http://slskd:${slskdPort}
|
|
39
|
+
url_base = /
|
|
40
|
+
# Download path inside Slskd container
|
|
41
|
+
download_dir = /downloads
|
|
42
|
+
# Delete search after Soularr runs
|
|
43
|
+
delete_searches = False
|
|
44
|
+
# Max seconds to wait for downloads (prevents infinite hangs)
|
|
45
|
+
stalled_timeout = 3600
|
|
46
|
+
|
|
47
|
+
[Release Settings]
|
|
48
|
+
# Pick release with most common track count
|
|
49
|
+
use_most_common_tracknum = True
|
|
50
|
+
allow_multi_disc = True
|
|
51
|
+
# Accepted release countries
|
|
52
|
+
accepted_countries = Europe,Japan,United Kingdom,United States,[Worldwide],Australia,Canada
|
|
53
|
+
# Don't check the region of the release
|
|
54
|
+
skip_region_check = False
|
|
55
|
+
# Accepted formats
|
|
56
|
+
accepted_formats = CD,Digital Media,Vinyl
|
|
57
|
+
|
|
58
|
+
[Search Settings]
|
|
59
|
+
search_timeout = 5000
|
|
60
|
+
maximum_peer_queue = 50
|
|
61
|
+
# Minimum upload speed (bits/sec)
|
|
62
|
+
minimum_peer_upload_speed = 0
|
|
63
|
+
# Minimum match ratio between Lidarr track and Soulseek filename
|
|
64
|
+
minimum_filename_match_ratio = 0.8
|
|
65
|
+
# Preferred file types and qualities (most to least preferred)
|
|
66
|
+
allowed_filetypes = flac 24/192,flac 16/44.1,flac,mp3 320,mp3
|
|
67
|
+
ignored_users =
|
|
68
|
+
# Set to False to only search for album titles
|
|
69
|
+
search_for_tracks = True
|
|
70
|
+
# Prepend artist name when searching
|
|
71
|
+
album_prepend_artist = False
|
|
72
|
+
track_prepend_artist = True
|
|
73
|
+
# Search modes: all, incrementing_page, first_page
|
|
74
|
+
search_type = incrementing_page
|
|
75
|
+
# Albums to process per run
|
|
76
|
+
number_of_albums_to_grab = 10
|
|
77
|
+
# Unmonitor album on failure
|
|
78
|
+
remove_wanted_on_failure = False
|
|
79
|
+
# Blacklist words in album or track titles
|
|
80
|
+
title_blacklist =
|
|
81
|
+
# Lidarr search source: "missing" or "cutoff_unmet"
|
|
82
|
+
search_source = missing
|
|
83
|
+
# Enable search denylist to skip albums that repeatedly fail
|
|
84
|
+
enable_search_denylist = False
|
|
85
|
+
# Number of consecutive search failures before denylisting
|
|
86
|
+
max_search_failures = 3
|
|
87
|
+
|
|
88
|
+
[Download Settings]
|
|
89
|
+
download_filtering = True
|
|
90
|
+
use_extension_whitelist = False
|
|
91
|
+
extensions_whitelist = lrc,nfo,txt
|
|
92
|
+
|
|
93
|
+
[Logging]
|
|
94
|
+
level = INFO
|
|
95
|
+
format = [%(levelname)s|%(module)s|L%(lineno)d] %(asctime)s: %(message)s
|
|
96
|
+
datefmt = %Y-%m-%dT%H:%M:%S%z
|
|
97
|
+
`
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get the path where Soularr config should be saved
|
|
102
|
+
*/
|
|
103
|
+
export function getSoularrConfigPath(rootDir: string): string {
|
|
104
|
+
return `${rootDir}/config/soularr/config.ini`
|
|
105
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TRaSH Guides Quality Definitions (File Size Limits)
|
|
3
|
+
* Min/Preferred/Max in MB/min
|
|
4
|
+
* Source: ../Guides/docs/json/radarr/quality-size/movie.json
|
|
5
|
+
* Source: ../Guides/docs/json/sonarr/quality-size/series.json
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface TrashQualityDefinition {
|
|
9
|
+
quality: string
|
|
10
|
+
min: number
|
|
11
|
+
preferred: number
|
|
12
|
+
max: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const TRASH_RADARR_QUALITY_DEFINITIONS: TrashQualityDefinition[] = [
|
|
16
|
+
{
|
|
17
|
+
quality: "HDTV-720p",
|
|
18
|
+
min: 17.1,
|
|
19
|
+
preferred: 1999,
|
|
20
|
+
max: 2000,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
quality: "WEBDL-720p",
|
|
24
|
+
min: 12.5,
|
|
25
|
+
preferred: 1999,
|
|
26
|
+
max: 2000,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
quality: "WEBRip-720p",
|
|
30
|
+
min: 12.5,
|
|
31
|
+
preferred: 1999,
|
|
32
|
+
max: 2000,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
quality: "Bluray-720p",
|
|
36
|
+
min: 25.7,
|
|
37
|
+
preferred: 1999,
|
|
38
|
+
max: 2000,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
quality: "HDTV-1080p",
|
|
42
|
+
min: 33.8,
|
|
43
|
+
preferred: 1999,
|
|
44
|
+
max: 2000,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
quality: "WEBDL-1080p",
|
|
48
|
+
min: 12.5,
|
|
49
|
+
preferred: 1999,
|
|
50
|
+
max: 2000,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
quality: "WEBRip-1080p",
|
|
54
|
+
min: 12.5,
|
|
55
|
+
preferred: 1999,
|
|
56
|
+
max: 2000,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
quality: "Bluray-1080p",
|
|
60
|
+
min: 50.8,
|
|
61
|
+
preferred: 1999,
|
|
62
|
+
max: 2000,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
quality: "Remux-1080p",
|
|
66
|
+
min: 102,
|
|
67
|
+
preferred: 1999,
|
|
68
|
+
max: 2000,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
quality: "HDTV-2160p",
|
|
72
|
+
min: 85,
|
|
73
|
+
preferred: 1999,
|
|
74
|
+
max: 2000,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
quality: "WEBDL-2160p",
|
|
78
|
+
min: 34.5,
|
|
79
|
+
preferred: 1999,
|
|
80
|
+
max: 2000,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
quality: "WEBRip-2160p",
|
|
84
|
+
min: 34.5,
|
|
85
|
+
preferred: 1999,
|
|
86
|
+
max: 2000,
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
quality: "Bluray-2160p",
|
|
90
|
+
min: 102,
|
|
91
|
+
preferred: 1999,
|
|
92
|
+
max: 2000,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
quality: "Remux-2160p",
|
|
96
|
+
min: 187.4,
|
|
97
|
+
preferred: 1999,
|
|
98
|
+
max: 2000,
|
|
99
|
+
},
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
export const TRASH_SONARR_QUALITY_DEFINITIONS: TrashQualityDefinition[] = [
|
|
103
|
+
{
|
|
104
|
+
quality: "HDTV-720p",
|
|
105
|
+
min: 10,
|
|
106
|
+
preferred: 995,
|
|
107
|
+
max: 1000,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
quality: "HDTV-1080p",
|
|
111
|
+
min: 15,
|
|
112
|
+
preferred: 995,
|
|
113
|
+
max: 1000,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
quality: "WEBRip-720p",
|
|
117
|
+
min: 10,
|
|
118
|
+
preferred: 995,
|
|
119
|
+
max: 1000,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
quality: "WEBDL-720p",
|
|
123
|
+
min: 10,
|
|
124
|
+
preferred: 995,
|
|
125
|
+
max: 1000,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
quality: "Bluray-720p",
|
|
129
|
+
min: 17.1,
|
|
130
|
+
preferred: 995,
|
|
131
|
+
max: 1000,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
quality: "WEBRip-1080p",
|
|
135
|
+
min: 15,
|
|
136
|
+
preferred: 995,
|
|
137
|
+
max: 1000,
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
quality: "WEBDL-1080p",
|
|
141
|
+
min: 15,
|
|
142
|
+
preferred: 995,
|
|
143
|
+
max: 1000,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
quality: "Bluray-1080p",
|
|
147
|
+
min: 50.4,
|
|
148
|
+
preferred: 995,
|
|
149
|
+
max: 1000,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
quality: "Bluray-1080p Remux",
|
|
153
|
+
min: 69.1,
|
|
154
|
+
preferred: 995,
|
|
155
|
+
max: 1000,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
quality: "HDTV-2160p",
|
|
159
|
+
min: 25,
|
|
160
|
+
preferred: 995,
|
|
161
|
+
max: 1000,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
quality: "WEBRip-2160p",
|
|
165
|
+
min: 25,
|
|
166
|
+
preferred: 995,
|
|
167
|
+
max: 1000,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
quality: "WEBDL-2160p",
|
|
171
|
+
min: 25,
|
|
172
|
+
preferred: 995,
|
|
173
|
+
max: 1000,
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
quality: "Bluray-2160p",
|
|
177
|
+
min: 94.6,
|
|
178
|
+
preferred: 995,
|
|
179
|
+
max: 1000,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
quality: "Bluray-2160p Remux",
|
|
183
|
+
min: 187.4,
|
|
184
|
+
preferred: 995,
|
|
185
|
+
max: 1000,
|
|
186
|
+
},
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Lidarr Quality Definitions (Davo's Community Guide)
|
|
191
|
+
* Source: https://wiki.servarr.com/lidarr/community-guide
|
|
192
|
+
* Filters out single track rips for entire albums (FLAC/CUE files)
|
|
193
|
+
*/
|
|
194
|
+
export const TRASH_LIDARR_QUALITY_DEFINITIONS: TrashQualityDefinition[] = [
|
|
195
|
+
{
|
|
196
|
+
quality: "FLAC",
|
|
197
|
+
min: 0,
|
|
198
|
+
preferred: 895,
|
|
199
|
+
max: 1400,
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
quality: "FLAC 24bit",
|
|
203
|
+
min: 0,
|
|
204
|
+
preferred: 895,
|
|
205
|
+
max: 1495,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
quality: "MP3-320",
|
|
209
|
+
min: 0,
|
|
210
|
+
preferred: 0,
|
|
211
|
+
max: 0, // No size limit for MP3
|
|
212
|
+
},
|
|
213
|
+
]
|