From 9a3fdc23e6a6ce299127014f6277cd5e44c6d765 Mon Sep 17 00:00:00 2001 From: Jobobby04 Date: Mon, 10 Aug 2020 23:29:10 -0400 Subject: [PATCH] Delegate hitomi, it is now the first fully delegated factory source. To continue using hitomi please download the extension. This comes with a lot of fixes for future delegated factory sources --- app/build.gradle | 2 +- .../tachiyomi/extension/ExtensionManager.kt | 2 - .../kanade/tachiyomi/source/SourceManager.kt | 12 +- .../tachiyomi/source/online/all/Hitomi.kt | 384 ++---------------- .../kanade/tachiyomi/ui/main/MainActivity.kt | 4 - .../ui/setting/SettingsAdvancedController.kt | 7 - app/src/main/java/exh/EHSourceHelpers.kt | 34 +- app/src/main/java/exh/EXHMigrations.kt | 18 + app/src/main/java/exh/debug/DebugFunctions.kt | 4 +- .../java/exh/source/DelegatedHttpSource.kt | 4 +- app/src/main/java/exh/util/SourceTagsUtil.kt | 6 +- 11 files changed, 91 insertions(+), 386 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 79d8734aa..0295a8ff9 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -42,7 +42,7 @@ android { minSdkVersion AndroidConfig.minSdk targetSdkVersion AndroidConfig.targetSdk testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - versionCode 4 + versionCode 5 versionName "1.1.1" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt index 4aecea4e5..865058dc7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt @@ -20,7 +20,6 @@ import eu.kanade.tachiyomi.util.lang.launchNow import eu.kanade.tachiyomi.util.system.toast import exh.EH_SOURCE_ID import exh.EXH_SOURCE_ID -import exh.HITOMI_SOURCE_ID import exh.MERGED_SOURCE_ID import exh.NHENTAI_SOURCE_ID import exh.PERV_EDEN_EN_SOURCE_ID @@ -85,7 +84,6 @@ class ExtensionManager( PERV_EDEN_EN_SOURCE_ID -> context.getDrawable(R.mipmap.ic_perveden_source) PERV_EDEN_IT_SOURCE_ID -> context.getDrawable(R.mipmap.ic_perveden_source) NHENTAI_SOURCE_ID -> context.getDrawable(R.mipmap.ic_nhentai_source) - HITOMI_SOURCE_ID -> context.getDrawable(R.mipmap.ic_hitomi_source) MERGED_SOURCE_ID -> context.getDrawable(R.mipmap.ic_merged_source) else -> null } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt b/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt index f2fbc122f..1e9ae36b7 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/SourceManager.kt @@ -104,7 +104,7 @@ open class SourceManager(private val context: Context) { source, delegate.newSourceClass.constructors.find { it.parameters.size == 2 }!!.call(source, context) ) - val map = listOf(DelegatedSource(enhancedSource.originalSource.name, enhancedSource.originalSource.id, enhancedSource.originalSource::class.qualifiedName ?: delegate.originalSourceQualifiedClassName, (enhancedSource.enhancedSource as DelegatedHttpSource)::class, delegate.factory)).associateBy { it.originalSourceQualifiedClassName } + val map = listOf(DelegatedSource(enhancedSource.originalSource.name, enhancedSource.originalSource.id, enhancedSource.originalSource::class.qualifiedName ?: delegate.originalSourceQualifiedClassName, (enhancedSource.enhancedSource as DelegatedHttpSource)::class, delegate.factory)).associateBy { it.sourceId } currentDelegatedSources.plusAssign(map) enhancedSource } else source @@ -139,7 +139,6 @@ open class SourceManager(private val context: Context) { exSrcs += PervEden(PERV_EDEN_EN_SOURCE_ID, PervEdenLang.en, context) exSrcs += PervEden(PERV_EDEN_IT_SOURCE_ID, PervEdenLang.it, context) exSrcs += NHentai(context) - exSrcs += Hitomi(context) return exSrcs } // SY <-- @@ -210,10 +209,17 @@ open class SourceManager(private val context: Context) { 1802675169972965535, "eu.kanade.tachiyomi.extension.all.eromuse.EroMuse", EightMuses::class + ), + DelegatedSource( + "Hitomi", + fillInSourceId, + "eu.kanade.tachiyomi.extension.all.hitomi.Hitomi", + Hitomi::class, + true ) ).associateBy { it.originalSourceQualifiedClassName } - var currentDelegatedSources = mutableMapOf() + var currentDelegatedSources = mutableMapOf() data class DelegatedSource( val sourceName: String, diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt index 3627d3f9c..9685a9ae4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/Hitomi.kt @@ -3,100 +3,49 @@ package eu.kanade.tachiyomi.source.online.all import android.content.Context import android.net.Uri import android.os.Build -import com.github.salomonbrys.kotson.array -import com.github.salomonbrys.kotson.get -import com.github.salomonbrys.kotson.string -import com.google.gson.JsonParser -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.MangasPage -import eu.kanade.tachiyomi.source.model.Page -import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.LewdSource import eu.kanade.tachiyomi.source.online.UrlImportableSource import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.util.asJsoup -import exh.HITOMI_SOURCE_ID -import exh.hitomi.HitomiNozomi import exh.metadata.metadata.HitomiSearchMetadata -import exh.metadata.metadata.HitomiSearchMetadata.Companion.BASE_URL -import exh.metadata.metadata.HitomiSearchMetadata.Companion.LTN_BASE_URL -import exh.metadata.metadata.HitomiSearchMetadata.Companion.TAG_TYPE_DEFAULT -import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL +import exh.metadata.metadata.base.RaisedSearchMetadata import exh.metadata.metadata.base.RaisedTag +import exh.source.DelegatedHttpSource import exh.ui.metadata.adapters.HitomiDescriptionAdapter import exh.util.urlImportFetchSearchManga import java.text.SimpleDateFormat import java.util.Locale -import okhttp3.Request -import okhttp3.Response import org.jsoup.nodes.Document -import org.vepta.vdm.ByteCursor import rx.Observable -import rx.Single -import rx.schedulers.Schedulers -import uy.kohesive.injekt.injectLazy -/** - * Man, I hate this source :( - */ -class Hitomi(val context: Context) : HttpSource(), LewdSource, UrlImportableSource { - private val prefs: PreferencesHelper by injectLazy() - - override val id = HITOMI_SOURCE_ID - - /** - * Whether the source has support for latest updates. - */ - override val supportsLatest = true - /** - * Name of the source. - */ - override val name = "hitomi.la" - /** - * The class of the metadata used by this source - */ +class Hitomi(delegate: HttpSource, val context: Context) : + DelegatedHttpSource(delegate), + LewdSource, + UrlImportableSource { override val metaClass = HitomiSearchMetadata::class + override val lang = if (delegate.lang == "other") "all" else delegate.lang + override val id: Long + get() = if (delegate.lang == "other") otherId else delegate.id - private var cachedTagIndexVersion: Long? = null - private var tagIndexVersionCacheTime: Long = 0 - private fun tagIndexVersion(): Single { - val sCachedTagIndexVersion = cachedTagIndexVersion - return if (sCachedTagIndexVersion == null || - tagIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis() - ) { - HitomiNozomi.getIndexVersion(client, "tagindex").subscribeOn(Schedulers.io()).doOnNext { - cachedTagIndexVersion = it - tagIndexVersionCacheTime = System.currentTimeMillis() - }.toSingle() - } else { - Single.just(sCachedTagIndexVersion) + // Support direct URL importing + override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable = + urlImportFetchSearchManga(context, query) { + super.fetchSearchManga(page, query, filters) } + + override fun fetchMangaDetails(manga: SManga): Observable { + return client.newCall(mangaDetailsRequest(manga)) + .asObservableSuccess() + .flatMap { + parseToManga(manga, it.asJsoup()).andThen(Observable.just(manga)) + } } - private var cachedGalleryIndexVersion: Long? = null - private var galleryIndexVersionCacheTime: Long = 0 - private fun galleryIndexVersion(): Single { - val sCachedGalleryIndexVersion = cachedGalleryIndexVersion - return if (sCachedGalleryIndexVersion == null || - galleryIndexVersionCacheTime + INDEX_VERSION_CACHE_TIME_MS < System.currentTimeMillis() - ) { - HitomiNozomi.getIndexVersion(client, "galleriesindex").subscribeOn(Schedulers.io()).doOnNext { - cachedGalleryIndexVersion = it - galleryIndexVersionCacheTime = System.currentTimeMillis() - }.toSingle() - } else { - Single.just(sCachedGalleryIndexVersion) - } - } - - /** - * Parse the supplied input into the supplied metadata object - */ override fun parseIntoMetadata(metadata: HitomiSearchMetadata, input: Document) { with(metadata) { url = input.location() @@ -109,41 +58,49 @@ class Hitomi(val context: Context) : HttpSource(), LewdSource { group = content.text() - tags += RaisedTag("group", group!!, TAG_TYPE_VIRTUAL) + tags += RaisedTag("group", group!!, RaisedSearchMetadata.TAG_TYPE_VIRTUAL) } "type" -> { type = content.text() - tags += RaisedTag("type", type!!, TAG_TYPE_VIRTUAL) + tags += RaisedTag("type", type!!, RaisedSearchMetadata.TAG_TYPE_VIRTUAL) } "series" -> { series = content.select("a").map { it.text() } tags += series.map { - RaisedTag("series", it, TAG_TYPE_VIRTUAL) + RaisedTag("series", it, RaisedSearchMetadata.TAG_TYPE_VIRTUAL) } } "language" -> { language = content.selectFirst("a")?.attr("href")?.split('-')?.get(1) language?.let { - tags += RaisedTag("language", it, TAG_TYPE_VIRTUAL) + tags += RaisedTag("language", it, RaisedSearchMetadata.TAG_TYPE_VIRTUAL) } } "characters" -> { characters = content.select("a").map { it.text() } - tags += characters.map { RaisedTag("character", it, TAG_TYPE_DEFAULT) } + tags += characters.map { + RaisedTag( + "character", it, + HitomiSearchMetadata.TAG_TYPE_DEFAULT + ) + } } "tags" -> { tags += content.select("a").map { val ns = if (it.attr("href").startsWith("/tag/male")) "male" else if (it.attr("href").startsWith("/tag/female")) "female" else "misc" - RaisedTag(ns, it.text().dropLast(if (ns == "misc") 0 else 2), TAG_TYPE_DEFAULT) + RaisedTag( + ns, it.text().dropLast(if (ns == "misc") 0 else 2), + HitomiSearchMetadata.TAG_TYPE_DEFAULT + ) } } } @@ -153,273 +110,6 @@ class Hitomi(val context: Context) : HttpSource(), LewdSource { - return urlImportFetchSearchManga(context, query) { - val splitQuery = query.split(" ") - - val positive = splitQuery.filter { !it.startsWith('-') }.toMutableList() - val negative = (splitQuery - positive).map { it.removePrefix("-") } - - // TODO Cache the results coming out of HitomiNozomi - val hn = Single.zip(tagIndexVersion(), galleryIndexVersion()) { tv, gv -> tv to gv } - .map { HitomiNozomi(client, it.first, it.second) } - - var base = if (positive.isEmpty()) { - hn.flatMap { n -> n.getGalleryIdsFromNozomi(null, "index", "all").map { n to it.toSet() } } - } else { - val q = positive.removeAt(0) - hn.flatMap { n -> n.getGalleryIdsForQuery(q).map { n to it.toSet() } } - } - - base = positive.fold(base) { acc, q -> - acc.flatMap { (nozomi, mangas) -> - nozomi.getGalleryIdsForQuery(q).map { - nozomi to mangas.intersect(it) - } - } - } - - base = negative.fold(base) { acc, q -> - acc.flatMap { (nozomi, mangas) -> - nozomi.getGalleryIdsForQuery(q).map { - nozomi to (mangas - it) - } - } - } - - base.flatMap { (_, ids) -> - val chunks = ids.chunked(PAGE_SIZE) - - nozomiIdsToMangas(chunks[page - 1]).map { mangas -> - MangasPage(mangas, page < chunks.size) - } - }.toObservable() - } - } - - /** - * Parses the response from the site and returns a [MangasPage] object. - * - * @param response the response from the site. - */ - override fun searchMangaParse(response: Response) = throw UnsupportedOperationException() - - /** - * Returns the request for latest manga given the page. - * - * @param page the page number to retrieve. - */ - override fun latestUpdatesRequest(page: Int) = HitomiNozomi.rangedGet( - "$LTN_BASE_URL/index-all.nozomi", - 100L * (page - 1), - 99L + 100 * (page - 1) - ) - - /** - * Parses the response from the site and returns a [MangasPage] object. - * - * @param response the response from the site. - */ - override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException() - - override fun fetchPopularManga(page: Int): Observable { - return client.newCall(popularMangaRequest(page)) - .asObservableSuccess() - .flatMap { responseToMangas(it) } - } - - override fun fetchLatestUpdates(page: Int): Observable { - return client.newCall(latestUpdatesRequest(page)) - .asObservableSuccess() - .flatMap { responseToMangas(it) } - } - - fun responseToMangas(response: Response): Observable { - val range = response.header("Content-Range")!! - val total = range.substringAfter('/').toLong() - val end = range.substringBefore('/').substringAfter('-').toLong() - val body = response.body!! - return parseNozomiPage(body.bytes()) - .map { - MangasPage(it, end < total - 1) - } - } - - private fun parseNozomiPage(array: ByteArray): Observable> { - val cursor = ByteCursor(array) - val ids = (1..array.size / 4).map { - cursor.nextInt() - } - - return nozomiIdsToMangas(ids).toObservable() - } - - private fun nozomiIdsToMangas(ids: List): Single> { - return Single.zip( - ids.map { - client.newCall(GET("$LTN_BASE_URL/galleryblock/$it.html")) - .asObservableSuccess() - .subscribeOn(Schedulers.io()) // Perform all these requests in parallel - .map { parseGalleryBlock(it) } - .toSingle() - } - ) { it.map { m -> m as SManga } } - } - - private fun parseGalleryBlock(response: Response): SManga { - val doc = response.asJsoup() - return SManga.create().apply { - val titleElement = doc.selectFirst("h1") - title = titleElement.text() - thumbnail_url = "https:" + if (prefs.eh_hl_useHighQualityThumbs().get()) { - doc.selectFirst("img").attr("srcset").substringBefore(' ') - } else { - doc.selectFirst("img").attr("src") - } - url = titleElement.child(0).attr("href") - - // TODO Parse tags and stuff - } - } - - /** - * Returns an observable with the updated details for a manga. Normally it's not needed to - * override this method. - * - * @param manga the manga to be updated. - */ - override fun fetchMangaDetails(manga: SManga): Observable { - return client.newCall(mangaDetailsRequest(manga)) - .asObservableSuccess() - .flatMap { - parseToManga(manga, it.asJsoup()).andThen( - Observable.just( - manga.apply { - initialized = true - } - ) - ) - } - } - - override fun fetchChapterList(manga: SManga): Observable> { - return Observable.just( - listOf( - SChapter.create().apply { - url = manga.url - name = "Chapter" - chapter_number = 0.0f - } - ) - ) - } - - override fun pageListRequest(chapter: SChapter): Request { - return GET("$LTN_BASE_URL/galleries/${HitomiSearchMetadata.hlIdFromUrl(chapter.url)}.js") - } - - /** - * Parses the response from the site and returns the details of a manga. - * - * @param response the response from the site. - */ - override fun mangaDetailsParse(response: Response) = throw UnsupportedOperationException() - - /** - * Parses the response from the site and returns a list of chapters. - * - * @param response the response from the site. - */ - override fun chapterListParse(response: Response) = throw UnsupportedOperationException() - - /** - * Parses the response from the site and returns a list of pages. - * - * @param response the response from the site. - */ - override fun pageListParse(response: Response): List { - val str = response.body!!.string() - val json = JsonParser.parseString(str.removePrefix("var galleryinfo = ")) - return json["files"].array.mapIndexed { index, jsonElement -> - val hash = jsonElement["hash"].string - val ext = if (jsonElement["haswebp"].string == "0" || !prefs.hitomiAlwaysWebp().get()) jsonElement["name"].string.split('.').last() else "webp" - val path = if (jsonElement["haswebp"].string == "0" || !prefs.hitomiAlwaysWebp().get()) "images" else "webp" - val hashPath1 = hash.takeLast(1) - val hashPath2 = hash.takeLast(3).take(2) - Page( - index, - "", - "https://${subdomainFromGalleryId(hashPath2)}a.hitomi.la/$path/$hashPath1/$hashPath2/$hash.$ext" - ) - } - } - - // https://ltn.hitomi.la/common.js - private fun subdomainFromGalleryId(pathSegment: String): Char { - var numberOfFrontends = 3 - val b = 16 - var g = Integer.parseInt(pathSegment, b) - if (g < 0x30) { - numberOfFrontends = 2 - } - if (g < 0x09) { - g = 1 - } - - return (97 + g.rem(numberOfFrontends)).toChar() - } - - /** - * Parses the response from the site and returns the absolute url to the source image. - * - * @param response the response from the site. - */ - override fun imageUrlParse(response: Response) = throw UnsupportedOperationException() - - override fun imageRequest(page: Page): Request { - val request = super.imageRequest(page) - val hlId = request.url.pathSegments.let { - it[it.lastIndex - 1] - } - return request.newBuilder() - .header("Referer", "$BASE_URL/reader/$hlId.html") - .build() - } - override val matchingHosts = listOf( "hitomi.la" ) @@ -439,9 +129,7 @@ class Hitomi(val context: Context) : HttpSource(), LewdSource= Build.VERSION_CODES.N) { SimpleDateFormat("yyyy-MM-dd HH:mm:ssX", Locale.US) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 18ffc7874..7dd4061a7 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -44,7 +44,6 @@ import eu.kanade.tachiyomi.util.lang.launchUI import exh.EH_SOURCE_ID import exh.EXHMigrations import exh.EXH_SOURCE_ID -import exh.HITOMI_SOURCE_ID import exh.NHENTAI_SOURCE_ID import exh.PERV_EDEN_EN_SOURCE_ID import exh.PERV_EDEN_IT_SOURCE_ID @@ -221,9 +220,6 @@ class MainActivity : BaseActivity() { if (NHENTAI_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) { BlacklistedSources.HIDDEN_SOURCES += NHENTAI_SOURCE_ID } - if (HITOMI_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) { - BlacklistedSources.HIDDEN_SOURCES += HITOMI_SOURCE_ID - } } // SY --> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt index d5cc6c415..08b7ab3be 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt @@ -38,7 +38,6 @@ import eu.kanade.tachiyomi.util.system.powerManager import eu.kanade.tachiyomi.util.system.toast import exh.EH_SOURCE_ID import exh.EXH_SOURCE_ID -import exh.HITOMI_SOURCE_ID import exh.NHENTAI_SOURCE_ID import exh.PERV_EDEN_EN_SOURCE_ID import exh.PERV_EDEN_IT_SOURCE_ID @@ -189,9 +188,6 @@ class SettingsAdvancedController : SettingsController() { if (NHENTAI_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) { BlacklistedSources.HIDDEN_SOURCES += NHENTAI_SOURCE_ID } - if (HITOMI_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) { - BlacklistedSources.HIDDEN_SOURCES += HITOMI_SOURCE_ID - } } else { if (EH_SOURCE_ID in BlacklistedSources.HIDDEN_SOURCES) { BlacklistedSources.HIDDEN_SOURCES -= EH_SOURCE_ID @@ -208,9 +204,6 @@ class SettingsAdvancedController : SettingsController() { if (NHENTAI_SOURCE_ID in BlacklistedSources.HIDDEN_SOURCES) { BlacklistedSources.HIDDEN_SOURCES -= NHENTAI_SOURCE_ID } - if (HITOMI_SOURCE_ID in BlacklistedSources.HIDDEN_SOURCES) { - BlacklistedSources.HIDDEN_SOURCES -= HITOMI_SOURCE_ID - } } true } diff --git a/app/src/main/java/exh/EHSourceHelpers.kt b/app/src/main/java/exh/EHSourceHelpers.kt index d80bbc11f..f41755018 100755 --- a/app/src/main/java/exh/EHSourceHelpers.kt +++ b/app/src/main/java/exh/EHSourceHelpers.kt @@ -2,6 +2,7 @@ package exh import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.source.online.all.Hitomi import eu.kanade.tachiyomi.source.online.english.EightMuses import eu.kanade.tachiyomi.source.online.english.HBrowse import eu.kanade.tachiyomi.source.online.english.HentaiCafe @@ -22,7 +23,7 @@ const val NHENTAI_SOURCE_ID = LEWD_SOURCE_SERIES + 7 val HENTAI_CAFE_SOURCE_ID = delegatedSourceId() val PURURIN_SOURCE_ID = delegatedSourceId() val TSUMINO_SOURCE_ID = delegatedSourceId() -const val HITOMI_SOURCE_ID = LEWD_SOURCE_SERIES + 10 +const val HITOMI_OLD_SOURCE_ID = LEWD_SOURCE_SERIES + 10 val EIGHTMUSES_SOURCE_ID = delegatedSourceId() val HBROWSE_SOURCE_ID = delegatedSourceId() const val MERGED_SOURCE_ID = LEWD_SOURCE_SERIES + 69 @@ -32,18 +33,11 @@ private val DELEGATED_LEWD_SOURCES = listOf( Pururin::class, Tsumino::class, HBrowse::class, - EightMuses::class + EightMuses::class, + Hitomi::class ) -val LIBRARY_UPDATE_EXCLUDED_SOURCES = listOf( - EH_SOURCE_ID, - EXH_SOURCE_ID, - NHENTAI_SOURCE_ID, - HENTAI_CAFE_SOURCE_ID, - TSUMINO_SOURCE_ID, - HITOMI_SOURCE_ID, - PURURIN_SOURCE_ID -) +private val hitomiClass = listOf(Hitomi::class) private inline fun delegatedSourceId(): Long? { return SourceManager.DELEGATED_SOURCES.entries.find { @@ -53,13 +47,27 @@ private inline fun delegatedSourceId(): Long? { // Used to speed up isLewdSource val lewdDelegatedSourceIds = SourceManager.currentDelegatedSources.filter { - !it.value.factory && it.value.newSourceClass in DELEGATED_LEWD_SOURCES + it.value.newSourceClass in DELEGATED_LEWD_SOURCES +}.map { it.value.sourceId }.sorted() + +val hitomiSourceIds = SourceManager.currentDelegatedSources.filter { + it.value.newSourceClass in hitomiClass }.map { it.value.sourceId }.sorted() // This method MUST be fast! fun isLewdSource(source: Long) = source in 6900..6999 || lewdDelegatedSourceIds.binarySearch(source) >= 0 +val LIBRARY_UPDATE_EXCLUDED_SOURCES = listOf( + EH_SOURCE_ID, + EXH_SOURCE_ID, + NHENTAI_SOURCE_ID, + HENTAI_CAFE_SOURCE_ID, + TSUMINO_SOURCE_ID, + PURURIN_SOURCE_ID, + *hitomiSourceIds.toTypedArray() +) + fun Source.isEhBasedSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID -fun Source.isNamespaceSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID || id == NHENTAI_SOURCE_ID || id == HITOMI_SOURCE_ID || id == PURURIN_SOURCE_ID || id == TSUMINO_SOURCE_ID || id == EIGHTMUSES_SOURCE_ID || id == HBROWSE_SOURCE_ID +fun Source.isNamespaceSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID || id == NHENTAI_SOURCE_ID || id in hitomiSourceIds || id == PURURIN_SOURCE_ID || id == TSUMINO_SOURCE_ID || id == EIGHTMUSES_SOURCE_ID || id == HBROWSE_SOURCE_ID diff --git a/app/src/main/java/exh/EXHMigrations.kt b/app/src/main/java/exh/EXHMigrations.kt index 461e0c3a1..c4ddc9102 100644 --- a/app/src/main/java/exh/EXHMigrations.kt +++ b/app/src/main/java/exh/EXHMigrations.kt @@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.updater.UpdaterJob import eu.kanade.tachiyomi.extension.ExtensionUpdateJob +import eu.kanade.tachiyomi.source.online.all.Hitomi import exh.source.BlacklistedSources import java.io.File import java.net.URI @@ -85,6 +86,23 @@ object EXHMigrations { .executeAsBlocking() } } + if (oldVersion < 5) { + db.inTransaction { + // Migrate Tsumino source IDs + db.lowLevel().executeSQL( + RawQuery.builder() + .query( + """ + UPDATE ${MangaTable.TABLE} + SET ${MangaTable.COL_SOURCE} = ${Hitomi.otherId} + WHERE ${MangaTable.COL_SOURCE} = 6910 + """.trimIndent() + ) + .affectsTables(MangaTable.TABLE) + .build() + ) + } + } // if (oldVersion < 1) { } // do stuff here when releasing changed crap diff --git a/app/src/main/java/exh/debug/DebugFunctions.kt b/app/src/main/java/exh/debug/DebugFunctions.kt index f3aa4af72..3bec1c3f7 100644 --- a/app/src/main/java/exh/debug/DebugFunctions.kt +++ b/app/src/main/java/exh/debug/DebugFunctions.kt @@ -41,7 +41,7 @@ object DebugFunctions { val sourceManager: SourceManager by injectLazy() fun forceUpgradeMigration() { - prefs.eh_lastVersionCode().set(0) + prefs.eh_lastVersionCode().set(1) EXHMigrations.upgrade(prefs) } @@ -68,7 +68,7 @@ object DebugFunctions { } private val throttleManager = EHentaiThrottleManager() - fun getDelegatedSourceList(): String = currentDelegatedSources.map { it.value.sourceName }.joinToString(separator = "\n") + fun getDelegatedSourceList(): String = currentDelegatedSources.map { it.value.sourceName + " : " + it.value.sourceId + " : " + it.value.factory }.joinToString(separator = "\n") fun resetEHGalleriesForUpdater() { throttleManager.resetThrottle() diff --git a/app/src/main/java/exh/source/DelegatedHttpSource.kt b/app/src/main/java/exh/source/DelegatedHttpSource.kt index 490fdcd8d..9b7ea856f 100644 --- a/app/src/main/java/exh/source/DelegatedHttpSource.kt +++ b/app/src/main/java/exh/source/DelegatedHttpSource.kt @@ -239,9 +239,7 @@ abstract class DelegatedHttpSource(val delegate: HttpSource) : HttpSource() { override fun getFilterList() = delegate.getFilterList() private fun ensureDelegateCompatible() { - if (versionId != delegate.versionId || - lang != delegate.lang - ) { + if ((versionId != delegate.versionId || lang != delegate.lang) && id != delegate.id) { throw IncompatibleDelegateException("Delegate source is not compatible (versionId: $versionId <=> ${delegate.versionId}, lang: $lang <=> ${delegate.lang})!") } } diff --git a/app/src/main/java/exh/util/SourceTagsUtil.kt b/app/src/main/java/exh/util/SourceTagsUtil.kt index 1d0bba9b3..4bb1ea829 100644 --- a/app/src/main/java/exh/util/SourceTagsUtil.kt +++ b/app/src/main/java/exh/util/SourceTagsUtil.kt @@ -3,20 +3,20 @@ package exh.util import eu.kanade.tachiyomi.data.database.models.Manga import exh.EH_SOURCE_ID import exh.EXH_SOURCE_ID -import exh.HITOMI_SOURCE_ID import exh.NHENTAI_SOURCE_ID import exh.PURURIN_SOURCE_ID import exh.TSUMINO_SOURCE_ID +import exh.hitomiSourceIds import exh.metadata.metadata.base.RaisedTag import java.util.Locale class SourceTagsUtil { fun getWrappedTag(sourceId: Long, namespace: String? = null, tag: String? = null, fullTag: String? = null): String? { - return if (sourceId == EXH_SOURCE_ID || sourceId == EH_SOURCE_ID || sourceId == NHENTAI_SOURCE_ID || sourceId == HITOMI_SOURCE_ID) { + return if (sourceId == EXH_SOURCE_ID || sourceId == EH_SOURCE_ID || sourceId == NHENTAI_SOURCE_ID || sourceId in hitomiSourceIds) { val parsed = if (fullTag != null) parseTag(fullTag) else if (namespace != null && tag != null) RaisedTag(namespace, tag, TAG_TYPE_DEFAULT) else null if (parsed?.namespace != null) { when (sourceId) { - HITOMI_SOURCE_ID -> wrapTagHitomi(parsed.namespace, parsed.name.substringBefore('|').trim()) + in hitomiSourceIds -> wrapTagHitomi(parsed.namespace, parsed.name.substringBefore('|').trim()) NHENTAI_SOURCE_ID -> wrapTagNHentai(parsed.namespace, parsed.name.substringBefore('|').trim()) PURURIN_SOURCE_ID -> parsed.name.substringBefore('|').trim() TSUMINO_SOURCE_ID -> parsed.name.substringBefore('|').trim()