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 {
|
defaultConfig {
|
||||||
applicationId = "app.komikku"
|
applicationId = "app.komikku"
|
||||||
|
|
||||||
versionCode = 71
|
versionCode = 72
|
||||||
versionName = "1.12.2"
|
versionName = "1.13.0"
|
||||||
|
|
||||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||||
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
|
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class SourcePreferences(
|
||||||
|
|
||||||
fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet())
|
fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet())
|
||||||
|
|
||||||
fun pinnedSources() = preferenceStore.getStringSet("pinned_catalogues", emptySet())
|
fun pinnedSources() = preferenceStore.getStringSet(pinnedSourcesPrefKey, emptySet())
|
||||||
|
|
||||||
fun lastUsedSource() = preferenceStore.getLong(
|
fun lastUsedSource() = preferenceStore.getLong(
|
||||||
Preference.appStateKey("last_catalogue_source"),
|
Preference.appStateKey("last_catalogue_source"),
|
||||||
|
|
@ -109,3 +109,5 @@ class SourcePreferences(
|
||||||
fun relatedMangas() = preferenceStore.getBoolean("related_mangas", true)
|
fun relatedMangas() = preferenceStore.getBoolean("related_mangas", true)
|
||||||
// KMK <--
|
// 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.EHentaiSearchMetadata
|
||||||
import exh.metadata.metadata.RaisedSearchMetadata
|
import exh.metadata.metadata.RaisedSearchMetadata
|
||||||
import exh.metadata.metadata.base.RaisedTag
|
import exh.metadata.metadata.base.RaisedTag
|
||||||
import exh.source.EH_SOURCE_ID
|
|
||||||
import exh.source.EXH_SOURCE_ID
|
import exh.source.EXH_SOURCE_ID
|
||||||
|
import exh.source.isEhBasedSource
|
||||||
import exh.util.SourceTagsUtil
|
import exh.util.SourceTagsUtil
|
||||||
import androidx.compose.material3.SuggestionChipDefaults as SuggestionChipDefaultsM3
|
import androidx.compose.material3.SuggestionChipDefaults as SuggestionChipDefaultsM3
|
||||||
|
|
||||||
|
|
@ -64,7 +64,7 @@ value class SearchMetadataChips(
|
||||||
} else {
|
} else {
|
||||||
SourceTagsUtil.getWrappedTag(source.id, fullTag = it.name)
|
SourceTagsUtil.getWrappedTag(source.id, fullTag = it.name)
|
||||||
} ?: it.name,
|
} ?: it.name,
|
||||||
border = if (source.id == EXH_SOURCE_ID || source.id == EH_SOURCE_ID) {
|
border = if (source.isEhBasedSource()) {
|
||||||
when (it.type) {
|
when (it.type) {
|
||||||
EHentaiSearchMetadata.TAG_TYPE_NORMAL -> 2
|
EHentaiSearchMetadata.TAG_TYPE_NORMAL -> 2
|
||||||
EHentaiSearchMetadata.TAG_TYPE_LIGHT -> 1
|
EHentaiSearchMetadata.TAG_TYPE_LIGHT -> 1
|
||||||
|
|
|
||||||
|
|
@ -72,9 +72,6 @@ import eu.kanade.tachiyomi.util.system.toast
|
||||||
import exh.debug.SettingsDebugScreen
|
import exh.debug.SettingsDebugScreen
|
||||||
import exh.log.EHLogLevel
|
import exh.log.EHLogLevel
|
||||||
import exh.pref.DelegateSourcePreferences
|
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 exh.util.toAnnotatedString
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.persistentMapOf
|
import kotlinx.collections.immutable.persistentMapOf
|
||||||
|
|
@ -740,16 +737,17 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||||
title = stringResource(SYMR.strings.toggle_hentai_features),
|
title = stringResource(SYMR.strings.toggle_hentai_features),
|
||||||
subtitle = stringResource(SYMR.strings.toggle_hentai_features_summary),
|
subtitle = stringResource(SYMR.strings.toggle_hentai_features_summary),
|
||||||
onValueChanged = {
|
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
|
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(
|
Preference.PreferenceItem.SwitchPreference(
|
||||||
pref = delegateSourcePreferences.delegateSources(),
|
pref = delegateSourcePreferences.delegateSources(),
|
||||||
title = stringResource(SYMR.strings.toggle_delegated_sources),
|
title = stringResource(SYMR.strings.toggle_delegated_sources),
|
||||||
|
|
@ -770,14 +768,6 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||||
})"
|
})"
|
||||||
}.toMap().toImmutableMap(),
|
}.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 {
|
kotlin.run {
|
||||||
var enableEncryptDatabase by rememberSaveable { mutableStateOf(false) }
|
var enableEncryptDatabase by rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupFeed
|
import eu.kanade.tachiyomi.data.backup.models.BackupFeed
|
||||||
|
import exh.EXHMigrations
|
||||||
import exh.util.nullIfBlank
|
import exh.util.nullIfBlank
|
||||||
import tachiyomi.data.DatabaseHandler
|
import tachiyomi.data.DatabaseHandler
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
|
@ -20,7 +21,11 @@ class FeedRestorer(
|
||||||
saved_searchQueries.selectAll()
|
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
|
// Filter out source's global Popular/Latest feed already existed
|
||||||
backupFeed.savedSearch == null &&
|
backupFeed.savedSearch == null &&
|
||||||
currentFeeds.none { currentFeed ->
|
currentFeeds.none { currentFeed ->
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||||
|
|
||||||
import android.content.Context
|
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.create.BackupCreateJob
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
|
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.backup.models.StringSetPreferenceValue
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
import eu.kanade.tachiyomi.source.sourcePreferences
|
import eu.kanade.tachiyomi.source.sourcePreferences
|
||||||
|
import exh.EXHMigrations
|
||||||
import tachiyomi.core.common.preference.AndroidPreferenceStore
|
import tachiyomi.core.common.preference.AndroidPreferenceStore
|
||||||
import tachiyomi.core.common.preference.PreferenceStore
|
import tachiyomi.core.common.preference.PreferenceStore
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
|
@ -70,7 +72,15 @@ class PreferenceRestorer(
|
||||||
}
|
}
|
||||||
is StringSetPreferenceValue -> {
|
is StringSetPreferenceValue -> {
|
||||||
if (prefs[key] is Set<*>?) {
|
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
|
package eu.kanade.tachiyomi.data.backup.restore.restorers
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
|
||||||
|
import exh.EXHMigrations
|
||||||
import exh.util.nullIfBlank
|
import exh.util.nullIfBlank
|
||||||
import tachiyomi.data.DatabaseHandler
|
import tachiyomi.data.DatabaseHandler
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
|
@ -22,7 +23,11 @@ class SavedSearchRestorer(
|
||||||
// KMK <--
|
// KMK <--
|
||||||
}
|
}
|
||||||
|
|
||||||
backupSavedSearches.filter { backupSavedSearch ->
|
backupSavedSearches.map {
|
||||||
|
// KMK -->
|
||||||
|
EXHMigrations.migrateBackupSavedSearch(it)
|
||||||
|
// KMK <--
|
||||||
|
}.filter { backupSavedSearch ->
|
||||||
currentSavedSearches.none { currentSavedSearch ->
|
currentSavedSearches.none { currentSavedSearch ->
|
||||||
currentSavedSearch.source == backupSavedSearch.source &&
|
currentSavedSearch.source == backupSavedSearch.source &&
|
||||||
currentSavedSearch.name == backupSavedSearch.name &&
|
currentSavedSearch.name == backupSavedSearch.name &&
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ import eu.kanade.tachiyomi.extension.util.ExtensionLoader
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import exh.log.xLogD
|
import exh.log.xLogD
|
||||||
import exh.source.BlacklistedSources
|
import exh.source.BlacklistedSources
|
||||||
import exh.source.EH_SOURCE_ID
|
import exh.source.EHENTAI_EXT_SOURCES
|
||||||
import exh.source.EXH_SOURCE_ID
|
import exh.source.EXHENTAI_EXT_SOURCES
|
||||||
import exh.source.MERGED_SOURCE_ID
|
import exh.source.MERGED_SOURCE_ID
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
|
@ -33,6 +33,7 @@ import kotlinx.coroutines.flow.stateIn
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.common.util.lang.withUIContext
|
import tachiyomi.core.common.util.lang.withUIContext
|
||||||
import tachiyomi.core.common.util.system.logcat
|
import tachiyomi.core.common.util.system.logcat
|
||||||
|
import tachiyomi.domain.UnsortedPreferences
|
||||||
import tachiyomi.domain.source.model.StubSource
|
import tachiyomi.domain.source.model.StubSource
|
||||||
import tachiyomi.i18n.MR
|
import tachiyomi.i18n.MR
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
|
|
@ -116,8 +117,10 @@ class ExtensionManager(
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
return when (sourceId) {
|
return when (sourceId) {
|
||||||
EH_SOURCE_ID -> ContextCompat.getDrawable(context, R.mipmap.ic_ehentai_source)
|
// KMK -->
|
||||||
EXH_SOURCE_ID -> ContextCompat.getDrawable(context, R.mipmap.ic_exhentai_source)
|
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)
|
MERGED_SOURCE_ID -> ContextCompat.getDrawable(context, R.mipmap.ic_merged_source)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
@ -166,8 +169,17 @@ class ExtensionManager(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Extension.isBlacklisted(blacklistEnabled: Boolean = preferences.enableSourceBlacklist().get()): Boolean {
|
private fun Extension.isBlacklisted(
|
||||||
return pkgName in BlacklistedSources.BLACKLISTED_EXTENSIONS && blacklistEnabled
|
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 <--
|
// EXH <--
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ import tachiyomi.core.common.preference.Preference
|
||||||
import tachiyomi.core.common.preference.PreferenceStore
|
import tachiyomi.core.common.preference.PreferenceStore
|
||||||
import tachiyomi.core.common.util.lang.withIOContext
|
import tachiyomi.core.common.util.lang.withIOContext
|
||||||
import tachiyomi.core.common.util.system.logcat
|
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 uy.kohesive.injekt.injectLazy
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
|
|
@ -179,8 +182,15 @@ internal class ExtensionApi {
|
||||||
// SY -->
|
// SY -->
|
||||||
private fun Extension.isBlacklisted(
|
private fun Extension.isBlacklisted(
|
||||||
blacklistEnabled: Boolean = sourcePreferences.enableSourceBlacklist().get(),
|
blacklistEnabled: Boolean = sourcePreferences.enableSourceBlacklist().get(),
|
||||||
|
// KMK -->
|
||||||
|
isHentaiEnabled: Boolean = Injekt.get<UnsortedPreferences>().isHentaiEnabled().get(),
|
||||||
|
// KMK <--
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return pkgName in BlacklistedSources.BLACKLISTED_EXTENSIONS && blacklistEnabled
|
return pkgName in BlacklistedSources.BLACKLISTED_EXTENSIONS &&
|
||||||
|
blacklistEnabled &&
|
||||||
|
// KMK -->
|
||||||
|
isHentaiEnabled
|
||||||
|
// KMK <--
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ import eu.kanade.tachiyomi.source.online.english.Tsumino
|
||||||
import exh.log.xLogD
|
import exh.log.xLogD
|
||||||
import exh.source.BlacklistedSources
|
import exh.source.BlacklistedSources
|
||||||
import exh.source.DelegatedHttpSource
|
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.EIGHTMUSES_SOURCE_ID
|
||||||
import exh.source.EXH_SOURCE_ID
|
import exh.source.EXHENTAI_EXT_SOURCES
|
||||||
import exh.source.EnhancedHttpSource
|
import exh.source.EnhancedHttpSource
|
||||||
import exh.source.HBROWSE_SOURCE_ID
|
import exh.source.HBROWSE_SOURCE_ID
|
||||||
import exh.source.MERGED_SOURCE_ID
|
import exh.source.MERGED_SOURCE_ID
|
||||||
|
|
@ -79,8 +79,13 @@ class AndroidSourceManager(
|
||||||
.combine(preferences.enableExhentai().changes()) { extensions, enableExhentai ->
|
.combine(preferences.enableExhentai().changes()) { extensions, enableExhentai ->
|
||||||
extensions to enableExhentai
|
extensions to enableExhentai
|
||||||
}
|
}
|
||||||
|
// KMK -->
|
||||||
|
.combine(
|
||||||
|
preferences.isHentaiEnabled().changes(),
|
||||||
|
) { (a, b), c -> Triple(a, b, c) }
|
||||||
|
// KMK <--
|
||||||
// SY <--
|
// SY <--
|
||||||
.collectLatest { (extensions, enableExhentai) ->
|
.collectLatest { (extensions, enableExhentai/* KMK --> */, isHentaiEnabled/* KMK <-- */) ->
|
||||||
val mutableMap = ConcurrentHashMap<Long, Source>(
|
val mutableMap = ConcurrentHashMap<Long, Source>(
|
||||||
mapOf(
|
mapOf(
|
||||||
LocalSource.ID to LocalSource(
|
LocalSource.ID to LocalSource(
|
||||||
|
|
@ -93,16 +98,24 @@ class AndroidSourceManager(
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
).apply {
|
).apply {
|
||||||
// SY -->
|
// KMK -->
|
||||||
put(EH_SOURCE_ID, EHentai(EH_SOURCE_ID, false, context))
|
if (isHentaiEnabled) {
|
||||||
if (enableExhentai) {
|
EHENTAI_EXT_SOURCES.forEach { (id, lang) ->
|
||||||
put(EXH_SOURCE_ID, EHentai(EXH_SOURCE_ID, true, context))
|
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())
|
// KMK <--
|
||||||
// SY <--
|
|
||||||
}
|
}
|
||||||
extensions.forEach { extension ->
|
extensions.forEach { extension ->
|
||||||
extension.sources.mapNotNull { it.toInternalSource() }.forEach {
|
extension.sources.mapNotNull { it.toInternalSource(/* KMK --> */isHentaiEnabled/* KMK <-- */) }.forEach {
|
||||||
mutableMap[it.id] = it
|
mutableMap[it.id] = it
|
||||||
registerStubSource(StubSource.from(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 -->
|
// EXH -->
|
||||||
val sourceQName = this::class.qualifiedName
|
val sourceQName = this::class.qualifiedName
|
||||||
val factories = DELEGATED_SOURCES.entries
|
val factories = DELEGATED_SOURCES.entries
|
||||||
|
|
@ -158,7 +175,12 @@ class AndroidSourceManager(
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (id in BlacklistedSources.BLACKLISTED_EXT_SOURCES) {
|
return if (
|
||||||
|
// KMK -->
|
||||||
|
isHentaiEnabled &&
|
||||||
|
// KMK <--
|
||||||
|
id in BlacklistedSources.BLACKLISTED_EXT_SOURCES
|
||||||
|
) {
|
||||||
xLogD(
|
xLogD(
|
||||||
"Removing blacklisted source: (id: %s, name: %s, lang: %s)!",
|
"Removing blacklisted source: (id: %s, name: %s, lang: %s)!",
|
||||||
id,
|
id,
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,13 @@ class EHentai(
|
||||||
override val id: Long,
|
override val id: Long,
|
||||||
val exh: Boolean,
|
val exh: Boolean,
|
||||||
val context: Context,
|
val context: Context,
|
||||||
|
// KMK -->
|
||||||
|
override val lang: String = "all",
|
||||||
|
// KMK <--
|
||||||
) : HttpSource(),
|
) : HttpSource(),
|
||||||
|
// KMK -->
|
||||||
|
EhBasedSource,
|
||||||
|
// KMK <--
|
||||||
MetadataSource<EHentaiSearchMetadata, Document>,
|
MetadataSource<EHentaiSearchMetadata, Document>,
|
||||||
UrlImportableSource,
|
UrlImportableSource,
|
||||||
NamespaceSource,
|
NamespaceSource,
|
||||||
|
|
@ -114,9 +120,19 @@ class EHentai(
|
||||||
override val baseUrl: String
|
override val baseUrl: String
|
||||||
get() = "https://$domain"
|
get() = "https://$domain"
|
||||||
|
|
||||||
override val lang = "all"
|
|
||||||
override val supportsLatest = true
|
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 preferences: UnsortedPreferences by injectLazy()
|
||||||
private val updateHelper: EHentaiUpdateHelper by injectLazy()
|
private val updateHelper: EHentaiUpdateHelper by injectLazy()
|
||||||
|
|
||||||
|
|
@ -273,7 +289,6 @@ class EHentai(
|
||||||
private fun getDateTag(element: Element?): Long? {
|
private fun getDateTag(element: Element?): Long? {
|
||||||
val text = element?.text()?.nullIfBlank()
|
val text = element?.text()?.nullIfBlank()
|
||||||
return if (text != null) {
|
return if (text != null) {
|
||||||
println(text)
|
|
||||||
val date = ZonedDateTime.parse(text, MetadataUtil.EX_DATE_FORMAT.withZone(ZoneOffset.UTC))
|
val date = ZonedDateTime.parse(text, MetadataUtil.EX_DATE_FORMAT.withZone(ZoneOffset.UTC))
|
||||||
date?.toInstant()?.toEpochMilli()
|
date?.toInstant()?.toEpochMilli()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -467,9 +482,18 @@ class EHentai(
|
||||||
return if (it.text() == ">") it.attr("href") else null
|
return if (it.text() == ">") it.attr("href") else null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request {
|
override fun popularMangaRequest(page: Int) =
|
||||||
return exGet("$baseUrl/popular")
|
// 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 {
|
private fun <T : MangasPage> Observable<T>.checkValid(): Observable<MangasPage> = map {
|
||||||
it.checkValid()
|
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 popularMangaParse(response: Response) = genericMangaParse(response)
|
||||||
override fun searchMangaParse(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)
|
// Session-less extended display mode (for users without ExHentai)
|
||||||
cookies["sl"] = "dm_2"
|
cookies["sl"] = "dm_2"
|
||||||
|
|
||||||
// Ignore all content warnings
|
// Ignore all content warnings ("Offensive For Everyone")
|
||||||
cookies["nw"] = "1"
|
cookies["nw"] = "1"
|
||||||
|
|
||||||
return cookies
|
return cookies
|
||||||
|
|
@ -1382,5 +1413,27 @@ class EHentai(
|
||||||
fun buildCookies(cookies: Map<String, String>) = cookies.entries.joinToString(separator = "; ") {
|
fun buildCookies(cookies: Map<String, String>) = cookies.entries.joinToString(separator = "; ") {
|
||||||
"${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}"
|
"${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.RaisedSearchMetadata
|
||||||
import exh.metadata.metadata.base.RaisedTag
|
import exh.metadata.metadata.base.RaisedTag
|
||||||
import exh.source.DelegatedHttpSource
|
import exh.source.DelegatedHttpSource
|
||||||
import exh.source.NHENTAI_SOURCE_ID
|
|
||||||
import exh.util.trimOrNull
|
import exh.util.trimOrNull
|
||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
import exh.util.urlImportFetchSearchMangaSuspend
|
import exh.util.urlImportFetchSearchMangaSuspend
|
||||||
|
|
@ -239,8 +238,6 @@ class NHentai(delegate: HttpSource, val context: Context) :
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val otherId = NHENTAI_SOURCE_ID
|
|
||||||
|
|
||||||
private val jsonParser = Json {
|
private val jsonParser = Json {
|
||||||
ignoreUnknownKeys = true
|
ignoreUnknownKeys = true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -998,31 +998,21 @@ class LibraryScreenModel(
|
||||||
unfiltered.asFlow().cancellable().filter { item ->
|
unfiltered.asFlow().cancellable().filter { item ->
|
||||||
val mangaId = item.libraryManga.manga.id
|
val mangaId = item.libraryManga.manga.id
|
||||||
val sourceId = item.libraryManga.manga.source
|
val sourceId = item.libraryManga.manga.source
|
||||||
if (isMetadataSource(sourceId)) {
|
if (isMetadataSource(sourceId) && mangaWithMetaIds.binarySearch(mangaId) >= 0) {
|
||||||
if (mangaWithMetaIds.binarySearch(mangaId) < 0) {
|
val tags = getSearchTags.await(mangaId)
|
||||||
// No meta? Filter using title
|
val titles = getSearchTitles.await(mangaId)
|
||||||
filterManga(
|
filterManga(
|
||||||
queries = parsedQuery,
|
queries = parsedQuery,
|
||||||
libraryManga = item.libraryManga,
|
libraryManga = item.libraryManga,
|
||||||
tracks = tracks[mangaId],
|
tracks = tracks[mangaId],
|
||||||
source = sources[sourceId],
|
source = sources[sourceId],
|
||||||
loggedInTrackServices = loggedInTrackServices,
|
checkGenre = false,
|
||||||
)
|
searchTags = tags,
|
||||||
} else {
|
searchTitles = titles,
|
||||||
val tags = getSearchTags.await(mangaId)
|
loggedInTrackServices = loggedInTrackServices,
|
||||||
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 {
|
} else {
|
||||||
|
// No meta? Filter using title
|
||||||
filterManga(
|
filterManga(
|
||||||
queries = parsedQuery,
|
queries = parsedQuery,
|
||||||
libraryManga = item.libraryManga,
|
libraryManga = item.libraryManga,
|
||||||
|
|
|
||||||
|
|
@ -94,9 +94,6 @@ import eu.kanade.tachiyomi.util.view.setComposeContent
|
||||||
import exh.debug.DebugToggles
|
import exh.debug.DebugToggles
|
||||||
import exh.eh.EHentaiUpdateWorker
|
import exh.eh.EHentaiUpdateWorker
|
||||||
import exh.log.DebugModeOverlay
|
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.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
|
@ -400,13 +397,6 @@ class MainActivity : BaseActivity() {
|
||||||
chapterCache.clear()
|
chapterCache.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SY -->
|
|
||||||
if (!unsortedPreferences.isHentaiEnabled().get()) {
|
|
||||||
BlacklistedSources.HIDDEN_SOURCES += EH_SOURCE_ID
|
|
||||||
BlacklistedSources.HIDDEN_SOURCES += EXH_SOURCE_ID
|
|
||||||
}
|
|
||||||
// SY -->
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMK -->
|
// KMK -->
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
package exh
|
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.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_OLD_ID
|
||||||
import exh.source.HBROWSE_SOURCE_ID
|
import exh.source.HBROWSE_SOURCE_ID
|
||||||
import exh.source.NHENTAI_OLD_ID
|
import exh.source.NHENTAI_OLD_ID
|
||||||
|
|
@ -42,16 +46,101 @@ object EXHMigrations {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KMK -->
|
||||||
// Allow importing of EHentai extension backups
|
// Allow importing of EHentai extension backups
|
||||||
if (newManga.source in BlacklistedSources.EHENTAI_EXT_SOURCES) {
|
if (newManga.source == EH_OLD_ID) {
|
||||||
newManga = newManga.copy(
|
newManga = newManga.copy(
|
||||||
source = EH_SOURCE_ID,
|
source = EH_SOURCE_ID,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (newManga.source == EXH_OLD_ID) {
|
||||||
|
newManga = newManga.copy(
|
||||||
|
source = EXH_SOURCE_ID,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// KMK <--
|
||||||
|
|
||||||
return newManga
|
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 {
|
private fun getUrlWithoutDomain(orig: String): String {
|
||||||
return try {
|
return try {
|
||||||
val uri = URI(orig)
|
val uri = URI(orig)
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,7 @@
|
||||||
package exh.source
|
package exh.source
|
||||||
|
|
||||||
object BlacklistedSources {
|
object BlacklistedSources {
|
||||||
val EHENTAI_EXT_SOURCES = longArrayOf(
|
val BLACKLISTED_EXT_SOURCES = EHENTAI_EXT_SOURCES.keys
|
||||||
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_EXTENSIONS = arrayOf(
|
val BLACKLISTED_EXTENSIONS = arrayOf(
|
||||||
"eu.kanade.tachiyomi.extension.all.ehentai",
|
"eu.kanade.tachiyomi.extension.all.ehentai",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package mihon.core.migration
|
package mihon.core.migration
|
||||||
|
|
||||||
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import tachiyomi.core.common.preference.PreferenceStore
|
import tachiyomi.core.common.preference.PreferenceStore
|
||||||
|
import tachiyomi.core.common.preference.getAndSet
|
||||||
import tachiyomi.data.DatabaseHandler
|
import tachiyomi.data.DatabaseHandler
|
||||||
|
|
||||||
object MigrateUtils {
|
object MigrateUtils {
|
||||||
|
|
@ -9,7 +11,23 @@ object MigrateUtils {
|
||||||
val handler = migrationContext.get<DatabaseHandler>() ?: return
|
val handler = migrationContext.get<DatabaseHandler>() ?: return
|
||||||
runBlocking {
|
runBlocking {
|
||||||
handler.await { ehQueries.migrateSource(newId, oldId) }
|
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")
|
@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(),
|
OfficialExtensionRepositoryMigration(),
|
||||||
IntegratedHentaiMigration(),
|
IntegratedHentaiMigration(),
|
||||||
SetupAppUpdateMigration(),
|
SetupAppUpdateMigration(),
|
||||||
|
EHentaiMigration(),
|
||||||
// KMK <--
|
// KMK <--
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,18 @@ UPDATE mangas
|
||||||
SET source = :newId
|
SET source = :newId
|
||||||
WHERE source = :oldId;
|
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:
|
getChaptersByMangaIds:
|
||||||
SELECT * FROM chapters WHERE manga_id IN :mangaIds;
|
SELECT * FROM chapters WHERE manga_id IN :mangaIds;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package exh.source
|
package exh.source
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
|
import eu.kanade.tachiyomi.source.online.all.EhBasedSource
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
|
|
||||||
// Used to speed up isLewdSource
|
// Used to speed up isLewdSource
|
||||||
|
|
@ -18,13 +19,21 @@ var LIBRARY_UPDATE_EXCLUDED_SOURCES = listOf(
|
||||||
|
|
||||||
// This method MUST be fast!
|
// This method MUST be fast!
|
||||||
fun isMetadataSource(source: Long) = source in 6900..6999 ||
|
fun isMetadataSource(source: Long) = source in 6900..6999 ||
|
||||||
|
// KMK -->
|
||||||
|
source == EH_SOURCE_ID ||
|
||||||
|
source == EXH_SOURCE_ID ||
|
||||||
|
// KMK <--
|
||||||
metadataDelegatedSourceIds.binarySearch(source) >= 0
|
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 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) {
|
fun Source.getMainSource(): Source = if (this is EnhancedHttpSource) {
|
||||||
this.source()
|
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
|
// Lewd source IDs
|
||||||
const val LEWD_SOURCE_SERIES = 6900L
|
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 NHENTAI_SOURCE_ID = 7309872737163460316L
|
||||||
const val PURURIN_SOURCE_ID = 2221515250486218861L
|
const val PURURIN_SOURCE_ID = 2221515250486218861L
|
||||||
const val TSUMINO_SOURCE_ID = 6707338697138388238L
|
const val TSUMINO_SOURCE_ID = 6707338697138388238L
|
||||||
|
|
@ -11,11 +15,58 @@ const val EIGHTMUSES_SOURCE_ID = 1802675169972965535L
|
||||||
const val HBROWSE_SOURCE_ID = 1401584337232758222L
|
const val HBROWSE_SOURCE_ID = 1401584337232758222L
|
||||||
const val MERGED_SOURCE_ID = LEWD_SOURCE_SERIES + 69
|
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 NHENTAI_OLD_ID = 6907L
|
||||||
const val TSUMINO_OLD_ID = 6909L
|
const val TSUMINO_OLD_ID = 6909L
|
||||||
const val HBROWSE_OLD_ID = 6912L
|
const val HBROWSE_OLD_ID = 6912L
|
||||||
|
|
||||||
// KMK -->
|
// 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(
|
val COMICK_IDS = setOf(
|
||||||
982606170401027267, // all
|
982606170401027267, // all
|
||||||
2971557565147974499, // en
|
2971557565147974499, // en
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue