diff --git a/komf-core/src/commonMain/kotlin/snd/komf/providers/kodansha/model/KodanshaBook.kt b/komf-core/src/commonMain/kotlin/snd/komf/providers/kodansha/model/KodanshaBook.kt index 16636050..c067f9dc 100644 --- a/komf-core/src/commonMain/kotlin/snd/komf/providers/kodansha/model/KodanshaBook.kt +++ b/komf-core/src/commonMain/kotlin/snd/komf/providers/kodansha/model/KodanshaBook.kt @@ -24,7 +24,7 @@ data class KodanshaBook( val creators: List? = null, - val readableUrl: String?, + val readableUrl: String? = null, ) @JvmInline diff --git a/komf-core/src/commonMain/kotlin/snd/komf/providers/yenpress/YenPressMetadataProvider.kt b/komf-core/src/commonMain/kotlin/snd/komf/providers/yenpress/YenPressMetadataProvider.kt index 707a9ed8..10bc88e9 100644 --- a/komf-core/src/commonMain/kotlin/snd/komf/providers/yenpress/YenPressMetadataProvider.kt +++ b/komf-core/src/commonMain/kotlin/snd/komf/providers/yenpress/YenPressMetadataProvider.kt @@ -37,9 +37,9 @@ class YenPressMetadataProvider( override suspend fun getSeriesMetadata(seriesId: ProviderSeriesId): ProviderSeriesMetadata { val allBooks = client.getBookList(YenPressSeriesId(seriesId.value)) - val firstBook = allBooks.firstOrNull { it.number != null } - ?: (if (allBooks.size == 1) allBooks.first() else null) - ?: throw IllegalStateException("Can't find first book") + val firstBook = allBooks.firstOrNull { it.number?.start != null } + ?: allBooks.firstOrNull() + ?: throw IllegalStateException("No books found for YenPress series ${seriesId.value}") val seriesBook = client.getBook(firstBook.id) val thumbnail = if (fetchSeriesCovers) client.getBookThumbnail(seriesBook) else null @@ -81,16 +81,6 @@ class YenPressMetadataProvider( } } .firstOrNull { nameMatcher.matches(seriesName, seriesTitleFromBook(it.title.raw)) } - ?.let { getSeriesMetadata(it.id) } - } - - private suspend fun getSeriesMetadata(seriesId: YenPressSeriesId): ProviderSeriesMetadata? { - val books = client.getBookList(seriesId) - val firstBook = books.find { book -> book.number?.start != null } - ?: (if (books.size == 1) books.first() else null) - - val seriesBook = firstBook?.let { client.getBook(it.id) } ?: return null - val thumbnail = if (fetchSeriesCovers) client.getBookThumbnail(seriesBook) else null - return metadataMapper.toSeriesMetadata(seriesBook, books, thumbnail) + ?.let { getSeriesMetadata(ProviderSeriesId(it.id.value)) } } } diff --git a/komf-mediaserver/src/commonMain/kotlin/snd/komf/mediaserver/metadata/MetadataService.kt b/komf-mediaserver/src/commonMain/kotlin/snd/komf/mediaserver/metadata/MetadataService.kt index ef1827a7..ccd20cda 100644 --- a/komf-mediaserver/src/commonMain/kotlin/snd/komf/mediaserver/metadata/MetadataService.kt +++ b/komf-mediaserver/src/commonMain/kotlin/snd/komf/mediaserver/metadata/MetadataService.kt @@ -230,6 +230,13 @@ class MetadataService( eventFlow.emit(ProviderSeriesEvent(provider.providerName())) val result = try { provider.matchSeriesMetadata(createMatchQuery(searchTitle, series, books)) + } catch (e: IllegalStateException) { + // Handle YenPress empty book list case gracefully - skip provider + if (e.message?.startsWith("No books found for YenPress series") == true) { + logger.debug { "YenPress has no books for series, skipping provider" } + return null + } + throw ProviderException(provider.providerName(), e) } catch (e: Exception) { throw ProviderException(provider.providerName(), e) } @@ -393,6 +400,12 @@ class MetadataService( return try { provider.getSeriesMetadata(providerSeriesId) + } catch (e: IllegalStateException) { + // Handle YenPress empty book list case - re-throw without wrapping so it can be handled differently + if (e.message?.startsWith("No books found for YenPress series") == true) { + throw e + } + throw ProviderException(provider.providerName(), e) } catch (e: Exception) { throw ProviderException(provider.providerName(), e) } @@ -428,6 +441,15 @@ class MetadataService( ) ) logger.catching(providerException) + } catch (exception: IllegalStateException) { + // Handle YenPress empty book list case gracefully - log at debug level instead of error + if (exception.message?.startsWith("No books found for YenPress series") == true) { + logger.debug { "YenPress has no books for series: ${exception.message}" } + // Don't emit error event, just complete silently + } else { + eventFlow.emit(ProcessingErrorEvent("${exception::class.simpleName}: ${exception.message}")) + logger.catching(exception) + } } catch (exception: CancellationException) { throw exception } catch (exception: ResponseException) {