From 553b35d218d4b8a3569d37f5264004e448d259b4 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sat, 16 Sep 2023 19:07:24 +0200 Subject: [PATCH] Feature/improve automatic chapter downloads (#680) * Rename "newChapters" to "updatedChapterList" * Do not auto download new chapters of entries with unread chapters Makes it possible to prevent unnecessary chapter downloads in case the entry hasn't yet been caught up * Optionally limit auto new chapter downloads * Prevent downloading new chapters for mangas not in the library --- .../suwayomi/tachidesk/manga/impl/Chapter.kt | 38 ++++++++++++++----- .../suwayomi/tachidesk/server/ServerConfig.kt | 2 + .../src/main/resources/server-reference.conf | 2 + .../src/test/resources/server-reference.conf | 2 + 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Chapter.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Chapter.kt index 3637a71fc..21e8093ce 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Chapter.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Chapter.kt @@ -196,28 +196,48 @@ object Chapter { } } - downloadNewChapters(mangaId, numberOfCurrentChapters, newChapters) + if (manga.inLibrary) { + downloadNewChapters(mangaId, numberOfCurrentChapters, newChapters) + } return chapterList } - private fun downloadNewChapters(mangaId: Int, prevNumberOfChapters: Int, newChapters: List) { + private fun downloadNewChapters(mangaId: Int, prevNumberOfChapters: Int, updatedChapterList: List) { // convert numbers to be index based val currentNumberOfChapters = (prevNumberOfChapters - 1).coerceAtLeast(0) - val updatedNumberOfChapters = (newChapters.size - 1).coerceAtLeast(0) + val updatedNumberOfChapters = (updatedChapterList.size - 1).coerceAtLeast(0) + val numberOfNewChapters = updatedNumberOfChapters - currentNumberOfChapters - val areNewChaptersAvailable = currentNumberOfChapters < updatedNumberOfChapters + val areNewChaptersAvailable = numberOfNewChapters > 0 val wasInitialFetch = currentNumberOfChapters == 0 // make sure to ignore initial fetch - val downloadNewChapters = serverConfig.autoDownloadNewChapters.value && !wasInitialFetch && areNewChaptersAvailable - if (!downloadNewChapters) { + val isDownloadPossible = + serverConfig.autoDownloadNewChapters.value && areNewChaptersAvailable && !wasInitialFetch + if (!isDownloadPossible) { return } - val numberOfNewChapters = updatedNumberOfChapters - currentNumberOfChapters - val chapterIdsToDownload = newChapters.subList(0, numberOfNewChapters) - .filter { !it[ChapterTable.isRead] && !it[ChapterTable.isDownloaded] }.map { it[ChapterTable.id].value } + val newChapters = updatedChapterList.subList(0, numberOfNewChapters) + + // make sure to only consider the latest chapters. e.g. old unread chapters should be ignored + val latestReadChapterIndex = + updatedChapterList.indexOfFirst { it[ChapterTable.isRead] }.takeIf { it > -1 } ?: return + val unreadChapters = updatedChapterList.subList(numberOfNewChapters, latestReadChapterIndex) + .filter { !it[ChapterTable.isRead] } + + val skipDueToUnreadChapters = serverConfig.excludeEntryWithUnreadChapters.value && unreadChapters.isNotEmpty() + if (skipDueToUnreadChapters) { + return + } + + val firstChapterToDownloadIndex = + (numberOfNewChapters - serverConfig.autoDownloadAheadLimit.value).coerceAtLeast(0) + + val chapterIdsToDownload = newChapters.subList(firstChapterToDownloadIndex, numberOfNewChapters) + .filter { !it[ChapterTable.isRead] && !it[ChapterTable.isDownloaded] } + .map { it[ChapterTable.id].value } if (chapterIdsToDownload.isEmpty()) { return diff --git a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt index f0e574f2a..b6e79fd7f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt @@ -73,6 +73,8 @@ class ServerConfig(getConfig: () -> Config, val moduleName: String = SERVER_CONF val downloadAsCbz: MutableStateFlow by OverrideConfigValue(BooleanConfigAdapter) val downloadsPath: MutableStateFlow by OverrideConfigValue(StringConfigAdapter) val autoDownloadNewChapters: MutableStateFlow by OverrideConfigValue(BooleanConfigAdapter) + val excludeEntryWithUnreadChapters: MutableStateFlow by OverrideConfigValue(BooleanConfigAdapter) + val autoDownloadAheadLimit: MutableStateFlow by OverrideConfigValue(IntConfigAdapter) // requests val maxSourcesInParallel: MutableStateFlow by OverrideConfigValue(IntConfigAdapter) diff --git a/server/src/main/resources/server-reference.conf b/server/src/main/resources/server-reference.conf index 7671f3ccc..46cfb0e9f 100644 --- a/server/src/main/resources/server-reference.conf +++ b/server/src/main/resources/server-reference.conf @@ -20,6 +20,8 @@ server.webUIUpdateCheckInterval = 23 # time in hours - 0 to disable auto update server.downloadAsCbz = false server.downloadsPath = "" server.autoDownloadNewChapters = false # if new chapters that have been retrieved should get automatically downloaded +server.excludeEntryWithUnreadChapters = true # ignore automatic chapter downloads of entries with unread chapters +server.autoDownloadAheadLimit = 5 # 0 to disable it - how many unread downloaded chapters should be available - if the limit is reached, new chapters won't be downloaded automatically # requests server.maxSourcesInParallel = 6 # range: 1 <= n <= 20 - default: 6 - sets how many sources can do requests (updates, downloads) in parallel. updates/downloads are grouped by source and all mangas of a source are updated/downloaded synchronously diff --git a/server/src/test/resources/server-reference.conf b/server/src/test/resources/server-reference.conf index 179ce3204..f524e7730 100644 --- a/server/src/test/resources/server-reference.conf +++ b/server/src/test/resources/server-reference.conf @@ -10,6 +10,8 @@ server.socksProxyPort = "" # downloader server.downloadAsCbz = false server.autoDownloadNewChapters = false +server.excludeEntryWithUnreadChapters = true +server.autoDownloadAheadLimit = 5 # requests server.maxSourcesInParallel = 10