@muhammedaksam/easiarr 1.1.0 → 1.1.2
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/huntarr-api.ts +622 -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 +54 -4
- package/src/apps/registry.ts +35 -1
- package/src/config/homepage-config.ts +46 -13
- package/src/config/trash-quality-definitions.ts +187 -0
- package/src/ui/screens/FullAutoSetup.ts +245 -20
- package/src/ui/screens/TRaSHProfileSetup.ts +9 -1
- package/src/utils/url-utils.ts +38 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muhammedaksam/easiarr",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "TUI tool for generating docker-compose files for the *arr media ecosystem with 41 apps, TRaSH Guides best practices, VPN routing, and Traefik reverse proxy support",
|
|
5
5
|
"module": "src/index.ts",
|
|
6
6
|
"type": "module",
|
package/src/api/arr-api.ts
CHANGED
|
@@ -46,6 +46,7 @@ export interface RemotePathMapping {
|
|
|
46
46
|
|
|
47
47
|
import type { AppId } from "../config/schema"
|
|
48
48
|
import { getCategoryForApp, getCategoryFieldName } from "../utils/categories"
|
|
49
|
+
import { TRASH_NAMING_CONFIG, type NamingConfig } from "./naming-config"
|
|
49
50
|
|
|
50
51
|
// qBittorrent download client config
|
|
51
52
|
export function createQBittorrentConfig(
|
|
@@ -239,11 +240,63 @@ export class ArrApiClient {
|
|
|
239
240
|
})
|
|
240
241
|
}
|
|
241
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Set application URL for external access (e.g., from Jellyseerr/dashboard links)
|
|
245
|
+
* URL will be used when generating external links in the app
|
|
246
|
+
*/
|
|
247
|
+
async setApplicationUrl(applicationUrl: string): Promise<HostConfig> {
|
|
248
|
+
const currentConfig = await this.getHostConfig()
|
|
249
|
+
|
|
250
|
+
const updatedConfig: HostConfig = {
|
|
251
|
+
...currentConfig,
|
|
252
|
+
applicationUrl,
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
debugLog("ArrAPI", `Setting applicationUrl to: ${applicationUrl}`)
|
|
256
|
+
|
|
257
|
+
return this.request<HostConfig>("/config/host", {
|
|
258
|
+
method: "PUT",
|
|
259
|
+
body: JSON.stringify(updatedConfig),
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
|
|
242
263
|
// Remote Path Mapping methods - for Docker path translation
|
|
264
|
+
|
|
243
265
|
async getRemotePathMappings(): Promise<RemotePathMapping[]> {
|
|
244
266
|
return this.request<RemotePathMapping[]>("/remotepathmapping")
|
|
245
267
|
}
|
|
246
268
|
|
|
269
|
+
// Naming Configuration methods
|
|
270
|
+
async getNamingConfig<T extends NamingConfig>(): Promise<T> {
|
|
271
|
+
return this.request<T>("/config/naming")
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async updateNamingConfig<T extends NamingConfig>(config: T): Promise<T> {
|
|
275
|
+
return this.request<T>("/config/naming", {
|
|
276
|
+
method: "PUT",
|
|
277
|
+
body: JSON.stringify(config),
|
|
278
|
+
})
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
async configureTRaSHNaming(appType: "radarr" | "sonarr"): Promise<void> {
|
|
282
|
+
try {
|
|
283
|
+
// 1. Get current configuration to preserve ID and other fields
|
|
284
|
+
const currentConfig = await this.getNamingConfig<NamingConfig & { id?: number }>()
|
|
285
|
+
|
|
286
|
+
// 2. Merge with TRaSH defaults
|
|
287
|
+
const trashConfig = TRASH_NAMING_CONFIG[appType]
|
|
288
|
+
const newConfig = {
|
|
289
|
+
...currentConfig,
|
|
290
|
+
...trashConfig,
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// 3. Update configuration
|
|
294
|
+
await this.updateNamingConfig(newConfig)
|
|
295
|
+
} catch (e) {
|
|
296
|
+
throw new Error(`Failed to configure naming: ${e}`)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
247
300
|
async addRemotePathMapping(host: string, remotePath: string, localPath: string): Promise<RemotePathMapping> {
|
|
248
301
|
return this.request<RemotePathMapping>("/remotepathmapping", {
|
|
249
302
|
method: "POST",
|
package/src/api/bazarr-api.ts
CHANGED
|
@@ -6,6 +6,19 @@
|
|
|
6
6
|
import { debugLog } from "../utils/debug"
|
|
7
7
|
import type { IAutoSetupClient, AutoSetupOptions, AutoSetupResult } from "./auto-setup-types"
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Bazarr Language Profile Structure
|
|
11
|
+
*/
|
|
12
|
+
export interface BazarrLanguageProfile {
|
|
13
|
+
name: string
|
|
14
|
+
cutoff: string
|
|
15
|
+
languages: {
|
|
16
|
+
code: string
|
|
17
|
+
forced: boolean
|
|
18
|
+
hi: boolean
|
|
19
|
+
}[]
|
|
20
|
+
}
|
|
21
|
+
|
|
9
22
|
/**
|
|
10
23
|
* Bazarr System Settings (partial - auth related fields)
|
|
11
24
|
*/
|
|
@@ -232,6 +245,76 @@ export class BazarrApiClient implements IAutoSetupClient {
|
|
|
232
245
|
}
|
|
233
246
|
}
|
|
234
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Configure General Settings (TRaSH Recommended)
|
|
250
|
+
*/
|
|
251
|
+
async configureGeneralSettings(): Promise<boolean> {
|
|
252
|
+
try {
|
|
253
|
+
debugLog("Bazarr", "Configuring general settings")
|
|
254
|
+
await this.postForm("/system/settings", {
|
|
255
|
+
"settings-subtitles-use_embedded_subtitles": "true",
|
|
256
|
+
"settings-subtitles-autosearch": "true",
|
|
257
|
+
"settings-subtitles-path_mapping": "", // Empty = Alongside Media File
|
|
258
|
+
})
|
|
259
|
+
return true
|
|
260
|
+
} catch (e) {
|
|
261
|
+
debugLog("Bazarr", `Failed to configure general settings: ${e}`)
|
|
262
|
+
return false
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Get all language profiles
|
|
268
|
+
*/
|
|
269
|
+
async getLanguageProfiles(): Promise<BazarrLanguageProfile[]> {
|
|
270
|
+
return this.get<BazarrLanguageProfile[]>("/system/languages/profiles")
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Configure Default Language Profile
|
|
275
|
+
* Creates an english profile if it doesn't exist
|
|
276
|
+
*/
|
|
277
|
+
async configureDefaultLanguageProfile(name = "English", language = "en"): Promise<boolean> {
|
|
278
|
+
try {
|
|
279
|
+
debugLog("Bazarr", `Configuring language profile: ${name}`)
|
|
280
|
+
|
|
281
|
+
// Get existing profiles to check and to preserve them
|
|
282
|
+
const profiles = (await this.getLanguageProfiles()) || []
|
|
283
|
+
const existing = profiles.find((p) => p.name === name)
|
|
284
|
+
|
|
285
|
+
if (existing) {
|
|
286
|
+
debugLog("Bazarr", `Language profile '${name}' already exists`)
|
|
287
|
+
return true
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const newProfile: BazarrLanguageProfile = {
|
|
291
|
+
name: name,
|
|
292
|
+
cutoff: language,
|
|
293
|
+
languages: [
|
|
294
|
+
{
|
|
295
|
+
code: language,
|
|
296
|
+
forced: false,
|
|
297
|
+
hi: false,
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
profiles.push(newProfile)
|
|
303
|
+
|
|
304
|
+
// Update settings with the new list (serialized as JSON)
|
|
305
|
+
// Note: Bazarr expects 'languages_profiles' as a JSON string in the form data
|
|
306
|
+
await this.postForm("/system/settings", {
|
|
307
|
+
languages_profiles: JSON.stringify(profiles),
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
debugLog("Bazarr", `Created language profile: ${name}`)
|
|
311
|
+
return true
|
|
312
|
+
} catch (e) {
|
|
313
|
+
debugLog("Bazarr", `Failed to configure language profile: ${e}`)
|
|
314
|
+
return false
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
235
318
|
/**
|
|
236
319
|
* Run the auto-setup process for Bazarr
|
|
237
320
|
*/
|