Update four "all" sources (#1314)

* ComiCake: Some cleanup work

Signed-off-by: TacoTheDank <SkytkRSfan3895@gmail.com>

* E-Hentai: Some cleanup work

Signed-off-by: TacoTheDank <SkytkRSfan3895@gmail.com>

* FoolSlide: Some cleanup work and source updates

Signed-off-by: TacoTheDank <SkytkRSfan3895@gmail.com>

* Genkan: Some cleanup work

Signed-off-by: TacoTheDank <SkytkRSfan3895@gmail.com>
This commit is contained in:
TacoTheDank 2019-08-03 21:38:05 -04:00 committed by Eugene
parent 27175b3dee
commit c94cc58e7d
16 changed files with 188 additions and 214 deletions

View File

@ -3,9 +3,9 @@ apply plugin: 'kotlin-android'
ext {
appName = 'Tachiyomi: ComiCake'
pkgNameSuffix = "all.comicake"
pkgNameSuffix = 'all.comicake'
extClass = '.ComiCakeFactory'
extVersionCode = 3
extVersionCode = 4
libVersion = '1.2'
}

View File

@ -2,21 +2,24 @@ package eu.kanade.tachiyomi.extension.all.comicake
import android.os.Build
import eu.kanade.tachiyomi.extension.BuildConfig
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.*
import eu.kanade.tachiyomi.source.online.HttpSource
import okhttp3.Headers
import okhttp3.Request
import okhttp3.Response
import eu.kanade.tachiyomi.network.GET
import org.json.JSONArray
import org.json.JSONObject
import java.text.SimpleDateFormat
import kotlin.collections.ArrayList
const val COMICAKE_DEFAULT_API_ENDPOINT = "/api" // Highly unlikely to change
const val COMICAKE_DEFAULT_READER_ENDPOINT = "/r" // Can change based on CC config
open class ComiCake(override val name: String, override val baseUrl: String, override val lang: String, val readerEndpoint: String = COMICAKE_DEFAULT_READER_ENDPOINT, val apiEndpoint: String = COMICAKE_DEFAULT_API_ENDPOINT) : HttpSource() {
open class ComiCake(override val name: String,
final override val baseUrl: String,
override val lang: String,
readerEndpoint: String = COMICAKE_DEFAULT_READER_ENDPOINT,
apiEndpoint: String = COMICAKE_DEFAULT_API_ENDPOINT) : HttpSource() {
override val versionId = 1
override val supportsLatest = true
private val readerBase = baseUrl + readerEndpoint
@ -40,18 +43,18 @@ open class ComiCake(override val name: String, override val baseUrl: String, ove
return getMangasPageFromComicsResponse(res)
}
private fun getMangasPageFromComicsResponse(json: String, nested: Boolean = false) : MangasPage {
var response = JSONObject(json)
var results = response.getJSONArray("results")
private fun getMangasPageFromComicsResponse(json: String, nested: Boolean = false): MangasPage {
val response = JSONObject(json)
val results = response.getJSONArray("results")
val mangas = ArrayList<SManga>()
val ids = mutableListOf<Int>();
val ids = mutableListOf<Int>()
for (i in 0 until results.length()) {
val obj = results.getJSONObject(i)
if(nested) {
val nestedComic = obj.getJSONObject("comic");
if (nested) {
val nestedComic = obj.getJSONObject("comic")
val id = nestedComic.getInt("id")
if(ids.contains(id))
if (ids.contains(id))
continue
ids.add(id)
val manga = SManga.create()
@ -60,13 +63,13 @@ open class ComiCake(override val name: String, override val baseUrl: String, ove
mangas.add(manga)
} else {
val id = obj.getInt("id")
if(ids.contains(id))
if (ids.contains(id))
continue
ids.add(id)
mangas.add(parseComicJson(obj))
}
}
return MangasPage(mangas, if (response.getString("next").isNullOrEmpty() || response.getString("next") == "null") false else true)
return MangasPage(mangas, !(response.getString("next").isNullOrEmpty() || response.getString("next") == "null"))
}
override fun mangaDetailsRequest(manga: SManga): Request {
@ -79,10 +82,10 @@ open class ComiCake(override val name: String, override val baseUrl: String, ove
}
private fun parseComicJson(obj: JSONObject, human: Boolean = false) = SManga.create().apply {
if(human) {
url = "$readerBase/series/${obj.getString("slug")}/"
url = if (human) {
"$readerBase/series/${obj.getString("slug")}/"
} else {
url = obj.getInt("id").toString() // Yeah, I know... Feel free to improve on this
obj.getInt("id").toString() // Yeah, I know... Feel free to improve on this
}
title = obj.getString("name")
thumbnail_url = obj.getString("cover")
@ -93,9 +96,9 @@ open class ComiCake(override val name: String, override val baseUrl: String, ove
status = SManga.UNKNOWN
}
private fun parseListNames(arr: JSONArray) : String {
var hold = ArrayList<String>(arr.length())
for(i in 0 until arr.length())
private fun parseListNames(arr: JSONArray): String {
val hold = ArrayList<String>(arr.length())
for (i in 0 until arr.length())
hold.add(arr.getJSONObject(i).getString("name"))
return hold.sorted().joinToString(", ")
}
@ -133,7 +136,7 @@ open class ComiCake(override val name: String, override val baseUrl: String, ove
override fun chapterListParse(response: Response): List<SChapter> {
val chapterJson = JSONObject(response.body()!!.string())
var results = chapterJson.getJSONArray("results")
val results = chapterJson.getJSONArray("results")
val ret = ArrayList<SChapter>()
for (i in 0 until results.length()) {
ret.add(parseChapterJson(results.getJSONObject(i)))
@ -144,9 +147,9 @@ open class ComiCake(override val name: String, override val baseUrl: String, ove
override fun pageListParse(response: Response): List<Page> {
val webPub = JSONObject(response.body()!!.string())
val readingOrder = webPub.getJSONArray("readingOrder")
val ret = ArrayList<Page>();
val ret = ArrayList<Page>()
for (i in 0 until readingOrder.length()) {
var pageUrl = readingOrder.getJSONObject(i).getString("href")
val pageUrl = readingOrder.getJSONObject(i).getString("href")
ret.add(Page(i, "", pageUrl))
}
return ret

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; .EHPolish; .EHPortuguese; .EHRussian; .EHSpanish; .EHThai; .EHVietnamese; .EHSpeechless; .EHOther'
extVersionCode = 4
extClass = '.EHJapanese; .EHEnglish; .EHChinese; .EHDutch; .EHFrench; .EHGerman; .EHHungarian; .EHItalian; .EHKorean; .EHPolish; .EHPortuguese; .EHRussian; .EHSpanish; .EHThai; .EHVietnamese; .EHSpeechless; .EHOther'
extVersionCode = 5
libVersion = '1.2'
}

View File

@ -3,23 +3,23 @@ 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")
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(),

View File

@ -1,5 +1,8 @@
package eu.kanade.tachiyomi.extension.all.ehentai
import kotlin.math.ln
import kotlin.math.pow
/**
* Various utility methods used in the E-Hentai source
*/
@ -36,18 +39,18 @@ operator fun StringBuilder.plusAssign(other: String) {
*/
fun humanReadableByteCount(bytes: Long, si: Boolean): String {
val unit = if (si) 1000 else 1024
if (bytes < unit) return bytes.toString() + " B"
val exp = (Math.log(bytes.toDouble()) / Math.log(unit.toDouble())).toInt()
if (bytes < unit) return "$bytes B"
val exp = (ln(bytes.toDouble()) / ln(unit.toDouble())).toInt()
val pre = (if (si) "kMGTPE" else "KMGTPE")[exp - 1] + if (si) "" else "i"
return String.format("%.1f %sB", bytes / Math.pow(unit.toDouble(), exp.toDouble()), pre)
return String.format("%.1f %sB", bytes / unit.toDouble().pow(exp.toDouble()), pre)
}
private val KB_FACTOR = 1000
private val KIB_FACTOR = 1024
private val MB_FACTOR = 1000 * KB_FACTOR
private val MIB_FACTOR = 1024 * KIB_FACTOR
private val GB_FACTOR = 1000 * MB_FACTOR
private val GIB_FACTOR = 1024 * MIB_FACTOR
private const val KB_FACTOR = 1000
private const val KIB_FACTOR = 1024
private const val MB_FACTOR = 1000 * KB_FACTOR
private const val MIB_FACTOR = 1024 * KIB_FACTOR
private const val GB_FACTOR = 1000 * MB_FACTOR
private const val GIB_FACTOR = 1024 * MIB_FACTOR
/**
* Parse human readable size Strings

View File

@ -3,24 +3,15 @@ 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.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.model.*
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.CacheControl
import okhttp3.CookieJar
import okhttp3.Headers
import okhttp3.Request
import okhttp3.Response
import okhttp3.*
import org.jsoup.nodes.Element
import rx.Observable
import java.net.URLEncoder
open class EHentai(override val lang: String, val ehLang: String) : HttpSource() {
open class EHentai(override val lang: String, private val ehLang: String) : HttpSource() {
override val name = "E-Hentai"
@ -51,15 +42,13 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
return MangasPage(parsedMangas, hasNextPage)
}
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>>
= Observable.just(listOf(SChapter.create().apply {
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.just(listOf(SChapter.create().apply {
url = manga.url
name = "Chapter"
chapter_number = 1f
}))
override fun fetchPageList(chapter: SChapter)
= fetchChapterPage(chapter, "$baseUrl/${chapter.url}").map {
override fun fetchPageList(chapter: SChapter) = fetchChapterPage(chapter, "$baseUrl/${chapter.url}").map {
it.mapIndexed { i, s ->
Page(i, s)
}
@ -80,8 +69,7 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
}
}
private fun parseChapterPage(response: Element)
= with(response) {
private fun parseChapterPage(response: Element) = with(response) {
select(".gdtm a").map {
Pair(it.child(0).attr("alt").toInt(), it.attr("href"))
}.sortedBy(Pair<Int, String>::first).map { it.second }
@ -90,8 +78,7 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
private fun chapterPageCall(np: String) = client.newCall(chapterPageRequest(np)).asObservableSuccess()
private fun chapterPageRequest(np: String) = exGet(np, null, headers)
private fun nextPageUrl(element: Element)
= element.select("a[onclick=return false]").last()?.let {
private fun nextPageUrl(element: Element) = element.select("a[onclick=return false]").last()?.let {
if (it.text() == ">") it.attr("href") else null
}
@ -115,8 +102,7 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
override fun searchMangaParse(response: Response) = genericMangaParse(response)
override fun latestUpdatesParse(response: Response) = genericMangaParse(response)
private fun exGet(url: String, page: Int? = null, additionalHeaders: Headers? = null, cache: Boolean = true)
= GET(page?.let {
private fun exGet(url: String, page: Int? = null, additionalHeaders: Headers? = null, cache: Boolean = true) = GET(page?.let {
addParam(url, "page", (it - 1).toString())
} ?: url, additionalHeaders?.let {
val headers = headers.newBuilder()
@ -204,7 +190,7 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
Tag(it.text().trim(),
it.hasClass("gtl"))
}
tags.put(namespace, currentTags)
tags[namespace] = currentTags
}
//Copy metadata to manga
@ -214,19 +200,15 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
}
}
override fun chapterListParse(response: Response)
= throw UnsupportedOperationException("Unused method was called somehow!")
override fun chapterListParse(response: Response) = throw UnsupportedOperationException("Unused method was called somehow!")
override fun pageListParse(response: Response)
= throw UnsupportedOperationException("Unused method was called somehow!")
override fun pageListParse(response: Response) = throw UnsupportedOperationException("Unused method was called somehow!")
override fun fetchImageUrl(page: Page)
= client.newCall(imageUrlRequest(page))
override fun fetchImageUrl(page: Page) = client.newCall(imageUrlRequest(page))
.asObservableSuccess()
.map { realImageUrlParse(it, page) }!!
private fun realImageUrlParse(response: Response, page: Page)
= with(response.asJsoup()) {
private fun realImageUrlParse(response: Response, page: Page) = with(response.asJsoup()) {
val currentImage = getElementById("img").attr("src")
//TODO We cannot currently do this as page.url is immutable
//Each press of the retry button will choose another server
@ -236,8 +218,7 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
currentImage
}!!
override fun imageUrlParse(response: Response)
= throw UnsupportedOperationException("Unused method was called somehow!")
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Unused method was called somehow!")
private val cookiesHeader by lazy {
val cookies = mutableMapOf<String, String>()
@ -253,25 +234,21 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
.flatMap { it.second }
.joinToString("x")
cookies.put("uconfig", buildSettings(settings))
cookies["uconfig"] = buildSettings(settings)
buildCookies(cookies)
}
//Headers
override fun headersBuilder()
= super.headersBuilder().add("Cookie", cookiesHeader)!!
override fun headersBuilder() = super.headersBuilder().add("Cookie", cookiesHeader)!!
private fun buildSettings(settings: List<String?>)
= settings.filterNotNull().joinToString(separator = "-")
private fun buildSettings(settings: List<String?>) = settings.filterNotNull().joinToString(separator = "-")
private fun buildCookies(cookies: Map<String, String>)
= cookies.entries.map {
private fun buildCookies(cookies: Map<String, String>) = cookies.entries.joinToString(separator = "; ", postfix = ";") {
"${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}"
}.joinToString(separator = "; ", postfix = ";")
}
private fun addParam(url: String, param: String, value: String)
= Uri.parse(url)
private fun addParam(url: String, param: String, value: String) = Uri.parse(url)
.buildUpon()
.appendQueryParameter(param, value)
.toString()
@ -295,9 +272,9 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
AdvancedGroup()
)
class GenreOption(name: String, val genreId: String) : Filter.CheckBox(name, false), UriFilter {
class GenreOption(name: String, private val genreId: String) : Filter.CheckBox(name, false), UriFilter {
override fun addToUri(builder: Uri.Builder) {
builder.appendQueryParameter("f_" + genreId, if (state) "1" else "0")
builder.appendQueryParameter("f_$genreId", if (state) "1" else "0")
}
}
@ -314,7 +291,7 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
GenreOption("Misc", "misc")
))
class AdvancedOption(name: String, val param: String, defValue: Boolean = false) : Filter.CheckBox(name, defValue), UriFilter {
class AdvancedOption(name: String, private val param: String, defValue: Boolean = false) : Filter.CheckBox(name, defValue), UriFilter {
override fun addToUri(builder: Uri.Builder) {
if (state)
builder.appendQueryParameter(param, "on")
@ -329,7 +306,7 @@ open class EHentai(override val lang: String, val ehLang: String) : HttpSource()
"5 stars"
)), UriFilter {
override fun addToUri(builder: Uri.Builder) {
if (state > 0) builder.appendQueryParameter("f_srdd", Integer.toString(state + 1))
if (state > 0) builder.appendQueryParameter("f_srdd", (state + 1).toString())
}
}

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.extension.all.ehentai;
package eu.kanade.tachiyomi.extension.all.ehentai
import android.net.Uri
@ -32,25 +32,21 @@ class ExGalleryMetadata {
val tags: MutableMap<String, List<Tag>> = mutableMapOf()
companion object {
private fun splitGalleryUrl(url: String)
= url.let {
private fun splitGalleryUrl(url: String) = url.let {
//Only parse URL if is full URL
val pathSegments = if(it.startsWith("http"))
val pathSegments = if (it.startsWith("http"))
Uri.parse(it).pathSegments
else
it.split('/')
pathSegments.filterNot(String::isNullOrBlank)
}
fun galleryId(url: String) = splitGalleryUrl(url)[1]
private fun galleryId(url: String) = splitGalleryUrl(url)[1]
fun galleryToken(url: String) =
splitGalleryUrl(url)[2]
private fun galleryToken(url: String) = splitGalleryUrl(url)[2]
fun normalizeUrl(id: String, token: String)
= "/g/$id/$token/?nw=always"
private fun normalizeUrl(id: String, token: String) = "/g/$id/$token/?nw=always"
fun normalizeUrl(url: String)
= normalizeUrl(galleryId(url), galleryToken(url))
fun normalizeUrl(url: String) = normalizeUrl(galleryId(url), galleryToken(url))
}
}

View File

@ -71,8 +71,7 @@ fun ExGalleryMetadata.copyTo(manga: SManga) {
.joinToString(separator = "\n")
}
private fun buildTagsDescription(metadata: ExGalleryMetadata)
= StringBuilder("Tags:\n").apply {
private fun buildTagsDescription(metadata: ExGalleryMetadata) = StringBuilder("Tags:\n").apply {
//BiConsumer only available in Java 8, we have to use destructuring here
metadata.tags.forEach { (namespace, tags) ->
if (tags.isNotEmpty()) {

View File

@ -3,9 +3,9 @@ apply plugin: 'kotlin-android'
ext {
appName = 'Tachiyomi: FoolSlide'
pkgNameSuffix = "all.foolslide"
pkgNameSuffix = 'all.foolslide'
extClass = '.FoolSlideFactory'
extVersionCode = 21
extVersionCode = 22
libVersion = '1.2'
}

View File

@ -16,7 +16,10 @@ import java.text.SimpleDateFormat
import java.util.*
open class FoolSlide(override val name: String, override val baseUrl: String, override val lang: String, val urlModifier: String = "") : ParsedHttpSource() {
open class FoolSlide(override val name: String,
override val baseUrl: String,
override val lang: String,
val urlModifier: String = "") : ParsedHttpSource() {
protected open val dedupeLatestUpdates = true
@ -32,7 +35,7 @@ open class FoolSlide(override val name: String, override val baseUrl: String, ov
override fun latestUpdatesParse(response: Response): MangasPage {
val mp = super.latestUpdatesParse(response)
return if(dedupeLatestUpdates) {
return if (dedupeLatestUpdates) {
val mangas = mp.mangas.distinctBy { it.url }.filterNot { latestUpdatesUrls.contains(it.url) }
latestUpdatesUrls.addAll(mangas.map { it.url })
MangasPage(mangas, mp.hasNextPage)
@ -96,8 +99,7 @@ open class FoolSlide(override val name: String, override val baseUrl: String, ov
override fun searchMangaNextPageSelector() = "a:has(span.next)"
override fun mangaDetailsRequest(manga: SManga)
= allowAdult(super.mangaDetailsRequest(manga))
override fun mangaDetailsRequest(manga: SManga) = allowAdult(super.mangaDetailsRequest(manga))
open val mangaDetailsInfoSelector = "div.info"
open val mangaDetailsThumbnailSelector = "div.thumbnail img"
@ -119,14 +121,13 @@ open class FoolSlide(override val name: String, override val baseUrl: String, ov
*/
private fun allowAdult(request: Request) = allowAdult(request.url().toString())
protected fun allowAdult(url: String): Request {
private fun allowAdult(url: String): Request {
return POST(url, body = FormBody.Builder()
.add("adult", "true")
.build())
}
override fun chapterListRequest(manga: SManga)
= allowAdult(super.chapterListRequest(manga))
override fun chapterListRequest(manga: SManga) = allowAdult(super.chapterListRequest(manga))
override fun chapterListSelector() = "div.group div.element, div.list div.element"
@ -140,7 +141,8 @@ open class FoolSlide(override val name: String, override val baseUrl: String, ov
val chapter = SChapter.create()
chapter.setUrlWithoutDomain(urlElement.attr("href"))
chapter.name = urlElement.text()
chapter.date_upload = dateElement.text()?.let { parseChapterDate(it.substringAfter(", ")) } ?: 0
chapter.date_upload = dateElement.text()?.let { parseChapterDate(it.substringAfter(", ")) }
?: 0
return chapter
}
@ -172,18 +174,18 @@ open class FoolSlide(override val name: String, override val baseUrl: String, ov
var result = DATE_FORMAT_1.parseOrNull(date)
for(dateFormat in DATE_FORMATS_WITH_ORDINAL_SUFFIXES) {
for (dateFormat in DATE_FORMATS_WITH_ORDINAL_SUFFIXES) {
if (result == null)
result = dateFormat.parseOrNull(date)
else
break
}
for(dateFormat in DATE_FORMATS_WITH_ORDINAL_SUFFIXES_NO_YEAR) {
for (dateFormat in DATE_FORMATS_WITH_ORDINAL_SUFFIXES_NO_YEAR) {
if (result == null) {
result = dateFormat.parseOrNull(date)
if(result != null) {
if (result != null) {
// Result parsed but no year, copy current year over
result = Calendar.getInstance().apply {
time = result
@ -230,13 +232,12 @@ open class FoolSlide(override val name: String, override val baseUrl: String, ov
private fun SimpleDateFormat.parseOrNull(string: String): Date? {
return try {
parse(string)
} catch(e: ParseException) {
} catch (e: ParseException) {
null
}
}
override fun pageListRequest(chapter: SChapter)
= allowAdult(super.pageListRequest(chapter))
override fun pageListRequest(chapter: SChapter) = allowAdult(super.pageListRequest(chapter))
override fun pageListParse(document: Document): List<Page> {
val doc = document.toString()

View File

@ -6,7 +6,8 @@ import com.google.gson.JsonParser
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory
import eu.kanade.tachiyomi.source.model.*
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.Request
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
@ -36,7 +37,6 @@ fun getAllFoolSlide(): List<Source> {
MangaScouts(),
StormInHeaven(),
Lilyreader(),
MidnightHaven(),
Russification(),
EvilFlowers(),
AkaiYuhiMunTeam(),
@ -74,7 +74,7 @@ class SenseScans : FoolSlide("Sense-Scans", "https://sensescans.com", "en", "/re
class KireiCake : FoolSlide("Kirei Cake", "https://reader.kireicake.com", "en")
class SilentSky : FoolSlide("Silent Sky", "http://reader.silentsky-scans.net", "en")
class SilentSky : FoolSlide("Silent Sky", "https://reader.silentsky-scans.net", "en")
class Mangatellers : FoolSlide("Mangatellers", "http://www.mangatellers.gr", "en", "/reader/reader") {
override fun popularMangaRequest(page: Int): Request {
@ -108,12 +108,10 @@ class TsubasaSociety : FoolSlide("Tsubasa Society", "https://www.tsubasasociety.
class MangaScouts : FoolSlide("MangaScouts", "http://onlinereader.mangascouts.org", "de")
class StormInHeaven : FoolSlide("Storm in Heaven", "http://www.storm-in-heaven.net", "it", "/reader-sih")
class StormInHeaven : FoolSlide("Storm in Heaven", "https://www.storm-in-heaven.net", "it", "/reader-sih")
class Lilyreader : FoolSlide("Lilyreader", "https://manga.smuglo.li", "en")
class MidnightHaven : FoolSlide("Midnight Haven", "http://midnighthaven.shounen-ai.net", "en", "/reader")
class Russification : FoolSlide("Русификация", "https://rusmanga.ru", "ru")
class EvilFlowers : FoolSlide("Evil Flowers", "http://reader.evilflowers.com", "en")
@ -158,5 +156,3 @@ class ShoujoHearts : FoolSlide("ShoujoHearts", "http://shoujohearts.com", "en",
return manga
}
}

View File

@ -63,7 +63,7 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
}
filters.findInstance<ArtistFilter>()?.let { f ->
if(f.state.isNotBlank()) {
if (f.state.isNotBlank()) {
requireNoUrl()
url = "/artist/${f.state
.trim()
@ -72,19 +72,19 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
}
}
filters.findInstance<BookFilter>()?.let { f ->
if(f.state) {
if (f.state) {
requireNoUrl()
url = "/category/book/"
}
}
filters.findInstance<TagFilter>()?.let { f ->
if(f.state != 0) {
if (f.state != 0) {
requireNoUrl()
url = "/tag/${f.values[f.state].name}/"
}
}
if(query.isNotBlank()) {
if (query.isNotBlank()) {
requireNoUrl()
url = "/"
queryString = "s=" + URLEncoder.encode(query, "UTF-8")
@ -97,8 +97,8 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
private fun pagedRequest(url: String, page: Int, queryString: String? = null): Request {
// The site redirects page 1 -> url-without-page so we do this redirect early for optimization
val builtUrl = if(page == 1) url else "${url}page/$page/"
return GET(if(queryString != null) "$builtUrl?$queryString" else builtUrl)
val builtUrl = if (page == 1) url else "${url}page/$page/"
return GET(if (queryString != null) "$builtUrl?$queryString" else builtUrl)
}
override fun searchMangaParse(response: Response) = latestUpdatesParse(response)
@ -106,7 +106,7 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return client.newCall(searchMangaRequest(page, query, filters))
.asObservable().doOnNext { response ->
if(!response.isSuccessful) {
if (!response.isSuccessful) {
response.close()
// Better error message for invalid artist
if (response.code() == 404
@ -132,7 +132,6 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
class ArtistFilter : Filter.Text("Artist (must be exact match)")
class BookFilter : Filter.CheckBox("Show books only", false)
class TagFilter : Filter.Select<Tag>("Tag", arrayOf(
Tag("all", "All"),
Tag("ahegao", "Ahegao"),
Tag("anal", "Anal"),
Tag("big-ass", "Big ass"),
@ -155,9 +154,9 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
Tag("group", "Group"),
Tag("hairy", "Hairy"),
Tag("handjob", "Handjob"),
Tag("heart-pupils", "Heart pupils"),
Tag("housewife", "Housewife"),
Tag("incest", "Incest"),
Tag("large-breast", "Large breast"),
Tag("lingerie", "Lingerie"),
Tag("loli", "Loli"),
Tag("masturbation", "Masturbation"),
@ -167,7 +166,7 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
Tag("pettanko", "Pettanko"),
Tag("rape", "Rape"),
Tag("schoolgirl", "Schoolgirl"),
Tag("sex-toys", "Sex Toys"),
Tag("sex-toys", "Sex toys"),
Tag("shota", "Shota"),
Tag("socks", "Socks"),
Tag("stocking", "Stocking"),
@ -175,11 +174,12 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
Tag("swimsuit", "Swimsuit"),
Tag("teacher", "Teacher"),
Tag("tsundere", "Tsundere"),
Tag("uncensored", "uncensored"),
Tag("uncensored", "Uncensored"),
Tag("vanilla", "Vanilla"),
Tag("x-ray", "X-ray")
Tag("x-ray", "X-Ray")
))
class Tag(val name: String, val displayName: String) {
class Tag(val name: String, private val displayName: String) {
override fun toString() = displayName
}

View File

@ -5,7 +5,7 @@ ext {
appName = 'Tachiyomi: Genkan (multiple sources)'
pkgNameSuffix = 'all.genkan'
extClass = '.GenkanFactory'
extVersionCode = 2
extVersionCode = 3
libVersion = '1.2'
}

View File

@ -15,7 +15,7 @@ import java.util.*
abstract class Genkan(
override val name: String,
override val baseUrl: String,
final override val baseUrl: String,
override val lang: String
) : ParsedHttpSource() {
@ -165,10 +165,10 @@ abstract class Genkan(
// If the date string contains the word "ago" send it off for relative date parsing otherwise use dateFormat
private fun parseChapterDate(string: String): Long? {
if ("ago" in string) {
return parseRelativeDate(string) ?: 0
return if ("ago" in string) {
parseRelativeDate(string) ?: 0
} else {
return dateFormat.parse(string).time
dateFormat.parse(string).time
}
}
@ -177,13 +177,13 @@ abstract class Genkan(
val trimmedDate = date.substringBefore(" ago").removeSuffix("s").split(" ")
val calendar = Calendar.getInstance()
when (trimmedDate[1]){
"month" -> calendar.apply{add(Calendar.MONTH, -trimmedDate[0].toInt())}
"week" -> calendar.apply{add(Calendar.WEEK_OF_MONTH, -trimmedDate[0].toInt())}
"day" -> calendar.apply{add(Calendar.DAY_OF_MONTH, -trimmedDate[0].toInt())}
"hour" -> calendar.apply{add(Calendar.HOUR_OF_DAY, -trimmedDate[0].toInt())}
"minute" -> calendar.apply{add(Calendar.MINUTE, -trimmedDate[0].toInt())}
"second" -> calendar.apply{add(Calendar.SECOND, 0)}
when (trimmedDate[1]) {
"month" -> calendar.apply { add(Calendar.MONTH, -trimmedDate[0].toInt()) }
"week" -> calendar.apply { add(Calendar.WEEK_OF_MONTH, -trimmedDate[0].toInt()) }
"day" -> calendar.apply { add(Calendar.DAY_OF_MONTH, -trimmedDate[0].toInt()) }
"hour" -> calendar.apply { add(Calendar.HOUR_OF_DAY, -trimmedDate[0].toInt()) }
"minute" -> calendar.apply { add(Calendar.MINUTE, -trimmedDate[0].toInt()) }
"second" -> calendar.apply { add(Calendar.SECOND, 0) }
}
return calendar.timeInMillis
@ -207,5 +207,4 @@ abstract class Genkan(
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
override fun getFilterList() = FilterList()
}