feat: simplify language support in quality profiles

- moved language field in quality profile general page
- simplify transformation for sonarr by making languages optional
This commit is contained in:
Sam Chau
2026-01-22 14:02:43 +10:30
parent 12ba7540f7
commit 4efefe63ca
23 changed files with 5153 additions and 440 deletions

View File

@@ -9,6 +9,7 @@ export interface CreateQualityProfileInput {
name: string;
description: string | null;
tags: string[];
language: string | null;
}
export interface CreateQualityProfileOptions {
@@ -89,6 +90,16 @@ export async function create(options: CreateQualityProfileOptions) {
queries.push(insertQuality);
}
// 4. Insert language if one is selected
if (input.language !== null) {
const insertLanguage = {
sql: `INSERT INTO quality_profile_languages (quality_profile_name, language_name, type) VALUES ('${esc(input.name)}', '${esc(input.language)}', 'simple')`,
parameters: [],
query: {} as never
};
queries.push(insertLanguage);
}
// Write the operation
const result = await writeOperation({
databaseId,

View File

@@ -32,6 +32,13 @@ export async function general(
.orderBy('t.name')
.execute();
// Get language for this profile (first one if exists)
const languageRow = await db
.selectFrom('quality_profile_languages as qpl')
.select(['qpl.language_name'])
.where('qpl.quality_profile_name', '=', profile.name)
.executeTakeFirst();
return {
id: profile.id,
name: profile.name,
@@ -39,6 +46,7 @@ export async function general(
tags: tags.map((tag) => ({
name: tag.tag_name,
created_at: tag.tag_created_at
}))
})),
language: languageRow?.language_name ?? null
};
}

View File

@@ -40,6 +40,7 @@ export interface QualityProfileGeneral {
name: string;
description: string; // Raw markdown
tags: Tag[];
language: string | null; // Language name, null means "Any"
}
/** Language configuration for a quality profile */

View File

@@ -11,6 +11,7 @@ export interface UpdateGeneralInput {
name: string;
description: string;
tags: string[];
language: string | null; // Language name, null means no language set
}
export interface UpdateGeneralOptions {
@@ -92,6 +93,27 @@ export async function updateGeneral(options: UpdateGeneralOptions) {
queries.push(linkTag);
}
// 3. Handle language changes
const profileNameForLanguage = input.name !== current.name ? input.name : current.name;
// Delete existing language for this profile
const deleteLanguage = {
sql: `DELETE FROM quality_profile_languages WHERE quality_profile_name = '${esc(profileNameForLanguage)}'`,
parameters: [],
query: {} as never
};
queries.push(deleteLanguage);
// Insert new language if one is selected
if (input.language !== null) {
const insertLanguage = {
sql: `INSERT INTO quality_profile_languages (quality_profile_name, language_name, type) VALUES ('${esc(profileNameForLanguage)}', '${esc(input.language)}', 'simple')`,
parameters: [],
query: {} as never
};
queries.push(insertLanguage);
}
// Log what's being changed
const changes: Record<string, { from: unknown; to: unknown }> = {};
@@ -104,6 +126,9 @@ export async function updateGeneral(options: UpdateGeneralOptions) {
if (tagsToAdd.length > 0 || tagsToRemove.length > 0) {
changes.tags = { from: currentTagNames, to: input.tags };
}
if (current.language !== input.language) {
changes.language = { from: current.language, to: input.language };
}
await logger.info(`Save quality profile "${input.name}"`, {
source: 'QualityProfile',