@muhammedaksam/easiarr 0.3.2 → 0.3.4
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muhammedaksam/easiarr",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
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
|
@@ -17,6 +17,7 @@ export interface RootFolder {
|
|
|
17
17
|
// Options for adding root folder (some apps like Lidarr need extra fields)
|
|
18
18
|
export interface AddRootFolderOptions {
|
|
19
19
|
path: string
|
|
20
|
+
name?: string // Required for Lidarr
|
|
20
21
|
defaultMetadataProfileId?: number
|
|
21
22
|
defaultQualityProfileId?: number
|
|
22
23
|
}
|
package/src/api/prowlarr-api.ts
CHANGED
|
@@ -188,13 +188,13 @@ export class ProwlarrClient {
|
|
|
188
188
|
await this.request(`/indexerproxy/${id}`, { method: "DELETE" })
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
// Sync Profile management
|
|
191
|
+
// Sync Profile management (aka App Sync Profile)
|
|
192
192
|
async getSyncProfiles(): Promise<SyncProfile[]> {
|
|
193
|
-
return this.request<SyncProfile[]>("/
|
|
193
|
+
return this.request<SyncProfile[]>("/appsyncprofile")
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
async createSyncProfile(profile: Omit<SyncProfile, "id">): Promise<SyncProfile> {
|
|
197
|
-
return this.request<SyncProfile>("/
|
|
197
|
+
return this.request<SyncProfile>("/appsyncprofile", {
|
|
198
198
|
method: "POST",
|
|
199
199
|
body: JSON.stringify(profile),
|
|
200
200
|
})
|
|
@@ -260,11 +260,21 @@ export class ProwlarrClient {
|
|
|
260
260
|
appApiKey: string,
|
|
261
261
|
syncLevel: "disabled" | "addOnly" | "fullSync" = "fullSync"
|
|
262
262
|
): Promise<Application> {
|
|
263
|
+
// Default sync categories for each app type
|
|
264
|
+
// Radarr: Movies (2000, 2010, etc), Sonarr: TV (5000, 5010, etc)
|
|
265
|
+
// Lidarr: Audio (3000), Readarr: Books (7000, 8010)
|
|
266
|
+
const syncCategoriesMap: Record<ArrAppType, number[]> = {
|
|
267
|
+
Radarr: [2000, 2010, 2020, 2030, 2040, 2045, 2050, 2060, 2070, 2080],
|
|
268
|
+
Sonarr: [5000, 5010, 5020, 5030, 5040, 5045, 5050, 5060, 5070, 5080],
|
|
269
|
+
Lidarr: [3000, 3010, 3020, 3030, 3040],
|
|
270
|
+
Readarr: [7000, 7010, 7020, 7030, 8000, 8010, 8020],
|
|
271
|
+
}
|
|
272
|
+
|
|
263
273
|
const fields: { name: string; value: unknown }[] = [
|
|
264
274
|
{ name: "prowlarrUrl", value: prowlarrUrl },
|
|
265
275
|
{ name: "baseUrl", value: appUrl },
|
|
266
276
|
{ name: "apiKey", value: appApiKey },
|
|
267
|
-
{ name: "syncCategories", value: [] },
|
|
277
|
+
{ name: "syncCategories", value: syncCategoriesMap[appType] || [] },
|
|
268
278
|
]
|
|
269
279
|
|
|
270
280
|
return this.request<Application>("/applications", {
|
|
@@ -286,7 +296,10 @@ export class ProwlarrClient {
|
|
|
286
296
|
|
|
287
297
|
// Sync all apps - triggers Prowlarr to push indexers to connected apps
|
|
288
298
|
async syncApplications(): Promise<void> {
|
|
289
|
-
await this.request("/applications/action/sync", {
|
|
299
|
+
await this.request("/applications/action/sync", {
|
|
300
|
+
method: "POST",
|
|
301
|
+
body: JSON.stringify({}), // API requires non-empty body
|
|
302
|
+
})
|
|
290
303
|
}
|
|
291
304
|
|
|
292
305
|
// Add *arr app with auto-detection
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* API docs: https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-(qBittorrent-4.1)
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { debugLog } from "../utils/debug"
|
|
8
|
+
|
|
7
9
|
export interface QBittorrentPreferences {
|
|
8
10
|
save_path?: string
|
|
9
11
|
temp_path_enabled?: boolean
|
|
@@ -172,7 +174,10 @@ export class QBittorrentClient {
|
|
|
172
174
|
* @param categories - Array of {name, savePath} for each enabled *arr app
|
|
173
175
|
*/
|
|
174
176
|
async configureTRaSHCompliant(categories: QBittorrentCategory[] = []): Promise<void> {
|
|
177
|
+
debugLog("qBittorrent", "Configuring TRaSH-compliant settings")
|
|
178
|
+
|
|
175
179
|
// 1. Set global preferences
|
|
180
|
+
debugLog("qBittorrent", "Setting save_path to /data/torrents")
|
|
176
181
|
await this.setPreferences({
|
|
177
182
|
save_path: "/data/torrents",
|
|
178
183
|
temp_path_enabled: false,
|
|
@@ -183,6 +188,7 @@ export class QBittorrentClient {
|
|
|
183
188
|
|
|
184
189
|
// 2. Create categories for each enabled media type
|
|
185
190
|
for (const cat of categories) {
|
|
191
|
+
debugLog("qBittorrent", `Creating category: ${cat.name} -> ${cat.savePath}`)
|
|
186
192
|
try {
|
|
187
193
|
await this.createCategory(cat.name, cat.savePath)
|
|
188
194
|
} catch {
|
|
@@ -194,5 +200,6 @@ export class QBittorrentClient {
|
|
|
194
200
|
}
|
|
195
201
|
}
|
|
196
202
|
}
|
|
203
|
+
debugLog("qBittorrent", "TRaSH configuration complete")
|
|
197
204
|
}
|
|
198
205
|
}
|
|
@@ -252,7 +252,8 @@ export class AppConfigurator extends BoxRenderable {
|
|
|
252
252
|
|
|
253
253
|
const appDef = getApp(appId as AppId)
|
|
254
254
|
const port = appConfig.port || appDef?.defaultPort || 9696
|
|
255
|
-
|
|
255
|
+
// Prowlarr uses v1 API, not v3
|
|
256
|
+
const client = new ArrApiClient("localhost", port, apiKey, "v1")
|
|
256
257
|
|
|
257
258
|
try {
|
|
258
259
|
await client.updateHostConfig(this.globalUsername, this.globalPassword, this.overrideExisting)
|
|
@@ -313,12 +314,13 @@ export class AppConfigurator extends BoxRenderable {
|
|
|
313
314
|
throw new Error("Already configured")
|
|
314
315
|
}
|
|
315
316
|
|
|
316
|
-
// Add root folder - Lidarr requires profile IDs
|
|
317
|
+
// Add root folder - Lidarr requires profile IDs and name
|
|
317
318
|
if (appId === "lidarr") {
|
|
318
319
|
const metadataProfiles = await client.getMetadataProfiles()
|
|
319
320
|
const qualityProfiles = await client.getQualityProfiles()
|
|
320
321
|
await client.addRootFolder({
|
|
321
322
|
path: appDef.rootFolder.path,
|
|
323
|
+
name: "Music", // Required by Lidarr
|
|
322
324
|
defaultMetadataProfileId: metadataProfiles[0]?.id || 1,
|
|
323
325
|
defaultQualityProfileId: qualityProfiles[0]?.id || 1,
|
|
324
326
|
})
|
|
@@ -560,6 +562,12 @@ export class AppConfigurator extends BoxRenderable {
|
|
|
560
562
|
const client = new ArrApiClient("localhost", port, apiKey, appDef.rootFolder.apiVersion)
|
|
561
563
|
|
|
562
564
|
try {
|
|
565
|
+
// Check if download client already exists
|
|
566
|
+
const existingClients = await client.getDownloadClients()
|
|
567
|
+
const clientName = type === "qbittorrent" ? "qBittorrent" : "SABnzbd"
|
|
568
|
+
const alreadyExists = existingClients.some((c) => c.name === clientName)
|
|
569
|
+
if (alreadyExists) continue
|
|
570
|
+
|
|
563
571
|
if (type === "qbittorrent") {
|
|
564
572
|
const config = createQBittorrentConfig(this.qbHost, this.qbPort, this.qbUser, this.qbPass, appConfig.id)
|
|
565
573
|
await client.addDownloadClient(config)
|