2024-10-05 23:17:20 +02:00
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
2024-10-06 01:27:51 +02:00
import { requestManager } from '@/lib/requests/RequestManager.ts' ;
2025-08-15 22:02:58 +02:00
import { CategoryIdInfo } from '@/features/category/Category.types.ts' ;
2024-10-05 23:17:20 +02:00
import {
AppMetadataKeys ,
GqlMetaHolder ,
2025-01-05 02:15:03 +01:00
MetadataHolder ,
2024-10-26 17:25:04 +02:00
MetadataHolderType ,
2024-10-05 23:17:20 +02:00
MetadataKeyValuePair ,
2025-08-15 22:02:58 +02:00
} from '@/features/metadata/Metadata.types.ts' ;
import { MangaIdInfo } from '@/features/manga/Manga.types.ts' ;
import { getMetadataKey } from '@/features/metadata/Metadata.utils.ts' ;
import { convertToGqlMeta } from '@/features/metadata/services/MetadataConverter.ts' ;
import { SourceIdInfo } from '@/features/source/Source.types.ts' ;
import { ChapterIdInfo } from '@/features/chapter/Chapter.types.ts' ;
2024-10-05 23:17:20 +02:00
2026-01-25 20:32:56 +01:00
type MetadataUpdateOptions = {
update? : MetadataKeyValuePair [];
delete ?: AppMetadataKeys [];
/**
* Only ever pass the "migration" key value pair into this.
*/
migrate? : MetadataKeyValuePair [];
keyPrefixes? : string [];
/**
* Applies to "update" and "delete" metadata value pairs. "migrate" is excluded from this and is always expected to not be already converted to a metadata key
*/
isMetadataKey? : boolean ;
};
const requestMetadataUpdate = async (
2024-10-05 23:17:20 +02:00
metadataHolder : GqlMetaHolder ,
holderType : MetadataHolderType ,
2026-01-25 20:32:56 +01:00
{
update : keysToValues = [],
delete : keysToDelete = [],
migrate : keysToMigrate = [],
keyPrefixes ,
isMetadataKey = false ,
} : MetadataUpdateOptions ,
2026-01-24 21:04:06 +01:00
) : Promise < void > => {
2026-01-25 20:32:56 +01:00
if ( keysToMigrate ? . length > 1 || ( keysToMigrate ? . length === 1 && keysToMigrate [ 0 ][ 0 ] !== 'migration' )) {
throw new Error (
`requestMetadataUpdate: "migrate" option must only contain a single key-value pair with the key "migration"` ,
);
}
const updateMetas = keysToValues . map (([ key , value ]) => ({
2026-01-24 21:04:06 +01:00
key : isMetadataKey ? key : getMetadataKey ( key , keyPrefixes ),
value : ` ${ value } ` ,
}));
2026-01-25 20:32:56 +01:00
const deleteKeys = keysToDelete . map (( key ) => ( isMetadataKey ? key : getMetadataKey ( key , keyPrefixes )));
const migrateMetas = keysToMigrate . map (([ key , value ]) => ({
key : getMetadataKey ( key , keyPrefixes ),
value : ` ${ value } ` ,
}));
const updateMetaInput = {
updateInput : { metas : updateMetas },
deleteInput : { keys : deleteKeys },
migrateInput : { metas : migrateMetas },
};
2026-01-24 21:04:06 +01:00
switch ( holderType ) {
case 'category' :
2026-01-25 20:32:56 +01:00
await requestManager . updateCategoryMeta ([( metadataHolder as CategoryIdInfo ). id ], updateMetaInput ). response ;
2026-01-24 21:04:06 +01:00
break ;
case 'chapter' :
2026-01-25 20:32:56 +01:00
await requestManager . updateChapterMeta ([( metadataHolder as ChapterIdInfo ). id ], updateMetaInput ). response ;
2026-01-24 21:04:06 +01:00
break ;
case 'global' :
2026-01-25 20:32:56 +01:00
await requestManager . updateGlobalMeta ( updateMetaInput ). response ;
2026-01-24 21:04:06 +01:00
break ;
case 'manga' :
2026-01-25 20:32:56 +01:00
await requestManager . updateMangaMeta ([( metadataHolder as MangaIdInfo ). id ], updateMetaInput ). response ;
2026-01-24 21:04:06 +01:00
break ;
case 'source' :
2026-01-25 20:32:56 +01:00
await requestManager . updateSourceMeta ([( metadataHolder as SourceIdInfo ). id ], updateMetaInput ). response ;
2026-01-24 21:04:06 +01:00
break ;
default :
2026-01-25 20:32:56 +01:00
throw new Error ( `requestMetadataUpdate: unknown holderType " ${ holderType } "` );
2026-01-24 21:04:06 +01:00
}
};
2024-10-05 23:17:20 +02:00
2026-01-25 20:32:56 +01:00
export const requestServerMetadataUpdate = async ( options : MetadataUpdateOptions ) : Promise < void > =>
requestMetadataUpdate ({}, 'global' , options );
2024-10-05 23:17:20 +02:00
2026-01-25 20:32:56 +01:00
export const requestMangaMetadataUpdate = async (
2024-10-05 23:17:20 +02:00
manga : MangaIdInfo & GqlMetaHolder ,
2026-01-25 20:32:56 +01:00
options : MetadataUpdateOptions ,
) : Promise < void > => requestMetadataUpdate ( manga , 'manga' , options );
2024-10-05 23:17:20 +02:00
2026-01-25 20:32:56 +01:00
export const requestChapterMetadataUpdate = async (
2024-10-05 23:17:20 +02:00
chapter : ChapterIdInfo & GqlMetaHolder ,
2026-01-25 20:32:56 +01:00
options : MetadataUpdateOptions ,
) : Promise < void > => requestMetadataUpdate ( chapter , 'chapter' , options );
2024-10-05 23:17:20 +02:00
2026-01-25 20:32:56 +01:00
export const requestCategoryMetadataUpdate = async (
2024-10-05 23:17:20 +02:00
category : CategoryIdInfo & GqlMetaHolder ,
2026-01-25 20:32:56 +01:00
options : MetadataUpdateOptions ,
) : Promise < void > => requestMetadataUpdate ( category , 'category' , options );
2024-10-05 23:17:20 +02:00
2026-01-25 20:32:56 +01:00
export const requestSourceMetadataUpdate = async (
2025-04-21 17:00:13 +02:00
source : SourceIdInfo & GqlMetaHolder ,
2026-01-25 20:32:56 +01:00
options : MetadataUpdateOptions ,
) : Promise < void > => requestMetadataUpdate ( source , 'source' , options );
2025-01-05 02:15:03 +01:00
export const getMetadataUpdateFunction = (
type : MetadataHolderType ,
metadataHolder :
| MetadataHolder
| ( MangaIdInfo & MetadataHolder )
| ( ChapterIdInfo & MetadataHolder )
| ( CategoryIdInfo & MetadataHolder )
2025-04-21 17:00:13 +02:00
| ( SourceIdInfo & MetadataHolder ),
2026-01-25 20:32:56 +01:00
) : (( options : MetadataUpdateOptions ) => Promise < void >) => {
2025-01-05 02:15:03 +01:00
switch ( type ) {
case 'global' :
2026-01-25 20:32:56 +01:00
return ( options ) => requestServerMetadataUpdate ( options );
2025-01-05 02:15:03 +01:00
case 'manga' :
2026-01-25 20:32:56 +01:00
return ( options ) =>
requestMangaMetadataUpdate (
2025-01-05 02:15:03 +01:00
{ id : ( metadataHolder as MangaIdInfo ). id , meta : convertToGqlMeta ( metadataHolder . meta ) },
2026-01-25 20:32:56 +01:00
options ,
2025-01-05 02:15:03 +01:00
);
case 'chapter' :
2026-01-25 20:32:56 +01:00
return ( options ) =>
requestChapterMetadataUpdate (
2025-01-05 02:15:03 +01:00
{ id : ( metadataHolder as ChapterIdInfo ). id , meta : convertToGqlMeta ( metadataHolder . meta ) },
2026-01-25 20:32:56 +01:00
options ,
2025-01-05 02:15:03 +01:00
);
case 'category' :
2026-01-25 20:32:56 +01:00
return ( options ) =>
requestCategoryMetadataUpdate (
2025-01-05 02:15:03 +01:00
{ id : ( metadataHolder as CategoryIdInfo ). id , meta : convertToGqlMeta ( metadataHolder . meta ) },
2026-01-25 20:32:56 +01:00
options ,
2025-01-05 02:15:03 +01:00
);
case 'source' :
2026-01-25 20:32:56 +01:00
return ( options ) =>
requestSourceMetadataUpdate (
{ id : ( metadataHolder as SourceIdInfo ). id , meta : convertToGqlMeta ( metadataHolder . meta ) },
options ,
2025-01-05 02:15:03 +01:00
);
default :
throw new Error ( `Unexpected "type" ( ${ type } )` );
}
};