E-Hentai: switch to SourceFactory

This commit is contained in:
Eugene 2019-10-27 15:24:12 -04:00
parent 40c5cb33aa
commit 170c382b15
No known key found for this signature in database
GPG Key ID: E1FD745328866B0A
6 changed files with 145 additions and 152 deletions

View File

@ -4,8 +4,8 @@ apply plugin: 'kotlin-android'
ext {
appName = 'Tachiyomi: E-Hentai'
pkgNameSuffix = 'all.ehentai'
extClass = '.EHJapanese; .EHEnglish; .EHChinese; .EHDutch; .EHFrench; .EHGerman; .EHHungarian; .EHItalian; .EHKorean; .EHPolish; .EHPortuguese; .EHRussian; .EHSpanish; .EHThai; .EHVietnamese; .EHSpeechless; .EHOther'
extVersionCode = 6
extClass = '.EHFactory'
extVersionCode = 7
libVersion = '1.2'
}

View File

@ -0,0 +1,26 @@
package eu.kanade.tachiyomi.extension.all.ehentai
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory
class EHFactory : SourceFactory {
override fun createSources(): List<Source> = listOf(
EHentai("ja", "japanese"),
EHentai("en", "english"),
EHentai("zh", "chinese"),
EHentai("nl", "dutch"),
EHentai("fr", "french"),
EHentai("de", "german"),
EHentai("hu", "hungarian"),
EHentai("it", "italian"),
EHentai("ko", "korean"),
EHentai("pl", "polish"),
EHentai("pt", "portuguese"),
EHentai("ru", "russian"),
EHentai("es", "spanish"),
EHentai("th", "thai"),
EHentai("vi", "vietnamese"),
EHentai("none", "n/a"),
EHentai("other", "other")
)
}

View File

@ -1,42 +0,0 @@
package eu.kanade.tachiyomi.extension.all.ehentai
/**
* E-Hentai languages
*/
class EHJapanese : EHentai("ja", "japanese")
class EHEnglish : EHentai("en", "english")
class EHChinese : EHentai("zh", "chinese")
class EHDutch : EHentai("nl", "dutch")
class EHFrench : EHentai("fr", "french")
class EHGerman : EHentai("de", "german")
class EHHungarian : EHentai("hu", "hungarian")
class EHItalian : EHentai("it", "italian")
class EHKorean : EHentai("ko", "korean")
class EHPolish : EHentai("pl", "polish")
class EHPortuguese : EHentai("pt", "portuguese")
class EHRussian : EHentai("ru", "russian")
class EHSpanish : EHentai("es", "spanish")
class EHThai : EHentai("th", "thai")
class EHVietnamese : EHentai("vi", "vietnamese")
class EHSpeechless : EHentai("none", "n/a")
class EHOther : EHentai("other", "other")
fun getAllEHentaiLanguages() = listOf(
EHJapanese(),
EHEnglish(),
EHChinese(),
EHDutch(),
EHFrench(),
EHGerman(),
EHHungarian(),
EHItalian(),
EHKorean(),
EHPolish(),
EHPortuguese(),
EHRussian(),
EHSpanish(),
EHThai(),
EHVietnamese(),
EHSpeechless(),
EHOther()
)

View File

@ -3,10 +3,19 @@ package eu.kanade.tachiyomi.extension.all.ehentai
import android.net.Uri
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.*
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.*
import okhttp3.CacheControl
import okhttp3.CookieJar
import okhttp3.Headers
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Element
import rx.Observable
import java.net.URLEncoder
@ -31,7 +40,7 @@ open class EHentai(override val lang: String, private val ehLang: String) : Http
//Get image
it.parent().select(".glthumb img")?.first().apply {
thumbnail_url = this?.attr("data-src")?.nullIfBlank()
?: this?.attr("src")
?: this?.attr("src")
}
}
}
@ -140,46 +149,46 @@ open class EHentai(override val lang: String, private val ehLang: String) : Http
//Parse the table
select("#gdd tr").forEach {
it.select(".gdt1")
.text()
.nullIfBlank()
?.trim()
?.let { left ->
it.select(".gdt2")
.text()
.nullIfBlank()
?.trim()
?.let { right ->
ignore {
when (left.removeSuffix(":")
.toLowerCase()) {
"posted" -> datePosted = EX_DATE_FORMAT.parse(right).time
"visible" -> visible = right.nullIfBlank()
"language" -> {
language = right.removeSuffix(TR_SUFFIX).trim().nullIfBlank()
translated = right.endsWith(TR_SUFFIX, true)
}
"file size" -> size = parseHumanReadableByteCount(right)?.toLong()
"length" -> length = right.removeSuffix("pages").trim().nullIfBlank()?.toInt()
"favorited" -> favorites = right.removeSuffix("times").trim().nullIfBlank()?.toInt()
}
.text()
.nullIfBlank()
?.trim()
?.let { left ->
it.select(".gdt2")
.text()
.nullIfBlank()
?.trim()
?.let { right ->
ignore {
when (left.removeSuffix(":")
.toLowerCase()) {
"posted" -> datePosted = EX_DATE_FORMAT.parse(right).time
"visible" -> visible = right.nullIfBlank()
"language" -> {
language = right.removeSuffix(TR_SUFFIX).trim().nullIfBlank()
translated = right.endsWith(TR_SUFFIX, true)
}
"file size" -> size = parseHumanReadableByteCount(right)?.toLong()
"length" -> length = right.removeSuffix("pages").trim().nullIfBlank()?.toInt()
"favorited" -> favorites = right.removeSuffix("times").trim().nullIfBlank()?.toInt()
}
}
}
}
}
}
//Parse ratings
ignore {
averageRating = select("#rating_label")
.text()
.removePrefix("Average:")
.trim()
.nullIfBlank()
?.toDouble()
.text()
.removePrefix("Average:")
.trim()
.nullIfBlank()
?.toDouble()
ratingCount = select("#rating_count")
.text()
.trim()
.nullIfBlank()
?.toInt()
.text()
.trim()
.nullIfBlank()
?.toInt()
}
//Parse tags
@ -188,7 +197,7 @@ open class EHentai(override val lang: String, private val ehLang: String) : Http
val namespace = it.select(".tc").text().removeSuffix(":")
val currentTags = it.select("div").map {
Tag(it.text().trim(),
it.hasClass("gtl"))
it.hasClass("gtl"))
}
tags[namespace] = currentTags
}
@ -205,8 +214,8 @@ open class EHentai(override val lang: String, private val ehLang: String) : Http
override fun pageListParse(response: Response) = throw UnsupportedOperationException("Unused method was called somehow!")
override fun fetchImageUrl(page: Page) = client.newCall(imageUrlRequest(page))
.asObservableSuccess()
.map { realImageUrlParse(it, page) }!!
.asObservableSuccess()
.map { realImageUrlParse(it, page) }!!
private fun realImageUrlParse(response: Response, page: Page) = with(response.asJsoup()) {
val currentImage = getElementById("img").attr("src")
@ -231,8 +240,8 @@ open class EHentai(override val lang: String, private val ehLang: String) : Http
//Exclude every other language except the one we have selected
settings += "xl_" + languageMappings.filter { it.first != ehLang }
.flatMap { it.second }
.joinToString("x")
.flatMap { it.second }
.joinToString("x")
cookies["uconfig"] = buildSettings(settings)
@ -252,27 +261,27 @@ open class EHentai(override val lang: String, private val ehLang: String) : Http
}
private fun addParam(url: String, param: String, value: String) = Uri.parse(url)
.buildUpon()
.appendQueryParameter(param, value)
.toString()
.buildUpon()
.appendQueryParameter(param, value)
.toString()
override val client = network.client.newBuilder()
.cookieJar(CookieJar.NO_COOKIES)
.addInterceptor { chain ->
val newReq = chain
.request()
.newBuilder()
.removeHeader("Cookie")
.addHeader("Cookie", cookiesHeader)
.build()
.cookieJar(CookieJar.NO_COOKIES)
.addInterceptor { chain ->
val newReq = chain
.request()
.newBuilder()
.removeHeader("Cookie")
.addHeader("Cookie", cookiesHeader)
.build()
chain.proceed(newReq)
}.build()!!
chain.proceed(newReq)
}.build()!!
//Filters
override fun getFilterList() = FilterList(
GenreGroup(),
AdvancedGroup()
GenreGroup(),
AdvancedGroup()
)
class GenreOption(name: String, private val genreId: String) : Filter.CheckBox(name, false), UriFilter {
@ -282,16 +291,16 @@ open class EHentai(override val lang: String, private val ehLang: String) : Http
}
class GenreGroup : UriGroup<GenreOption>("Genres", listOf(
GenreOption("Dōjinshi", "doujinshi"),
GenreOption("Manga", "manga"),
GenreOption("Artist CG", "artistcg"),
GenreOption("Game CG", "gamecg"),
GenreOption("Western", "western"),
GenreOption("Non-H", "non-h"),
GenreOption("Image Set", "imageset"),
GenreOption("Cosplay", "cosplay"),
GenreOption("Asian Porn", "asianporn"),
GenreOption("Misc", "misc")
GenreOption("Dōjinshi", "doujinshi"),
GenreOption("Manga", "manga"),
GenreOption("Artist CG", "artistcg"),
GenreOption("Game CG", "gamecg"),
GenreOption("Western", "western"),
GenreOption("Non-H", "non-h"),
GenreOption("Image Set", "imageset"),
GenreOption("Cosplay", "cosplay"),
GenreOption("Asian Porn", "asianporn"),
GenreOption("Misc", "misc")
))
class AdvancedOption(name: String, private val param: String, defValue: Boolean = false) : Filter.CheckBox(name, defValue), UriFilter {
@ -302,11 +311,11 @@ open class EHentai(override val lang: String, private val ehLang: String) : Http
}
class RatingOption : Filter.Select<String>("Minimum Rating", arrayOf(
"Any",
"2 stars",
"3 stars",
"4 stars",
"5 stars"
"Any",
"2 stars",
"3 stars",
"4 stars",
"5 stars"
)), UriFilter {
override fun addToUri(builder: Uri.Builder) {
if (state > 0) builder.appendQueryParameter("f_srdd", (state + 1).toString())
@ -314,37 +323,37 @@ open class EHentai(override val lang: String, private val ehLang: String) : Http
}
//Explicit type arg for listOf() to workaround this: KT-16570
class AdvancedGroup : UriGroup<Filter<*>>("Advanced Options", listOf<Filter<*>>(
AdvancedOption("Search Gallery Name", "f_sname", true),
AdvancedOption("Search Gallery Tags", "f_stags", true),
AdvancedOption("Search Gallery Description", "f_sdesc"),
AdvancedOption("Search Torrent Filenames", "f_storr"),
AdvancedOption("Only Show Galleries With Torrents", "f_sto"),
AdvancedOption("Search Low-Power Tags", "f_sdt1"),
AdvancedOption("Search Downvoted Tags", "f_sdt2"),
AdvancedOption("Show Expunged Galleries", "f_sh"),
RatingOption()
class AdvancedGroup : UriGroup<Filter<*>>("Advanced Options", listOf(
AdvancedOption("Search Gallery Name", "f_sname", true),
AdvancedOption("Search Gallery Tags", "f_stags", true),
AdvancedOption("Search Gallery Description", "f_sdesc"),
AdvancedOption("Search Torrent Filenames", "f_storr"),
AdvancedOption("Only Show Galleries With Torrents", "f_sto"),
AdvancedOption("Search Low-Power Tags", "f_sdt1"),
AdvancedOption("Search Downvoted Tags", "f_sdt2"),
AdvancedOption("Show Expunged Galleries", "f_sh"),
RatingOption()
))
//map languages to their internal ids
private val languageMappings = listOf(
Pair("japanese", listOf("0", "1024", "2048")),
Pair("english", listOf("1", "1025", "2049")),
Pair("chinese", listOf("10", "1034", "2058")),
Pair("dutch", listOf("20", "1044", "2068")),
Pair("french", listOf("30", "1054", "2078")),
Pair("german", listOf("40", "1064", "2088")),
Pair("hungarian", listOf("50", "1074", "2098")),
Pair("italian", listOf("60", "1084", "2108")),
Pair("korean", listOf("70", "1094", "2118")),
Pair("polish", listOf("80", "1104", "2128")),
Pair("portuguese", listOf("90", "1114", "2138")),
Pair("russian", listOf("100", "1124", "2148")),
Pair("spanish", listOf("110", "1134", "2158")),
Pair("thai", listOf("120", "1144", "2168")),
Pair("vietnamese", listOf("130", "1154", "2178")),
Pair("n/a", listOf("254", "1278", "2302")),
Pair("other", listOf("255", "1279", "2303"))
Pair("japanese", listOf("0", "1024", "2048")),
Pair("english", listOf("1", "1025", "2049")),
Pair("chinese", listOf("10", "1034", "2058")),
Pair("dutch", listOf("20", "1044", "2068")),
Pair("french", listOf("30", "1054", "2078")),
Pair("german", listOf("40", "1064", "2088")),
Pair("hungarian", listOf("50", "1074", "2098")),
Pair("italian", listOf("60", "1084", "2108")),
Pair("korean", listOf("70", "1094", "2118")),
Pair("polish", listOf("80", "1104", "2128")),
Pair("portuguese", listOf("90", "1114", "2138")),
Pair("russian", listOf("100", "1124", "2148")),
Pair("spanish", listOf("110", "1134", "2158")),
Pair("thai", listOf("120", "1144", "2168")),
Pair("vietnamese", listOf("130", "1154", "2178")),
Pair("n/a", listOf("254", "1278", "2302")),
Pair("other", listOf("255", "1279", "2303"))
)
companion object {

View File

@ -2,15 +2,16 @@ package eu.kanade.tachiyomi.extension.all.ehentai
import eu.kanade.tachiyomi.source.model.SManga
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import java.util.Locale
private const val EH_ARTIST_NAMESPACE = "artist"
private const val EH_AUTHOR_NAMESPACE = "author"
private val ONGOING_SUFFIX = arrayOf(
"[ongoing]",
"(ongoing)",
"{ongoing}"
"[ongoing]",
"(ongoing)",
"{ongoing}"
)
val EX_DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US)
@ -37,8 +38,8 @@ fun ExGalleryMetadata.copyTo(manga: SManga) {
manga.status = SManga.COMPLETED
title?.let { t ->
if (ONGOING_SUFFIX.any {
t.endsWith(it, ignoreCase = true)
}) manga.status = SManga.ONGOING
t.endsWith(it, ignoreCase = true)
}) manga.status = SManga.ONGOING
}
//Build a nice looking description out of what we know
@ -67,8 +68,8 @@ fun ExGalleryMetadata.copyTo(manga: SManga) {
val tagsDesc = buildTagsDescription(this)
manga.description = listOf(titleDesc.toString(), detailsDesc.toString(), tagsDesc.toString())
.filter(String::isNotBlank)
.joinToString(separator = "\n")
.filter(String::isNotBlank)
.joinToString(separator = "\n")
}
private fun buildTagsDescription(metadata: ExGalleryMetadata) = StringBuilder("Tags:\n").apply {

View File

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.extension.all.ehentai;
package eu.kanade.tachiyomi.extension.all.ehentai
/**
* Simple tag model
*/
data class Tag(val name: String, val light: Boolean)
data class Tag(val name: String, val light: Boolean)