tsarr 2.3.2 → 2.4.0
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/dist/cli/commands/lidarr.d.ts.map +1 -1
- package/dist/cli/commands/prowlarr.d.ts.map +1 -1
- package/dist/cli/commands/radarr.d.ts.map +1 -1
- package/dist/cli/commands/readarr.d.ts.map +1 -1
- package/dist/cli/commands/service.d.ts +1 -1
- package/dist/cli/commands/service.d.ts.map +1 -1
- package/dist/cli/commands/sonarr.d.ts.map +1 -1
- package/dist/cli/index.js +1100 -70
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/clients/lidarr.d.ts +10 -0
- package/dist/clients/lidarr.d.ts.map +1 -1
- package/dist/clients/lidarr.js +12 -0
- package/dist/clients/prowlarr.d.ts +10 -0
- package/dist/clients/prowlarr.d.ts.map +1 -1
- package/dist/clients/prowlarr.js +12 -0
- package/dist/clients/radarr.d.ts +24 -1
- package/dist/clients/radarr.d.ts.map +1 -1
- package/dist/clients/radarr.js +39 -2
- package/dist/clients/readarr.d.ts +10 -0
- package/dist/clients/readarr.d.ts.map +1 -1
- package/dist/clients/readarr.js +12 -0
- package/dist/clients/sonarr.d.ts +6 -3
- package/dist/clients/sonarr.d.ts.map +1 -1
- package/dist/clients/sonarr.js +15 -5
- package/dist/index.js +13 -13
- package/dist/tsarr-2.4.0.tgz +0 -0
- package/package.json +1 -1
- package/dist/tsarr-2.3.2.tgz +0 -0
package/dist/cli/index.js
CHANGED
|
@@ -1471,6 +1471,14 @@ var getApiV3SystemBackup = (options) => (options?.client ?? client).get({
|
|
|
1471
1471
|
}],
|
|
1472
1472
|
url: "/api/v3/customformat/schema",
|
|
1473
1473
|
...options
|
|
1474
|
+
}), getApiV3WantedCutoff = (options) => (options?.client ?? client).get({
|
|
1475
|
+
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
1476
|
+
in: "query",
|
|
1477
|
+
name: "apikey",
|
|
1478
|
+
type: "apiKey"
|
|
1479
|
+
}],
|
|
1480
|
+
url: "/api/v3/wanted/cutoff",
|
|
1481
|
+
...options
|
|
1474
1482
|
}), getApiV3Diskspace = (options) => (options?.client ?? client).get({
|
|
1475
1483
|
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
1476
1484
|
in: "query",
|
|
@@ -1867,6 +1875,14 @@ var getApiV3SystemBackup = (options) => (options?.client ?? client).get({
|
|
|
1867
1875
|
"Content-Type": "application/json",
|
|
1868
1876
|
...options.headers
|
|
1869
1877
|
}
|
|
1878
|
+
}), getApiV3WantedMissing = (options) => (options?.client ?? client).get({
|
|
1879
|
+
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
1880
|
+
in: "query",
|
|
1881
|
+
name: "apikey",
|
|
1882
|
+
type: "apiKey"
|
|
1883
|
+
}],
|
|
1884
|
+
url: "/api/v3/wanted/missing",
|
|
1885
|
+
...options
|
|
1870
1886
|
}), getApiV3Movie = (options) => (options?.client ?? client).get({
|
|
1871
1887
|
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
1872
1888
|
in: "query",
|
|
@@ -2370,8 +2386,11 @@ class RadarrClient {
|
|
|
2370
2386
|
async updateMovie(id, movie) {
|
|
2371
2387
|
return putApiV3MovieById({ path: { id: String(id) }, body: movie });
|
|
2372
2388
|
}
|
|
2373
|
-
async deleteMovie(id) {
|
|
2374
|
-
return deleteApiV3MovieById({
|
|
2389
|
+
async deleteMovie(id, options) {
|
|
2390
|
+
return deleteApiV3MovieById({
|
|
2391
|
+
path: { id },
|
|
2392
|
+
...options ? { query: options } : {}
|
|
2393
|
+
});
|
|
2375
2394
|
}
|
|
2376
2395
|
async searchMovies(term) {
|
|
2377
2396
|
return getApiV3MovieLookup({ query: { term } });
|
|
@@ -2700,6 +2719,22 @@ class RadarrClient {
|
|
|
2700
2719
|
async removeBlocklistItemsBulk(ids) {
|
|
2701
2720
|
return deleteApiV3BlocklistBulk({ body: { ids } });
|
|
2702
2721
|
}
|
|
2722
|
+
async getWantedMissing(page, pageSize) {
|
|
2723
|
+
const query = {};
|
|
2724
|
+
if (page !== undefined)
|
|
2725
|
+
query.page = page;
|
|
2726
|
+
if (pageSize !== undefined)
|
|
2727
|
+
query.pageSize = pageSize;
|
|
2728
|
+
return getApiV3WantedMissing(Object.keys(query).length > 0 ? { query } : {});
|
|
2729
|
+
}
|
|
2730
|
+
async getWantedCutoff(page, pageSize) {
|
|
2731
|
+
const query = {};
|
|
2732
|
+
if (page !== undefined)
|
|
2733
|
+
query.page = page;
|
|
2734
|
+
if (pageSize !== undefined)
|
|
2735
|
+
query.pageSize = pageSize;
|
|
2736
|
+
return getApiV3WantedCutoff(Object.keys(query).length > 0 ? { query } : {});
|
|
2737
|
+
}
|
|
2703
2738
|
async getHostConfig() {
|
|
2704
2739
|
return getApiV3ConfigHost();
|
|
2705
2740
|
}
|
|
@@ -4810,6 +4845,10 @@ function formatOutput(data, options) {
|
|
|
4810
4845
|
if (data == null) {
|
|
4811
4846
|
return;
|
|
4812
4847
|
}
|
|
4848
|
+
if (isMessageOnly(data) && options.format !== "json" && options.format !== "quiet") {
|
|
4849
|
+
console.log(data.message);
|
|
4850
|
+
return;
|
|
4851
|
+
}
|
|
4813
4852
|
switch (options.format) {
|
|
4814
4853
|
case "json": {
|
|
4815
4854
|
const output = options.select ? selectFields(data, options.select) : data;
|
|
@@ -4901,6 +4940,13 @@ function formatHeader(col) {
|
|
|
4901
4940
|
function formatCell(column, value) {
|
|
4902
4941
|
if (value == null)
|
|
4903
4942
|
return "—";
|
|
4943
|
+
const flattened = flattenStructuredValue(value);
|
|
4944
|
+
if (flattened !== undefined) {
|
|
4945
|
+
if (column === "status") {
|
|
4946
|
+
return formatStatus(flattened);
|
|
4947
|
+
}
|
|
4948
|
+
return flattened;
|
|
4949
|
+
}
|
|
4904
4950
|
if (typeof value === "boolean") {
|
|
4905
4951
|
return value ? `${GREEN}✓${RESET}` : `${RED}✗${RESET}`;
|
|
4906
4952
|
}
|
|
@@ -4913,8 +4959,6 @@ function formatCell(column, value) {
|
|
|
4913
4959
|
if (column.toLowerCase().includes("date") || column === "createdAt" || column === "updatedAt") {
|
|
4914
4960
|
return formatDate(value);
|
|
4915
4961
|
}
|
|
4916
|
-
if (typeof value === "object")
|
|
4917
|
-
return JSON.stringify(value);
|
|
4918
4962
|
return String(value);
|
|
4919
4963
|
}
|
|
4920
4964
|
function formatCellPlain(value) {
|
|
@@ -4922,10 +4966,46 @@ function formatCellPlain(value) {
|
|
|
4922
4966
|
return "";
|
|
4923
4967
|
if (typeof value === "boolean")
|
|
4924
4968
|
return value ? "true" : "false";
|
|
4969
|
+
const flattened = flattenStructuredValue(value);
|
|
4970
|
+
if (flattened !== undefined)
|
|
4971
|
+
return flattened;
|
|
4925
4972
|
if (typeof value === "object")
|
|
4926
4973
|
return JSON.stringify(value);
|
|
4927
4974
|
return String(value);
|
|
4928
4975
|
}
|
|
4976
|
+
function flattenStructuredValue(value) {
|
|
4977
|
+
if (Array.isArray(value)) {
|
|
4978
|
+
if (value.length === 0)
|
|
4979
|
+
return "—";
|
|
4980
|
+
const flattened = value.map((item) => getObjectLabel(item) ?? (isPrimitive(item) ? String(item) : undefined)).filter((item) => typeof item === "string" && item.length > 0);
|
|
4981
|
+
if (flattened.length === value.length) {
|
|
4982
|
+
return flattened.join(", ");
|
|
4983
|
+
}
|
|
4984
|
+
return `${value.length} item${value.length === 1 ? "" : "s"}`;
|
|
4985
|
+
}
|
|
4986
|
+
if (typeof value === "object") {
|
|
4987
|
+
return getObjectLabel(value) ?? JSON.stringify(value);
|
|
4988
|
+
}
|
|
4989
|
+
return;
|
|
4990
|
+
}
|
|
4991
|
+
function getObjectLabel(value) {
|
|
4992
|
+
if (value == null || typeof value !== "object" || Array.isArray(value)) {
|
|
4993
|
+
return;
|
|
4994
|
+
}
|
|
4995
|
+
const record = value;
|
|
4996
|
+
for (const key of ["name", "title", "label", "path", "value"]) {
|
|
4997
|
+
if (typeof record[key] === "string" || typeof record[key] === "number") {
|
|
4998
|
+
return String(record[key]);
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
return;
|
|
5002
|
+
}
|
|
5003
|
+
function isPrimitive(value) {
|
|
5004
|
+
return ["string", "number", "boolean", "bigint", "symbol"].includes(typeof value);
|
|
5005
|
+
}
|
|
5006
|
+
function isMessageOnly(data) {
|
|
5007
|
+
return typeof data === "object" && data !== null && !Array.isArray(data) && Object.keys(data).length === 1 && typeof data.message === "string";
|
|
5008
|
+
}
|
|
4929
5009
|
function formatStatus(status) {
|
|
4930
5010
|
const lower = status.toLowerCase();
|
|
4931
5011
|
if (lower === "ok" || lower === "available" || lower === "ended" || lower === "continuing") {
|
|
@@ -4963,20 +5043,10 @@ function stripAnsi3(str) {
|
|
|
4963
5043
|
return str.replace(ANSI_PATTERN, "");
|
|
4964
5044
|
}
|
|
4965
5045
|
function truncateWithAnsi(str, maxWidth) {
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
const end = str.indexOf("m", i2);
|
|
4971
|
-
if (end !== -1) {
|
|
4972
|
-
i2 = end + 1;
|
|
4973
|
-
continue;
|
|
4974
|
-
}
|
|
4975
|
-
}
|
|
4976
|
-
visible++;
|
|
4977
|
-
i2++;
|
|
4978
|
-
}
|
|
4979
|
-
return `${str.slice(0, i2)}…${RESET}`;
|
|
5046
|
+
const plain = stripAnsi3(str);
|
|
5047
|
+
if (plain.length <= maxWidth)
|
|
5048
|
+
return str;
|
|
5049
|
+
return `${plain.slice(0, Math.max(0, maxWidth - 1))}…`;
|
|
4980
5050
|
}
|
|
4981
5051
|
var ESC, GREEN, RED, YELLOW, RESET, ANSI_PATTERN;
|
|
4982
5052
|
var init_output = __esm(() => {
|
|
@@ -5005,6 +5075,7 @@ function buildServiceCommand(serviceName, description, clientFactory, resources)
|
|
|
5005
5075
|
plain: { type: "boolean", description: "Output as TSV (no colors, for piping)" },
|
|
5006
5076
|
quiet: { type: "boolean", alias: "q", description: "Output IDs only" },
|
|
5007
5077
|
"no-header": { type: "boolean", description: "Hide table header row" },
|
|
5078
|
+
"dry-run": { type: "boolean", description: "Show what would happen without executing" },
|
|
5008
5079
|
select: {
|
|
5009
5080
|
type: "string",
|
|
5010
5081
|
description: "Cherry-pick fields (comma-separated, JSON mode)"
|
|
@@ -5012,7 +5083,7 @@ function buildServiceCommand(serviceName, description, clientFactory, resources)
|
|
|
5012
5083
|
yes: { type: "boolean", alias: "y", description: "Skip confirmation prompts" },
|
|
5013
5084
|
...(action.args ?? []).reduce((acc, arg) => {
|
|
5014
5085
|
acc[arg.name] = {
|
|
5015
|
-
type: arg.type === "number" ? "string" : "string",
|
|
5086
|
+
type: arg.type === "boolean" ? "boolean" : arg.type === "number" ? "string" : "string",
|
|
5016
5087
|
description: arg.description,
|
|
5017
5088
|
required: false
|
|
5018
5089
|
};
|
|
@@ -5038,8 +5109,20 @@ function buildServiceCommand(serviceName, description, clientFactory, resources)
|
|
|
5038
5109
|
consola.error(`${argDef.name} must be a number.`);
|
|
5039
5110
|
process.exit(1);
|
|
5040
5111
|
}
|
|
5112
|
+
} else if (argDef.type === "boolean" && resolvedArgs[argDef.name] != null) {
|
|
5113
|
+
resolvedArgs[argDef.name] = coerceBooleanArg(resolvedArgs[argDef.name]);
|
|
5041
5114
|
}
|
|
5042
5115
|
}
|
|
5116
|
+
const format = detectFormat(args);
|
|
5117
|
+
const noHeader = process.argv.includes("--no-header") || !!args.noHeader;
|
|
5118
|
+
const dryRun = !!(args["dry-run"] ?? args.dryRun ?? process.argv.includes("--dry-run"));
|
|
5119
|
+
if (dryRun && isWriteAction(action.name)) {
|
|
5120
|
+
formatOutput(buildDryRunPreview(format, serviceName, resource.name, action.name, resolvedArgs), {
|
|
5121
|
+
format,
|
|
5122
|
+
noHeader
|
|
5123
|
+
});
|
|
5124
|
+
return;
|
|
5125
|
+
}
|
|
5043
5126
|
if (action.confirmMessage) {
|
|
5044
5127
|
const confirmed = await promptConfirm(action.confirmMessage, !!args.yes);
|
|
5045
5128
|
if (!confirmed) {
|
|
@@ -5068,12 +5151,11 @@ Run \`tsarr config init\` or set TSARR_${serviceName.toUpperCase()}_API_KEY`);
|
|
|
5068
5151
|
if (result?.records !== undefined && Array.isArray(result.records)) {
|
|
5069
5152
|
result = result.records;
|
|
5070
5153
|
}
|
|
5071
|
-
const format = detectFormat(args);
|
|
5072
5154
|
formatOutput(result, {
|
|
5073
5155
|
format,
|
|
5074
5156
|
columns: action.columns,
|
|
5075
5157
|
idField: action.idField,
|
|
5076
|
-
noHeader
|
|
5158
|
+
noHeader,
|
|
5077
5159
|
select: args.select
|
|
5078
5160
|
});
|
|
5079
5161
|
} catch (error) {
|
|
@@ -5098,6 +5180,53 @@ Run \`tsarr config init\` or set TSARR_${serviceName.toUpperCase()}_API_KEY`);
|
|
|
5098
5180
|
subCommands
|
|
5099
5181
|
});
|
|
5100
5182
|
}
|
|
5183
|
+
function coerceBooleanArg(value) {
|
|
5184
|
+
if (typeof value === "boolean")
|
|
5185
|
+
return value;
|
|
5186
|
+
if (typeof value === "string") {
|
|
5187
|
+
const normalized = value.trim().toLowerCase();
|
|
5188
|
+
if (normalized === "true")
|
|
5189
|
+
return true;
|
|
5190
|
+
if (normalized === "false")
|
|
5191
|
+
return false;
|
|
5192
|
+
}
|
|
5193
|
+
return Boolean(value);
|
|
5194
|
+
}
|
|
5195
|
+
function isWriteAction(actionName) {
|
|
5196
|
+
return [
|
|
5197
|
+
"add",
|
|
5198
|
+
"create",
|
|
5199
|
+
"delete",
|
|
5200
|
+
"edit",
|
|
5201
|
+
"refresh",
|
|
5202
|
+
"manual-search",
|
|
5203
|
+
"grab",
|
|
5204
|
+
"sync",
|
|
5205
|
+
"test",
|
|
5206
|
+
"search"
|
|
5207
|
+
].includes(actionName);
|
|
5208
|
+
}
|
|
5209
|
+
function buildDryRunPreview(format, serviceName, resourceName, actionName, args) {
|
|
5210
|
+
const filteredArgs = Object.fromEntries(Object.entries(args).filter(([key, value]) => value !== undefined && key !== "_" && key !== "json" && key !== "table" && key !== "plain" && key !== "quiet" && key !== "select" && key !== "no-header" && key !== "noHeader" && key !== "dry-run" && key !== "dryRun"));
|
|
5211
|
+
if (format === "json") {
|
|
5212
|
+
return {
|
|
5213
|
+
dryRun: true,
|
|
5214
|
+
service: serviceName,
|
|
5215
|
+
resource: resourceName,
|
|
5216
|
+
action: actionName,
|
|
5217
|
+
args: filteredArgs
|
|
5218
|
+
};
|
|
5219
|
+
}
|
|
5220
|
+
return {
|
|
5221
|
+
message: `Dry run: would execute ${serviceName} ${resourceName} ${actionName}${formatDryRunArgs(filteredArgs)}`
|
|
5222
|
+
};
|
|
5223
|
+
}
|
|
5224
|
+
function formatDryRunArgs(args) {
|
|
5225
|
+
const entries = Object.entries(args);
|
|
5226
|
+
if (entries.length === 0)
|
|
5227
|
+
return "";
|
|
5228
|
+
return ` with ${entries.map(([key, value]) => `${key}=${String(value)}`).join(", ")}`;
|
|
5229
|
+
}
|
|
5101
5230
|
function handleError(error, serviceName) {
|
|
5102
5231
|
if (error instanceof ApiKeyError) {
|
|
5103
5232
|
consola.error(`API key error: ${error.message}
|
|
@@ -5130,6 +5259,46 @@ var exports_radarr3 = {};
|
|
|
5130
5259
|
__export(exports_radarr3, {
|
|
5131
5260
|
radarr: () => radarr
|
|
5132
5261
|
});
|
|
5262
|
+
function unwrapData(result) {
|
|
5263
|
+
return result?.data ?? result;
|
|
5264
|
+
}
|
|
5265
|
+
function parseBooleanArg(value, fallback) {
|
|
5266
|
+
if (value === undefined)
|
|
5267
|
+
return fallback;
|
|
5268
|
+
if (typeof value === "boolean")
|
|
5269
|
+
return value;
|
|
5270
|
+
if (typeof value === "string") {
|
|
5271
|
+
const normalized = value.trim().toLowerCase();
|
|
5272
|
+
if (normalized === "true")
|
|
5273
|
+
return true;
|
|
5274
|
+
if (normalized === "false")
|
|
5275
|
+
return false;
|
|
5276
|
+
}
|
|
5277
|
+
return Boolean(value);
|
|
5278
|
+
}
|
|
5279
|
+
function resolveQualityProfileId(profiles, profileId) {
|
|
5280
|
+
const profile = profiles.find((item) => item?.id === profileId);
|
|
5281
|
+
if (!profile) {
|
|
5282
|
+
throw new Error(`Quality profile ${profileId} was not found.`);
|
|
5283
|
+
}
|
|
5284
|
+
return profileId;
|
|
5285
|
+
}
|
|
5286
|
+
function resolveRootFolderPath(folders, rootFolderPath) {
|
|
5287
|
+
const folder = folders.find((item) => item?.path === rootFolderPath);
|
|
5288
|
+
if (!folder) {
|
|
5289
|
+
throw new Error(`Root folder "${rootFolderPath}" was not found.`);
|
|
5290
|
+
}
|
|
5291
|
+
return rootFolderPath;
|
|
5292
|
+
}
|
|
5293
|
+
async function findMovieByTmdbId(client2, tmdbId) {
|
|
5294
|
+
if (tmdbId === undefined)
|
|
5295
|
+
return;
|
|
5296
|
+
const movies = unwrapData(await client2.getMovies());
|
|
5297
|
+
return movies.find((movie) => movie?.tmdbId === tmdbId);
|
|
5298
|
+
}
|
|
5299
|
+
function getApiStatus(result) {
|
|
5300
|
+
return result?.error?.status ?? result?.response?.status;
|
|
5301
|
+
}
|
|
5133
5302
|
var resources, radarr;
|
|
5134
5303
|
var init_radarr3 = __esm(() => {
|
|
5135
5304
|
init_radarr2();
|
|
@@ -5163,40 +5332,68 @@ var init_radarr3 = __esm(() => {
|
|
|
5163
5332
|
{
|
|
5164
5333
|
name: "add",
|
|
5165
5334
|
description: "Search and add a movie",
|
|
5166
|
-
args: [
|
|
5335
|
+
args: [
|
|
5336
|
+
{ name: "term", description: "Search term" },
|
|
5337
|
+
{ name: "tmdb-id", description: "TMDB ID", type: "number" },
|
|
5338
|
+
{ name: "quality-profile-id", description: "Quality profile ID", type: "number" },
|
|
5339
|
+
{ name: "root-folder", description: "Root folder path" },
|
|
5340
|
+
{ name: "monitored", description: "Set monitored (true/false)" }
|
|
5341
|
+
],
|
|
5167
5342
|
run: async (c3, a2) => {
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5343
|
+
let movie;
|
|
5344
|
+
if (a2["tmdb-id"] !== undefined) {
|
|
5345
|
+
const lookupResult = await c3.lookupMovieByTmdbId(a2["tmdb-id"]);
|
|
5346
|
+
const lookup = unwrapData(lookupResult);
|
|
5347
|
+
const matches = Array.isArray(lookup) ? lookup : [lookup];
|
|
5348
|
+
movie = matches.find((m2) => m2?.tmdbId === a2["tmdb-id"]) ?? matches[0];
|
|
5349
|
+
if (!movie) {
|
|
5350
|
+
throw new Error(`No movie found for TMDB ID ${a2["tmdb-id"]}.`);
|
|
5351
|
+
}
|
|
5352
|
+
} else {
|
|
5353
|
+
const term = await promptIfMissing(a2.term, "Search term:");
|
|
5354
|
+
const searchResult = await c3.searchMovies(term);
|
|
5355
|
+
const results = unwrapData(searchResult);
|
|
5356
|
+
if (!Array.isArray(results) || results.length === 0) {
|
|
5357
|
+
throw new Error("No movies found.");
|
|
5358
|
+
}
|
|
5359
|
+
const movieId = await promptSelect("Select a movie:", results.map((m2) => ({
|
|
5360
|
+
label: `${m2.title} (${m2.year})`,
|
|
5361
|
+
value: String(m2.tmdbId)
|
|
5362
|
+
})));
|
|
5363
|
+
movie = results.find((m2) => String(m2.tmdbId) === movieId);
|
|
5364
|
+
if (!movie) {
|
|
5365
|
+
throw new Error("Selected movie was not found in the search results.");
|
|
5366
|
+
}
|
|
5177
5367
|
}
|
|
5178
5368
|
const profilesResult = await c3.getQualityProfiles();
|
|
5179
|
-
const profiles = profilesResult
|
|
5369
|
+
const profiles = unwrapData(profilesResult);
|
|
5180
5370
|
if (!Array.isArray(profiles) || profiles.length === 0) {
|
|
5181
5371
|
throw new Error("No quality profiles found. Configure one in Radarr first.");
|
|
5182
5372
|
}
|
|
5183
|
-
const profileId = await promptSelect("Select quality profile:", profiles.map((p) => ({ label: p.name, value: String(p.id) })));
|
|
5373
|
+
const profileId = a2["quality-profile-id"] !== undefined ? resolveQualityProfileId(profiles, a2["quality-profile-id"]) : Number(await promptSelect("Select quality profile:", profiles.map((p) => ({ label: p.name, value: String(p.id) }))));
|
|
5184
5374
|
const foldersResult = await c3.getRootFolders();
|
|
5185
|
-
const folders = foldersResult
|
|
5375
|
+
const folders = unwrapData(foldersResult);
|
|
5186
5376
|
if (!Array.isArray(folders) || folders.length === 0) {
|
|
5187
5377
|
throw new Error("No root folders found. Configure one in Radarr first.");
|
|
5188
5378
|
}
|
|
5189
|
-
const rootFolderPath = await promptSelect("Select root folder:", folders.map((f3) => ({ label: f3.path, value: f3.path })));
|
|
5379
|
+
const rootFolderPath = a2["root-folder"] !== undefined ? resolveRootFolderPath(folders, a2["root-folder"]) : await promptSelect("Select root folder:", folders.map((f3) => ({ label: f3.path, value: f3.path })));
|
|
5190
5380
|
const confirmed = await promptConfirm(`Add "${movie.title} (${movie.year})"?`, !!a2.yes);
|
|
5191
5381
|
if (!confirmed)
|
|
5192
5382
|
throw new Error("Cancelled.");
|
|
5193
|
-
|
|
5383
|
+
const addResult = await c3.addMovie({
|
|
5194
5384
|
...movie,
|
|
5195
|
-
qualityProfileId:
|
|
5385
|
+
qualityProfileId: profileId,
|
|
5196
5386
|
rootFolderPath,
|
|
5197
|
-
monitored: true,
|
|
5387
|
+
monitored: parseBooleanArg(a2.monitored, true),
|
|
5198
5388
|
addOptions: { searchForMovie: true }
|
|
5199
5389
|
});
|
|
5390
|
+
if (addResult?.error && getApiStatus(addResult) === 400) {
|
|
5391
|
+
const existingMovie = await findMovieByTmdbId(c3, movie.tmdbId);
|
|
5392
|
+
if (existingMovie) {
|
|
5393
|
+
throw new Error(`${existingMovie.title} is already in your library (ID: ${existingMovie.id})`);
|
|
5394
|
+
}
|
|
5395
|
+
}
|
|
5396
|
+
return addResult;
|
|
5200
5397
|
}
|
|
5201
5398
|
},
|
|
5202
5399
|
{
|
|
@@ -5236,9 +5433,29 @@ var init_radarr3 = __esm(() => {
|
|
|
5236
5433
|
{
|
|
5237
5434
|
name: "delete",
|
|
5238
5435
|
description: "Delete a movie",
|
|
5239
|
-
args: [
|
|
5436
|
+
args: [
|
|
5437
|
+
{ name: "id", description: "Movie ID", required: true, type: "number" },
|
|
5438
|
+
{ name: "delete-files", description: "Delete movie files", type: "boolean" },
|
|
5439
|
+
{
|
|
5440
|
+
name: "add-import-exclusion",
|
|
5441
|
+
description: "Add import exclusion after delete",
|
|
5442
|
+
type: "boolean"
|
|
5443
|
+
}
|
|
5444
|
+
],
|
|
5240
5445
|
confirmMessage: "Are you sure you want to delete this movie?",
|
|
5241
|
-
run: (c3, a2) =>
|
|
5446
|
+
run: async (c3, a2) => {
|
|
5447
|
+
const movieResult = await c3.getMovie(a2.id);
|
|
5448
|
+
if (movieResult?.error)
|
|
5449
|
+
return movieResult;
|
|
5450
|
+
const movie = unwrapData(movieResult);
|
|
5451
|
+
const deleteResult = await c3.deleteMovie(a2.id, {
|
|
5452
|
+
deleteFiles: a2["delete-files"],
|
|
5453
|
+
addImportExclusion: a2["add-import-exclusion"]
|
|
5454
|
+
});
|
|
5455
|
+
if (deleteResult?.error)
|
|
5456
|
+
return deleteResult;
|
|
5457
|
+
return { message: `Deleted: ${movie.title} (ID: ${movie.id})` };
|
|
5458
|
+
}
|
|
5242
5459
|
}
|
|
5243
5460
|
]
|
|
5244
5461
|
},
|
|
@@ -5264,6 +5481,28 @@ var init_radarr3 = __esm(() => {
|
|
|
5264
5481
|
name: "tag",
|
|
5265
5482
|
description: "Manage tags",
|
|
5266
5483
|
actions: [
|
|
5484
|
+
{
|
|
5485
|
+
name: "create",
|
|
5486
|
+
description: "Create a tag",
|
|
5487
|
+
args: [{ name: "label", description: "Tag label", required: true }],
|
|
5488
|
+
run: (c3, a2) => c3.addTag({ label: a2.label })
|
|
5489
|
+
},
|
|
5490
|
+
{
|
|
5491
|
+
name: "delete",
|
|
5492
|
+
description: "Delete a tag",
|
|
5493
|
+
args: [{ name: "id", description: "Tag ID", required: true, type: "number" }],
|
|
5494
|
+
confirmMessage: "Are you sure you want to delete this tag?",
|
|
5495
|
+
run: async (c3, a2) => {
|
|
5496
|
+
const tagResult = await c3.getTag(a2.id);
|
|
5497
|
+
if (tagResult?.error)
|
|
5498
|
+
return tagResult;
|
|
5499
|
+
const tag = unwrapData(tagResult);
|
|
5500
|
+
const deleteResult = await c3.deleteTag(a2.id);
|
|
5501
|
+
if (deleteResult?.error)
|
|
5502
|
+
return deleteResult;
|
|
5503
|
+
return { message: `Deleted tag: ${tag.label} (ID: ${tag.id})` };
|
|
5504
|
+
}
|
|
5505
|
+
},
|
|
5267
5506
|
{
|
|
5268
5507
|
name: "list",
|
|
5269
5508
|
description: "List all tags",
|
|
@@ -5286,6 +5525,27 @@ var init_radarr3 = __esm(() => {
|
|
|
5286
5525
|
name: "status",
|
|
5287
5526
|
description: "Get queue status",
|
|
5288
5527
|
run: (c3) => c3.getQueueStatus()
|
|
5528
|
+
},
|
|
5529
|
+
{
|
|
5530
|
+
name: "delete",
|
|
5531
|
+
description: "Remove an item from the queue",
|
|
5532
|
+
args: [
|
|
5533
|
+
{ name: "id", description: "Queue item ID", required: true, type: "number" },
|
|
5534
|
+
{ name: "blocklist", description: "Add to blocklist", type: "boolean" },
|
|
5535
|
+
{
|
|
5536
|
+
name: "remove-from-client",
|
|
5537
|
+
description: "Remove from download client",
|
|
5538
|
+
type: "boolean"
|
|
5539
|
+
}
|
|
5540
|
+
],
|
|
5541
|
+
confirmMessage: "Are you sure you want to remove this queue item?",
|
|
5542
|
+
run: (c3, a2) => c3.removeQueueItem(a2.id, a2["remove-from-client"], a2.blocklist)
|
|
5543
|
+
},
|
|
5544
|
+
{
|
|
5545
|
+
name: "grab",
|
|
5546
|
+
description: "Force download a queue item",
|
|
5547
|
+
args: [{ name: "id", description: "Queue item ID", required: true, type: "number" }],
|
|
5548
|
+
run: (c3, a2) => c3.grabQueueItem(a2.id)
|
|
5289
5549
|
}
|
|
5290
5550
|
]
|
|
5291
5551
|
},
|
|
@@ -5298,6 +5558,19 @@ var init_radarr3 = __esm(() => {
|
|
|
5298
5558
|
description: "List root folders",
|
|
5299
5559
|
columns: ["id", "path", "freeSpace"],
|
|
5300
5560
|
run: (c3) => c3.getRootFolders()
|
|
5561
|
+
},
|
|
5562
|
+
{
|
|
5563
|
+
name: "add",
|
|
5564
|
+
description: "Add a root folder",
|
|
5565
|
+
args: [{ name: "path", description: "Folder path", required: true }],
|
|
5566
|
+
run: (c3, a2) => c3.addRootFolder(a2.path)
|
|
5567
|
+
},
|
|
5568
|
+
{
|
|
5569
|
+
name: "delete",
|
|
5570
|
+
description: "Delete a root folder",
|
|
5571
|
+
args: [{ name: "id", description: "Root folder ID", required: true, type: "number" }],
|
|
5572
|
+
confirmMessage: "Are you sure you want to delete this root folder?",
|
|
5573
|
+
run: (c3, a2) => c3.deleteRootFolder(a2.id)
|
|
5301
5574
|
}
|
|
5302
5575
|
]
|
|
5303
5576
|
},
|
|
@@ -5325,8 +5598,168 @@ var init_radarr3 = __esm(() => {
|
|
|
5325
5598
|
{
|
|
5326
5599
|
name: "list",
|
|
5327
5600
|
description: "List recent history",
|
|
5601
|
+
args: [
|
|
5602
|
+
{ name: "since", description: "Start date (ISO 8601, e.g. 2024-01-01)" },
|
|
5603
|
+
{ name: "until", description: "End date (ISO 8601, e.g. 2024-12-31)" }
|
|
5604
|
+
],
|
|
5328
5605
|
columns: ["id", "eventType", "sourceTitle", "date"],
|
|
5329
|
-
run: (c3) =>
|
|
5606
|
+
run: async (c3, a2) => {
|
|
5607
|
+
if (a2.since) {
|
|
5608
|
+
const result2 = await c3.getHistorySince(a2.since);
|
|
5609
|
+
const items2 = unwrapData(result2);
|
|
5610
|
+
if (a2.until) {
|
|
5611
|
+
const untilDate = new Date(a2.until);
|
|
5612
|
+
return items2.filter((item) => new Date(item.date) <= untilDate);
|
|
5613
|
+
}
|
|
5614
|
+
return items2;
|
|
5615
|
+
}
|
|
5616
|
+
const result = await c3.getHistory();
|
|
5617
|
+
const items = unwrapData(result);
|
|
5618
|
+
if (a2.until) {
|
|
5619
|
+
const untilDate = new Date(a2.until);
|
|
5620
|
+
return items.filter((item) => new Date(item.date) <= untilDate);
|
|
5621
|
+
}
|
|
5622
|
+
return items;
|
|
5623
|
+
}
|
|
5624
|
+
}
|
|
5625
|
+
]
|
|
5626
|
+
},
|
|
5627
|
+
{
|
|
5628
|
+
name: "calendar",
|
|
5629
|
+
description: "View upcoming releases",
|
|
5630
|
+
actions: [
|
|
5631
|
+
{
|
|
5632
|
+
name: "list",
|
|
5633
|
+
description: "List upcoming movie releases",
|
|
5634
|
+
args: [
|
|
5635
|
+
{ name: "start", description: "Start date (ISO 8601)" },
|
|
5636
|
+
{ name: "end", description: "End date (ISO 8601)" },
|
|
5637
|
+
{ name: "unmonitored", description: "Include unmonitored", type: "boolean" }
|
|
5638
|
+
],
|
|
5639
|
+
columns: ["id", "title", "year", "inCinemas", "digitalRelease", "physicalRelease"],
|
|
5640
|
+
run: (c3, a2) => c3.getCalendar(a2.start, a2.end, a2.unmonitored)
|
|
5641
|
+
}
|
|
5642
|
+
]
|
|
5643
|
+
},
|
|
5644
|
+
{
|
|
5645
|
+
name: "notification",
|
|
5646
|
+
description: "Manage notifications",
|
|
5647
|
+
actions: [
|
|
5648
|
+
{
|
|
5649
|
+
name: "list",
|
|
5650
|
+
description: "List notification providers",
|
|
5651
|
+
columns: ["id", "name", "implementation"],
|
|
5652
|
+
run: (c3) => c3.getNotifications()
|
|
5653
|
+
},
|
|
5654
|
+
{
|
|
5655
|
+
name: "get",
|
|
5656
|
+
description: "Get a notification by ID",
|
|
5657
|
+
args: [{ name: "id", description: "Notification ID", required: true, type: "number" }],
|
|
5658
|
+
run: (c3, a2) => c3.getNotification(a2.id)
|
|
5659
|
+
},
|
|
5660
|
+
{
|
|
5661
|
+
name: "delete",
|
|
5662
|
+
description: "Delete a notification",
|
|
5663
|
+
args: [{ name: "id", description: "Notification ID", required: true, type: "number" }],
|
|
5664
|
+
confirmMessage: "Are you sure you want to delete this notification?",
|
|
5665
|
+
run: (c3, a2) => c3.deleteNotification(a2.id)
|
|
5666
|
+
},
|
|
5667
|
+
{
|
|
5668
|
+
name: "test",
|
|
5669
|
+
description: "Test all notifications",
|
|
5670
|
+
run: (c3) => c3.testAllNotifications()
|
|
5671
|
+
}
|
|
5672
|
+
]
|
|
5673
|
+
},
|
|
5674
|
+
{
|
|
5675
|
+
name: "downloadclient",
|
|
5676
|
+
description: "Manage download clients",
|
|
5677
|
+
actions: [
|
|
5678
|
+
{
|
|
5679
|
+
name: "list",
|
|
5680
|
+
description: "List download clients",
|
|
5681
|
+
columns: ["id", "name", "implementation", "enable"],
|
|
5682
|
+
run: (c3) => c3.getDownloadClients()
|
|
5683
|
+
},
|
|
5684
|
+
{
|
|
5685
|
+
name: "get",
|
|
5686
|
+
description: "Get a download client by ID",
|
|
5687
|
+
args: [{ name: "id", description: "Download client ID", required: true, type: "number" }],
|
|
5688
|
+
run: (c3, a2) => c3.getDownloadClient(a2.id)
|
|
5689
|
+
},
|
|
5690
|
+
{
|
|
5691
|
+
name: "delete",
|
|
5692
|
+
description: "Delete a download client",
|
|
5693
|
+
args: [{ name: "id", description: "Download client ID", required: true, type: "number" }],
|
|
5694
|
+
confirmMessage: "Are you sure you want to delete this download client?",
|
|
5695
|
+
run: (c3, a2) => c3.deleteDownloadClient(a2.id)
|
|
5696
|
+
},
|
|
5697
|
+
{
|
|
5698
|
+
name: "test",
|
|
5699
|
+
description: "Test all download clients",
|
|
5700
|
+
run: (c3) => c3.testAllDownloadClients()
|
|
5701
|
+
}
|
|
5702
|
+
]
|
|
5703
|
+
},
|
|
5704
|
+
{
|
|
5705
|
+
name: "blocklist",
|
|
5706
|
+
description: "Manage blocked releases",
|
|
5707
|
+
actions: [
|
|
5708
|
+
{
|
|
5709
|
+
name: "list",
|
|
5710
|
+
description: "List blocked releases",
|
|
5711
|
+
columns: ["id", "sourceTitle", "date"],
|
|
5712
|
+
run: (c3) => c3.getBlocklist()
|
|
5713
|
+
},
|
|
5714
|
+
{
|
|
5715
|
+
name: "delete",
|
|
5716
|
+
description: "Remove a release from the blocklist",
|
|
5717
|
+
args: [{ name: "id", description: "Blocklist item ID", required: true, type: "number" }],
|
|
5718
|
+
confirmMessage: "Are you sure you want to remove this blocklist entry?",
|
|
5719
|
+
run: (c3, a2) => c3.removeBlocklistItem(a2.id)
|
|
5720
|
+
}
|
|
5721
|
+
]
|
|
5722
|
+
},
|
|
5723
|
+
{
|
|
5724
|
+
name: "wanted",
|
|
5725
|
+
description: "View missing and cutoff unmet movies",
|
|
5726
|
+
actions: [
|
|
5727
|
+
{
|
|
5728
|
+
name: "missing",
|
|
5729
|
+
description: "List movies with missing files",
|
|
5730
|
+
columns: ["id", "title", "year", "monitored"],
|
|
5731
|
+
run: (c3) => c3.getWantedMissing()
|
|
5732
|
+
},
|
|
5733
|
+
{
|
|
5734
|
+
name: "cutoff",
|
|
5735
|
+
description: "List movies below quality cutoff",
|
|
5736
|
+
columns: ["id", "title", "year", "monitored"],
|
|
5737
|
+
run: (c3) => c3.getWantedCutoff()
|
|
5738
|
+
}
|
|
5739
|
+
]
|
|
5740
|
+
},
|
|
5741
|
+
{
|
|
5742
|
+
name: "importlist",
|
|
5743
|
+
description: "Manage import lists",
|
|
5744
|
+
actions: [
|
|
5745
|
+
{
|
|
5746
|
+
name: "list",
|
|
5747
|
+
description: "List import lists",
|
|
5748
|
+
columns: ["id", "name", "implementation", "enable"],
|
|
5749
|
+
run: (c3) => c3.getImportLists()
|
|
5750
|
+
},
|
|
5751
|
+
{
|
|
5752
|
+
name: "get",
|
|
5753
|
+
description: "Get an import list by ID",
|
|
5754
|
+
args: [{ name: "id", description: "Import list ID", required: true, type: "number" }],
|
|
5755
|
+
run: (c3, a2) => c3.getImportList(a2.id)
|
|
5756
|
+
},
|
|
5757
|
+
{
|
|
5758
|
+
name: "delete",
|
|
5759
|
+
description: "Delete an import list",
|
|
5760
|
+
args: [{ name: "id", description: "Import list ID", required: true, type: "number" }],
|
|
5761
|
+
confirmMessage: "Are you sure you want to delete this import list?",
|
|
5762
|
+
run: (c3, a2) => c3.deleteImportList(a2.id)
|
|
5330
5763
|
}
|
|
5331
5764
|
]
|
|
5332
5765
|
},
|
|
@@ -7261,8 +7694,11 @@ class SonarrClient {
|
|
|
7261
7694
|
async updateSeries(id, series) {
|
|
7262
7695
|
return putApiV3SeriesById({ path: { id }, body: series });
|
|
7263
7696
|
}
|
|
7264
|
-
async deleteSeries(id) {
|
|
7265
|
-
return deleteApiV3SeriesById({
|
|
7697
|
+
async deleteSeries(id, options) {
|
|
7698
|
+
return deleteApiV3SeriesById({
|
|
7699
|
+
path: { id },
|
|
7700
|
+
...options ? { query: options } : {}
|
|
7701
|
+
});
|
|
7266
7702
|
}
|
|
7267
7703
|
async getSeriesFolder(id) {
|
|
7268
7704
|
return getApiV3SeriesByIdFolder({ path: { id } });
|
|
@@ -7385,8 +7821,13 @@ class SonarrClient {
|
|
|
7385
7821
|
async getTagDetailById(id) {
|
|
7386
7822
|
return getApiV3TagDetailById2({ path: { id } });
|
|
7387
7823
|
}
|
|
7388
|
-
async getEpisodes() {
|
|
7389
|
-
|
|
7824
|
+
async getEpisodes(seriesId, episodeIds) {
|
|
7825
|
+
const query = {};
|
|
7826
|
+
if (seriesId !== undefined)
|
|
7827
|
+
query.seriesId = seriesId;
|
|
7828
|
+
if (episodeIds !== undefined)
|
|
7829
|
+
query.episodeIds = episodeIds;
|
|
7830
|
+
return getApiV3Episode(Object.keys(query).length > 0 ? { query } : {});
|
|
7390
7831
|
}
|
|
7391
7832
|
async getEpisode(id) {
|
|
7392
7833
|
return getApiV3EpisodeById({ path: { id } });
|
|
@@ -7600,7 +8041,7 @@ class SonarrClient {
|
|
|
7600
8041
|
query.tags = tags;
|
|
7601
8042
|
return getFeedV3CalendarSonarrIcs(Object.keys(query).length > 0 ? { query } : {});
|
|
7602
8043
|
}
|
|
7603
|
-
async getQueue(page, pageSize, sortKey, sortDirection, includeUnknownSeriesItems) {
|
|
8044
|
+
async getQueue(page, pageSize, sortKey, sortDirection, includeUnknownSeriesItems, seriesId) {
|
|
7604
8045
|
const query = {};
|
|
7605
8046
|
if (page !== undefined)
|
|
7606
8047
|
query.page = page;
|
|
@@ -7612,6 +8053,8 @@ class SonarrClient {
|
|
|
7612
8053
|
query.sortDirection = sortDirection;
|
|
7613
8054
|
if (includeUnknownSeriesItems !== undefined)
|
|
7614
8055
|
query.includeUnknownSeriesItems = includeUnknownSeriesItems;
|
|
8056
|
+
if (seriesId !== undefined)
|
|
8057
|
+
query.seriesIds = [seriesId];
|
|
7615
8058
|
return getApiV3Queue2(Object.keys(query).length > 0 ? { query } : {});
|
|
7616
8059
|
}
|
|
7617
8060
|
async removeQueueItem(id, removeFromClient, blocklist) {
|
|
@@ -7734,6 +8177,65 @@ var exports_sonarr3 = {};
|
|
|
7734
8177
|
__export(exports_sonarr3, {
|
|
7735
8178
|
sonarr: () => sonarr
|
|
7736
8179
|
});
|
|
8180
|
+
function unwrapData2(result) {
|
|
8181
|
+
return result?.data ?? result;
|
|
8182
|
+
}
|
|
8183
|
+
function parseBooleanArg2(value, fallback) {
|
|
8184
|
+
if (value === undefined)
|
|
8185
|
+
return fallback;
|
|
8186
|
+
if (typeof value === "boolean")
|
|
8187
|
+
return value;
|
|
8188
|
+
if (typeof value === "string") {
|
|
8189
|
+
const normalized = value.trim().toLowerCase();
|
|
8190
|
+
if (normalized === "true")
|
|
8191
|
+
return true;
|
|
8192
|
+
if (normalized === "false")
|
|
8193
|
+
return false;
|
|
8194
|
+
}
|
|
8195
|
+
return Boolean(value);
|
|
8196
|
+
}
|
|
8197
|
+
function resolveQualityProfileId2(profiles, profileId) {
|
|
8198
|
+
const profile = profiles.find((item) => item?.id === profileId);
|
|
8199
|
+
if (!profile) {
|
|
8200
|
+
throw new Error(`Quality profile ${profileId} was not found.`);
|
|
8201
|
+
}
|
|
8202
|
+
return profileId;
|
|
8203
|
+
}
|
|
8204
|
+
function resolveRootFolderPath2(folders, rootFolderPath) {
|
|
8205
|
+
const folder = folders.find((item) => item?.path === rootFolderPath);
|
|
8206
|
+
if (!folder) {
|
|
8207
|
+
throw new Error(`Root folder "${rootFolderPath}" was not found.`);
|
|
8208
|
+
}
|
|
8209
|
+
return rootFolderPath;
|
|
8210
|
+
}
|
|
8211
|
+
function formatSeriesListItem(series) {
|
|
8212
|
+
const seasons = Array.isArray(series?.seasons) ? series.seasons.filter((season) => season?.seasonNumber !== 0) : [];
|
|
8213
|
+
const statistics = series?.statistics ?? {};
|
|
8214
|
+
return {
|
|
8215
|
+
...series,
|
|
8216
|
+
seasonCount: seasons.length,
|
|
8217
|
+
episodeCount: statistics.episodeCount !== undefined ? `${statistics.episodeFileCount ?? 0}/${statistics.episodeCount}` : "—",
|
|
8218
|
+
network: series?.network,
|
|
8219
|
+
status: series?.status
|
|
8220
|
+
};
|
|
8221
|
+
}
|
|
8222
|
+
async function lookupSeriesByTvdbId(client3, tvdbId) {
|
|
8223
|
+
const tvdbSearch = unwrapData2(await client3.searchSeries(`tvdb:${tvdbId}`));
|
|
8224
|
+
const exactTvdbMatch = tvdbSearch.find((series) => series?.tvdbId === tvdbId);
|
|
8225
|
+
if (exactTvdbMatch)
|
|
8226
|
+
return exactTvdbMatch;
|
|
8227
|
+
const fallbackSearch = unwrapData2(await client3.searchSeries(String(tvdbId)));
|
|
8228
|
+
return fallbackSearch.find((series) => series?.tvdbId === tvdbId);
|
|
8229
|
+
}
|
|
8230
|
+
async function findSeriesByTvdbId(client3, tvdbId) {
|
|
8231
|
+
if (tvdbId === undefined)
|
|
8232
|
+
return;
|
|
8233
|
+
const series = unwrapData2(await client3.getSeries());
|
|
8234
|
+
return series.find((item) => item?.tvdbId === tvdbId);
|
|
8235
|
+
}
|
|
8236
|
+
function getApiStatus2(result) {
|
|
8237
|
+
return result?.error?.status ?? result?.response?.status;
|
|
8238
|
+
}
|
|
7737
8239
|
var resources2, sonarr;
|
|
7738
8240
|
var init_sonarr3 = __esm(() => {
|
|
7739
8241
|
init_sonarr2();
|
|
@@ -7747,8 +8249,20 @@ var init_sonarr3 = __esm(() => {
|
|
|
7747
8249
|
{
|
|
7748
8250
|
name: "list",
|
|
7749
8251
|
description: "List all series",
|
|
7750
|
-
columns: [
|
|
7751
|
-
|
|
8252
|
+
columns: [
|
|
8253
|
+
"id",
|
|
8254
|
+
"title",
|
|
8255
|
+
"year",
|
|
8256
|
+
"monitored",
|
|
8257
|
+
"seasonCount",
|
|
8258
|
+
"episodeCount",
|
|
8259
|
+
"network",
|
|
8260
|
+
"status"
|
|
8261
|
+
],
|
|
8262
|
+
run: async (c3) => {
|
|
8263
|
+
const series = unwrapData2(await c3.getSeries());
|
|
8264
|
+
return series.map(formatSeriesListItem);
|
|
8265
|
+
}
|
|
7752
8266
|
},
|
|
7753
8267
|
{
|
|
7754
8268
|
name: "get",
|
|
@@ -7766,40 +8280,65 @@ var init_sonarr3 = __esm(() => {
|
|
|
7766
8280
|
{
|
|
7767
8281
|
name: "add",
|
|
7768
8282
|
description: "Search and add a series",
|
|
7769
|
-
args: [
|
|
8283
|
+
args: [
|
|
8284
|
+
{ name: "term", description: "Search term" },
|
|
8285
|
+
{ name: "tvdb-id", description: "TVDB ID", type: "number" },
|
|
8286
|
+
{ name: "quality-profile-id", description: "Quality profile ID", type: "number" },
|
|
8287
|
+
{ name: "root-folder", description: "Root folder path" },
|
|
8288
|
+
{ name: "monitored", description: "Set monitored (true/false)" }
|
|
8289
|
+
],
|
|
7770
8290
|
run: async (c3, a2) => {
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
8291
|
+
let series;
|
|
8292
|
+
if (a2["tvdb-id"] !== undefined) {
|
|
8293
|
+
series = await lookupSeriesByTvdbId(c3, a2["tvdb-id"]);
|
|
8294
|
+
if (!series) {
|
|
8295
|
+
throw new Error(`No series found for TVDB ID ${a2["tvdb-id"]}.`);
|
|
8296
|
+
}
|
|
8297
|
+
} else {
|
|
8298
|
+
const term = await promptIfMissing(a2.term, "Search term:");
|
|
8299
|
+
const searchResult = await c3.searchSeries(term);
|
|
8300
|
+
const results = unwrapData2(searchResult);
|
|
8301
|
+
if (!Array.isArray(results) || results.length === 0) {
|
|
8302
|
+
throw new Error("No series found.");
|
|
8303
|
+
}
|
|
8304
|
+
const seriesId = await promptSelect("Select a series:", results.map((s2) => ({
|
|
8305
|
+
label: `${s2.title} (${s2.year})`,
|
|
8306
|
+
value: String(s2.tvdbId)
|
|
8307
|
+
})));
|
|
8308
|
+
series = results.find((s2) => String(s2.tvdbId) === seriesId);
|
|
8309
|
+
if (!series) {
|
|
8310
|
+
throw new Error("Selected series was not found in the search results.");
|
|
8311
|
+
}
|
|
7780
8312
|
}
|
|
7781
8313
|
const profilesResult = await c3.getQualityProfiles();
|
|
7782
|
-
const profiles = profilesResult
|
|
8314
|
+
const profiles = unwrapData2(profilesResult);
|
|
7783
8315
|
if (!Array.isArray(profiles) || profiles.length === 0) {
|
|
7784
8316
|
throw new Error("No quality profiles found. Configure one in Sonarr first.");
|
|
7785
8317
|
}
|
|
7786
|
-
const profileId = await promptSelect("Select quality profile:", profiles.map((p) => ({ label: p.name, value: String(p.id) })));
|
|
8318
|
+
const profileId = a2["quality-profile-id"] !== undefined ? resolveQualityProfileId2(profiles, a2["quality-profile-id"]) : Number(await promptSelect("Select quality profile:", profiles.map((p) => ({ label: p.name, value: String(p.id) }))));
|
|
7787
8319
|
const foldersResult = await c3.getRootFolders();
|
|
7788
|
-
const folders = foldersResult
|
|
8320
|
+
const folders = unwrapData2(foldersResult);
|
|
7789
8321
|
if (!Array.isArray(folders) || folders.length === 0) {
|
|
7790
8322
|
throw new Error("No root folders found. Configure one in Sonarr first.");
|
|
7791
8323
|
}
|
|
7792
|
-
const rootFolderPath = await promptSelect("Select root folder:", folders.map((f3) => ({ label: f3.path, value: f3.path })));
|
|
8324
|
+
const rootFolderPath = a2["root-folder"] !== undefined ? resolveRootFolderPath2(folders, a2["root-folder"]) : await promptSelect("Select root folder:", folders.map((f3) => ({ label: f3.path, value: f3.path })));
|
|
7793
8325
|
const confirmed = await promptConfirm(`Add "${series.title} (${series.year})"?`, !!a2.yes);
|
|
7794
8326
|
if (!confirmed)
|
|
7795
8327
|
throw new Error("Cancelled.");
|
|
7796
|
-
|
|
8328
|
+
const addResult = await c3.addSeries({
|
|
7797
8329
|
...series,
|
|
7798
|
-
qualityProfileId:
|
|
8330
|
+
qualityProfileId: profileId,
|
|
7799
8331
|
rootFolderPath,
|
|
7800
|
-
monitored: true,
|
|
8332
|
+
monitored: parseBooleanArg2(a2.monitored, true),
|
|
7801
8333
|
addOptions: { searchForMissingEpisodes: true }
|
|
7802
8334
|
});
|
|
8335
|
+
if (addResult?.error && getApiStatus2(addResult) === 400) {
|
|
8336
|
+
const existingSeries = await findSeriesByTvdbId(c3, series.tvdbId);
|
|
8337
|
+
if (existingSeries) {
|
|
8338
|
+
throw new Error(`${existingSeries.title} is already in your library (ID: ${existingSeries.id})`);
|
|
8339
|
+
}
|
|
8340
|
+
}
|
|
8341
|
+
return addResult;
|
|
7803
8342
|
}
|
|
7804
8343
|
},
|
|
7805
8344
|
{
|
|
@@ -7839,9 +8378,29 @@ var init_sonarr3 = __esm(() => {
|
|
|
7839
8378
|
{
|
|
7840
8379
|
name: "delete",
|
|
7841
8380
|
description: "Delete a series",
|
|
7842
|
-
args: [
|
|
8381
|
+
args: [
|
|
8382
|
+
{ name: "id", description: "Series ID", required: true, type: "number" },
|
|
8383
|
+
{ name: "delete-files", description: "Delete series files", type: "boolean" },
|
|
8384
|
+
{
|
|
8385
|
+
name: "add-import-list-exclusion",
|
|
8386
|
+
description: "Add import list exclusion after delete",
|
|
8387
|
+
type: "boolean"
|
|
8388
|
+
}
|
|
8389
|
+
],
|
|
7843
8390
|
confirmMessage: "Are you sure you want to delete this series?",
|
|
7844
|
-
run: (c3, a2) =>
|
|
8391
|
+
run: async (c3, a2) => {
|
|
8392
|
+
const seriesResult = await c3.getSeriesById(a2.id);
|
|
8393
|
+
if (seriesResult?.error)
|
|
8394
|
+
return seriesResult;
|
|
8395
|
+
const series = unwrapData2(seriesResult);
|
|
8396
|
+
const deleteResult = await c3.deleteSeries(a2.id, {
|
|
8397
|
+
deleteFiles: a2["delete-files"],
|
|
8398
|
+
addImportListExclusion: a2["add-import-list-exclusion"]
|
|
8399
|
+
});
|
|
8400
|
+
if (deleteResult?.error)
|
|
8401
|
+
return deleteResult;
|
|
8402
|
+
return { message: `Deleted: ${series.title} (ID: ${series.id})` };
|
|
8403
|
+
}
|
|
7845
8404
|
}
|
|
7846
8405
|
]
|
|
7847
8406
|
},
|
|
@@ -7852,14 +8411,21 @@ var init_sonarr3 = __esm(() => {
|
|
|
7852
8411
|
{
|
|
7853
8412
|
name: "list",
|
|
7854
8413
|
description: "List all episodes",
|
|
8414
|
+
args: [{ name: "series-id", description: "Series ID", required: true, type: "number" }],
|
|
7855
8415
|
columns: ["id", "title", "seasonNumber", "episodeNumber", "hasFile"],
|
|
7856
|
-
run: (c3) => c3.getEpisodes()
|
|
8416
|
+
run: (c3, a2) => c3.getEpisodes(a2["series-id"])
|
|
7857
8417
|
},
|
|
7858
8418
|
{
|
|
7859
8419
|
name: "get",
|
|
7860
8420
|
description: "Get an episode by ID",
|
|
7861
8421
|
args: [{ name: "id", description: "Episode ID", required: true, type: "number" }],
|
|
7862
8422
|
run: (c3, a2) => c3.getEpisode(a2.id)
|
|
8423
|
+
},
|
|
8424
|
+
{
|
|
8425
|
+
name: "search",
|
|
8426
|
+
description: "Trigger a search for an episode",
|
|
8427
|
+
args: [{ name: "id", description: "Episode ID", required: true, type: "number" }],
|
|
8428
|
+
run: (c3, a2) => c3.runCommand({ name: "EpisodeSearch", episodeIds: [a2.id] })
|
|
7863
8429
|
}
|
|
7864
8430
|
]
|
|
7865
8431
|
},
|
|
@@ -7879,6 +8445,28 @@ var init_sonarr3 = __esm(() => {
|
|
|
7879
8445
|
name: "tag",
|
|
7880
8446
|
description: "Manage tags",
|
|
7881
8447
|
actions: [
|
|
8448
|
+
{
|
|
8449
|
+
name: "create",
|
|
8450
|
+
description: "Create a tag",
|
|
8451
|
+
args: [{ name: "label", description: "Tag label", required: true }],
|
|
8452
|
+
run: (c3, a2) => c3.addTag({ label: a2.label })
|
|
8453
|
+
},
|
|
8454
|
+
{
|
|
8455
|
+
name: "delete",
|
|
8456
|
+
description: "Delete a tag",
|
|
8457
|
+
args: [{ name: "id", description: "Tag ID", required: true, type: "number" }],
|
|
8458
|
+
confirmMessage: "Are you sure you want to delete this tag?",
|
|
8459
|
+
run: async (c3, a2) => {
|
|
8460
|
+
const tagResult = await c3.getTag(a2.id);
|
|
8461
|
+
if (tagResult?.error)
|
|
8462
|
+
return tagResult;
|
|
8463
|
+
const tag = unwrapData2(tagResult);
|
|
8464
|
+
const deleteResult = await c3.deleteTag(a2.id);
|
|
8465
|
+
if (deleteResult?.error)
|
|
8466
|
+
return deleteResult;
|
|
8467
|
+
return { message: `Deleted tag: ${tag.label} (ID: ${tag.id})` };
|
|
8468
|
+
}
|
|
8469
|
+
},
|
|
7882
8470
|
{
|
|
7883
8471
|
name: "list",
|
|
7884
8472
|
description: "List all tags",
|
|
@@ -7887,6 +8475,79 @@ var init_sonarr3 = __esm(() => {
|
|
|
7887
8475
|
}
|
|
7888
8476
|
]
|
|
7889
8477
|
},
|
|
8478
|
+
{
|
|
8479
|
+
name: "queue",
|
|
8480
|
+
description: "Manage download queue",
|
|
8481
|
+
actions: [
|
|
8482
|
+
{
|
|
8483
|
+
name: "list",
|
|
8484
|
+
description: "List queue items",
|
|
8485
|
+
args: [{ name: "series-id", description: "Series ID", type: "number" }],
|
|
8486
|
+
columns: ["id", "title", "status", "sizeleft", "timeleft"],
|
|
8487
|
+
run: (c3, a2) => c3.getQueue(undefined, undefined, undefined, undefined, undefined, a2["series-id"])
|
|
8488
|
+
},
|
|
8489
|
+
{
|
|
8490
|
+
name: "status",
|
|
8491
|
+
description: "Get queue status",
|
|
8492
|
+
run: (c3) => c3.getQueueStatus()
|
|
8493
|
+
},
|
|
8494
|
+
{
|
|
8495
|
+
name: "delete",
|
|
8496
|
+
description: "Remove an item from the queue",
|
|
8497
|
+
args: [
|
|
8498
|
+
{ name: "id", description: "Queue item ID", required: true, type: "number" },
|
|
8499
|
+
{ name: "blocklist", description: "Add to blocklist", type: "boolean" },
|
|
8500
|
+
{
|
|
8501
|
+
name: "remove-from-client",
|
|
8502
|
+
description: "Remove from download client",
|
|
8503
|
+
type: "boolean"
|
|
8504
|
+
}
|
|
8505
|
+
],
|
|
8506
|
+
confirmMessage: "Are you sure you want to remove this queue item?",
|
|
8507
|
+
run: (c3, a2) => c3.removeQueueItem(a2.id, a2["remove-from-client"], a2.blocklist)
|
|
8508
|
+
},
|
|
8509
|
+
{
|
|
8510
|
+
name: "grab",
|
|
8511
|
+
description: "Force download a queue item",
|
|
8512
|
+
args: [{ name: "id", description: "Queue item ID", required: true, type: "number" }],
|
|
8513
|
+
run: (c3, a2) => c3.grabQueueItem(a2.id)
|
|
8514
|
+
}
|
|
8515
|
+
]
|
|
8516
|
+
},
|
|
8517
|
+
{
|
|
8518
|
+
name: "history",
|
|
8519
|
+
description: "View history",
|
|
8520
|
+
actions: [
|
|
8521
|
+
{
|
|
8522
|
+
name: "list",
|
|
8523
|
+
description: "List recent history",
|
|
8524
|
+
args: [
|
|
8525
|
+
{ name: "series-id", description: "Series ID", type: "number" },
|
|
8526
|
+
{ name: "since", description: "Start date (ISO 8601, e.g. 2024-01-01)" },
|
|
8527
|
+
{ name: "until", description: "End date (ISO 8601, e.g. 2024-12-31)" }
|
|
8528
|
+
],
|
|
8529
|
+
columns: ["id", "eventType", "sourceTitle", "date"],
|
|
8530
|
+
run: async (c3, a2) => {
|
|
8531
|
+
if (a2.since) {
|
|
8532
|
+
const result2 = await c3.getHistorySince(a2.since, a2["series-id"]);
|
|
8533
|
+
const items2 = unwrapData2(result2);
|
|
8534
|
+
if (a2.until) {
|
|
8535
|
+
const untilDate = new Date(a2.until);
|
|
8536
|
+
return items2.filter((item) => new Date(item.date) <= untilDate);
|
|
8537
|
+
}
|
|
8538
|
+
return items2;
|
|
8539
|
+
}
|
|
8540
|
+
const result = await c3.getHistory(undefined, undefined, undefined, undefined, a2["series-id"]);
|
|
8541
|
+
const items = unwrapData2(result);
|
|
8542
|
+
if (a2.until) {
|
|
8543
|
+
const untilDate = new Date(a2.until);
|
|
8544
|
+
return items.filter((item) => new Date(item.date) <= untilDate);
|
|
8545
|
+
}
|
|
8546
|
+
return items;
|
|
8547
|
+
}
|
|
8548
|
+
}
|
|
8549
|
+
]
|
|
8550
|
+
},
|
|
7890
8551
|
{
|
|
7891
8552
|
name: "rootfolder",
|
|
7892
8553
|
description: "Manage root folders",
|
|
@@ -7896,6 +8557,158 @@ var init_sonarr3 = __esm(() => {
|
|
|
7896
8557
|
description: "List root folders",
|
|
7897
8558
|
columns: ["id", "path", "freeSpace"],
|
|
7898
8559
|
run: (c3) => c3.getRootFolders()
|
|
8560
|
+
},
|
|
8561
|
+
{
|
|
8562
|
+
name: "add",
|
|
8563
|
+
description: "Add a root folder",
|
|
8564
|
+
args: [{ name: "path", description: "Folder path", required: true }],
|
|
8565
|
+
run: (c3, a2) => c3.addRootFolder(a2.path)
|
|
8566
|
+
},
|
|
8567
|
+
{
|
|
8568
|
+
name: "delete",
|
|
8569
|
+
description: "Delete a root folder",
|
|
8570
|
+
args: [{ name: "id", description: "Root folder ID", required: true, type: "number" }],
|
|
8571
|
+
confirmMessage: "Are you sure you want to delete this root folder?",
|
|
8572
|
+
run: (c3, a2) => c3.deleteRootFolder(a2.id)
|
|
8573
|
+
}
|
|
8574
|
+
]
|
|
8575
|
+
},
|
|
8576
|
+
{
|
|
8577
|
+
name: "calendar",
|
|
8578
|
+
description: "View upcoming releases",
|
|
8579
|
+
actions: [
|
|
8580
|
+
{
|
|
8581
|
+
name: "list",
|
|
8582
|
+
description: "List upcoming episode releases",
|
|
8583
|
+
args: [
|
|
8584
|
+
{ name: "start", description: "Start date (ISO 8601)" },
|
|
8585
|
+
{ name: "end", description: "End date (ISO 8601)" },
|
|
8586
|
+
{ name: "unmonitored", description: "Include unmonitored", type: "boolean" }
|
|
8587
|
+
],
|
|
8588
|
+
columns: ["id", "seriesTitle", "title", "seasonNumber", "episodeNumber", "airDateUtc"],
|
|
8589
|
+
run: (c3, a2) => c3.getCalendar(a2.start, a2.end, a2.unmonitored)
|
|
8590
|
+
}
|
|
8591
|
+
]
|
|
8592
|
+
},
|
|
8593
|
+
{
|
|
8594
|
+
name: "notification",
|
|
8595
|
+
description: "Manage notifications",
|
|
8596
|
+
actions: [
|
|
8597
|
+
{
|
|
8598
|
+
name: "list",
|
|
8599
|
+
description: "List notification providers",
|
|
8600
|
+
columns: ["id", "name", "implementation"],
|
|
8601
|
+
run: (c3) => c3.getNotifications()
|
|
8602
|
+
},
|
|
8603
|
+
{
|
|
8604
|
+
name: "get",
|
|
8605
|
+
description: "Get a notification by ID",
|
|
8606
|
+
args: [{ name: "id", description: "Notification ID", required: true, type: "number" }],
|
|
8607
|
+
run: (c3, a2) => c3.getNotification(a2.id)
|
|
8608
|
+
},
|
|
8609
|
+
{
|
|
8610
|
+
name: "delete",
|
|
8611
|
+
description: "Delete a notification",
|
|
8612
|
+
args: [{ name: "id", description: "Notification ID", required: true, type: "number" }],
|
|
8613
|
+
confirmMessage: "Are you sure you want to delete this notification?",
|
|
8614
|
+
run: (c3, a2) => c3.deleteNotification(a2.id)
|
|
8615
|
+
},
|
|
8616
|
+
{
|
|
8617
|
+
name: "test",
|
|
8618
|
+
description: "Test all notifications",
|
|
8619
|
+
run: (c3) => c3.testAllNotifications()
|
|
8620
|
+
}
|
|
8621
|
+
]
|
|
8622
|
+
},
|
|
8623
|
+
{
|
|
8624
|
+
name: "downloadclient",
|
|
8625
|
+
description: "Manage download clients",
|
|
8626
|
+
actions: [
|
|
8627
|
+
{
|
|
8628
|
+
name: "list",
|
|
8629
|
+
description: "List download clients",
|
|
8630
|
+
columns: ["id", "name", "implementation", "enable"],
|
|
8631
|
+
run: (c3) => c3.getDownloadClients()
|
|
8632
|
+
},
|
|
8633
|
+
{
|
|
8634
|
+
name: "get",
|
|
8635
|
+
description: "Get a download client by ID",
|
|
8636
|
+
args: [{ name: "id", description: "Download client ID", required: true, type: "number" }],
|
|
8637
|
+
run: (c3, a2) => c3.getDownloadClient(a2.id)
|
|
8638
|
+
},
|
|
8639
|
+
{
|
|
8640
|
+
name: "delete",
|
|
8641
|
+
description: "Delete a download client",
|
|
8642
|
+
args: [{ name: "id", description: "Download client ID", required: true, type: "number" }],
|
|
8643
|
+
confirmMessage: "Are you sure you want to delete this download client?",
|
|
8644
|
+
run: (c3, a2) => c3.deleteDownloadClient(a2.id)
|
|
8645
|
+
},
|
|
8646
|
+
{
|
|
8647
|
+
name: "test",
|
|
8648
|
+
description: "Test all download clients",
|
|
8649
|
+
run: (c3) => c3.testAllDownloadClients()
|
|
8650
|
+
}
|
|
8651
|
+
]
|
|
8652
|
+
},
|
|
8653
|
+
{
|
|
8654
|
+
name: "blocklist",
|
|
8655
|
+
description: "Manage blocked releases",
|
|
8656
|
+
actions: [
|
|
8657
|
+
{
|
|
8658
|
+
name: "list",
|
|
8659
|
+
description: "List blocked releases",
|
|
8660
|
+
columns: ["id", "sourceTitle", "date"],
|
|
8661
|
+
run: (c3) => c3.getBlocklist()
|
|
8662
|
+
},
|
|
8663
|
+
{
|
|
8664
|
+
name: "delete",
|
|
8665
|
+
description: "Remove a release from the blocklist",
|
|
8666
|
+
args: [{ name: "id", description: "Blocklist item ID", required: true, type: "number" }],
|
|
8667
|
+
confirmMessage: "Are you sure you want to remove this blocklist entry?",
|
|
8668
|
+
run: (c3, a2) => c3.removeBlocklistItem(a2.id)
|
|
8669
|
+
}
|
|
8670
|
+
]
|
|
8671
|
+
},
|
|
8672
|
+
{
|
|
8673
|
+
name: "wanted",
|
|
8674
|
+
description: "View missing and cutoff unmet episodes",
|
|
8675
|
+
actions: [
|
|
8676
|
+
{
|
|
8677
|
+
name: "missing",
|
|
8678
|
+
description: "List episodes with missing files",
|
|
8679
|
+
columns: ["id", "title", "seasonNumber", "episodeNumber", "airDateUtc"],
|
|
8680
|
+
run: (c3) => c3.getWantedMissing()
|
|
8681
|
+
},
|
|
8682
|
+
{
|
|
8683
|
+
name: "cutoff",
|
|
8684
|
+
description: "List episodes below quality cutoff",
|
|
8685
|
+
columns: ["id", "title", "seasonNumber", "episodeNumber", "airDateUtc"],
|
|
8686
|
+
run: (c3) => c3.getWantedCutoff()
|
|
8687
|
+
}
|
|
8688
|
+
]
|
|
8689
|
+
},
|
|
8690
|
+
{
|
|
8691
|
+
name: "importlist",
|
|
8692
|
+
description: "Manage import lists",
|
|
8693
|
+
actions: [
|
|
8694
|
+
{
|
|
8695
|
+
name: "list",
|
|
8696
|
+
description: "List import lists",
|
|
8697
|
+
columns: ["id", "name", "implementation", "enable"],
|
|
8698
|
+
run: (c3) => c3.getImportLists()
|
|
8699
|
+
},
|
|
8700
|
+
{
|
|
8701
|
+
name: "get",
|
|
8702
|
+
description: "Get an import list by ID",
|
|
8703
|
+
args: [{ name: "id", description: "Import list ID", required: true, type: "number" }],
|
|
8704
|
+
run: (c3, a2) => c3.getImportList(a2.id)
|
|
8705
|
+
},
|
|
8706
|
+
{
|
|
8707
|
+
name: "delete",
|
|
8708
|
+
description: "Delete an import list",
|
|
8709
|
+
args: [{ name: "id", description: "Import list ID", required: true, type: "number" }],
|
|
8710
|
+
confirmMessage: "Are you sure you want to delete this import list?",
|
|
8711
|
+
run: (c3, a2) => c3.deleteImportList(a2.id)
|
|
7899
8712
|
}
|
|
7900
8713
|
]
|
|
7901
8714
|
},
|
|
@@ -9649,6 +10462,14 @@ var getApiV1Album = (options) => (options?.client ?? client3).get({
|
|
|
9649
10462
|
}],
|
|
9650
10463
|
url: "/api/v1/queue/status",
|
|
9651
10464
|
...options
|
|
10465
|
+
}), deleteApiV1RootfolderById = (options) => (options.client ?? client3).delete({
|
|
10466
|
+
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
10467
|
+
in: "query",
|
|
10468
|
+
name: "apikey",
|
|
10469
|
+
type: "apiKey"
|
|
10470
|
+
}],
|
|
10471
|
+
url: "/api/v1/rootfolder/{id}",
|
|
10472
|
+
...options
|
|
9652
10473
|
}), getApiV1Rootfolder = (options) => (options?.client ?? client3).get({
|
|
9653
10474
|
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
9654
10475
|
in: "query",
|
|
@@ -9854,6 +10675,9 @@ class LidarrClient {
|
|
|
9854
10675
|
body: { path }
|
|
9855
10676
|
});
|
|
9856
10677
|
}
|
|
10678
|
+
async deleteRootFolder(id) {
|
|
10679
|
+
return deleteApiV1RootfolderById({ path: { id } });
|
|
10680
|
+
}
|
|
9857
10681
|
async addAlbum(album) {
|
|
9858
10682
|
return postApiV1Album({ body: album });
|
|
9859
10683
|
}
|
|
@@ -10409,6 +11233,28 @@ var init_lidarr3 = __esm(() => {
|
|
|
10409
11233
|
name: "tag",
|
|
10410
11234
|
description: "Manage tags",
|
|
10411
11235
|
actions: [
|
|
11236
|
+
{
|
|
11237
|
+
name: "create",
|
|
11238
|
+
description: "Create a tag",
|
|
11239
|
+
args: [{ name: "label", description: "Tag label", required: true }],
|
|
11240
|
+
run: (c3, a2) => c3.addTag({ label: a2.label })
|
|
11241
|
+
},
|
|
11242
|
+
{
|
|
11243
|
+
name: "delete",
|
|
11244
|
+
description: "Delete a tag",
|
|
11245
|
+
args: [{ name: "id", description: "Tag ID", required: true, type: "number" }],
|
|
11246
|
+
confirmMessage: "Are you sure you want to delete this tag?",
|
|
11247
|
+
run: async (c3, a2) => {
|
|
11248
|
+
const tagResult = await c3.getTag(a2.id);
|
|
11249
|
+
if (tagResult?.error)
|
|
11250
|
+
return tagResult;
|
|
11251
|
+
const tag = tagResult?.data ?? tagResult;
|
|
11252
|
+
const deleteResult = await c3.deleteTag(a2.id);
|
|
11253
|
+
if (deleteResult?.error)
|
|
11254
|
+
return deleteResult;
|
|
11255
|
+
return { message: `Deleted tag: ${tag.label} (ID: ${tag.id})` };
|
|
11256
|
+
}
|
|
11257
|
+
},
|
|
10412
11258
|
{
|
|
10413
11259
|
name: "list",
|
|
10414
11260
|
description: "List all tags",
|
|
@@ -10426,6 +11272,19 @@ var init_lidarr3 = __esm(() => {
|
|
|
10426
11272
|
description: "List root folders",
|
|
10427
11273
|
columns: ["id", "path", "freeSpace"],
|
|
10428
11274
|
run: (c3) => c3.getRootFolders()
|
|
11275
|
+
},
|
|
11276
|
+
{
|
|
11277
|
+
name: "add",
|
|
11278
|
+
description: "Add a root folder",
|
|
11279
|
+
args: [{ name: "path", description: "Folder path", required: true }],
|
|
11280
|
+
run: (c3, a2) => c3.addRootFolder(a2.path)
|
|
11281
|
+
},
|
|
11282
|
+
{
|
|
11283
|
+
name: "delete",
|
|
11284
|
+
description: "Delete a root folder",
|
|
11285
|
+
args: [{ name: "id", description: "Root folder ID", required: true, type: "number" }],
|
|
11286
|
+
confirmMessage: "Are you sure you want to delete this root folder?",
|
|
11287
|
+
run: (c3, a2) => c3.deleteRootFolder(a2.id)
|
|
10429
11288
|
}
|
|
10430
11289
|
]
|
|
10431
11290
|
},
|
|
@@ -12163,6 +13022,14 @@ var getApiV1Author = (options) => (options?.client ?? client4).get({
|
|
|
12163
13022
|
"Content-Type": "application/json",
|
|
12164
13023
|
...options?.headers
|
|
12165
13024
|
}
|
|
13025
|
+
}), deleteApiV1RootfolderById2 = (options) => (options.client ?? client4).delete({
|
|
13026
|
+
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
13027
|
+
in: "query",
|
|
13028
|
+
name: "apikey",
|
|
13029
|
+
type: "apiKey"
|
|
13030
|
+
}],
|
|
13031
|
+
url: "/api/v1/rootfolder/{id}",
|
|
13032
|
+
...options
|
|
12166
13033
|
}), getApiV1SystemStatus2 = (options) => (options?.client ?? client4).get({
|
|
12167
13034
|
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
12168
13035
|
in: "query",
|
|
@@ -12348,6 +13215,9 @@ class ReadarrClient {
|
|
|
12348
13215
|
body: { path }
|
|
12349
13216
|
});
|
|
12350
13217
|
}
|
|
13218
|
+
async deleteRootFolder(id) {
|
|
13219
|
+
return deleteApiV1RootfolderById2({ path: { id } });
|
|
13220
|
+
}
|
|
12351
13221
|
async getHostConfig() {
|
|
12352
13222
|
return getApiV1ConfigHost2();
|
|
12353
13223
|
}
|
|
@@ -12880,6 +13750,28 @@ var init_readarr3 = __esm(() => {
|
|
|
12880
13750
|
name: "tag",
|
|
12881
13751
|
description: "Manage tags",
|
|
12882
13752
|
actions: [
|
|
13753
|
+
{
|
|
13754
|
+
name: "create",
|
|
13755
|
+
description: "Create a tag",
|
|
13756
|
+
args: [{ name: "label", description: "Tag label", required: true }],
|
|
13757
|
+
run: (c3, a2) => c3.addTag({ label: a2.label })
|
|
13758
|
+
},
|
|
13759
|
+
{
|
|
13760
|
+
name: "delete",
|
|
13761
|
+
description: "Delete a tag",
|
|
13762
|
+
args: [{ name: "id", description: "Tag ID", required: true, type: "number" }],
|
|
13763
|
+
confirmMessage: "Are you sure you want to delete this tag?",
|
|
13764
|
+
run: async (c3, a2) => {
|
|
13765
|
+
const tagResult = await c3.getTag(a2.id);
|
|
13766
|
+
if (tagResult?.error)
|
|
13767
|
+
return tagResult;
|
|
13768
|
+
const tag = tagResult?.data ?? tagResult;
|
|
13769
|
+
const deleteResult = await c3.deleteTag(a2.id);
|
|
13770
|
+
if (deleteResult?.error)
|
|
13771
|
+
return deleteResult;
|
|
13772
|
+
return { message: `Deleted tag: ${tag.label} (ID: ${tag.id})` };
|
|
13773
|
+
}
|
|
13774
|
+
},
|
|
12883
13775
|
{
|
|
12884
13776
|
name: "list",
|
|
12885
13777
|
description: "List all tags",
|
|
@@ -12897,6 +13789,19 @@ var init_readarr3 = __esm(() => {
|
|
|
12897
13789
|
description: "List root folders",
|
|
12898
13790
|
columns: ["id", "path", "freeSpace"],
|
|
12899
13791
|
run: (c3) => c3.getRootFolders()
|
|
13792
|
+
},
|
|
13793
|
+
{
|
|
13794
|
+
name: "add",
|
|
13795
|
+
description: "Add a root folder",
|
|
13796
|
+
args: [{ name: "path", description: "Folder path", required: true }],
|
|
13797
|
+
run: (c3, a2) => c3.addRootFolder(a2.path)
|
|
13798
|
+
},
|
|
13799
|
+
{
|
|
13800
|
+
name: "delete",
|
|
13801
|
+
description: "Delete a root folder",
|
|
13802
|
+
args: [{ name: "id", description: "Root folder ID", required: true, type: "number" }],
|
|
13803
|
+
confirmMessage: "Are you sure you want to delete this root folder?",
|
|
13804
|
+
run: (c3, a2) => c3.deleteRootFolder(a2.id)
|
|
12900
13805
|
}
|
|
12901
13806
|
]
|
|
12902
13807
|
},
|
|
@@ -14066,6 +14971,14 @@ var deleteApiV1ApplicationsById = (options) => (options.client ?? client5).delet
|
|
|
14066
14971
|
}],
|
|
14067
14972
|
url: "/api/v1/indexer/testall",
|
|
14068
14973
|
...options
|
|
14974
|
+
}), getApiV1Indexerstats = (options) => (options?.client ?? client5).get({
|
|
14975
|
+
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
14976
|
+
in: "query",
|
|
14977
|
+
name: "apikey",
|
|
14978
|
+
type: "apiKey"
|
|
14979
|
+
}],
|
|
14980
|
+
url: "/api/v1/indexerstats",
|
|
14981
|
+
...options
|
|
14069
14982
|
}), getApiV1Log3 = (options) => (options?.client ?? client5).get({
|
|
14070
14983
|
security: [{ name: "X-Api-Key", type: "apiKey" }, {
|
|
14071
14984
|
in: "query",
|
|
@@ -14336,6 +15249,9 @@ class ProwlarrClient {
|
|
|
14336
15249
|
async deleteIndexer(id) {
|
|
14337
15250
|
return deleteApiV1IndexerById3({ path: { id } });
|
|
14338
15251
|
}
|
|
15252
|
+
async getIndexerStats() {
|
|
15253
|
+
return getApiV1Indexerstats();
|
|
15254
|
+
}
|
|
14339
15255
|
async getDownloadClients() {
|
|
14340
15256
|
return getApiV1Downloadclient3();
|
|
14341
15257
|
}
|
|
@@ -14533,6 +15449,7 @@ __export(exports_prowlarr3, {
|
|
|
14533
15449
|
var resources5, prowlarr;
|
|
14534
15450
|
var init_prowlarr3 = __esm(() => {
|
|
14535
15451
|
init_prowlarr2();
|
|
15452
|
+
init_prompt2();
|
|
14536
15453
|
init_service();
|
|
14537
15454
|
resources5 = [
|
|
14538
15455
|
{
|
|
@@ -14557,6 +15474,11 @@ var init_prowlarr3 = __esm(() => {
|
|
|
14557
15474
|
args: [{ name: "id", description: "Indexer ID", required: true, type: "number" }],
|
|
14558
15475
|
confirmMessage: "Are you sure you want to delete this indexer?",
|
|
14559
15476
|
run: (c3, a2) => c3.deleteIndexer(a2.id)
|
|
15477
|
+
},
|
|
15478
|
+
{
|
|
15479
|
+
name: "test",
|
|
15480
|
+
description: "Test all indexers",
|
|
15481
|
+
run: (c3) => c3.testAllIndexers()
|
|
14560
15482
|
}
|
|
14561
15483
|
]
|
|
14562
15484
|
},
|
|
@@ -14567,9 +15489,12 @@ var init_prowlarr3 = __esm(() => {
|
|
|
14567
15489
|
{
|
|
14568
15490
|
name: "run",
|
|
14569
15491
|
description: "Search across indexers",
|
|
14570
|
-
args: [
|
|
15492
|
+
args: [
|
|
15493
|
+
{ name: "term", description: "Search term" },
|
|
15494
|
+
{ name: "query", description: "Search query" }
|
|
15495
|
+
],
|
|
14571
15496
|
columns: ["indexer", "title", "size", "seeders"],
|
|
14572
|
-
run: (c3, a2) => c3.search(a2.query)
|
|
15497
|
+
run: async (c3, a2) => c3.search(await promptIfMissing(a2.term ?? a2.query, "Search term:"))
|
|
14573
15498
|
}
|
|
14574
15499
|
]
|
|
14575
15500
|
},
|
|
@@ -14588,6 +15513,18 @@ var init_prowlarr3 = __esm(() => {
|
|
|
14588
15513
|
description: "Get an application by ID",
|
|
14589
15514
|
args: [{ name: "id", description: "Application ID", required: true, type: "number" }],
|
|
14590
15515
|
run: (c3, a2) => c3.getApplication(a2.id)
|
|
15516
|
+
},
|
|
15517
|
+
{
|
|
15518
|
+
name: "delete",
|
|
15519
|
+
description: "Delete an application",
|
|
15520
|
+
args: [{ name: "id", description: "Application ID", required: true, type: "number" }],
|
|
15521
|
+
confirmMessage: "Are you sure you want to delete this application?",
|
|
15522
|
+
run: (c3, a2) => c3.deleteApplication(a2.id)
|
|
15523
|
+
},
|
|
15524
|
+
{
|
|
15525
|
+
name: "sync",
|
|
15526
|
+
description: "Trigger app indexer sync",
|
|
15527
|
+
run: (c3) => c3.runCommand({ name: "AppIndexerMapSync" })
|
|
14591
15528
|
}
|
|
14592
15529
|
]
|
|
14593
15530
|
},
|
|
@@ -14595,6 +15532,28 @@ var init_prowlarr3 = __esm(() => {
|
|
|
14595
15532
|
name: "tag",
|
|
14596
15533
|
description: "Manage tags",
|
|
14597
15534
|
actions: [
|
|
15535
|
+
{
|
|
15536
|
+
name: "create",
|
|
15537
|
+
description: "Create a tag",
|
|
15538
|
+
args: [{ name: "label", description: "Tag label", required: true }],
|
|
15539
|
+
run: (c3, a2) => c3.addTag({ label: a2.label })
|
|
15540
|
+
},
|
|
15541
|
+
{
|
|
15542
|
+
name: "delete",
|
|
15543
|
+
description: "Delete a tag",
|
|
15544
|
+
args: [{ name: "id", description: "Tag ID", required: true, type: "number" }],
|
|
15545
|
+
confirmMessage: "Are you sure you want to delete this tag?",
|
|
15546
|
+
run: async (c3, a2) => {
|
|
15547
|
+
const tagResult = await c3.getTag(a2.id);
|
|
15548
|
+
if (tagResult?.error)
|
|
15549
|
+
return tagResult;
|
|
15550
|
+
const tag = tagResult?.data ?? tagResult;
|
|
15551
|
+
const deleteResult = await c3.deleteTag(a2.id);
|
|
15552
|
+
if (deleteResult?.error)
|
|
15553
|
+
return deleteResult;
|
|
15554
|
+
return { message: `Deleted tag: ${tag.label} (ID: ${tag.id})` };
|
|
15555
|
+
}
|
|
15556
|
+
},
|
|
14598
15557
|
{
|
|
14599
15558
|
name: "list",
|
|
14600
15559
|
description: "List all tags",
|
|
@@ -14603,6 +15562,77 @@ var init_prowlarr3 = __esm(() => {
|
|
|
14603
15562
|
}
|
|
14604
15563
|
]
|
|
14605
15564
|
},
|
|
15565
|
+
{
|
|
15566
|
+
name: "indexerstats",
|
|
15567
|
+
description: "View indexer statistics",
|
|
15568
|
+
actions: [
|
|
15569
|
+
{
|
|
15570
|
+
name: "list",
|
|
15571
|
+
description: "Get indexer performance statistics",
|
|
15572
|
+
run: (c3) => c3.getIndexerStats()
|
|
15573
|
+
}
|
|
15574
|
+
]
|
|
15575
|
+
},
|
|
15576
|
+
{
|
|
15577
|
+
name: "notification",
|
|
15578
|
+
description: "Manage notifications",
|
|
15579
|
+
actions: [
|
|
15580
|
+
{
|
|
15581
|
+
name: "list",
|
|
15582
|
+
description: "List notification providers",
|
|
15583
|
+
columns: ["id", "name", "implementation"],
|
|
15584
|
+
run: (c3) => c3.getNotifications()
|
|
15585
|
+
},
|
|
15586
|
+
{
|
|
15587
|
+
name: "get",
|
|
15588
|
+
description: "Get a notification by ID",
|
|
15589
|
+
args: [{ name: "id", description: "Notification ID", required: true, type: "number" }],
|
|
15590
|
+
run: (c3, a2) => c3.getNotification(a2.id)
|
|
15591
|
+
},
|
|
15592
|
+
{
|
|
15593
|
+
name: "delete",
|
|
15594
|
+
description: "Delete a notification",
|
|
15595
|
+
args: [{ name: "id", description: "Notification ID", required: true, type: "number" }],
|
|
15596
|
+
confirmMessage: "Are you sure you want to delete this notification?",
|
|
15597
|
+
run: (c3, a2) => c3.deleteNotification(a2.id)
|
|
15598
|
+
},
|
|
15599
|
+
{
|
|
15600
|
+
name: "test",
|
|
15601
|
+
description: "Test all notifications",
|
|
15602
|
+
run: (c3) => c3.testAllNotifications()
|
|
15603
|
+
}
|
|
15604
|
+
]
|
|
15605
|
+
},
|
|
15606
|
+
{
|
|
15607
|
+
name: "downloadclient",
|
|
15608
|
+
description: "Manage download clients",
|
|
15609
|
+
actions: [
|
|
15610
|
+
{
|
|
15611
|
+
name: "list",
|
|
15612
|
+
description: "List download clients",
|
|
15613
|
+
columns: ["id", "name", "implementation", "enable"],
|
|
15614
|
+
run: (c3) => c3.getDownloadClients()
|
|
15615
|
+
},
|
|
15616
|
+
{
|
|
15617
|
+
name: "get",
|
|
15618
|
+
description: "Get a download client by ID",
|
|
15619
|
+
args: [{ name: "id", description: "Download client ID", required: true, type: "number" }],
|
|
15620
|
+
run: (c3, a2) => c3.getDownloadClient(a2.id)
|
|
15621
|
+
},
|
|
15622
|
+
{
|
|
15623
|
+
name: "delete",
|
|
15624
|
+
description: "Delete a download client",
|
|
15625
|
+
args: [{ name: "id", description: "Download client ID", required: true, type: "number" }],
|
|
15626
|
+
confirmMessage: "Are you sure you want to delete this download client?",
|
|
15627
|
+
run: (c3, a2) => c3.deleteDownloadClient(a2.id)
|
|
15628
|
+
},
|
|
15629
|
+
{
|
|
15630
|
+
name: "test",
|
|
15631
|
+
description: "Test all download clients",
|
|
15632
|
+
run: (c3) => c3.testAllDownloadClients()
|
|
15633
|
+
}
|
|
15634
|
+
]
|
|
15635
|
+
},
|
|
14606
15636
|
{
|
|
14607
15637
|
name: "system",
|
|
14608
15638
|
description: "System information",
|