Skip to content

Commit

Permalink
Merge pull request #132 from raydak-labs/fix/min-format-cases
Browse files Browse the repository at this point in the history
  • Loading branch information
BlackDark authored Dec 29, 2024
2 parents 909ec8d + a2494db commit 7f030ff
Show file tree
Hide file tree
Showing 4 changed files with 407 additions and 16 deletions.
128 changes: 121 additions & 7 deletions src/quality-profiles.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
import path from "path";
import { describe, expect, test } from "vitest";
import { MergedQualityDefinitionResource } from "./__generated__/mergedTypes";
import { doAllQualitiesExist, isOrderOfQualitiesEqual, mapQualities } from "./quality-profiles";
import { ConfigQualityProfile, ConfigQualityProfileItem } from "./types/config.types";
import { MergedCustomFormatResource, MergedQualityDefinitionResource, MergedQualityProfileResource } from "./__generated__/mergedTypes";
import { calculateQualityProfilesDiff, doAllQualitiesExist, isOrderOfQualitiesEqual, mapQualities } from "./quality-profiles";
import { CFProcessing } from "./types/common.types";
import { ConfigQualityProfile, ConfigQualityProfileItem, MergedConfigInstance } from "./types/config.types";
import { cloneWithJSON, loadJsonFile } from "./util";

describe("QualityProfiles", async () => {
const sampleQualityProfile = loadJsonFile<MergedQualityProfileResource>(
path.resolve(__dirname, `../tests/samples/single_quality_profile.json`),
);

const sampleQualityDefinitions = loadJsonFile<MergedQualityDefinitionResource[]>(
path.resolve(__dirname, `../tests/samples/qualityDefinition.json`),
);

const sampleCustomFormat = loadJsonFile<MergedCustomFormatResource>(
path.resolve(__dirname, `../tests/samples/single_custom_format.json`),
);

test("doAllQualitiesExist - all exist", async ({}) => {
const fromConfig: ConfigQualityProfileItem[] = [
{ name: "WEB 1080p", qualities: ["WEBDL-1080p", "WEBRip-1080p"] },
Expand Down Expand Up @@ -184,12 +199,111 @@ describe("QualityProfiles", async () => {
expect(result[2]!.allowed).toBe(true);
});

test("calculateQualityProfilesDiff - should diff if minUpgradeFormatScore is different", async ({}) => {
// TODO
test("calculateQualityProfilesDiff - should diff if minUpgradeFormatScore / minFormatScore is different", async ({}) => {
const cfMap: CFProcessing = { carrIdMapping: new Map(), cfNameToCarrConfig: new Map() };

const fromConfig: ConfigQualityProfileItem[] = [{ name: "HDTV-1080p", enabled: false }];

const resources: MergedQualityDefinitionResource[] = [
{ id: 1, title: "HDTV-1080p", weight: 2, quality: { id: 1, name: "HDTV-1080p" } },
];

const profile: ConfigQualityProfile = {
name: "hi",
min_format_score: 2,
qualities: fromConfig,
quality_sort: "sort",
upgrade: { allowed: true, until_quality: "HDTV-1080p", until_score: 1000 },
score_set: "default",
};

const config: MergedConfigInstance = {
custom_formats: [],
quality_profiles: [profile],
customFormatDefinitions: [],
media_management: {},
media_naming: {},
};

const serverProfile = cloneWithJSON(sampleQualityProfile);
serverProfile.name = "hi";
serverProfile.formatItems = [];
serverProfile.minUpgradeFormatScore = 3;
serverProfile.minFormatScore = 3;
serverProfile.cutoff = 1;
serverProfile.items = [{ allowed: false, items: [], quality: { id: 1, name: "HDTV-1080p" } }];

const serverQP: MergedQualityProfileResource[] = [serverProfile];
const serverQD: MergedQualityDefinitionResource[] = resources;
const serverCF: MergedCustomFormatResource[] = [cloneWithJSON(sampleCustomFormat)];

let diff = await calculateQualityProfilesDiff(cfMap, config, serverQP, serverQD, serverCF);
expect(diff.changedQPs.length).toBe(1);
expect(diff.create.length).toBe(0);
expect(diff.noChanges.length).toBe(0);

serverProfile.minFormatScore = 0;
diff = await calculateQualityProfilesDiff(cfMap, config, serverQP, serverQD, serverCF);
expect(diff.changedQPs.length).toBe(1);
expect(diff.create.length).toBe(0);
expect(diff.noChanges.length).toBe(0);

serverProfile.minUpgradeFormatScore = 0;
diff = await calculateQualityProfilesDiff(cfMap, config, serverQP, serverQD, serverCF);
expect(diff.changedQPs.length).toBe(1);
expect(diff.create.length).toBe(0);
expect(diff.noChanges.length).toBe(0);

profile.min_format_score = 0;
serverProfile.minFormatScore = 1;
diff = await calculateQualityProfilesDiff(cfMap, config, serverQP, serverQD, serverCF);
expect(diff.changedQPs.length).toBe(1);
expect(diff.create.length).toBe(0);
expect(diff.noChanges.length).toBe(0);
});

test("calculateQualityProfilesDiff - should not diff if minUpgradeFormatScore is equal", async ({}) => {
// TODO
test("calculateQualityProfilesDiff - should not diff if minFormatScore is equal", async ({}) => {
const cfMap: CFProcessing = { carrIdMapping: new Map(), cfNameToCarrConfig: new Map() };

const fromConfig: ConfigQualityProfileItem[] = [{ name: "HDTV-1080p", enabled: false }];

const resources: MergedQualityDefinitionResource[] = [
{ id: 1, title: "HDTV-1080p", weight: 2, quality: { id: 1, name: "HDTV-1080p" } },
];

const profile: ConfigQualityProfile = {
name: "hi",
min_format_score: 2,
qualities: fromConfig,
quality_sort: "sort",
upgrade: { allowed: true, until_quality: "HDTV-1080p", until_score: 1000 },
score_set: "default",
};

const config: MergedConfigInstance = {
custom_formats: [],
quality_profiles: [profile],
customFormatDefinitions: [],
media_management: {},
media_naming: {},
};

const serverProfile = cloneWithJSON(sampleQualityProfile);
serverProfile.name = "hi";
serverProfile.formatItems = [];
serverProfile.minUpgradeFormatScore = 3;
serverProfile.minFormatScore = 2;
serverProfile.cutoff = 1;
serverProfile.items = [{ allowed: false, items: [], quality: { id: 1, name: "HDTV-1080p" } }];

const serverQP: MergedQualityProfileResource[] = [serverProfile];
const serverQD: MergedQualityDefinitionResource[] = resources;
const serverCF: MergedCustomFormatResource[] = [cloneWithJSON(sampleCustomFormat)];

const diff = await calculateQualityProfilesDiff(cfMap, config, serverQP, serverQD, serverCF);
expect(diff.changedQPs.length).toBe(0);
expect(diff.create.length).toBe(0);
expect(diff.noChanges.length).toBe(1);
});

test("calculateQualityProfilesDiff - should not diff if minUpgradeFormatScore is not configured", async ({}) => {
Expand Down
18 changes: 9 additions & 9 deletions src/quality-profiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export const doAllQualitiesExist = (serverResource: ConfigQualityProfileItem[],
const sortedServerConfig = serverCloned.sort((a, b) => (a.name < b.name ? -1 : 1));
const sortedLocalConfig = localCloned.sort((a, b) => (a.name < b.name ? -1 : 1));

if (sortedLocalConfig.length !== sortedServerConfig.length) {
if (sortedLocalConfig.length !== sortedServerConfig.length || sortedLocalConfig.length === 0) {
return false;
}

Expand Down Expand Up @@ -256,7 +256,7 @@ export const calculateQualityProfilesDiff = async (
return p;
}, new Map()) ?? new Map();

if (!serverMatch) {
if (serverMatch == null) {
logger.info(`QualityProfile '${name}' not found in server. Will be created.`);
const mappedQ = mapQualities(serverQD, value);

Expand Down Expand Up @@ -350,10 +350,10 @@ export const calculateQualityProfilesDiff = async (

// TODO do we want to enforce the whole structure or only match those which are enabled by us?
if (!doAllQualitiesExist(serverQualitiesMapped, value.qualities)) {
logger.info(`QualityProfile items mismatch will update whole array`);
logger.info(`QualityProfile qualities mismatch will update whole array`);
diffExist = true;

changeList.push(`QualityProfile items do not match`);
changeList.push(`QualityProfile qualities mismatch will update whole array`);
updatedServerObject.items = mapQualities(serverQD, value);
} else {
if (!isOrderOfQualitiesEqual(value.qualities, serverQualitiesMapped.toReversed())) {
Expand All @@ -378,15 +378,15 @@ export const calculateQualityProfilesDiff = async (
return p;
}, new Map());

if (value.min_format_score) {
if (value.min_format_score != null) {
if (serverMatch.minFormatScore !== value.min_format_score) {
updatedServerObject.minFormatScore = value.min_format_score;
diffExist = true;
changeList.push(`MinFormatScore diff: server: ${serverMatch.minFormatScore} - expected: ${value.min_format_score}`);
}
}

if (value.upgrade) {
if (value.upgrade != null) {
if (serverMatch.upgradeAllowed !== value.upgrade.allowed) {
updatedServerObject.upgradeAllowed = value.upgrade.allowed;
diffExist = true;
Expand All @@ -396,7 +396,7 @@ export const calculateQualityProfilesDiff = async (

const upgradeUntil = qualityToId.get(value.upgrade.until_quality);

if (!upgradeUntil) {
if (upgradeUntil == null) {
throw new Error(`Did not find expected Quality to upgrade until: ${value.upgrade.until_quality}`);
}

Expand Down Expand Up @@ -431,7 +431,7 @@ export const calculateQualityProfilesDiff = async (

let scoringDiff = false;

if (scoringForQP) {
if (scoringForQP != null) {
const newCFFormats: MergedProfileFormatItemResource[] = [];

for (const [scoreKey, scoreValue] of scoringForQP.entries()) {
Expand Down Expand Up @@ -477,7 +477,7 @@ export const calculateQualityProfilesDiff = async (

updatedServerObject.formatItems = newCFFormats;
} else {
logger.info(`No scoring for QualityProfile ${serverMatch.name!} found`);
logger.info(`No scoring for QualityProfile '${serverMatch.name!}' found`);
}

logger.debug(
Expand Down
28 changes: 28 additions & 0 deletions tests/samples/single_custom_format.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"id": 1,
"name": "BR-DISK",
"includeCustomFormatWhenRenaming": false,
"specifications": [
{
"name": "BR-DISK",
"implementation": "ReleaseTitleSpecification",
"implementationName": "Release Title",
"infoLink": "https://wiki.servarr.com/sonarr/settings#custom-formats-2",
"negate": false,
"required": true,
"fields": [
{
"order": 0,
"name": "value",
"label": "Regular Expression",
"helpText": "Custom Format RegEx is Case Insensitive",
"value": "^(?!.*\\b((?<!HD[._ -]|HD)DVD|BDRip|720p|MKV|XviD|WMV|d3g|(BD)?REMUX|^(?=.*1080p)(?=.*HEVC)|[xh][-_. ]?26[45]|German.*[DM]L|((?<=\\d{4}).*German.*([DM]L)?)(?=.*\\b(AVC|HEVC|VC[-_. ]?1|MVC|MPEG[-_. ]?2)\\b))\\b)(((?=.*\\b(Blu[-_. ]?ray|BD|HD[-_. ]?DVD)\\b)(?=.*\\b(AVC|HEVC|VC[-_. ]?1|MVC|MPEG[-_. ]?2|BDMV|ISO)\\b))|^((?=.*\\b(((?=.*\\b((.*_)?COMPLETE.*|Dis[ck])\\b)(?=.*(Blu[-_. ]?ray|HD[-_. ]?DVD)))|3D[-_. ]?BD|BR[-_. ]?DISK|Full[-_. ]?Blu[-_. ]?ray|^((?=.*((BD|UHD)[-_. ]?(25|50|66|100|ISO)))))))).*",
"type": "textbox",
"advanced": false,
"privacy": "normal",
"isFloat": false
}
]
}
]
}
Loading

0 comments on commit 7f030ff

Please sign in to comment.