Skip to content

Commit

Permalink
feat: make Trash template / QualityProfiles includable
Browse files Browse the repository at this point in the history
  • Loading branch information
BlackDark committed Nov 1, 2024
1 parent 2077c17 commit 5339ced
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 12 deletions.
64 changes: 57 additions & 7 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,64 @@ import {
mapQualityProfiles,
} from "./src/quality-profiles";
import { cloneRecyclarrTemplateRepo, loadRecyclarrTemplates } from "./src/recyclarr-importer";
import { cloneTrashRepo, loadQualityDefinitionSonarrFromTrash, loadSonarrTrashCFs } from "./src/trash-guide";
import { ArrType, ConfigArrInstance, ConfigQualityProfile, MappedMergedTemplates, TrashQualityDefintion } from "./src/types";
import {
cloneTrashRepo,
loadQPFromTrash,
loadQualityDefinitionSonarrFromTrash,
loadSonarrTrashCFs,
transformTrashQPCFs,
transformTrashQPToTemplate,
} from "./src/trash-guide";
import {
ArrType,
ConfigArrInstance,
ConfigQualityProfile,
MappedMergedTemplates,
TrashQualityDefintion,
YamlConfigIncludeRecyclarr,
YamlConfigIncludeTrash,
} from "./src/types";
import { DEBUG_CREATE_FILES, IS_DRY_RUN } from "./src/util";

const pipeline = async (value: ConfigArrInstance, arrType: ArrType) => {
const api = getArrApi();
const recyclarrTemplateMap = loadRecyclarrTemplates(arrType);
const trashTemplates = await loadQPFromTrash(arrType);

const recylarrMergedTemplates: MappedMergedTemplates = {
custom_formats: [],
quality_profiles: [],
};

if (value.include) {
logger.info(`Recyclarr includes ${value.include.length} templates`);
logger.debug(
value.include.map((e) => e.template),
"Included templates",
logger.info(`Found ${value.include.length} templates to include ...`);

const mappedIncludes = value.include.reduce<{ recyclarr: YamlConfigIncludeRecyclarr[]; trash: YamlConfigIncludeTrash[] }>(
(previous, current) => {
if (current.type == null) {
previous.recyclarr.push(current as YamlConfigIncludeRecyclarr);
} else {
switch (current.type) {
case "TRASH":
previous.trash.push(current);
break;
case "RECYCLARR":
previous.recyclarr.push(current as YamlConfigIncludeRecyclarr);
break;
default:
logger.warn(`Unknown type for template requested: ${(current as any).type}. Ignoring.`);
}
}

return previous;
},
{ recyclarr: [], trash: [] },
);

value.include.forEach((e) => {
logger.debug(mappedIncludes.recyclarr, `Included ${mappedIncludes.recyclarr.length} templates [recyclarr]`);
logger.debug(mappedIncludes.trash, `Included ${mappedIncludes.trash.length} templates [trash]`);

mappedIncludes.recyclarr.forEach((e) => {
const template = recyclarrTemplateMap.get(e.template);

if (!template) {
Expand All @@ -65,6 +102,18 @@ const pipeline = async (value: ConfigArrInstance, arrType: ArrType) => {

// TODO Ignore recursive include for now
});

mappedIncludes.trash.forEach((e) => {
const template = trashTemplates.get(e.id);

if (!template) {
logger.info(`Unknown trash template requested: ${e.id}`);
return;
}

recylarrMergedTemplates.quality_profiles.push(transformTrashQPToTemplate(template));
recylarrMergedTemplates.custom_formats.push(transformTrashQPCFs(template));
});
}

if (value.custom_formats) {
Expand Down Expand Up @@ -103,6 +152,7 @@ const pipeline = async (value: ConfigArrInstance, arrType: ArrType) => {
recylarrMergedTemplates.quality_profiles = filterInvalidQualityProfiles(recylarrMergedTemplates.quality_profiles);

const trashCFs = await loadSonarrTrashCFs(arrType);

const localFileCFs = await loadLocalCfs();
const configCFDefinition = loadCFFromConfig();
const mergedCFs = mergeCfSources([trashCFs, localFileCFs, configCFDefinition]);
Expand Down
10 changes: 10 additions & 0 deletions src/trash-guide.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { describe, test } from "vitest";
import { loadQPFromTrash } from "./trash-guide";

describe("TrashGuide", async () => {
test("loadQPFromTrash - normal", async ({}) => {
const results = await loadQPFromTrash("RADARR");

console.log(results.keys());
});
});
60 changes: 58 additions & 2 deletions src/trash-guide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ import {
ArrType,
CFProcessing,
ConfigarrCF,
ConfigCustomFormat,
QualityDefintionsRadarr,
QualityDefintionsSonarr,
TrashCF,
TrashQP,
TrashQualityDefintion,
YamlConfigQualityProfile,
YamlConfigQualityProfileItems,
} from "./types";
import { loadJsonFile, mapImportCfToRequestCf, toCarrCF, trashRepoPaths } from "./util";
import { loadJsonFile, mapImportCfToRequestCf, notEmpty, toCarrCF, trashRepoPaths } from "./util";

const DEFAULT_TRASH_GIT_URL = "https://github.com/TRaSH-Guides/Guides";

Expand Down Expand Up @@ -98,7 +102,7 @@ export const loadQualityDefinitionSonarrFromTrash = async (
qdType: QualityDefintionsSonarr | QualityDefintionsRadarr,
arrType: ArrType,
): Promise<TrashQualityDefintion> => {
let trashPath = arrType === "RADARR" ? trashRepoPaths.radarrQuality : trashRepoPaths.sonarrQuality;
let trashPath = arrType === "RADARR" ? trashRepoPaths.radarrQualitySize : trashRepoPaths.sonarrQualitySize;

switch (qdType) {
case "anime":
Expand All @@ -113,3 +117,55 @@ export const loadQualityDefinitionSonarrFromTrash = async (
throw new Error(`Unknown QualityDefintion type: ${qdType}`);
}
};

export const loadQPFromTrash = async (arrType: ArrType) => {
let trashPath = arrType === "RADARR" ? trashRepoPaths.radarrQP : trashRepoPaths.sonarrQP;
const map = new Map<string, TrashQP>();

try {
const files = fs.readdirSync(`${trashPath}`).filter((fn) => fn.endsWith("json"));

if (files.length <= 0) {
logger.info(`Not found any TrashGuide QualityProfiles. Skipping.`);
}

for (const item of files) {
const importTrashQP = loadJsonFile<TrashQP>(`${trashPath}/${item}`);

map.set(importTrashQP.trash_id, importTrashQP);
}
} catch (err: any) {
logger.warn("Failed loading TrashGuide QualityProfiles. Continue without ...", err?.message);
}

// const localPath = getLocalTemplatePath();

// if (localPath) {
// fillMap(localPath);
// }

return map;
};

export const transformTrashQPToTemplate = (data: TrashQP): YamlConfigQualityProfile => {
return {
min_format_score: data.minFormatScore,
score_set: data.trash_score_set,
upgrade: { allowed: data.upgradeAllowed, until_quality: data.cutoff, until_score: data.cutoffFormatScore },
name: data.name,
qualities: data.items
.map((e): YamlConfigQualityProfileItems | null => {
if (!e.allowed) {
return null;
}
return { name: e.name, qualities: e.items };
})
.filter(notEmpty)
.toReversed(),
quality_sort: "top", // default
};
};

export const transformTrashQPCFs = (data: TrashQP): ConfigCustomFormat => {
return { assign_scores_to: [{ name: data.name }], trash_ids: Object.values(data.formatItems) };
};
72 changes: 71 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,26 @@ export type TrashCF = {
trash_description?: string;
} & ImportCF;

type TrashQPItem = {
name: string;
allowed: boolean;
items?: string[];
};

export type TrashQP = {
trash_id: string;
name: string;
trash_score_set: keyof TrashCF["trash_scores"];
upgradeAllowed: boolean;
cutoff: string;
minFormatScore: number;
cutoffFormatScore: number;
items: TrashQPItem[];
formatItems: {
[key: string]: string;
};
};

export type ConfigarrCF = {
configarr_id: string;
configarr_scores?: TrashCF["trash_scores"];
Expand Down Expand Up @@ -100,6 +120,9 @@ export type ConfigSchema = InputConfigSchema & {

export type InputConfigCustomFormat = {
trash_ids?: string[];
/**
* @deprecated replaced with assign_scores_to
*/
quality_profiles?: { name: string; score?: number }[];
assign_scores_to?: { name: string; score?: number }[];
};
Expand All @@ -114,7 +137,7 @@ export type ConfigArrInstance = {
quality_definition?: {
type: string;
};
include?: { template: string }[];
include?: YamlConfigIncludeItem[];
custom_formats: ConfigCustomFormat[];
quality_profiles: ConfigQualityProfile[];
};
Expand Down Expand Up @@ -166,6 +189,53 @@ export type RecyclarrConfigInstance = Omit<ConfigArrInstance, "custom_formats">
custom_formats: RecyclarrCustomFormats[];
};

// TODO
export type YamlConfigIncludeRecyclarr = {
template: string;
type: "RECYCLARR";
};

export type YamlConfigIncludeTrash = {
// TODO or use template?
id: string;
type: "TRASH";
};
export type YamlConfigIncludeItem = YamlConfigIncludeRecyclarr | YamlConfigIncludeTrash;

export type YamlConfigInstance = {
base_url: string;
api_key: string;
quality_definition?: {
type: string;
};
include?: YamlConfigIncludeItem[];
custom_formats: InputConfigCustomFormat[];
quality_profiles: YamlConfigQualityProfile[];
};

export type YamlConfigQualityProfile = {
name: string;
reset_unmatched_scores?: {
enabled: boolean;
except?: string[];
};
upgrade: {
allowed: boolean;
until_quality: string;
until_score: number;
};
min_format_score: number;
score_set: keyof TrashCF["trash_scores"];
quality_sort: "top" | "bottom";
qualities: YamlConfigQualityProfileItems[];
};

export type YamlConfigQualityProfileItems = {
name: string;
qualities?: string[];
};
// END TODO

export type RecyclarrTemplates = Partial<
Pick<RecyclarrConfigInstance, "quality_definition" | "custom_formats" | "include" | "quality_profiles">
>;
Expand Down
6 changes: 4 additions & 2 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ const trashRepoRadarrRoot = `${trashRepoRoot}/${trashRepoPath}/radarr`;
export const trashRepoPaths = {
root: trashRepoRoot,
sonarrCF: `${trashRepoSonarrRoot}/cf`,
sonarrQuality: `${trashRepoSonarrRoot}/quality-size`,
sonarrQualitySize: `${trashRepoSonarrRoot}/quality-size`,
sonarrQP: `${trashRepoSonarrRoot}/quality-profiles`,
sonarrNaming: `${trashRepoSonarrRoot}/naming`,
radarrCF: `${trashRepoRadarrRoot}/cf`,
radarrQuality: `${trashRepoRadarrRoot}/quality-size`,
radarrQualitySize: `${trashRepoRadarrRoot}/quality-size`,
radarrQP: `${trashRepoRadarrRoot}/quality-profiles`,
radarrNaming: `${trashRepoRadarrRoot}/naming`,
};

Expand Down

0 comments on commit 5339ced

Please sign in to comment.