@muhammedaksam/easiarr 1.3.5 → 1.4.1

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.
Files changed (94) hide show
  1. package/README.md +8 -5
  2. package/dist/index.js +29837 -0
  3. package/package.json +18 -16
  4. package/src/VersionInfo.ts +0 -12
  5. package/src/api/arr-api.ts +0 -508
  6. package/src/api/auto-setup-types.ts +0 -64
  7. package/src/api/bazarr-api.ts +0 -356
  8. package/src/api/cloudflare-api.ts +0 -577
  9. package/src/api/custom-format-api.ts +0 -212
  10. package/src/api/grafana-api.ts +0 -314
  11. package/src/api/heimdall-api.ts +0 -209
  12. package/src/api/homarr-api.ts +0 -296
  13. package/src/api/huntarr-api.ts +0 -622
  14. package/src/api/index.ts +0 -1
  15. package/src/api/jellyfin-api.ts +0 -473
  16. package/src/api/jellyseerr-api.ts +0 -660
  17. package/src/api/maintainerr-api.ts +0 -731
  18. package/src/api/naming-config.ts +0 -93
  19. package/src/api/overseerr-api.ts +0 -513
  20. package/src/api/plex-api.ts +0 -358
  21. package/src/api/portainer-api.ts +0 -467
  22. package/src/api/profilarr-api.ts +0 -380
  23. package/src/api/prowlarr-api.ts +0 -859
  24. package/src/api/qbittorrent-api.ts +0 -339
  25. package/src/api/quality-profile-api.ts +0 -269
  26. package/src/api/tautulli-api.ts +0 -277
  27. package/src/api/uptime-kuma-api.ts +0 -342
  28. package/src/apps/categories.ts +0 -14
  29. package/src/apps/index.ts +0 -2
  30. package/src/apps/registry.ts +0 -1255
  31. package/src/compose/caddy-config.ts +0 -129
  32. package/src/compose/generator.ts +0 -262
  33. package/src/compose/index.ts +0 -3
  34. package/src/compose/templates.ts +0 -78
  35. package/src/compose/traefik-config.ts +0 -185
  36. package/src/config/bookmarks-generator.ts +0 -149
  37. package/src/config/defaults.ts +0 -37
  38. package/src/config/homepage-config.ts +0 -376
  39. package/src/config/index.ts +0 -3
  40. package/src/config/manager.ts +0 -149
  41. package/src/config/recyclarr-config.ts +0 -179
  42. package/src/config/schema.ts +0 -310
  43. package/src/config/slskd-config.ts +0 -85
  44. package/src/config/soularr-config.ts +0 -105
  45. package/src/config/trash-quality-definitions.ts +0 -213
  46. package/src/data/lidarr-custom-formats.ts +0 -127
  47. package/src/data/trash-profiles.ts +0 -326
  48. package/src/docker/client.ts +0 -291
  49. package/src/docker/index.ts +0 -1
  50. package/src/index.ts +0 -77
  51. package/src/structure/manager.ts +0 -128
  52. package/src/ui/App.ts +0 -109
  53. package/src/ui/components/ApplicationSelector.ts +0 -272
  54. package/src/ui/components/FileEditor.ts +0 -91
  55. package/src/ui/components/FooterHint.ts +0 -119
  56. package/src/ui/components/PageLayout.ts +0 -152
  57. package/src/ui/components/UpdateNotification.ts +0 -101
  58. package/src/ui/index.ts +0 -1
  59. package/src/ui/screens/AdvancedSettings.ts +0 -181
  60. package/src/ui/screens/ApiKeyViewer.ts +0 -500
  61. package/src/ui/screens/AppConfigurator.ts +0 -731
  62. package/src/ui/screens/AppManager.ts +0 -276
  63. package/src/ui/screens/CloudflaredSetup.ts +0 -974
  64. package/src/ui/screens/ContainerControl.ts +0 -579
  65. package/src/ui/screens/FullAutoSetup.ts +0 -1719
  66. package/src/ui/screens/HomepageSetup.ts +0 -306
  67. package/src/ui/screens/JellyfinSetup.ts +0 -471
  68. package/src/ui/screens/JellyseerrSetup.ts +0 -612
  69. package/src/ui/screens/LogsViewer.ts +0 -468
  70. package/src/ui/screens/MainMenu.ts +0 -288
  71. package/src/ui/screens/MonitorDashboard.ts +0 -866
  72. package/src/ui/screens/ProwlarrSetup.ts +0 -623
  73. package/src/ui/screens/QBittorrentSetup.ts +0 -268
  74. package/src/ui/screens/QuickSetup.ts +0 -1161
  75. package/src/ui/screens/RecyclarrSetup.ts +0 -418
  76. package/src/ui/screens/SecretsEditor.ts +0 -214
  77. package/src/ui/screens/SettingsScreen.ts +0 -605
  78. package/src/ui/screens/TRaSHProfileSetup.ts +0 -395
  79. package/src/ui/screens/index.ts +0 -4
  80. package/src/util/arch.ts +0 -78
  81. package/src/utils/browser.ts +0 -26
  82. package/src/utils/categories.ts +0 -59
  83. package/src/utils/debug.ts +0 -91
  84. package/src/utils/env.ts +0 -137
  85. package/src/utils/logs.ts +0 -118
  86. package/src/utils/migrations/1765626338_rename_env_variables.ts +0 -101
  87. package/src/utils/migrations/1765707135_rename_easiarr_status.ts +0 -90
  88. package/src/utils/migrations/1765732722_remove_cloudflare_dns_api_token.ts +0 -44
  89. package/src/utils/migrations/1769515650_migrate_to_xdg.ts +0 -107
  90. package/src/utils/migrations.ts +0 -164
  91. package/src/utils/password.ts +0 -42
  92. package/src/utils/unraid.ts +0 -101
  93. package/src/utils/update-checker.ts +0 -210
  94. package/src/utils/url-utils.ts +0 -38
@@ -1,356 +0,0 @@
1
- /**
2
- * Bazarr API Client
3
- * Handles Bazarr-specific API calls for authentication and settings
4
- */
5
-
6
- import { debugLog } from "../utils/debug"
7
- import type { IAutoSetupClient, AutoSetupOptions, AutoSetupResult } from "./auto-setup-types"
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
-
22
- /**
23
- * Bazarr System Settings (partial - auth related fields)
24
- */
25
- export interface BazarrAuthSettings {
26
- auth: {
27
- type: "None" | "Basic" | "Form"
28
- username: string
29
- password: string
30
- apikey: string
31
- }
32
- }
33
-
34
- /**
35
- * Bazarr API Client
36
- * Note: Bazarr uses form data for POST, not JSON!
37
- */
38
- export class BazarrApiClient implements IAutoSetupClient {
39
- private baseUrl: string
40
- private apiKey: string | null = null
41
-
42
- constructor(host: string, port: number) {
43
- this.baseUrl = `http://${host}:${port}`
44
- }
45
-
46
- /**
47
- * Set API key for authentication
48
- */
49
- setApiKey(key: string): void {
50
- this.apiKey = key
51
- debugLog("Bazarr", `API key set`)
52
- }
53
-
54
- /**
55
- * Make a GET request to Bazarr API (JSON response)
56
- */
57
- private async get<T>(endpoint: string): Promise<T> {
58
- let url = `${this.baseUrl}/api${endpoint}`
59
- if (this.apiKey) {
60
- url = `${url}${url.includes("?") ? "&" : "?"}apikey=${this.apiKey}`
61
- }
62
-
63
- debugLog("Bazarr", `GET ${url}`)
64
-
65
- const response = await fetch(url, {
66
- method: "GET",
67
- headers: {
68
- Accept: "application/json",
69
- },
70
- })
71
-
72
- if (!response.ok) {
73
- const errorText = await response.text()
74
- debugLog("Bazarr", `Error ${response.status}: ${errorText}`)
75
- throw new Error(`Bazarr API error: ${response.status} ${response.statusText}`)
76
- }
77
-
78
- const text = await response.text()
79
- debugLog("Bazarr", `Response: ${text.substring(0, 200)}${text.length > 200 ? "..." : ""}`)
80
- if (!text) return {} as T
81
-
82
- return JSON.parse(text) as T
83
- }
84
-
85
- /**
86
- * Make a POST request to Bazarr API using form data (NOT JSON)
87
- * Bazarr uses request.form, not request.json
88
- */
89
- private async postForm(endpoint: string, data: Record<string, string>): Promise<void> {
90
- let url = `${this.baseUrl}/api${endpoint}`
91
- if (this.apiKey) {
92
- url = `${url}${url.includes("?") ? "&" : "?"}apikey=${this.apiKey}`
93
- }
94
-
95
- // Convert object to form data
96
- const formData = new URLSearchParams()
97
- for (const [key, value] of Object.entries(data)) {
98
- formData.append(key, value)
99
- }
100
-
101
- debugLog("Bazarr", `POST ${url}`)
102
- debugLog("Bazarr", `Form data: ${formData.toString()}`)
103
-
104
- const response = await fetch(url, {
105
- method: "POST",
106
- headers: {
107
- "Content-Type": "application/x-www-form-urlencoded",
108
- },
109
- body: formData.toString(),
110
- })
111
-
112
- if (!response.ok) {
113
- const errorText = await response.text()
114
- debugLog("Bazarr", `Error ${response.status}: ${errorText}`)
115
- throw new Error(`Bazarr API error: ${response.status} ${response.statusText}`)
116
- }
117
-
118
- debugLog("Bazarr", `Response status: ${response.status}`)
119
- }
120
-
121
- /**
122
- * Check if Bazarr is healthy and reachable
123
- */
124
- async isHealthy(): Promise<boolean> {
125
- try {
126
- await this.get("/system/status")
127
- return true
128
- } catch {
129
- return false
130
- }
131
- }
132
-
133
- /**
134
- * Get current system settings
135
- */
136
- async getSettings(): Promise<Record<string, unknown>> {
137
- return this.get<Record<string, unknown>>("/system/settings")
138
- }
139
-
140
- /**
141
- * Update authentication settings to enable form-based auth
142
- * Bazarr settings use dot notation in form fields
143
- */
144
- async enableFormAuth(username: string, password: string, override = false): Promise<boolean> {
145
- try {
146
- // First get current settings to check if auth is already configured
147
- const currentSettings = await this.getSettings()
148
- const currentAuth = (currentSettings as { auth?: { type?: string } }).auth
149
-
150
- // Skip if auth is already configured and override is false
151
- if (currentAuth?.type && currentAuth.type !== "None" && currentAuth.type !== null && !override) {
152
- debugLog("Bazarr", `Auth already configured (type: ${currentAuth.type}), skipping`)
153
- return false
154
- }
155
-
156
- debugLog("Bazarr", `Current auth type: ${currentAuth?.type || "None"}`)
157
- debugLog("Bazarr", `Setting form auth for user: ${username}`)
158
-
159
- // Bazarr uses dot notation for nested settings in form data
160
- await this.postForm("/system/settings", {
161
- "settings-auth-type": "form",
162
- "settings-auth-username": username,
163
- "settings-auth-password": password,
164
- })
165
-
166
- debugLog("Bazarr", `Form auth enabled for user: ${username}`)
167
- return true
168
- } catch (e) {
169
- debugLog("Bazarr", `Failed to enable form auth: ${e}`)
170
- throw e
171
- }
172
- }
173
-
174
- /**
175
- * Get API key from settings
176
- */
177
- async getApiKey(): Promise<string | null> {
178
- try {
179
- const settings = await this.getSettings()
180
- const auth = (settings as unknown as BazarrAuthSettings).auth
181
- return auth?.apikey || null
182
- } catch {
183
- return null
184
- }
185
- }
186
-
187
- /**
188
- * Configure Radarr connection in Bazarr
189
- */
190
- async configureRadarr(host: string, port: number, apiKey: string): Promise<boolean> {
191
- try {
192
- debugLog("Bazarr", `Configuring Radarr connection: ${host}:${port}`)
193
-
194
- await this.postForm("/system/settings", {
195
- "settings-radarr-ip": host,
196
- "settings-radarr-port": String(port),
197
- "settings-radarr-apikey": apiKey,
198
- "settings-radarr-base_url": "",
199
- "settings-radarr-ssl": "false",
200
- "settings-general-use_radarr": "true",
201
- })
202
-
203
- debugLog("Bazarr", "Radarr connection configured successfully")
204
- return true
205
- } catch (e) {
206
- debugLog("Bazarr", `Failed to configure Radarr: ${e}`)
207
- throw e
208
- }
209
- }
210
-
211
- /**
212
- * Configure Sonarr connection in Bazarr
213
- */
214
- async configureSonarr(host: string, port: number, apiKey: string): Promise<boolean> {
215
- try {
216
- debugLog("Bazarr", `Configuring Sonarr connection: ${host}:${port}`)
217
-
218
- await this.postForm("/system/settings", {
219
- "settings-sonarr-ip": host,
220
- "settings-sonarr-port": String(port),
221
- "settings-sonarr-apikey": apiKey,
222
- "settings-sonarr-base_url": "",
223
- "settings-sonarr-ssl": "false",
224
- "settings-general-use_sonarr": "true",
225
- })
226
-
227
- debugLog("Bazarr", "Sonarr connection configured successfully")
228
- return true
229
- } catch (e) {
230
- debugLog("Bazarr", `Failed to configure Sonarr: ${e}`)
231
- throw e
232
- }
233
- }
234
-
235
- /**
236
- * Check if already configured (has auth set up)
237
- */
238
- async isInitialized(): Promise<boolean> {
239
- try {
240
- const settings = await this.getSettings()
241
- const auth = (settings as { auth?: { type?: string } }).auth
242
- return !!auth?.type && auth.type !== "None"
243
- } catch {
244
- return false
245
- }
246
- }
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
-
318
- /**
319
- * Run the auto-setup process for Bazarr
320
- */
321
- async setup(options: AutoSetupOptions): Promise<AutoSetupResult> {
322
- const { username, password } = options
323
-
324
- try {
325
- // Check if reachable
326
- const healthy = await this.isHealthy()
327
- if (!healthy) {
328
- return { success: false, message: "Bazarr not reachable" }
329
- }
330
-
331
- // Get API key first (needed for subsequent requests)
332
- const apiKey = await this.getApiKey()
333
- if (apiKey) {
334
- this.setApiKey(apiKey)
335
- }
336
-
337
- // Check if auth already configured
338
- const initialized = await this.isInitialized()
339
- let authConfigured = false
340
-
341
- if (!initialized) {
342
- // Enable form auth
343
- authConfigured = await this.enableFormAuth(username, password)
344
- }
345
-
346
- return {
347
- success: true,
348
- message: initialized ? "Already configured" : authConfigured ? "Auth enabled" : "Ready",
349
- data: { apiKey, authConfigured },
350
- envUpdates: apiKey ? { API_KEY_BAZARR: apiKey } : undefined,
351
- }
352
- } catch (error) {
353
- return { success: false, message: `${error}` }
354
- }
355
- }
356
- }