built-in EH compatible with extension (#613)
* switch off integrated H to show E-H source & extension * More languages for E-H/ExH, also more popular with rate 5 * Don't hide Multi source when toggle Integrated H * Avoid crash trying to load ehentaiBrowseDisplayMode * change source ID to matching general extension * migration old source ID to new source ID * Allow importing of EHentai extension backups * limit library update & metadata source to only Multi lang * update app version * fix spotless * also migrate saved search/feed & pinned EH/EXH source ID when restore from backup or update app
This commit is contained in:
parent
747cd48abc
commit
2e744ed5e9
23 changed files with 386 additions and 116 deletions
|
|
@ -30,8 +30,8 @@ android {
|
|||
defaultConfig {
|
||||
applicationId = "app.komikku"
|
||||
|
||||
versionCode = 71
|
||||
versionName = "1.12.2"
|
||||
versionCode = 72
|
||||
versionName = "1.13.0"
|
||||
|
||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class SourcePreferences(
|
|||
|
||||
fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet())
|
||||
|
||||
fun pinnedSources() = preferenceStore.getStringSet("pinned_catalogues", emptySet())
|
||||
fun pinnedSources() = preferenceStore.getStringSet(pinnedSourcesPrefKey, emptySet())
|
||||
|
||||
fun lastUsedSource() = preferenceStore.getLong(
|
||||
Preference.appStateKey("last_catalogue_source"),
|
||||
|
|
@ -109,3 +109,5 @@ class SourcePreferences(
|
|||
fun relatedMangas() = preferenceStore.getBoolean("related_mangas", true)
|
||||
// KMK <--
|
||||
}
|
||||
|
||||
const val pinnedSourcesPrefKey = "pinned_catalogues"
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ import eu.kanade.tachiyomi.source.online.all.EHentai
|
|||
import exh.metadata.metadata.EHentaiSearchMetadata
|
||||
import exh.metadata.metadata.RaisedSearchMetadata
|
||||
import exh.metadata.metadata.base.RaisedTag
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.EXH_SOURCE_ID
|
||||
import exh.source.isEhBasedSource
|
||||
import exh.util.SourceTagsUtil
|
||||
import androidx.compose.material3.SuggestionChipDefaults as SuggestionChipDefaultsM3
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ value class SearchMetadataChips(
|
|||
} else {
|
||||
SourceTagsUtil.getWrappedTag(source.id, fullTag = it.name)
|
||||
} ?: it.name,
|
||||
border = if (source.id == EXH_SOURCE_ID || source.id == EH_SOURCE_ID) {
|
||||
border = if (source.isEhBasedSource()) {
|
||||
when (it.type) {
|
||||
EHentaiSearchMetadata.TAG_TYPE_NORMAL -> 2
|
||||
EHentaiSearchMetadata.TAG_TYPE_LIGHT -> 1
|
||||
|
|
|
|||
|
|
@ -72,9 +72,6 @@ import eu.kanade.tachiyomi.util.system.toast
|
|||
import exh.debug.SettingsDebugScreen
|
||||
import exh.log.EHLogLevel
|
||||
import exh.pref.DelegateSourcePreferences
|
||||
import exh.source.BlacklistedSources
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.EXH_SOURCE_ID
|
||||
import exh.util.toAnnotatedString
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
|
|
@ -740,16 +737,17 @@ object SettingsAdvancedScreen : SearchableSettings {
|
|||
title = stringResource(SYMR.strings.toggle_hentai_features),
|
||||
subtitle = stringResource(SYMR.strings.toggle_hentai_features_summary),
|
||||
onValueChanged = {
|
||||
if (it) {
|
||||
BlacklistedSources.HIDDEN_SOURCES += EH_SOURCE_ID
|
||||
BlacklistedSources.HIDDEN_SOURCES += EXH_SOURCE_ID
|
||||
} else {
|
||||
BlacklistedSources.HIDDEN_SOURCES -= EH_SOURCE_ID
|
||||
BlacklistedSources.HIDDEN_SOURCES -= EXH_SOURCE_ID
|
||||
}
|
||||
true
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = sourcePreferences.enableSourceBlacklist(),
|
||||
title = stringResource(SYMR.strings.enable_source_blacklist),
|
||||
subtitle = stringResource(
|
||||
SYMR.strings.enable_source_blacklist_summary,
|
||||
stringResource(MR.strings.app_name),
|
||||
),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = delegateSourcePreferences.delegateSources(),
|
||||
title = stringResource(SYMR.strings.toggle_delegated_sources),
|
||||
|
|
@ -770,14 +768,6 @@ object SettingsAdvancedScreen : SearchableSettings {
|
|||
})"
|
||||
}.toMap().toImmutableMap(),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = sourcePreferences.enableSourceBlacklist(),
|
||||
title = stringResource(SYMR.strings.enable_source_blacklist),
|
||||
subtitle = stringResource(
|
||||
SYMR.strings.enable_source_blacklist_summary,
|
||||
stringResource(MR.strings.app_name),
|
||||
),
|
||||
),
|
||||
kotlin.run {
|
||||
var enableEncryptDatabase by rememberSaveable { mutableStateOf(false) }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupFeed
|
||||
import exh.EXHMigrations
|
||||
import exh.util.nullIfBlank
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import uy.kohesive.injekt.Injekt
|
||||
|
|
@ -20,7 +21,11 @@ class FeedRestorer(
|
|||
saved_searchQueries.selectAll()
|
||||
}
|
||||
|
||||
backupFeeds.filter { backupFeed ->
|
||||
backupFeeds.map {
|
||||
// KMK -->
|
||||
EXHMigrations.migrateBackupFeed(it)
|
||||
// KMK <--
|
||||
}.filter { backupFeed ->
|
||||
// Filter out source's global Popular/Latest feed already existed
|
||||
backupFeed.savedSearch == null &&
|
||||
currentFeeds.none { currentFeed ->
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||
|
||||
import android.content.Context
|
||||
import eu.kanade.domain.source.service.pinnedSourcesPrefKey
|
||||
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
||||
|
|
@ -12,6 +13,7 @@ import eu.kanade.tachiyomi.data.backup.models.StringPreferenceValue
|
|||
import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.source.sourcePreferences
|
||||
import exh.EXHMigrations
|
||||
import tachiyomi.core.common.preference.AndroidPreferenceStore
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import uy.kohesive.injekt.Injekt
|
||||
|
|
@ -70,7 +72,15 @@ class PreferenceRestorer(
|
|||
}
|
||||
is StringSetPreferenceValue -> {
|
||||
if (prefs[key] is Set<*>?) {
|
||||
preferenceStore.getStringSet(key).set(value.value)
|
||||
preferenceStore.getStringSet(key).set(
|
||||
// KMK -->
|
||||
if (key == pinnedSourcesPrefKey) {
|
||||
EXHMigrations.migratePinnedSources(value.value)
|
||||
} else {
|
||||
// KMK <--
|
||||
value.value
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
||||
import exh.EXHMigrations
|
||||
import exh.util.nullIfBlank
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
import uy.kohesive.injekt.Injekt
|
||||
|
|
@ -22,7 +23,11 @@ class SavedSearchRestorer(
|
|||
// KMK <--
|
||||
}
|
||||
|
||||
backupSavedSearches.filter { backupSavedSearch ->
|
||||
backupSavedSearches.map {
|
||||
// KMK -->
|
||||
EXHMigrations.migrateBackupSavedSearch(it)
|
||||
// KMK <--
|
||||
}.filter { backupSavedSearch ->
|
||||
currentSavedSearches.none { currentSavedSearch ->
|
||||
currentSavedSearch.source == backupSavedSearch.source &&
|
||||
currentSavedSearch.name == backupSavedSearch.name &&
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ import eu.kanade.tachiyomi.extension.util.ExtensionLoader
|
|||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import exh.log.xLogD
|
||||
import exh.source.BlacklistedSources
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.EXH_SOURCE_ID
|
||||
import exh.source.EHENTAI_EXT_SOURCES
|
||||
import exh.source.EXHENTAI_EXT_SOURCES
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
|
@ -33,6 +33,7 @@ import kotlinx.coroutines.flow.stateIn
|
|||
import logcat.LogPriority
|
||||
import tachiyomi.core.common.util.lang.withUIContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.UnsortedPreferences
|
||||
import tachiyomi.domain.source.model.StubSource
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
|
|
@ -116,8 +117,10 @@ class ExtensionManager(
|
|||
|
||||
// SY -->
|
||||
return when (sourceId) {
|
||||
EH_SOURCE_ID -> ContextCompat.getDrawable(context, R.mipmap.ic_ehentai_source)
|
||||
EXH_SOURCE_ID -> ContextCompat.getDrawable(context, R.mipmap.ic_exhentai_source)
|
||||
// KMK -->
|
||||
in EHENTAI_EXT_SOURCES -> ContextCompat.getDrawable(context, R.mipmap.ic_ehentai_source)
|
||||
in EXHENTAI_EXT_SOURCES -> ContextCompat.getDrawable(context, R.mipmap.ic_exhentai_source)
|
||||
// KMK <--
|
||||
MERGED_SOURCE_ID -> ContextCompat.getDrawable(context, R.mipmap.ic_merged_source)
|
||||
else -> null
|
||||
}
|
||||
|
|
@ -166,8 +169,17 @@ class ExtensionManager(
|
|||
}
|
||||
}
|
||||
|
||||
private fun Extension.isBlacklisted(blacklistEnabled: Boolean = preferences.enableSourceBlacklist().get()): Boolean {
|
||||
return pkgName in BlacklistedSources.BLACKLISTED_EXTENSIONS && blacklistEnabled
|
||||
private fun Extension.isBlacklisted(
|
||||
blacklistEnabled: Boolean = preferences.enableSourceBlacklist().get(),
|
||||
// KMK -->
|
||||
isHentaiEnabled: Boolean = Injekt.get<UnsortedPreferences>().isHentaiEnabled().get(),
|
||||
// KMK <--
|
||||
): Boolean {
|
||||
return pkgName in BlacklistedSources.BLACKLISTED_EXTENSIONS &&
|
||||
blacklistEnabled &&
|
||||
// KMK -->
|
||||
isHentaiEnabled
|
||||
// KMK <--
|
||||
}
|
||||
// EXH <--
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ import tachiyomi.core.common.preference.Preference
|
|||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.UnsortedPreferences
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.time.Instant
|
||||
import kotlin.time.Duration.Companion.days
|
||||
|
|
@ -179,8 +182,15 @@ internal class ExtensionApi {
|
|||
// SY -->
|
||||
private fun Extension.isBlacklisted(
|
||||
blacklistEnabled: Boolean = sourcePreferences.enableSourceBlacklist().get(),
|
||||
// KMK -->
|
||||
isHentaiEnabled: Boolean = Injekt.get<UnsortedPreferences>().isHentaiEnabled().get(),
|
||||
// KMK <--
|
||||
): Boolean {
|
||||
return pkgName in BlacklistedSources.BLACKLISTED_EXTENSIONS && blacklistEnabled
|
||||
return pkgName in BlacklistedSources.BLACKLISTED_EXTENSIONS &&
|
||||
blacklistEnabled &&
|
||||
// KMK -->
|
||||
isHentaiEnabled
|
||||
// KMK <--
|
||||
}
|
||||
// SY <--
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ import eu.kanade.tachiyomi.source.online.english.Tsumino
|
|||
import exh.log.xLogD
|
||||
import exh.source.BlacklistedSources
|
||||
import exh.source.DelegatedHttpSource
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.EHENTAI_EXT_SOURCES
|
||||
import exh.source.EIGHTMUSES_SOURCE_ID
|
||||
import exh.source.EXH_SOURCE_ID
|
||||
import exh.source.EXHENTAI_EXT_SOURCES
|
||||
import exh.source.EnhancedHttpSource
|
||||
import exh.source.HBROWSE_SOURCE_ID
|
||||
import exh.source.MERGED_SOURCE_ID
|
||||
|
|
@ -79,8 +79,13 @@ class AndroidSourceManager(
|
|||
.combine(preferences.enableExhentai().changes()) { extensions, enableExhentai ->
|
||||
extensions to enableExhentai
|
||||
}
|
||||
// KMK -->
|
||||
.combine(
|
||||
preferences.isHentaiEnabled().changes(),
|
||||
) { (a, b), c -> Triple(a, b, c) }
|
||||
// KMK <--
|
||||
// SY <--
|
||||
.collectLatest { (extensions, enableExhentai) ->
|
||||
.collectLatest { (extensions, enableExhentai/* KMK --> */, isHentaiEnabled/* KMK <-- */) ->
|
||||
val mutableMap = ConcurrentHashMap<Long, Source>(
|
||||
mapOf(
|
||||
LocalSource.ID to LocalSource(
|
||||
|
|
@ -93,16 +98,24 @@ class AndroidSourceManager(
|
|||
),
|
||||
),
|
||||
).apply {
|
||||
// SY -->
|
||||
put(EH_SOURCE_ID, EHentai(EH_SOURCE_ID, false, context))
|
||||
if (enableExhentai) {
|
||||
put(EXH_SOURCE_ID, EHentai(EXH_SOURCE_ID, true, context))
|
||||
// KMK -->
|
||||
if (isHentaiEnabled) {
|
||||
EHENTAI_EXT_SOURCES.forEach { (id, lang) ->
|
||||
put(id, EHentai(id, false, context, lang))
|
||||
}
|
||||
if (enableExhentai) {
|
||||
EXHENTAI_EXT_SOURCES.forEach { (id, lang) ->
|
||||
put(id, EHentai(id, true, context, lang))
|
||||
}
|
||||
}
|
||||
// SY -->
|
||||
put(MERGED_SOURCE_ID, MergedSource())
|
||||
// SY <--
|
||||
}
|
||||
put(MERGED_SOURCE_ID, MergedSource())
|
||||
// SY <--
|
||||
// KMK <--
|
||||
}
|
||||
extensions.forEach { extension ->
|
||||
extension.sources.mapNotNull { it.toInternalSource() }.forEach {
|
||||
extension.sources.mapNotNull { it.toInternalSource(/* KMK --> */isHentaiEnabled/* KMK <-- */) }.forEach {
|
||||
mutableMap[it.id] = it
|
||||
registerStubSource(StubSource.from(it))
|
||||
}
|
||||
|
|
@ -123,7 +136,11 @@ class AndroidSourceManager(
|
|||
}
|
||||
}
|
||||
|
||||
private fun Source.toInternalSource(): Source? {
|
||||
private fun Source.toInternalSource(
|
||||
// KMK -->
|
||||
isHentaiEnabled: Boolean,
|
||||
// KMK <--
|
||||
): Source? {
|
||||
// EXH -->
|
||||
val sourceQName = this::class.qualifiedName
|
||||
val factories = DELEGATED_SOURCES.entries
|
||||
|
|
@ -158,7 +175,12 @@ class AndroidSourceManager(
|
|||
this
|
||||
}
|
||||
|
||||
return if (id in BlacklistedSources.BLACKLISTED_EXT_SOURCES) {
|
||||
return if (
|
||||
// KMK -->
|
||||
isHentaiEnabled &&
|
||||
// KMK <--
|
||||
id in BlacklistedSources.BLACKLISTED_EXT_SOURCES
|
||||
) {
|
||||
xLogD(
|
||||
"Removing blacklisted source: (id: %s, name: %s, lang: %s)!",
|
||||
id,
|
||||
|
|
|
|||
|
|
@ -97,7 +97,13 @@ class EHentai(
|
|||
override val id: Long,
|
||||
val exh: Boolean,
|
||||
val context: Context,
|
||||
// KMK -->
|
||||
override val lang: String = "all",
|
||||
// KMK <--
|
||||
) : HttpSource(),
|
||||
// KMK -->
|
||||
EhBasedSource,
|
||||
// KMK <--
|
||||
MetadataSource<EHentaiSearchMetadata, Document>,
|
||||
UrlImportableSource,
|
||||
NamespaceSource,
|
||||
|
|
@ -114,9 +120,19 @@ class EHentai(
|
|||
override val baseUrl: String
|
||||
get() = "https://$domain"
|
||||
|
||||
override val lang = "all"
|
||||
override val supportsLatest = true
|
||||
|
||||
// KMK -->
|
||||
private val ehLang = languageMapping[lang]
|
||||
|
||||
// true if lang is a "natural human language"
|
||||
private fun isLangNatural(): Boolean = lang !in listOf("none", "other", "all")
|
||||
|
||||
private fun languageTag(): String {
|
||||
return "language:$ehLang"
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
private val preferences: UnsortedPreferences by injectLazy()
|
||||
private val updateHelper: EHentaiUpdateHelper by injectLazy()
|
||||
|
||||
|
|
@ -273,7 +289,6 @@ class EHentai(
|
|||
private fun getDateTag(element: Element?): Long? {
|
||||
val text = element?.text()?.nullIfBlank()
|
||||
return if (text != null) {
|
||||
println(text)
|
||||
val date = ZonedDateTime.parse(text, MetadataUtil.EX_DATE_FORMAT.withZone(ZoneOffset.UTC))
|
||||
date?.toInstant()?.toEpochMilli()
|
||||
} else {
|
||||
|
|
@ -467,9 +482,18 @@ class EHentai(
|
|||
return if (it.text() == ">") it.attr("href") else null
|
||||
}
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
return exGet("$baseUrl/popular")
|
||||
}
|
||||
override fun popularMangaRequest(page: Int) =
|
||||
// KMK -->
|
||||
if (isLangNatural()) {
|
||||
exGet("$baseUrl/?f_search=${languageTag()}&f_srdd=5&f_sr=on", page)
|
||||
} else {
|
||||
if (page > 1) {
|
||||
exGet("$baseUrl/?f_srdd=5&f_sr=on", page - 1)
|
||||
} else {
|
||||
// KMK <--
|
||||
exGet("$baseUrl/popular")
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : MangasPage> Observable<T>.checkValid(): Observable<MangasPage> = map {
|
||||
it.checkValid()
|
||||
|
|
@ -565,7 +589,14 @@ class EHentai(
|
|||
)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int) = exGet(baseUrl, page)
|
||||
override fun latestUpdatesRequest(page: Int) =
|
||||
// KMK -->
|
||||
if (isLangNatural()) {
|
||||
exGet("$baseUrl/?f_search=${languageTag()}", page)
|
||||
} else {
|
||||
// KMK <--
|
||||
exGet(baseUrl, page)
|
||||
}
|
||||
|
||||
override fun popularMangaParse(response: Response) = genericMangaParse(response)
|
||||
override fun searchMangaParse(response: Response) = genericMangaParse(response)
|
||||
|
|
@ -911,7 +942,7 @@ class EHentai(
|
|||
// Session-less extended display mode (for users without ExHentai)
|
||||
cookies["sl"] = "dm_2"
|
||||
|
||||
// Ignore all content warnings
|
||||
// Ignore all content warnings ("Offensive For Everyone")
|
||||
cookies["nw"] = "1"
|
||||
|
||||
return cookies
|
||||
|
|
@ -1382,5 +1413,27 @@ class EHentai(
|
|||
fun buildCookies(cookies: Map<String, String>) = cookies.entries.joinToString(separator = "; ") {
|
||||
"${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}"
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
val languageMapping = mapOf(
|
||||
"ja" to "japanese",
|
||||
"en" to "english",
|
||||
"zh" to "chinese",
|
||||
"nl" to "dutch",
|
||||
"fr" to "french",
|
||||
"de" to "german",
|
||||
"hu" to "hungarian",
|
||||
"it" to "italian",
|
||||
"ko" to "korean",
|
||||
"pl" to "polish",
|
||||
"pt-BR" to "portuguese",
|
||||
"ru" to "russian",
|
||||
"es" to "spanish",
|
||||
"th" to "thai",
|
||||
"vi" to "vietnamese",
|
||||
"none" to "n/a",
|
||||
"other" to "other",
|
||||
)
|
||||
// KMK <--
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import exh.metadata.metadata.NHentaiSearchMetadata
|
|||
import exh.metadata.metadata.RaisedSearchMetadata
|
||||
import exh.metadata.metadata.base.RaisedTag
|
||||
import exh.source.DelegatedHttpSource
|
||||
import exh.source.NHENTAI_SOURCE_ID
|
||||
import exh.util.trimOrNull
|
||||
import exh.util.urlImportFetchSearchManga
|
||||
import exh.util.urlImportFetchSearchMangaSuspend
|
||||
|
|
@ -239,8 +238,6 @@ class NHentai(delegate: HttpSource, val context: Context) :
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val otherId = NHENTAI_SOURCE_ID
|
||||
|
||||
private val jsonParser = Json {
|
||||
ignoreUnknownKeys = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -998,31 +998,21 @@ class LibraryScreenModel(
|
|||
unfiltered.asFlow().cancellable().filter { item ->
|
||||
val mangaId = item.libraryManga.manga.id
|
||||
val sourceId = item.libraryManga.manga.source
|
||||
if (isMetadataSource(sourceId)) {
|
||||
if (mangaWithMetaIds.binarySearch(mangaId) < 0) {
|
||||
// No meta? Filter using title
|
||||
filterManga(
|
||||
queries = parsedQuery,
|
||||
libraryManga = item.libraryManga,
|
||||
tracks = tracks[mangaId],
|
||||
source = sources[sourceId],
|
||||
loggedInTrackServices = loggedInTrackServices,
|
||||
)
|
||||
} else {
|
||||
val tags = getSearchTags.await(mangaId)
|
||||
val titles = getSearchTitles.await(mangaId)
|
||||
filterManga(
|
||||
queries = parsedQuery,
|
||||
libraryManga = item.libraryManga,
|
||||
tracks = tracks[mangaId],
|
||||
source = sources[sourceId],
|
||||
checkGenre = false,
|
||||
searchTags = tags,
|
||||
searchTitles = titles,
|
||||
loggedInTrackServices = loggedInTrackServices,
|
||||
)
|
||||
}
|
||||
if (isMetadataSource(sourceId) && mangaWithMetaIds.binarySearch(mangaId) >= 0) {
|
||||
val tags = getSearchTags.await(mangaId)
|
||||
val titles = getSearchTitles.await(mangaId)
|
||||
filterManga(
|
||||
queries = parsedQuery,
|
||||
libraryManga = item.libraryManga,
|
||||
tracks = tracks[mangaId],
|
||||
source = sources[sourceId],
|
||||
checkGenre = false,
|
||||
searchTags = tags,
|
||||
searchTitles = titles,
|
||||
loggedInTrackServices = loggedInTrackServices,
|
||||
)
|
||||
} else {
|
||||
// No meta? Filter using title
|
||||
filterManga(
|
||||
queries = parsedQuery,
|
||||
libraryManga = item.libraryManga,
|
||||
|
|
|
|||
|
|
@ -94,9 +94,6 @@ import eu.kanade.tachiyomi.util.view.setComposeContent
|
|||
import exh.debug.DebugToggles
|
||||
import exh.eh.EHentaiUpdateWorker
|
||||
import exh.log.DebugModeOverlay
|
||||
import exh.source.BlacklistedSources
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.EXH_SOURCE_ID
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
|
|
@ -400,13 +397,6 @@ class MainActivity : BaseActivity() {
|
|||
chapterCache.clear()
|
||||
}
|
||||
}
|
||||
|
||||
// SY -->
|
||||
if (!unsortedPreferences.isHentaiEnabled().get()) {
|
||||
BlacklistedSources.HIDDEN_SOURCES += EH_SOURCE_ID
|
||||
BlacklistedSources.HIDDEN_SOURCES += EXH_SOURCE_ID
|
||||
}
|
||||
// SY -->
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
package exh
|
||||
|
||||
import exh.source.BlacklistedSources
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupFeed
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
||||
import exh.source.EH_OLD_ID
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.EXH_OLD_ID
|
||||
import exh.source.EXH_SOURCE_ID
|
||||
import exh.source.HBROWSE_OLD_ID
|
||||
import exh.source.HBROWSE_SOURCE_ID
|
||||
import exh.source.NHENTAI_OLD_ID
|
||||
|
|
@ -42,16 +46,101 @@ object EXHMigrations {
|
|||
)
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
// Allow importing of EHentai extension backups
|
||||
if (newManga.source in BlacklistedSources.EHENTAI_EXT_SOURCES) {
|
||||
if (newManga.source == EH_OLD_ID) {
|
||||
newManga = newManga.copy(
|
||||
source = EH_SOURCE_ID,
|
||||
)
|
||||
}
|
||||
if (newManga.source == EXH_OLD_ID) {
|
||||
newManga = newManga.copy(
|
||||
source = EXH_SOURCE_ID,
|
||||
)
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
return newManga
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
/**
|
||||
* Migrate old source ID of delegated sources in old backup
|
||||
*/
|
||||
fun migrateBackupSavedSearch(savedSearch: BackupSavedSearch): BackupSavedSearch {
|
||||
return when (savedSearch.source) {
|
||||
NHENTAI_OLD_ID -> savedSearch.copy(
|
||||
source = NHENTAI_SOURCE_ID,
|
||||
)
|
||||
TSUMINO_OLD_ID -> savedSearch.copy(
|
||||
source = TSUMINO_SOURCE_ID,
|
||||
)
|
||||
HBROWSE_OLD_ID -> savedSearch.copy(
|
||||
source = HBROWSE_SOURCE_ID,
|
||||
)
|
||||
EH_OLD_ID -> savedSearch.copy(
|
||||
source = EH_SOURCE_ID,
|
||||
)
|
||||
EXH_OLD_ID -> savedSearch.copy(
|
||||
source = EXH_SOURCE_ID,
|
||||
)
|
||||
else -> savedSearch
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate old source ID of delegated sources in old backup
|
||||
*/
|
||||
fun migrateBackupFeed(feed: BackupFeed): BackupFeed {
|
||||
return when (feed.source) {
|
||||
NHENTAI_OLD_ID -> feed.copy(
|
||||
source = NHENTAI_SOURCE_ID,
|
||||
)
|
||||
TSUMINO_OLD_ID -> feed.copy(
|
||||
source = TSUMINO_SOURCE_ID,
|
||||
)
|
||||
HBROWSE_OLD_ID -> feed.copy(
|
||||
source = HBROWSE_SOURCE_ID,
|
||||
)
|
||||
EH_OLD_ID -> feed.copy(
|
||||
source = EH_SOURCE_ID,
|
||||
)
|
||||
EXH_OLD_ID -> feed.copy(
|
||||
source = EXH_SOURCE_ID,
|
||||
)
|
||||
else -> feed
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate old source ID of delegated sources in old backup
|
||||
*/
|
||||
fun migratePinnedSources(pinnedSources: Set<String>): Set<String> {
|
||||
var pinned = pinnedSources
|
||||
if (NHENTAI_OLD_ID.toString() in pinned) {
|
||||
pinned = pinned.minus(NHENTAI_OLD_ID.toString())
|
||||
.plus(NHENTAI_SOURCE_ID.toString())
|
||||
}
|
||||
if (TSUMINO_OLD_ID.toString() in pinned) {
|
||||
pinned = pinned.minus(TSUMINO_OLD_ID.toString())
|
||||
.plus(TSUMINO_SOURCE_ID.toString())
|
||||
}
|
||||
if (HBROWSE_OLD_ID.toString() in pinned) {
|
||||
pinned = pinned.minus(HBROWSE_OLD_ID.toString())
|
||||
.plus(HBROWSE_SOURCE_ID.toString())
|
||||
}
|
||||
if (EH_OLD_ID.toString() in pinned) {
|
||||
pinned = pinned.minus(EH_OLD_ID.toString())
|
||||
.plus(EH_SOURCE_ID.toString())
|
||||
}
|
||||
if (EXH_OLD_ID.toString() in pinned) {
|
||||
pinned = pinned.minus(EXH_OLD_ID.toString())
|
||||
.plus(EXH_SOURCE_ID.toString())
|
||||
}
|
||||
return pinned
|
||||
}
|
||||
// KMK -->
|
||||
|
||||
private fun getUrlWithoutDomain(orig: String): String {
|
||||
return try {
|
||||
val uri = URI(orig)
|
||||
|
|
|
|||
|
|
@ -1,27 +1,7 @@
|
|||
package exh.source
|
||||
|
||||
object BlacklistedSources {
|
||||
val EHENTAI_EXT_SOURCES = longArrayOf(
|
||||
8100626124886895451,
|
||||
57122881048805941,
|
||||
4678440076103929247,
|
||||
1876021963378735852,
|
||||
3955189842350477641,
|
||||
4348288691341764259,
|
||||
773611868725221145,
|
||||
5759417018342755550,
|
||||
825187715438990384,
|
||||
6116711405602166104,
|
||||
7151438547982231541,
|
||||
2171445159732592630,
|
||||
3032959619549451093,
|
||||
5980349886941016589,
|
||||
6073266008352078708,
|
||||
5499077866612745456,
|
||||
6140480779421365791,
|
||||
)
|
||||
|
||||
val BLACKLISTED_EXT_SOURCES = EHENTAI_EXT_SOURCES
|
||||
val BLACKLISTED_EXT_SOURCES = EHENTAI_EXT_SOURCES.keys
|
||||
|
||||
val BLACKLISTED_EXTENSIONS = arrayOf(
|
||||
"eu.kanade.tachiyomi.extension.all.ehentai",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package mihon.core.migration
|
||||
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
|
||||
object MigrateUtils {
|
||||
|
|
@ -9,7 +11,23 @@ object MigrateUtils {
|
|||
val handler = migrationContext.get<DatabaseHandler>() ?: return
|
||||
runBlocking {
|
||||
handler.await { ehQueries.migrateSource(newId, oldId) }
|
||||
|
||||
// KMK -->
|
||||
// Migrate saved searches & feeds
|
||||
handler.await { ehQueries.migrateSourceSavedSearch(newId, oldId) }
|
||||
handler.await { ehQueries.migrateSourceFeed(newId, oldId) }
|
||||
}
|
||||
|
||||
// Also update pin
|
||||
val preferences = migrationContext.get<SourcePreferences>() ?: return
|
||||
val isPinned = oldId.toString() in preferences.pinnedSources().get()
|
||||
if (isPinned) {
|
||||
preferences.pinnedSources().getAndSet { pinned ->
|
||||
pinned.minus(oldId.toString())
|
||||
.plus(newId.toString())
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package mihon.core.migration.migrations
|
||||
|
||||
import exh.source.EH_OLD_ID
|
||||
import exh.source.EH_SOURCE_ID
|
||||
import exh.source.EXH_OLD_ID
|
||||
import exh.source.EXH_SOURCE_ID
|
||||
import mihon.core.migration.MigrateUtils
|
||||
import mihon.core.migration.Migration
|
||||
import mihon.core.migration.MigrationContext
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
|
||||
class EHentaiMigration : Migration {
|
||||
override val version: Float = 72f
|
||||
|
||||
override suspend fun invoke(migrationContext: MigrationContext): Boolean = withIOContext {
|
||||
MigrateUtils.updateSourceId(migrationContext, EH_SOURCE_ID, EH_OLD_ID)
|
||||
MigrateUtils.updateSourceId(migrationContext, EXH_SOURCE_ID, EXH_OLD_ID)
|
||||
|
||||
return@withIOContext true
|
||||
}
|
||||
}
|
||||
|
|
@ -49,5 +49,6 @@ val migrations: List<Migration>
|
|||
OfficialExtensionRepositoryMigration(),
|
||||
IntegratedHentaiMigration(),
|
||||
SetupAppUpdateMigration(),
|
||||
EHentaiMigration(),
|
||||
// KMK <--
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,18 @@ UPDATE mangas
|
|||
SET source = :newId
|
||||
WHERE source = :oldId;
|
||||
|
||||
-- KMK -->
|
||||
migrateSourceSavedSearch:
|
||||
UPDATE saved_search
|
||||
SET source = :newId
|
||||
WHERE source = :oldId;
|
||||
|
||||
migrateSourceFeed:
|
||||
UPDATE feed_saved_search
|
||||
SET source = :newId
|
||||
WHERE source = :oldId;
|
||||
-- KMK <--
|
||||
|
||||
getChaptersByMangaIds:
|
||||
SELECT * FROM chapters WHERE manga_id IN :mangaIds;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package exh.source
|
||||
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.online.all.EhBasedSource
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
|
||||
// Used to speed up isLewdSource
|
||||
|
|
@ -18,13 +19,21 @@ var LIBRARY_UPDATE_EXCLUDED_SOURCES = listOf(
|
|||
|
||||
// This method MUST be fast!
|
||||
fun isMetadataSource(source: Long) = source in 6900..6999 ||
|
||||
// KMK -->
|
||||
source == EH_SOURCE_ID ||
|
||||
source == EXH_SOURCE_ID ||
|
||||
// KMK <--
|
||||
metadataDelegatedSourceIds.binarySearch(source) >= 0
|
||||
|
||||
fun Source.isEhBasedSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID
|
||||
// KMK -->
|
||||
fun Source.isEhBasedSource() = this is EhBasedSource && id in EHENTAI_EXT_SOURCES || id in EXHENTAI_EXT_SOURCES
|
||||
// KMK <--
|
||||
|
||||
fun Source.isMdBasedSource() = id in mangaDexSourceIds
|
||||
|
||||
fun Manga.isEhBasedManga() = source == EH_SOURCE_ID || source == EXH_SOURCE_ID
|
||||
// KMK -->
|
||||
fun Manga.isEhBasedManga() = source in EHENTAI_EXT_SOURCES || source in EXHENTAI_EXT_SOURCES
|
||||
// KMK <--
|
||||
|
||||
fun Source.getMainSource(): Source = if (this is EnhancedHttpSource) {
|
||||
this.source()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
package eu.kanade.tachiyomi.source.online.all
|
||||
|
||||
interface EhBasedSource
|
||||
|
|
@ -2,8 +2,12 @@ package exh.source
|
|||
|
||||
// Lewd source IDs
|
||||
const val LEWD_SOURCE_SERIES = 6900L
|
||||
const val EH_SOURCE_ID = LEWD_SOURCE_SERIES + 1
|
||||
const val EXH_SOURCE_ID = LEWD_SOURCE_SERIES + 2
|
||||
|
||||
// KMK -->
|
||||
const val EH_SOURCE_ID = 1713178126840476467 // LEWD_SOURCE_SERIES + 1
|
||||
const val EXH_SOURCE_ID = 6225928719850211219 // LEWD_SOURCE_SERIES + 2
|
||||
// KMK <--
|
||||
|
||||
const val NHENTAI_SOURCE_ID = 7309872737163460316L
|
||||
const val PURURIN_SOURCE_ID = 2221515250486218861L
|
||||
const val TSUMINO_SOURCE_ID = 6707338697138388238L
|
||||
|
|
@ -11,11 +15,58 @@ const val EIGHTMUSES_SOURCE_ID = 1802675169972965535L
|
|||
const val HBROWSE_SOURCE_ID = 1401584337232758222L
|
||||
const val MERGED_SOURCE_ID = LEWD_SOURCE_SERIES + 69
|
||||
|
||||
// KMK -->
|
||||
const val EH_OLD_ID = 6901L
|
||||
const val EXH_OLD_ID = 6902L
|
||||
// KMK <--
|
||||
|
||||
const val NHENTAI_OLD_ID = 6907L
|
||||
const val TSUMINO_OLD_ID = 6909L
|
||||
const val HBROWSE_OLD_ID = 6912L
|
||||
|
||||
// KMK -->
|
||||
val EHENTAI_EXT_SOURCES = mapOf(
|
||||
8100626124886895451 to "ja", // E-Hentai (Ja)
|
||||
57122881048805941 to "en", // E-Hentai (En)
|
||||
4678440076103929247 to "zh", // E-Hentai (Zh)
|
||||
1876021963378735852 to "nl", // E-Hentai (Nl)
|
||||
3955189842350477641 to "fr", // E-Hentai (Fr)
|
||||
4348288691341764259 to "de", // E-Hentai (De)
|
||||
773611868725221145 to "hu", // E-Hentai (Hu)
|
||||
5759417018342755550 to "it", // E-Hentai (It)
|
||||
825187715438990384 to "ko", // E-Hentai (Ko)
|
||||
6116711405602166104 to "pl", // E-Hentai (Pl)
|
||||
7151438547982231541 to "pt-BR", // E-Hentai (PtBr)
|
||||
2171445159732592630 to "ru", // E-Hentai (Ru)
|
||||
3032959619549451093 to "es", // E-Hentai (Es)
|
||||
5980349886941016589 to "th", // E-Hentai (Th)
|
||||
6073266008352078708 to "vi", // E-Hentai (Vi)
|
||||
5499077866612745456 to "none", // E-Hentai (None)
|
||||
6140480779421365791 to "other", // E-Hentai (Other)
|
||||
EH_SOURCE_ID to "all", // E-Hentai (Multi)
|
||||
)
|
||||
|
||||
val EXHENTAI_EXT_SOURCES = mapOf(
|
||||
4069364610143267166 to "ja", // E-Hentai (Ja)
|
||||
6024400692103629868 to "en", // E-Hentai (En)
|
||||
1394807835077780591 to "zh", // E-Hentai (Zh)
|
||||
3403092744483051659 to "nl", // E-Hentai (Nl)
|
||||
2063958147920418330 to "fr", // E-Hentai (Fr)
|
||||
4277540540471304114 to "de", // E-Hentai (De)
|
||||
5580677059017993793 to "hu", // E-Hentai (Hu)
|
||||
6348816521182710144 to "it", // E-Hentai (It)
|
||||
933801322201782118 to "ko", // E-Hentai (Ko)
|
||||
250678340923599076 to "pl", // E-Hentai (Pl)
|
||||
7151438547982231541 to "pt-BR", // E-Hentai (PtBr)
|
||||
2298110591802103872 to "ru", // E-Hentai (Ru)
|
||||
1471697890032830855 to "es", // E-Hentai (Es)
|
||||
5297549186919793998 to "th", // E-Hentai (Th)
|
||||
1904260310237764859 to "vi", // E-Hentai (Vi)
|
||||
2351087900641384311 to "none", // E-Hentai (None)
|
||||
609703168489499116 to "other", // E-Hentai (Other)
|
||||
EXH_SOURCE_ID to "all", // E-Hentai (Multi)
|
||||
)
|
||||
|
||||
val COMICK_IDS = setOf(
|
||||
982606170401027267, // all
|
||||
2971557565147974499, // en
|
||||
|
|
|
|||
Loading…
Reference in a new issue