Delegate NHentai, to continue using NHentai download the extension, SY requires NHentai version 1.2.28
This commit is contained in:
parent
5a1bc6e25b
commit
3fa5322133
@ -187,8 +187,6 @@ object PreferenceKeys {
|
|||||||
|
|
||||||
const val eh_lock_manually = "eh_lock_manually"
|
const val eh_lock_manually = "eh_lock_manually"
|
||||||
|
|
||||||
const val eh_nh_useHighQualityThumbs = "eh_nh_hq_thumbs"
|
|
||||||
|
|
||||||
const val eh_showSyncIntro = "eh_show_sync_intro"
|
const val eh_showSyncIntro = "eh_show_sync_intro"
|
||||||
|
|
||||||
const val eh_readOnlySync = "eh_sync_read_only"
|
const val eh_readOnlySync = "eh_sync_read_only"
|
||||||
|
@ -312,8 +312,6 @@ class PreferencesHelper(val context: Context) {
|
|||||||
fun eh_sessionCookie() = flowPrefs.getString(Keys.eh_sessionCookie, "")
|
fun eh_sessionCookie() = flowPrefs.getString(Keys.eh_sessionCookie, "")
|
||||||
fun eh_hathPerksCookies() = flowPrefs.getString(Keys.eh_hathPerksCookie, "")
|
fun eh_hathPerksCookies() = flowPrefs.getString(Keys.eh_hathPerksCookie, "")
|
||||||
|
|
||||||
fun eh_nh_useHighQualityThumbs() = flowPrefs.getBoolean(Keys.eh_nh_useHighQualityThumbs, false)
|
|
||||||
|
|
||||||
fun eh_showSyncIntro() = flowPrefs.getBoolean(Keys.eh_showSyncIntro, true)
|
fun eh_showSyncIntro() = flowPrefs.getBoolean(Keys.eh_showSyncIntro, true)
|
||||||
|
|
||||||
fun eh_readOnlySync() = flowPrefs.getBoolean(Keys.eh_readOnlySync, false)
|
fun eh_readOnlySync() = flowPrefs.getBoolean(Keys.eh_readOnlySync, false)
|
||||||
|
@ -21,7 +21,6 @@ import eu.kanade.tachiyomi.util.system.toast
|
|||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.MERGED_SOURCE_ID
|
import exh.MERGED_SOURCE_ID
|
||||||
import exh.NHENTAI_SOURCE_ID
|
|
||||||
import exh.source.BlacklistedSources
|
import exh.source.BlacklistedSources
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
@ -79,7 +78,6 @@ class ExtensionManager(
|
|||||||
return when (source.id) {
|
return when (source.id) {
|
||||||
EH_SOURCE_ID -> context.getDrawable(R.mipmap.ic_ehentai_source)
|
EH_SOURCE_ID -> context.getDrawable(R.mipmap.ic_ehentai_source)
|
||||||
EXH_SOURCE_ID -> context.getDrawable(R.mipmap.ic_ehentai_source)
|
EXH_SOURCE_ID -> context.getDrawable(R.mipmap.ic_ehentai_source)
|
||||||
NHENTAI_SOURCE_ID -> context.getDrawable(R.mipmap.ic_nhentai_source)
|
|
||||||
MERGED_SOURCE_ID -> context.getDrawable(R.mipmap.ic_merged_source)
|
MERGED_SOURCE_ID -> context.getDrawable(R.mipmap.ic_merged_source)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,6 @@ open class SourceManager(private val context: Context) {
|
|||||||
if (prefs.enableExhentai().get()) {
|
if (prefs.enableExhentai().get()) {
|
||||||
exSrcs += EHentai(EXH_SOURCE_ID, true, context)
|
exSrcs += EHentai(EXH_SOURCE_ID, true, context)
|
||||||
}
|
}
|
||||||
exSrcs += NHentai(context)
|
|
||||||
return exSrcs
|
return exSrcs
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
@ -230,6 +229,13 @@ open class SourceManager(private val context: Context) {
|
|||||||
PERV_EDEN_IT_SOURCE_ID,
|
PERV_EDEN_IT_SOURCE_ID,
|
||||||
"eu.kanade.tachiyomi.extension.it.perveden.Perveden",
|
"eu.kanade.tachiyomi.extension.it.perveden.Perveden",
|
||||||
PervEden::class
|
PervEden::class
|
||||||
|
),
|
||||||
|
DelegatedSource(
|
||||||
|
"NHentai",
|
||||||
|
fillInSourceId,
|
||||||
|
"eu.kanade.tachiyomi.extension.all.nhentai.NHentai",
|
||||||
|
NHentai::class,
|
||||||
|
true
|
||||||
)
|
)
|
||||||
).associateBy { it.originalSourceQualifiedClassName }
|
).associateBy { it.originalSourceQualifiedClassName }
|
||||||
|
|
||||||
|
301
app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt
Executable file → Normal file
301
app/src/main/java/eu/kanade/tachiyomi/source/online/all/NHentai.kt
Executable file → Normal file
@ -8,116 +8,38 @@ import com.github.salomonbrys.kotson.nullLong
|
|||||||
import com.github.salomonbrys.kotson.nullObj
|
import com.github.salomonbrys.kotson.nullObj
|
||||||
import com.github.salomonbrys.kotson.nullString
|
import com.github.salomonbrys.kotson.nullString
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
|
||||||
import eu.kanade.tachiyomi.R
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
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.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
|
||||||
import exh.NHENTAI_SOURCE_ID
|
|
||||||
import exh.metadata.metadata.NHentaiSearchMetadata
|
import exh.metadata.metadata.NHentaiSearchMetadata
|
||||||
import exh.metadata.metadata.NHentaiSearchMetadata.Companion.TAG_TYPE_DEFAULT
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata.Companion.TAG_TYPE_VIRTUAL
|
|
||||||
import exh.metadata.metadata.base.RaisedTag
|
import exh.metadata.metadata.base.RaisedTag
|
||||||
|
import exh.source.DelegatedHttpSource
|
||||||
import exh.ui.metadata.adapters.NHentaiDescriptionAdapter
|
import exh.ui.metadata.adapters.NHentaiDescriptionAdapter
|
||||||
import exh.util.urlImportFetchSearchManga
|
import exh.util.urlImportFetchSearchManga
|
||||||
import okhttp3.HttpUrl
|
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
|
||||||
import okhttp3.Request
|
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
|
||||||
/**
|
open class NHentai(delegate: HttpSource, val context: Context) :
|
||||||
* NHentai source
|
DelegatedHttpSource(delegate),
|
||||||
*/
|
LewdSource<NHentaiSearchMetadata, Response>,
|
||||||
|
UrlImportableSource {
|
||||||
class NHentai(val context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata, Response>, UrlImportableSource {
|
|
||||||
override val metaClass = NHentaiSearchMetadata::class
|
override val metaClass = NHentaiSearchMetadata::class
|
||||||
|
override val lang = if (delegate.lang == "other") "all" else delegate.lang
|
||||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
override val id: Long
|
||||||
// TODO There is currently no way to get the most popular mangas
|
get() = if (delegate.lang == "other") otherId else delegate.id
|
||||||
// TODO Instead, we delegate this to the latest updates thing to avoid confusing users with an empty screen
|
|
||||||
return fetchLatestUpdates(page)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response) = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
// Support direct URL importing
|
// Support direct URL importing
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
|
||||||
val trimmedIdQuery = query.trim().removePrefix("id:")
|
urlImportFetchSearchManga(context, query) {
|
||||||
val newQuery = if (trimmedIdQuery.toIntOrNull() ?: -1 >= 0) {
|
super.fetchSearchManga(page, query, filters)
|
||||||
"$baseUrl/g/$trimmedIdQuery/"
|
|
||||||
} else query
|
|
||||||
|
|
||||||
return urlImportFetchSearchManga(context, newQuery) {
|
|
||||||
searchMangaRequestObservable(page, query, filters).flatMap {
|
|
||||||
client.newCall(it).asObservableSuccess()
|
|
||||||
}.map { response ->
|
|
||||||
searchMangaParse(response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun searchMangaRequestObservable(page: Int, query: String, filters: FilterList): Observable<Request> {
|
|
||||||
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
|
||||||
val advQuery = combineQuery(filterList)
|
|
||||||
val favoriteFilter = filterList.findInstance<FavoriteFilter>()
|
|
||||||
val isOkayToSort = filterList.findInstance<UploadedFilter>()?.state?.isBlank() ?: true
|
|
||||||
|
|
||||||
val url: HttpUrl.Builder
|
|
||||||
|
|
||||||
if (favoriteFilter?.state == true) {
|
|
||||||
url = "$baseUrl/favorites".toHttpUrlOrNull()!!.newBuilder()
|
|
||||||
.addQueryParameter("q", "$query $advQuery")
|
|
||||||
.addQueryParameter("page", page.toString())
|
|
||||||
} else {
|
|
||||||
url = "$baseUrl/search".toHttpUrlOrNull()!!.newBuilder()
|
|
||||||
.addQueryParameter("q", "$query $advQuery")
|
|
||||||
.addQueryParameter("page", page.toString())
|
|
||||||
|
|
||||||
if (isOkayToSort) {
|
|
||||||
filterList.findInstance<SortFilter>()?.let { f ->
|
|
||||||
url.addQueryParameter("sort", f.toUriPart())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return client.newCall(nhGet(url.toString()))
|
|
||||||
.asObservableSuccess()
|
|
||||||
.map { nhGet(url.toString(), page) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response) = parseResultPage(response)
|
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int): Request {
|
|
||||||
val uri = Uri.parse(baseUrl).buildUpon()
|
|
||||||
uri.appendQueryParameter("page", page.toString())
|
|
||||||
return nhGet(uri.toString(), page)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response) = parseResultPage(response)
|
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response) = throw UnsupportedOperationException()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<SManga> {
|
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||||
return client.newCall(mangaDetailsRequest(manga))
|
return client.newCall(mangaDetailsRequest(manga))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
@ -132,37 +54,10 @@ class NHentai(val context: Context) : HttpSource(), LewdSource<NHentaiSearchMeta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga) = nhGet(baseUrl + manga.url)
|
|
||||||
|
|
||||||
private fun parseResultPage(response: Response): MangasPage {
|
|
||||||
val doc = response.asJsoup()
|
|
||||||
|
|
||||||
// TODO Parse lang + tags
|
|
||||||
|
|
||||||
val mangas = doc.select(".gallery > a").map {
|
|
||||||
SManga.create().apply {
|
|
||||||
url = it.attr("href")
|
|
||||||
|
|
||||||
title = it.selectFirst(".caption").text()
|
|
||||||
|
|
||||||
// last() is a hack to ignore the lazy-loader placeholder image on the front page
|
|
||||||
thumbnail_url = it.select("img").last().attr("src")
|
|
||||||
// In some pages, the thumbnail url does not include the protocol
|
|
||||||
if (!thumbnail_url!!.startsWith("https:")) thumbnail_url = "https:$thumbnail_url"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val hasNextPage = if (!response.request.url.queryParameterNames.contains(REVERSE_PARAM)) {
|
|
||||||
doc.selectFirst(".next") != null
|
|
||||||
} else {
|
|
||||||
response.request.url.queryParameter(REVERSE_PARAM)!!.toBoolean()
|
|
||||||
}
|
|
||||||
|
|
||||||
return MangasPage(mangas, hasNextPage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun parseIntoMetadata(metadata: NHentaiSearchMetadata, input: Response) {
|
override fun parseIntoMetadata(metadata: NHentaiSearchMetadata, input: Response) {
|
||||||
val json = GALLERY_JSON_REGEX.find(input.body!!.string())!!.groupValues[1].replace(UNICODE_ESCAPE_REGEX) { it.groupValues[1].toInt(radix = 16).toChar().toString() }
|
val json = GALLERY_JSON_REGEX.find(input.body!!.string())!!.groupValues[1].replace(
|
||||||
|
UNICODE_ESCAPE_REGEX
|
||||||
|
) { it.groupValues[1].toInt(radix = 16).toChar().toString() }
|
||||||
val obj = JsonParser.parseString(json).asJsonObject
|
val obj = JsonParser.parseString(json).asJsonObject
|
||||||
|
|
||||||
with(metadata) {
|
with(metadata) {
|
||||||
@ -199,166 +94,12 @@ class NHentai(val context: Context) : HttpSource(), LewdSource<NHentaiSearchMeta
|
|||||||
tags.clear()
|
tags.clear()
|
||||||
}?.forEach {
|
}?.forEach {
|
||||||
if (it.first != null && it.second != null) {
|
if (it.first != null && it.second != null) {
|
||||||
tags.add(RaisedTag(it.first!!, it.second!!, if (it.first == "category") TAG_TYPE_VIRTUAL else TAG_TYPE_DEFAULT))
|
tags.add(RaisedTag(it.first!!, it.second!!, if (it.first == "category") RaisedSearchMetadata.TAG_TYPE_VIRTUAL else NHentaiSearchMetadata.TAG_TYPE_DEFAULT))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOrLoadMetadata(mangaId: Long?, nhId: Long) = getOrLoadMetadata(mangaId) {
|
|
||||||
client.newCall(nhGet(baseUrl + NHentaiSearchMetadata.nhIdToPath(nhId)))
|
|
||||||
.asObservableSuccess()
|
|
||||||
.toSingle()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.just(
|
|
||||||
listOf(
|
|
||||||
SChapter.create().apply {
|
|
||||||
url = manga.url
|
|
||||||
name = "Chapter"
|
|
||||||
chapter_number = 1f
|
|
||||||
getOrLoadMetadata(mangaId, NHentaiSearchMetadata.nhUrlToId(manga.url)).toBlocking().value().uploadDate?.let { date_upload = it * 1000 }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> = getOrLoadMetadata(chapter.mangaId, NHentaiSearchMetadata.nhUrlToId(chapter.url)).map { metadata ->
|
|
||||||
if (metadata.mediaId == null) {
|
|
||||||
emptyList()
|
|
||||||
} else {
|
|
||||||
metadata.pageImageTypes.mapIndexed { index, s ->
|
|
||||||
val imageUrl = imageUrlFromType(metadata.mediaId!!, index + 1, s)
|
|
||||||
Page(index, imageUrl!!, imageUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.toObservable()
|
|
||||||
|
|
||||||
override fun fetchImageUrl(page: Page) = Observable.just(page.imageUrl!!)!!
|
|
||||||
|
|
||||||
private fun imageUrlFromType(mediaId: String, page: Int, t: String) = NHentaiSearchMetadata.typeToExtension(t)?.let {
|
|
||||||
"https://i.nhentai.net/galleries/$mediaId/$page.$it"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
|
||||||
throw NotImplementedError("Unused method called!")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
|
||||||
throw NotImplementedError("Unused method called!")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String {
|
|
||||||
throw NotImplementedError("Unused method called!")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun combineQuery(filters: FilterList): String {
|
|
||||||
val stringBuilder = StringBuilder()
|
|
||||||
val advSearch = filters.filterIsInstance<AdvSearchEntryFilter>().flatMap { filter ->
|
|
||||||
val splitState = filter.state.split(",").map(String::trim).filterNot(String::isBlank)
|
|
||||||
splitState.map {
|
|
||||||
AdvSearchEntry(filter.name, it.removePrefix("-"), it.startsWith("-"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
advSearch.forEach { entry ->
|
|
||||||
if (entry.exclude) stringBuilder.append("-")
|
|
||||||
stringBuilder.append("${entry.name}:")
|
|
||||||
stringBuilder.append(entry.text)
|
|
||||||
stringBuilder.append(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
val langFilter = filters.filterIsInstance<FilterLang>().firstOrNull()
|
|
||||||
if (langFilter != null) {
|
|
||||||
val language = SOURCE_LANG_LIST.first { it.first == langFilter.values[langFilter.state] }.second
|
|
||||||
if (!language.isBlank()) {
|
|
||||||
stringBuilder.append("language:$language")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringBuilder.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
data class AdvSearchEntry(val name: String, val text: String, val exclude: Boolean)
|
|
||||||
|
|
||||||
override fun getFilterList(): FilterList = FilterList(
|
|
||||||
Filter.Header("Separate tags with commas (,)"),
|
|
||||||
Filter.Header("Prepend with dash (-) to exclude"),
|
|
||||||
TagFilter(),
|
|
||||||
CategoryFilter(),
|
|
||||||
GroupFilter(),
|
|
||||||
ArtistFilter(),
|
|
||||||
ParodyFilter(),
|
|
||||||
CharactersFilter(),
|
|
||||||
Filter.Header("Uploaded valid units are h, d, w, m, y."),
|
|
||||||
Filter.Header("example: (>20d)"),
|
|
||||||
UploadedFilter(),
|
|
||||||
|
|
||||||
Filter.Separator(),
|
|
||||||
SortFilter(),
|
|
||||||
Filter.Header("Sort is ignored if favorites only"),
|
|
||||||
FavoriteFilter(),
|
|
||||||
FilterLang()
|
|
||||||
)
|
|
||||||
|
|
||||||
class TagFilter : AdvSearchEntryFilter("Tags")
|
|
||||||
class CategoryFilter : AdvSearchEntryFilter("Categories")
|
|
||||||
class GroupFilter : AdvSearchEntryFilter("Groups")
|
|
||||||
class ArtistFilter : AdvSearchEntryFilter("Artists")
|
|
||||||
class ParodyFilter : AdvSearchEntryFilter("Parodies")
|
|
||||||
class CharactersFilter : AdvSearchEntryFilter("Characters")
|
|
||||||
class UploadedFilter : AdvSearchEntryFilter("Uploaded")
|
|
||||||
open class AdvSearchEntryFilter(name: String) : Filter.Text(name)
|
|
||||||
|
|
||||||
private class FavoriteFilter : Filter.CheckBox("Show favorites only", false)
|
|
||||||
|
|
||||||
// language filtering
|
|
||||||
private class FilterLang : Filter.Select<String>("Language", SOURCE_LANG_LIST.map { it.first }.toTypedArray())
|
|
||||||
|
|
||||||
private class SortFilter : UriPartFilter(
|
|
||||||
"Sort By",
|
|
||||||
arrayOf(
|
|
||||||
Pair("Popular: All Time", "popular"),
|
|
||||||
Pair("Popular: Week", "popular-week"),
|
|
||||||
Pair("Popular: Today", "popular-today"),
|
|
||||||
Pair("Recent", "date")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
|
||||||
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
|
||||||
fun toUriPart() = vals[state].second
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun <reified T> Iterable<*>.findInstance() = find { it is T } as? T
|
|
||||||
|
|
||||||
private val appName by lazy {
|
|
||||||
context.getString(R.string.app_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun nhGet(url: String, tag: Any? = null) = GET(url)
|
|
||||||
.newBuilder()
|
|
||||||
.header(
|
|
||||||
"User-Agent",
|
|
||||||
"Mozilla/5.0 (X11; Linux x86_64) " +
|
|
||||||
"AppleWebKit/537.36 (KHTML, like Gecko) " +
|
|
||||||
"Chrome/56.0.2924.87 " +
|
|
||||||
"Safari/537.36 " +
|
|
||||||
"$appName/${BuildConfig.VERSION_CODE}"
|
|
||||||
)
|
|
||||||
.tag(tag).build()
|
|
||||||
|
|
||||||
override val id = NHENTAI_SOURCE_ID
|
|
||||||
|
|
||||||
override val lang = "all"
|
|
||||||
|
|
||||||
override val name = "nhentai"
|
|
||||||
|
|
||||||
override val baseUrl = NHentaiSearchMetadata.BASE_URL
|
|
||||||
|
|
||||||
override val supportsLatest = true
|
|
||||||
|
|
||||||
// === URL IMPORT STUFF
|
|
||||||
|
|
||||||
override val matchingHosts = listOf(
|
override val matchingHosts = listOf(
|
||||||
"nhentai.net"
|
"nhentai.net"
|
||||||
)
|
)
|
||||||
@ -376,15 +117,9 @@ class NHentai(val context: Context) : HttpSource(), LewdSource<NHentaiSearchMeta
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
const val otherId = 7309872737163460316L
|
||||||
|
|
||||||
private val GALLERY_JSON_REGEX = Regex(".parse\\(\"(.*)\"\\);")
|
private val GALLERY_JSON_REGEX = Regex(".parse\\(\"(.*)\"\\);")
|
||||||
private val UNICODE_ESCAPE_REGEX = Regex("\\\\u([0-9a-fA-F]{4})")
|
private val UNICODE_ESCAPE_REGEX = Regex("\\\\u([0-9a-fA-F]{4})")
|
||||||
private const val REVERSE_PARAM = "TEH_REVERSE"
|
|
||||||
|
|
||||||
private val SOURCE_LANG_LIST = listOf(
|
|
||||||
Pair("All", ""),
|
|
||||||
Pair("English", "english"),
|
|
||||||
Pair("Japanese", "japanese"),
|
|
||||||
Pair("Chinese", "chinese")
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,9 +45,11 @@ import eu.kanade.tachiyomi.util.system.getResourceColor
|
|||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.NHENTAI_SOURCE_ID
|
import exh.PERV_EDEN_EN_SOURCE_ID
|
||||||
|
import exh.PERV_EDEN_IT_SOURCE_ID
|
||||||
import exh.favorites.FavoritesIntroDialog
|
import exh.favorites.FavoritesIntroDialog
|
||||||
import exh.favorites.FavoritesSyncStatus
|
import exh.favorites.FavoritesSyncStatus
|
||||||
|
import exh.nHentaiSourceIds
|
||||||
import exh.ui.LoaderManager
|
import exh.ui.LoaderManager
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlinx.android.synthetic.main.main_activity.tabs
|
import kotlinx.android.synthetic.main.main_activity.tabs
|
||||||
@ -521,7 +523,7 @@ class LibraryController(
|
|||||||
binding.actionToolbar.findItem(R.id.action_download_unread)?.isVisible = selectedMangas.any { it.source != LocalSource.ID }
|
binding.actionToolbar.findItem(R.id.action_download_unread)?.isVisible = selectedMangas.any { it.source != LocalSource.ID }
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
binding.actionToolbar.findItem(R.id.action_clean)?.isVisible = selectedMangas.any { it.source == EH_SOURCE_ID || it.source == EXH_SOURCE_ID || it.source == NHENTAI_SOURCE_ID }
|
binding.actionToolbar.findItem(R.id.action_clean)?.isVisible = selectedMangas.any { it.source == EH_SOURCE_ID || it.source == EXH_SOURCE_ID || it.source in nHentaiSourceIds || it.source == PERV_EDEN_EN_SOURCE_ID || it.source == PERV_EDEN_IT_SOURCE_ID }
|
||||||
// SY <--
|
// SY <--
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -640,7 +642,7 @@ class LibraryController(
|
|||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
private fun cleanTitles() {
|
private fun cleanTitles() {
|
||||||
val mangas = selectedMangas.filter { it.source == EH_SOURCE_ID || it.source == EXH_SOURCE_ID || it.source == NHENTAI_SOURCE_ID }.toList()
|
val mangas = selectedMangas.filter { it.source == EH_SOURCE_ID || it.source == EXH_SOURCE_ID || it.source in nHentaiSourceIds }.toList()
|
||||||
presenter.cleanTitles(mangas)
|
presenter.cleanTitles(mangas)
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,6 @@ import eu.kanade.tachiyomi.util.lang.launchUI
|
|||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXHMigrations
|
import exh.EXHMigrations
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.NHENTAI_SOURCE_ID
|
|
||||||
import exh.eh.EHentaiUpdateWorker
|
import exh.eh.EHentaiUpdateWorker
|
||||||
import exh.source.BlacklistedSources
|
import exh.source.BlacklistedSources
|
||||||
import exh.uconfig.WarnConfigureDialogController
|
import exh.uconfig.WarnConfigureDialogController
|
||||||
@ -209,9 +208,6 @@ class MainActivity : BaseActivity<MainActivityBinding>() {
|
|||||||
if (EXH_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) {
|
if (EXH_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) {
|
||||||
BlacklistedSources.HIDDEN_SOURCES += EXH_SOURCE_ID
|
BlacklistedSources.HIDDEN_SOURCES += EXH_SOURCE_ID
|
||||||
}
|
}
|
||||||
if (NHENTAI_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) {
|
|
||||||
BlacklistedSources.HIDDEN_SOURCES += NHENTAI_SOURCE_ID
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// SY -->
|
// SY -->
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ import eu.kanade.tachiyomi.util.system.powerManager
|
|||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.NHENTAI_SOURCE_ID
|
|
||||||
import exh.debug.SettingsDebugController
|
import exh.debug.SettingsDebugController
|
||||||
import exh.log.EHLogLevel
|
import exh.log.EHLogLevel
|
||||||
import exh.source.BlacklistedSources
|
import exh.source.BlacklistedSources
|
||||||
@ -177,9 +176,6 @@ class SettingsAdvancedController : SettingsController() {
|
|||||||
if (EXH_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) {
|
if (EXH_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) {
|
||||||
BlacklistedSources.HIDDEN_SOURCES += EXH_SOURCE_ID
|
BlacklistedSources.HIDDEN_SOURCES += EXH_SOURCE_ID
|
||||||
}
|
}
|
||||||
if (NHENTAI_SOURCE_ID !in BlacklistedSources.HIDDEN_SOURCES) {
|
|
||||||
BlacklistedSources.HIDDEN_SOURCES += NHENTAI_SOURCE_ID
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (EH_SOURCE_ID in BlacklistedSources.HIDDEN_SOURCES) {
|
if (EH_SOURCE_ID in BlacklistedSources.HIDDEN_SOURCES) {
|
||||||
BlacklistedSources.HIDDEN_SOURCES -= EH_SOURCE_ID
|
BlacklistedSources.HIDDEN_SOURCES -= EH_SOURCE_ID
|
||||||
@ -187,9 +183,6 @@ class SettingsAdvancedController : SettingsController() {
|
|||||||
if (EXH_SOURCE_ID in BlacklistedSources.HIDDEN_SOURCES) {
|
if (EXH_SOURCE_ID in BlacklistedSources.HIDDEN_SOURCES) {
|
||||||
BlacklistedSources.HIDDEN_SOURCES -= EXH_SOURCE_ID
|
BlacklistedSources.HIDDEN_SOURCES -= EXH_SOURCE_ID
|
||||||
}
|
}
|
||||||
if (NHENTAI_SOURCE_ID in BlacklistedSources.HIDDEN_SOURCES) {
|
|
||||||
BlacklistedSources.HIDDEN_SOURCES -= NHENTAI_SOURCE_ID
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -73,12 +73,6 @@ class SettingsMainController : SettingsController() {
|
|||||||
titleRes = R.string.pref_category_eh
|
titleRes = R.string.pref_category_eh
|
||||||
onClick { navigateTo(SettingsEhController()) }
|
onClick { navigateTo(SettingsEhController()) }
|
||||||
}
|
}
|
||||||
preference {
|
|
||||||
iconRes = R.drawable.eh_ic_nhlogo_color
|
|
||||||
iconTint = tintColor
|
|
||||||
titleRes = R.string.pref_category_nh
|
|
||||||
onClick { navigateTo(SettingsNhController()) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// SY <--
|
// SY <--
|
||||||
preference {
|
preference {
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.ui.setting
|
|
||||||
|
|
||||||
import androidx.preference.PreferenceScreen
|
|
||||||
import eu.kanade.tachiyomi.R
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
|
||||||
import eu.kanade.tachiyomi.util.preference.defaultValue
|
|
||||||
import eu.kanade.tachiyomi.util.preference.summaryRes
|
|
||||||
import eu.kanade.tachiyomi.util.preference.switchPreference
|
|
||||||
import eu.kanade.tachiyomi.util.preference.titleRes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* nhentai Settings fragment
|
|
||||||
*/
|
|
||||||
|
|
||||||
class SettingsNhController : SettingsController() {
|
|
||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
|
|
||||||
titleRes = R.string.pref_category_nh
|
|
||||||
|
|
||||||
switchPreference {
|
|
||||||
titleRes = R.string.high_quality_thumbnails
|
|
||||||
summaryRes = R.string.high_quality_thumbnails_summary
|
|
||||||
key = PreferenceKeys.eh_nh_useHighQualityThumbs
|
|
||||||
defaultValue = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,6 +3,7 @@ package exh
|
|||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.online.all.Hitomi
|
import eu.kanade.tachiyomi.source.online.all.Hitomi
|
||||||
|
import eu.kanade.tachiyomi.source.online.all.NHentai
|
||||||
import eu.kanade.tachiyomi.source.online.all.PervEden
|
import eu.kanade.tachiyomi.source.online.all.PervEden
|
||||||
import eu.kanade.tachiyomi.source.online.english.EightMuses
|
import eu.kanade.tachiyomi.source.online.english.EightMuses
|
||||||
import eu.kanade.tachiyomi.source.online.english.HBrowse
|
import eu.kanade.tachiyomi.source.online.english.HBrowse
|
||||||
@ -20,7 +21,6 @@ const val EH_SOURCE_ID = LEWD_SOURCE_SERIES + 1
|
|||||||
const val EXH_SOURCE_ID = LEWD_SOURCE_SERIES + 2
|
const val EXH_SOURCE_ID = LEWD_SOURCE_SERIES + 2
|
||||||
const val PERV_EDEN_EN_SOURCE_ID = 4673633799850248749
|
const val PERV_EDEN_EN_SOURCE_ID = 4673633799850248749
|
||||||
const val PERV_EDEN_IT_SOURCE_ID = 1433898225963724122
|
const val PERV_EDEN_IT_SOURCE_ID = 1433898225963724122
|
||||||
const val NHENTAI_SOURCE_ID = LEWD_SOURCE_SERIES + 7
|
|
||||||
const val HENTAI_CAFE_SOURCE_ID = 260868874183818481
|
const val HENTAI_CAFE_SOURCE_ID = 260868874183818481
|
||||||
const val PURURIN_SOURCE_ID = 2221515250486218861
|
const val PURURIN_SOURCE_ID = 2221515250486218861
|
||||||
const val TSUMINO_SOURCE_ID = 6707338697138388238
|
const val TSUMINO_SOURCE_ID = 6707338697138388238
|
||||||
@ -35,10 +35,12 @@ private val DELEGATED_LEWD_SOURCES = listOf(
|
|||||||
HBrowse::class,
|
HBrowse::class,
|
||||||
EightMuses::class,
|
EightMuses::class,
|
||||||
Hitomi::class,
|
Hitomi::class,
|
||||||
PervEden::class
|
PervEden::class,
|
||||||
|
NHentai::class
|
||||||
)
|
)
|
||||||
|
|
||||||
private val hitomiClass = listOf(Hitomi::class)
|
private val hitomiClass = listOf(Hitomi::class)
|
||||||
|
private val nHentaiClass = listOf(NHentai::class)
|
||||||
|
|
||||||
// Used to speed up isLewdSource
|
// Used to speed up isLewdSource
|
||||||
val lewdDelegatedSourceIds = SourceManager.currentDelegatedSources.filter {
|
val lewdDelegatedSourceIds = SourceManager.currentDelegatedSources.filter {
|
||||||
@ -49,6 +51,10 @@ val hitomiSourceIds = SourceManager.currentDelegatedSources.filter {
|
|||||||
it.value.newSourceClass in hitomiClass
|
it.value.newSourceClass in hitomiClass
|
||||||
}.map { it.value.sourceId }.sorted()
|
}.map { it.value.sourceId }.sorted()
|
||||||
|
|
||||||
|
val nHentaiSourceIds = SourceManager.currentDelegatedSources.filter {
|
||||||
|
it.value.newSourceClass in nHentaiClass
|
||||||
|
}.map { it.value.sourceId }.sorted()
|
||||||
|
|
||||||
// This method MUST be fast!
|
// This method MUST be fast!
|
||||||
fun isLewdSource(source: Long) = source in 6900..6999 ||
|
fun isLewdSource(source: Long) = source in 6900..6999 ||
|
||||||
lewdDelegatedSourceIds.binarySearch(source) >= 0
|
lewdDelegatedSourceIds.binarySearch(source) >= 0
|
||||||
@ -56,13 +62,13 @@ fun isLewdSource(source: Long) = source in 6900..6999 ||
|
|||||||
val LIBRARY_UPDATE_EXCLUDED_SOURCES = listOf(
|
val LIBRARY_UPDATE_EXCLUDED_SOURCES = listOf(
|
||||||
EH_SOURCE_ID,
|
EH_SOURCE_ID,
|
||||||
EXH_SOURCE_ID,
|
EXH_SOURCE_ID,
|
||||||
NHENTAI_SOURCE_ID,
|
|
||||||
HENTAI_CAFE_SOURCE_ID,
|
HENTAI_CAFE_SOURCE_ID,
|
||||||
TSUMINO_SOURCE_ID,
|
TSUMINO_SOURCE_ID,
|
||||||
PURURIN_SOURCE_ID,
|
PURURIN_SOURCE_ID,
|
||||||
*hitomiSourceIds.toTypedArray()
|
*hitomiSourceIds.toTypedArray(),
|
||||||
|
*nHentaiSourceIds.toTypedArray()
|
||||||
)
|
)
|
||||||
|
|
||||||
fun Source.isEhBasedSource() = id == EH_SOURCE_ID || id == EXH_SOURCE_ID
|
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 in hitomiSourceIds || 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 in nHentaiSourceIds || id in hitomiSourceIds || id == PURURIN_SOURCE_ID || id == TSUMINO_SOURCE_ID || id == EIGHTMUSES_SOURCE_ID || id == HBROWSE_SOURCE_ID
|
||||||
|
@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.data.updater.UpdaterJob
|
import eu.kanade.tachiyomi.data.updater.UpdaterJob
|
||||||
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
|
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
|
||||||
import eu.kanade.tachiyomi.source.online.all.Hitomi
|
import eu.kanade.tachiyomi.source.online.all.Hitomi
|
||||||
|
import eu.kanade.tachiyomi.source.online.all.NHentai
|
||||||
import exh.source.BlacklistedSources
|
import exh.source.BlacklistedSources
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
@ -128,10 +129,22 @@ object EXHMigrations {
|
|||||||
.affectsTables(MangaTable.TABLE)
|
.affectsTables(MangaTable.TABLE)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
db.lowLevel().executeSQL(
|
||||||
|
RawQuery.builder()
|
||||||
|
.query(
|
||||||
|
"""
|
||||||
|
UPDATE ${MangaTable.TABLE}
|
||||||
|
SET ${MangaTable.COL_SOURCE} = ${NHentai.otherId}
|
||||||
|
WHERE ${MangaTable.COL_SOURCE} = 6907
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
.affectsTables(MangaTable.TABLE)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (oldVersion < 1) { }
|
// if (oldVersion < 1) { } (1 is current release version)
|
||||||
// do stuff here when releasing changed crap
|
// do stuff here when releasing changed crap
|
||||||
|
|
||||||
// TODO BE CAREFUL TO NOT FUCK UP MergedSources IF CHANGING URLs
|
// TODO BE CAREFUL TO NOT FUCK UP MergedSources IF CHANGING URLs
|
||||||
@ -155,6 +168,13 @@ object EXHMigrations {
|
|||||||
manga.source = PERV_EDEN_IT_SOURCE_ID
|
manga.source = PERV_EDEN_IT_SOURCE_ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (manga.source == 6907L) {
|
||||||
|
// Migrate the old source to the delegated one
|
||||||
|
manga.source = NHentai.otherId
|
||||||
|
// Migrate nhentai URLs
|
||||||
|
manga.url = getUrlWithoutDomain(manga.url)
|
||||||
|
}
|
||||||
|
|
||||||
// Migrate HentaiCafe source IDs
|
// Migrate HentaiCafe source IDs
|
||||||
if (manga.source == 6908L) {
|
if (manga.source == 6908L) {
|
||||||
manga.source = HENTAI_CAFE_SOURCE_ID
|
manga.source = HENTAI_CAFE_SOURCE_ID
|
||||||
@ -173,16 +193,6 @@ object EXHMigrations {
|
|||||||
manga.source = HBROWSE_SOURCE_ID
|
manga.source = HBROWSE_SOURCE_ID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate nhentai URLs
|
|
||||||
if (manga.source == NHENTAI_SOURCE_ID) {
|
|
||||||
manga.url = getUrlWithoutDomain(manga.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow importing of nhentai extension backups
|
|
||||||
if (manga.source in BlacklistedSources.NHENTAI_EXT_SOURCES) {
|
|
||||||
manga.source = NHENTAI_SOURCE_ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow importing of EHentai extension backups
|
// Allow importing of EHentai extension backups
|
||||||
if (manga.source in BlacklistedSources.EHENTAI_EXT_SOURCES) {
|
if (manga.source in BlacklistedSources.EHENTAI_EXT_SOURCES) {
|
||||||
manga.source = EH_SOURCE_ID
|
manga.source = EH_SOURCE_ID
|
||||||
|
@ -2,13 +2,11 @@ package exh.metadata.metadata
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import exh.metadata.EX_DATE_FORMAT
|
import exh.metadata.EX_DATE_FORMAT
|
||||||
import exh.metadata.ONGOING_SUFFIX
|
import exh.metadata.ONGOING_SUFFIX
|
||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
||||||
@ -41,13 +39,8 @@ class NHentaiSearchMetadata : RaisedSearchMetadata() {
|
|||||||
nhId?.let { manga.url = nhIdToPath(it) }
|
nhId?.let { manga.url = nhIdToPath(it) }
|
||||||
|
|
||||||
if (mediaId != null) {
|
if (mediaId != null) {
|
||||||
val hqThumbs = Injekt.get<PreferencesHelper>().eh_nh_useHighQualityThumbs().get()
|
typeToExtension(coverImageType)?.let {
|
||||||
typeToExtension(if (hqThumbs) coverImageType else thumbnailImageType)?.let {
|
manga.thumbnail_url = "https://t.nhentai.net/galleries/$mediaId/cover.$it"
|
||||||
manga.thumbnail_url = "https://t.nhentai.net/galleries/$mediaId/${if (hqThumbs) {
|
|
||||||
"cover"
|
|
||||||
} else {
|
|
||||||
"thumb"
|
|
||||||
}}.$it"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,6 @@ package exh.source
|
|||||||
import exh.MERGED_SOURCE_ID
|
import exh.MERGED_SOURCE_ID
|
||||||
|
|
||||||
object BlacklistedSources {
|
object BlacklistedSources {
|
||||||
val NHENTAI_EXT_SOURCES = listOf(
|
|
||||||
3122156392225024195,
|
|
||||||
4726175775739752699,
|
|
||||||
2203215402871965477
|
|
||||||
)
|
|
||||||
val EHENTAI_EXT_SOURCES = listOf(
|
val EHENTAI_EXT_SOURCES = listOf(
|
||||||
8100626124886895451,
|
8100626124886895451,
|
||||||
57122881048805941,
|
57122881048805941,
|
||||||
@ -28,12 +23,10 @@ object BlacklistedSources {
|
|||||||
6140480779421365791
|
6140480779421365791
|
||||||
)
|
)
|
||||||
|
|
||||||
val BLACKLISTED_EXT_SOURCES = NHENTAI_EXT_SOURCES +
|
val BLACKLISTED_EXT_SOURCES = EHENTAI_EXT_SOURCES
|
||||||
EHENTAI_EXT_SOURCES
|
|
||||||
|
|
||||||
val BLACKLISTED_EXTENSIONS = listOf(
|
val BLACKLISTED_EXTENSIONS = listOf(
|
||||||
"eu.kanade.tachiyomi.extension.all.ehentai",
|
"eu.kanade.tachiyomi.extension.all.ehentai"
|
||||||
"eu.kanade.tachiyomi.extension.all.nhentai"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var HIDDEN_SOURCES = listOf(
|
var HIDDEN_SOURCES = listOf(
|
||||||
|
@ -4,7 +4,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
|||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.NHENTAI_SOURCE_ID
|
import exh.nHentaiSourceIds
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ fun Manga.isLewd(): Boolean {
|
|||||||
val sourceName = Injekt.get<SourceManager>().get(source)?.name
|
val sourceName = Injekt.get<SourceManager>().get(source)?.name
|
||||||
val currentTags = getGenres() ?: emptyList()
|
val currentTags = getGenres() ?: emptyList()
|
||||||
|
|
||||||
if (source == EH_SOURCE_ID || source == EXH_SOURCE_ID || source == NHENTAI_SOURCE_ID) {
|
if (source == EH_SOURCE_ID || source == EXH_SOURCE_ID || source in nHentaiSourceIds) {
|
||||||
return !currentTags.any { tag -> isNonHentaiTag(tag) }
|
return !currentTags.any { tag -> isNonHentaiTag(tag) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,21 +3,21 @@ package exh.util
|
|||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import exh.EH_SOURCE_ID
|
import exh.EH_SOURCE_ID
|
||||||
import exh.EXH_SOURCE_ID
|
import exh.EXH_SOURCE_ID
|
||||||
import exh.NHENTAI_SOURCE_ID
|
|
||||||
import exh.PURURIN_SOURCE_ID
|
import exh.PURURIN_SOURCE_ID
|
||||||
import exh.TSUMINO_SOURCE_ID
|
import exh.TSUMINO_SOURCE_ID
|
||||||
import exh.hitomiSourceIds
|
import exh.hitomiSourceIds
|
||||||
import exh.metadata.metadata.base.RaisedTag
|
import exh.metadata.metadata.base.RaisedTag
|
||||||
|
import exh.nHentaiSourceIds
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class SourceTagsUtil {
|
class SourceTagsUtil {
|
||||||
fun getWrappedTag(sourceId: Long, namespace: String? = null, tag: String? = null, fullTag: String? = null): String? {
|
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 in hitomiSourceIds) {
|
return if (sourceId == EXH_SOURCE_ID || sourceId == EH_SOURCE_ID || sourceId in nHentaiSourceIds || sourceId in hitomiSourceIds) {
|
||||||
val parsed = if (fullTag != null) parseTag(fullTag) else if (namespace != null && tag != null) RaisedTag(namespace, tag, TAG_TYPE_DEFAULT) else null
|
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) {
|
if (parsed?.namespace != null) {
|
||||||
when (sourceId) {
|
when (sourceId) {
|
||||||
in hitomiSourceIds -> 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())
|
in nHentaiSourceIds -> wrapTagNHentai(parsed.namespace, parsed.name.substringBefore('|').trim())
|
||||||
PURURIN_SOURCE_ID -> parsed.name.substringBefore('|').trim()
|
PURURIN_SOURCE_ID -> parsed.name.substringBefore('|').trim()
|
||||||
TSUMINO_SOURCE_ID -> parsed.name.substringBefore('|').trim()
|
TSUMINO_SOURCE_ID -> parsed.name.substringBefore('|').trim()
|
||||||
else -> wrapTag(parsed.namespace, parsed.name.substringBefore('|').trim())
|
else -> wrapTag(parsed.namespace, parsed.name.substringBefore('|').trim())
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 738 B |
Binary file not shown.
Before Width: | Height: | Size: 529 B |
Binary file not shown.
Before Width: | Height: | Size: 840 B |
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB |
@ -24,7 +24,6 @@
|
|||||||
<!-- Subsections -->
|
<!-- Subsections -->
|
||||||
<string name="pref_category_all_sources">Todas as fontes</string>
|
<string name="pref_category_all_sources">Todas as fontes</string>
|
||||||
<string name="pref_category_eh">E-Hentai</string>
|
<string name="pref_category_eh">E-Hentai</string>
|
||||||
<string name="pref_category_nh">nhentai</string>
|
|
||||||
<string name="pref_category_fork">Configurações do fork</string>
|
<string name="pref_category_fork">Configurações do fork</string>
|
||||||
|
|
||||||
<!-- EH Settings -->
|
<!-- EH Settings -->
|
||||||
@ -136,10 +135,6 @@
|
|||||||
<!-- Library settings -->
|
<!-- Library settings -->
|
||||||
<string name="pref_skip_pre_migration_summary">Use as últimas fontes e preferências da pré-migração salvas para migrar em massa</string>
|
<string name="pref_skip_pre_migration_summary">Use as últimas fontes e preferências da pré-migração salvas para migrar em massa</string>
|
||||||
|
|
||||||
<!-- Other Settings -->
|
|
||||||
<string name="high_quality_thumbnails">Usar miniaturas de alta qualidade</string>
|
|
||||||
<string name="high_quality_thumbnails_summary">Pode carregar os resultados da pesquisa mais lentamente</string>
|
|
||||||
|
|
||||||
<!-- Reader Settings -->
|
<!-- Reader Settings -->
|
||||||
<string name="download_threads">Downloads simultâneos</string>
|
<string name="download_threads">Downloads simultâneos</string>
|
||||||
<string name="download_threads_summary">Valores maiores podem acelerar significativamente o download, mas podem também causar banimentos. O valor recomendado é 2 ou 3. Valor atual: %s</string>
|
<string name="download_threads_summary">Valores maiores podem acelerar significativamente o download, mas podem também causar banimentos. O valor recomendado é 2 ou 3. Valor atual: %s</string>
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
<!-- Subsections -->
|
<!-- Subsections -->
|
||||||
<string name="pref_category_all_sources">All Sources</string>
|
<string name="pref_category_all_sources">All Sources</string>
|
||||||
<string name="pref_category_eh">E-Hentai</string>
|
<string name="pref_category_eh">E-Hentai</string>
|
||||||
<string name="pref_category_nh">nhentai</string>
|
|
||||||
<string name="pref_category_fork">Fork Settings</string>
|
<string name="pref_category_fork">Fork Settings</string>
|
||||||
|
|
||||||
<!-- EH Settings -->
|
<!-- EH Settings -->
|
||||||
@ -151,10 +150,6 @@
|
|||||||
<!-- Library settings -->
|
<!-- Library settings -->
|
||||||
<string name="pref_skip_pre_migration_summary">Use last saved pre-migration preferences and sources to mass migrate</string>
|
<string name="pref_skip_pre_migration_summary">Use last saved pre-migration preferences and sources to mass migrate</string>
|
||||||
|
|
||||||
<!-- Other Settings -->
|
|
||||||
<string name="high_quality_thumbnails">Use high-quality thumbnails</string>
|
|
||||||
<string name="high_quality_thumbnails_summary">May slow down search results</string>
|
|
||||||
|
|
||||||
<!-- Reader Settings -->
|
<!-- Reader Settings -->
|
||||||
<string name="download_threads">Download threads</string>
|
<string name="download_threads">Download threads</string>
|
||||||
<string name="download_threads_summary">Higher values can speed up image downloading significantly, but can also trigger bans. Recommended value is 2 or 3. Current value is: %s</string>
|
<string name="download_threads_summary">Higher values can speed up image downloading significantly, but can also trigger bans. Recommended value is 2 or 3. Current value is: %s</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user