Update Kotlin, coroutines, kolinter (#4363)
* Update kolinter, address some build warnings * Update to Kotlin 1.4.10, coroutines 1.3.9
This commit is contained in:
parent
19a3cd2367
commit
016653bdc0
|
@ -1,6 +1,6 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.3.72'
|
||||
ext.coroutines_version = '1.3.5'
|
||||
ext.kotlin_version = '1.4.10'
|
||||
ext.coroutines_version = '1.3.9'
|
||||
repositories {
|
||||
google()
|
||||
maven { url 'https://plugins.gradle.org/m2/' }
|
||||
|
@ -10,7 +10,7 @@ buildscript {
|
|||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||
classpath 'org.jmailen.gradle:kotlinter-gradle:2.3.2'
|
||||
classpath 'org.jmailen.gradle:kotlinter-gradle:3.0.2'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
object Deps {
|
||||
object kotlin {
|
||||
const val version = "1.3.72"
|
||||
const val version = "1.4.10"
|
||||
const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version"
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
open class BoomManga(
|
||||
override val name: String,
|
||||
|
@ -69,11 +69,11 @@ open class BoomManga(
|
|||
|
||||
override fun chapterFromElement(element: Element): SChapter {
|
||||
val chapter = SChapter.create()
|
||||
chapter.url = element.select("a").attr("href")
|
||||
chapter.chapter_number = element.select("[data-num]").attr("data-num").toFloat()
|
||||
val date = element.select(".date").text()
|
||||
if (date.isNotBlank()) { chapter.date_upload = parseDate(date) }
|
||||
chapter.name = nameselector(element).trim()
|
||||
chapter.url = element.select("a").attr("href")
|
||||
chapter.chapter_number = element.select("[data-num]").attr("data-num").toFloat()
|
||||
val date = element.select(".date").text()
|
||||
if (date.isNotBlank()) { chapter.date_upload = parseDate(date) }
|
||||
chapter.name = nameselector(element).trim()
|
||||
return chapter
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ open class BoomManga(
|
|||
}
|
||||
|
||||
private fun parseDate(date: String): Long {
|
||||
return SimpleDateFormat("yyyy-MM-dd kk:mm:ss", Locale.US).parse(date).time
|
||||
return SimpleDateFormat("yyyy-MM-dd kk:mm:ss", Locale.US).parse(date)?.time ?: 0L
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga {
|
||||
|
|
|
@ -10,14 +10,14 @@ 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 java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
abstract class ComiCake(
|
||||
override val name: String,
|
||||
|
@ -146,7 +146,7 @@ abstract class ComiCake(
|
|||
private fun parseChapterJson(obj: JSONObject) = SChapter.create().apply {
|
||||
name = obj.getString("title") // title will always have content, vs. name that's an optional field
|
||||
chapter_number = (obj.getInt("chapter") + (obj.getInt("subchapter") / 10.0)).toFloat()
|
||||
date_upload = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZ", Locale.getDefault()).parse(obj.getString("published_at")).time
|
||||
date_upload = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZ", Locale.getDefault()).parse(obj.getString("published_at"))?.time ?: 0L
|
||||
// TODO scanlator field by adding team to expandable in CC (low priority given the use case of CC)
|
||||
url = obj.getString("manifest")
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ import android.annotation.SuppressLint
|
|||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.support.v7.preference.CheckBoxPreference as LegacyCheckBoxPreference
|
||||
import android.support.v7.preference.PreferenceScreen as LegacyPreferenceScreen
|
||||
import androidx.preference.CheckBoxPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
|
@ -24,7 +22,6 @@ 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 java.net.URLEncoder
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.Headers
|
||||
|
@ -34,6 +31,9 @@ import org.jsoup.nodes.Element
|
|||
import rx.Observable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.net.URLEncoder
|
||||
import android.support.v7.preference.CheckBoxPreference as LegacyCheckBoxPreference
|
||||
import android.support.v7.preference.PreferenceScreen as LegacyPreferenceScreen
|
||||
|
||||
open class EHentai(override val lang: String, private val ehLang: String) : ConfigurableSource, HttpSource() {
|
||||
|
||||
|
@ -85,11 +85,15 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
|
|||
return MangasPage(parsedMangas, hasNextPage)
|
||||
}
|
||||
|
||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.just(listOf(SChapter.create().apply {
|
||||
url = manga.url
|
||||
name = "Chapter"
|
||||
chapter_number = 1f
|
||||
}))
|
||||
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 {
|
||||
it.mapIndexed { i, s ->
|
||||
|
@ -218,8 +222,10 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
|
|||
?.trim()
|
||||
?.let { right ->
|
||||
ignore {
|
||||
when (left.removeSuffix(":")
|
||||
.toLowerCase()) {
|
||||
when (
|
||||
left.removeSuffix(":")
|
||||
.toLowerCase()
|
||||
) {
|
||||
"posted" -> datePosted = EX_DATE_FORMAT.parse(right)?.time ?: 0
|
||||
"visible" -> visible = right.nullIfBlank()
|
||||
"language" -> {
|
||||
|
@ -255,8 +261,10 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
|
|||
select("#taglist tr").forEach {
|
||||
val namespace = it.select(".tc").text().removeSuffix(":")
|
||||
val currentTags = it.select("div").map { element ->
|
||||
Tag(element.text().trim(),
|
||||
element.hasClass("gtl"))
|
||||
Tag(
|
||||
element.text().trim(),
|
||||
element.hasClass("gtl")
|
||||
)
|
||||
}
|
||||
tags[namespace] = currentTags
|
||||
}
|
||||
|
@ -367,18 +375,21 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
|
|||
}
|
||||
}
|
||||
|
||||
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")
|
||||
))
|
||||
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")
|
||||
)
|
||||
)
|
||||
|
||||
class AdvancedOption(name: String, private val param: String, defValue: Boolean = false) : CheckBox(name, defValue), UriFilter {
|
||||
override fun addToUri(builder: Uri.Builder) {
|
||||
|
@ -423,19 +434,22 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
|
|||
}
|
||||
|
||||
// Explicit type arg for listOf() to workaround this: KT-16570
|
||||
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(),
|
||||
MinPagesOption(),
|
||||
MaxPagesOption()
|
||||
))
|
||||
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(),
|
||||
MinPagesOption(),
|
||||
MaxPagesOption()
|
||||
)
|
||||
)
|
||||
|
||||
private class EnforceLanguageFilter(default: Boolean) : CheckBox("Enforce language", default)
|
||||
|
||||
|
|
|
@ -38,8 +38,9 @@ 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
|
||||
|
|
|
@ -37,14 +37,17 @@ open class EliMangasProvider(
|
|||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val json = gson.fromJson<JsonArray>(response.body()!!.string()).asJsonArray
|
||||
|
||||
return MangasPage(json.map {
|
||||
SManga.create().apply {
|
||||
val id = it["id"].asString
|
||||
url = id
|
||||
title = it["name"].asString
|
||||
thumbnail_url = "https://www.elimangas.com/images/$id.jpg"
|
||||
}
|
||||
}, json.size() >= 30)
|
||||
return MangasPage(
|
||||
json.map {
|
||||
SManga.create().apply {
|
||||
val id = it["id"].asString
|
||||
url = id
|
||||
title = it["name"].asString
|
||||
thumbnail_url = "https://www.elimangas.com/images/$id.jpg"
|
||||
}
|
||||
},
|
||||
json.size() >= 30
|
||||
)
|
||||
}
|
||||
|
||||
// Latest
|
||||
|
|
|
@ -7,14 +7,14 @@ 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.ParsedHttpSource
|
||||
import java.util.Calendar
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.Calendar
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
open class Emerald(
|
||||
override val name: String,
|
||||
|
@ -76,8 +76,11 @@ open class Emerald(
|
|||
}
|
||||
}
|
||||
if (styleToInclude.isNotEmpty()) {
|
||||
url.addQueryParameter("styles", styleToInclude
|
||||
.joinToString(","))
|
||||
url.addQueryParameter(
|
||||
"styles",
|
||||
styleToInclude
|
||||
.joinToString(",")
|
||||
)
|
||||
}
|
||||
}
|
||||
is DemographicFilter -> {
|
||||
|
@ -88,8 +91,11 @@ open class Emerald(
|
|||
}
|
||||
}
|
||||
if (demographicToInclude.isNotEmpty()) {
|
||||
url.addQueryParameter("demogs", demographicToInclude
|
||||
.joinToString(","))
|
||||
url.addQueryParameter(
|
||||
"demogs",
|
||||
demographicToInclude
|
||||
.joinToString(",")
|
||||
)
|
||||
}
|
||||
}
|
||||
is StatusFilter -> {
|
||||
|
@ -110,8 +116,11 @@ open class Emerald(
|
|||
}
|
||||
}
|
||||
if (genreToInclude.isNotEmpty()) {
|
||||
url.addQueryParameter("genres", genreToInclude
|
||||
.joinToString(","))
|
||||
url.addQueryParameter(
|
||||
"genres",
|
||||
genreToInclude
|
||||
.joinToString(",")
|
||||
)
|
||||
}
|
||||
}
|
||||
is StarFilter -> {
|
||||
|
@ -154,8 +163,10 @@ open class Emerald(
|
|||
val manga = SManga.create()
|
||||
val genres = mutableListOf<String>()
|
||||
val status = infoElement.select("div.attr-item:contains(status) span").text()
|
||||
infoElement.select("div.attr-item:contains(genres) span").text().split(" / "
|
||||
.toRegex()).forEach { element ->
|
||||
infoElement.select("div.attr-item:contains(genres) span").text().split(
|
||||
" / "
|
||||
.toRegex()
|
||||
).forEach { element ->
|
||||
genres.add(element)
|
||||
}
|
||||
manga.title = infoElement.select("h3").text()
|
||||
|
@ -259,10 +270,12 @@ open class Emerald(
|
|||
val imgJson = JSONObject(script)
|
||||
val imgNames = imgJson.names()
|
||||
|
||||
for (i in 0 until imgNames.length()) {
|
||||
val imgKey = imgNames.getString(i)
|
||||
val imgUrl = imgJson.getString(imgKey)
|
||||
pages.add(Page(i, "", imgUrl))
|
||||
if (imgNames != null) {
|
||||
for (i in 0 until imgNames.length()) {
|
||||
val imgKey = imgNames.getString(i)
|
||||
val imgUrl = imgJson.getString(imgKey)
|
||||
pages.add(Page(i, "", imgUrl))
|
||||
}
|
||||
}
|
||||
|
||||
return pages
|
||||
|
@ -276,40 +289,49 @@ open class Emerald(
|
|||
private class GenreFilter(genres: List<Tag>) : Filter.Group<Tag>("Genres", genres)
|
||||
private class StatusFilter : Filter.TriState("Completed")
|
||||
|
||||
private class StarFilter : UriPartFilter("Stars", arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("5 Stars", "5"),
|
||||
Pair("4 Stars", "4"),
|
||||
Pair("3 Stars", "3"),
|
||||
Pair("2 Stars", "2"),
|
||||
Pair("1 Stars", "1")
|
||||
))
|
||||
private class StarFilter : UriPartFilter(
|
||||
"Stars",
|
||||
arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("5 Stars", "5"),
|
||||
Pair("4 Stars", "4"),
|
||||
Pair("3 Stars", "3"),
|
||||
Pair("2 Stars", "2"),
|
||||
Pair("1 Stars", "1")
|
||||
)
|
||||
)
|
||||
|
||||
private class ChapterFilter : UriPartFilter("Chapters", arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("1 ~ 9", "1-9"),
|
||||
Pair("10 ~ 29", "10-29"),
|
||||
Pair("30 ~ 99", "30-99"),
|
||||
Pair("100 ~ 199", "100-199"),
|
||||
Pair("200+", "200"),
|
||||
Pair("100+", "100"),
|
||||
Pair("50+", "50"),
|
||||
Pair("10+", "10"),
|
||||
Pair("1+", "1")
|
||||
))
|
||||
private class ChapterFilter : UriPartFilter(
|
||||
"Chapters",
|
||||
arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("1 ~ 9", "1-9"),
|
||||
Pair("10 ~ 29", "10-29"),
|
||||
Pair("30 ~ 99", "30-99"),
|
||||
Pair("100 ~ 199", "100-199"),
|
||||
Pair("200+", "200"),
|
||||
Pair("100+", "100"),
|
||||
Pair("50+", "50"),
|
||||
Pair("10+", "10"),
|
||||
Pair("1+", "1")
|
||||
)
|
||||
)
|
||||
|
||||
private class SortBy : UriPartFilter("Sorts By", arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("Totally", "views_t"),
|
||||
Pair("365 days", "views_y"),
|
||||
Pair("30 days", "views_m"),
|
||||
Pair("7 days", "views_w"),
|
||||
Pair("24 hours", "views_d"),
|
||||
Pair("60 minutes", "views_h"),
|
||||
Pair("A-Z", "title"),
|
||||
Pair("Update time", "update"),
|
||||
Pair("Add time", "create")
|
||||
))
|
||||
private class SortBy : UriPartFilter(
|
||||
"Sorts By",
|
||||
arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("Totally", "views_t"),
|
||||
Pair("365 days", "views_y"),
|
||||
Pair("30 days", "views_m"),
|
||||
Pair("7 days", "views_w"),
|
||||
Pair("24 hours", "views_d"),
|
||||
Pair("60 minutes", "views_h"),
|
||||
Pair("A-Z", "title"),
|
||||
Pair("Update time", "update"),
|
||||
Pair("Add time", "create")
|
||||
)
|
||||
)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
Filter.Header("NOTE: Ignored if using text search!"),
|
||||
|
|
|
@ -10,8 +10,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.nio.charset.Charset
|
||||
import java.util.Calendar
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -20,6 +18,8 @@ import okhttp3.Response
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import org.jsoup.select.Elements
|
||||
import java.nio.charset.Charset
|
||||
import java.util.Calendar
|
||||
|
||||
/**
|
||||
* For sites based on the Flat-Manga CMS
|
||||
|
@ -81,11 +81,14 @@ abstract class FMReader(
|
|||
url.addQueryParameter("ungenre", ungenre)
|
||||
}
|
||||
is SortBy -> {
|
||||
url.addQueryParameter("sort", when (filter.state?.index) {
|
||||
0 -> "name"
|
||||
1 -> "views"
|
||||
else -> "last_update"
|
||||
})
|
||||
url.addQueryParameter(
|
||||
"sort",
|
||||
when (filter.state?.index) {
|
||||
0 -> "name"
|
||||
1 -> "views"
|
||||
else -> "last_update"
|
||||
}
|
||||
)
|
||||
if (filter.state?.ascending == true)
|
||||
url.addQueryParameter("sort_type", "ASC")
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ 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.util.asJsoup
|
||||
import java.net.URLEncoder
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -20,6 +19,7 @@ import okhttp3.Response
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.net.URLEncoder
|
||||
|
||||
class FMReaderFactory : SourceFactory {
|
||||
override fun createSources(): List<Source> = listOf(
|
||||
|
@ -242,9 +242,11 @@ class SayTruyen : FMReader("Say Truyen", "https://saytruyen.com", "vi") {
|
|||
}
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return response.asJsoup().let { document ->
|
||||
document.select(chapterListSelector()).map { chapterFromElement(it).apply {
|
||||
scanlator = document.select("div.row li:has(b:contains(Nhóm dịch)) small").text()
|
||||
} }
|
||||
document.select(chapterListSelector()).map {
|
||||
chapterFromElement(it).apply {
|
||||
scanlator = document.select("div.row li:has(b:contains(Nhóm dịch)) small").text()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun pageListParse(document: Document): List<Page> = super.pageListParse(document).onEach { it.imageUrl!!.trim() }
|
||||
|
|
|
@ -10,17 +10,17 @@ 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.ParsedHttpSource
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.HashSet
|
||||
import java.util.Locale
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
abstract class FoolSlide(
|
||||
override val name: String,
|
||||
|
@ -116,9 +116,9 @@ abstract class FoolSlide(
|
|||
// if there's no image on the details page, get the first page of the first chapter
|
||||
fun getDetailsThumbnail(document: Document, urlSelector: String = chapterUrlSelector): String? {
|
||||
return document.select("div.thumbnail img, table.thumb img").firstOrNull()?.attr("abs:src")
|
||||
?: document.select(chapterListSelector()).last().select(urlSelector).attr("abs:href")
|
||||
.let { url -> client.newCall(allowAdult(GET(url, headers))).execute() }
|
||||
.let { response -> pageListParse(response).first().imageUrl }
|
||||
?: document.select(chapterListSelector()).last().select(urlSelector).attr("abs:href")
|
||||
.let { url -> client.newCall(allowAdult(GET(url, headers))).execute() }
|
||||
.let { response -> pageListParse(response).first().imageUrl }
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga {
|
||||
|
@ -138,9 +138,12 @@ abstract class FoolSlide(
|
|||
private fun allowAdult(request: Request) = allowAdult(request.url().toString())
|
||||
|
||||
private fun allowAdult(url: String): Request {
|
||||
return POST(url, body = FormBody.Builder()
|
||||
.add("adult", "true")
|
||||
.build())
|
||||
return POST(
|
||||
url,
|
||||
body = FormBody.Builder()
|
||||
.add("adult", "true")
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
override fun chapterListRequest(manga: SManga) = allowAdult(super.chapterListRequest(manga))
|
||||
|
@ -216,7 +219,7 @@ abstract class FoolSlide(
|
|||
if (result != null) {
|
||||
// Result parsed but no year, copy current year over
|
||||
result = Calendar.getInstance().apply {
|
||||
time = result
|
||||
time = result!!
|
||||
set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR))
|
||||
}.time
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@ import eu.kanade.tachiyomi.source.model.MangasPage
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.net.URLEncoder
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.net.URLEncoder
|
||||
|
||||
@Nsfw
|
||||
class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga") {
|
||||
|
@ -124,7 +124,8 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
|
|||
response.close()
|
||||
// Better error message for invalid artist
|
||||
if (response.code() == 404 &&
|
||||
!filters.findInstance<ArtistFilter>()?.state.isNullOrBlank())
|
||||
!filters.findInstance<ArtistFilter>()?.state.isNullOrBlank()
|
||||
)
|
||||
error("Invalid artist!")
|
||||
else throw Exception("HTTP error ${response.code()}")
|
||||
}
|
||||
|
@ -145,192 +146,195 @@ 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("", "<select>"),
|
||||
Tag("ahegao", "Ahegao"),
|
||||
Tag("anal", "Anal"),
|
||||
Tag("apron", "Apron"),
|
||||
Tag("ashioki", "Ashioki"),
|
||||
Tag("bakunyuu", "Bakunyuu"),
|
||||
Tag("bathroom-sex", "Bathroom sex"),
|
||||
Tag("beauty-mark", "Beauty mark"),
|
||||
Tag("big-ass", "Big ass"),
|
||||
Tag("big-breast", "Big breast"),
|
||||
Tag("big-dick", "Big dick"),
|
||||
Tag("biting", "Biting"),
|
||||
Tag("black-mail", "Blackmail"),
|
||||
Tag("blindfold", "Blindfold"),
|
||||
Tag("blowjob", "Blowjob"),
|
||||
Tag("body-swap", "Body swap"),
|
||||
Tag("bondage", "Bondage"),
|
||||
Tag("booty", "Booty"),
|
||||
Tag("bride", "Bride"),
|
||||
Tag("bukkake", "Bukkake"),
|
||||
Tag("bunny-girl", "Bunny girl"),
|
||||
Tag("busty", "Busty"),
|
||||
Tag("cat", "Cat"),
|
||||
Tag("cat-girl", "Cat girl"),
|
||||
Tag("catgirl", "Catgirl"),
|
||||
Tag("cheating", "Cheating"),
|
||||
Tag("cheerleader", "Cheerleader"),
|
||||
Tag("chikan", "Chikan"),
|
||||
Tag("christmas", "Christmas"),
|
||||
Tag("chubby", "Chubby"),
|
||||
Tag("color", "Color"),
|
||||
Tag("comedy", "Comedy"),
|
||||
Tag("condom", "Condom"),
|
||||
Tag("cosplay", "Cosplay"),
|
||||
Tag("creampie", "Creampie"),
|
||||
Tag("crossdressing", "Crossdressing"),
|
||||
Tag("crotch-tattoo", "Crotch tattoo"),
|
||||
Tag("cunnilingus", "Cunnilingus"),
|
||||
Tag("dark-skin", "Dark skin"),
|
||||
Tag("deepthroat", "Deepthroat"),
|
||||
Tag("defloration", "Defloration"),
|
||||
Tag("devil", "Devil"),
|
||||
Tag("double-penetration", "Double penetration"),
|
||||
Tag("doujin", "Doujin"),
|
||||
Tag("doujinshi", "Doujinshi"),
|
||||
Tag("drama", "Drama"),
|
||||
Tag("drug", "Drug"),
|
||||
Tag("drunk", "Drunk"),
|
||||
Tag("elf", "Elf"),
|
||||
Tag("exhibitionism", "Exhibitionism"),
|
||||
Tag("eyebrows", "Eyebrows"),
|
||||
Tag("eyepatch", "Eyepatch"),
|
||||
Tag("facesitting", "Facesitting"),
|
||||
Tag("fangs", "Fangs"),
|
||||
Tag("fantasy", "Fantasy"),
|
||||
Tag("fellatio", "Fellatio"),
|
||||
Tag("femboy", "Femboy"),
|
||||
Tag("femdom", "Femdom"),
|
||||
Tag("filming", "Filming"),
|
||||
Tag("flat-chest", "Flat chest"),
|
||||
Tag("footjob", "Footjob"),
|
||||
Tag("freckles", "Freckles"),
|
||||
Tag("full-color", "Full color"),
|
||||
Tag("furry", "Furry"),
|
||||
Tag("futanari", "Futanari"),
|
||||
Tag("gangbang", "Gangbang"),
|
||||
Tag("gender-bender", "Gender bender"),
|
||||
Tag("genderbend", "Genderbend"),
|
||||
Tag("girls4m", "Girls4m"),
|
||||
Tag("glasses", "Glasses"),
|
||||
Tag("group", "Group"),
|
||||
Tag("gyaru", "Gyaru"),
|
||||
Tag("hairy", "Hairy"),
|
||||
Tag("hairy-armpit", "Hairy armpit"),
|
||||
Tag("handjob", "Handjob"),
|
||||
Tag("harem", "Harem"),
|
||||
Tag("headphones", "Headphones"),
|
||||
Tag("heart-pupils", "Heart pupils"),
|
||||
Tag("hentai", "Hentai"),
|
||||
Tag("historical", "Historical"),
|
||||
Tag("horns", "Horns"),
|
||||
Tag("horror", "Horror"),
|
||||
Tag("housewife", "Housewife"),
|
||||
Tag("huge-boobs", "Huge-boobs"),
|
||||
Tag("humiliation", "Humiliation"),
|
||||
Tag("idol", "Idol"),
|
||||
Tag("imouto", "Imouto"),
|
||||
Tag("impregnation", "Impregnation"),
|
||||
Tag("incest", "Incest"),
|
||||
Tag("inseki", "Inseki"),
|
||||
Tag("inverted-nipples", "Inverted nipples"),
|
||||
Tag("irrumatio", "Irrumatio"),
|
||||
Tag("isekai", "Isekai"),
|
||||
Tag("kemono-mimi", "Kemono mimi"),
|
||||
Tag("kimono", "Kimono"),
|
||||
Tag("kogal", "Kogal"),
|
||||
Tag("lactation", "Lactation"),
|
||||
Tag("large-breast", "Large breast"),
|
||||
Tag("lingerie", "Lingerie"),
|
||||
Tag("loli", "Loli"),
|
||||
Tag("love-hotel", "Love hotel"),
|
||||
Tag("magical-girl", "Magical girl"),
|
||||
Tag("maid", "Maid"),
|
||||
Tag("masturbation", "Masturbation"),
|
||||
Tag("miko", "Miko"),
|
||||
Tag("milf", "Milf"),
|
||||
Tag("mind-break", "Mind break"),
|
||||
Tag("mind-control", "Mind control"),
|
||||
Tag("monster-girl", "Monster girl"),
|
||||
Tag("muscles", "Muscles"),
|
||||
Tag("nakadashi", "Nakadashi"),
|
||||
Tag("naked-apron", "Naked apron"),
|
||||
Tag("netorare", "Netorare"),
|
||||
Tag("netorase", "Netorase"),
|
||||
Tag("netori", "Netori"),
|
||||
Tag("ninja", "Ninja"),
|
||||
Tag("nun", "Nun"),
|
||||
Tag("nurse", "Nurse"),
|
||||
Tag("office-lady", "Office lady"),
|
||||
Tag("ojousama", "Ojousama"),
|
||||
Tag("old-man", "Old man"),
|
||||
Tag("onani", "Onani"),
|
||||
Tag("oni", "Oni"),
|
||||
Tag("orgasm-denial", "Orgasm denial"),
|
||||
Tag("osananajimi", "Osananajimi"),
|
||||
Tag("pailoli", "Pailoli"),
|
||||
Tag("paizuri", "Paizuri"),
|
||||
Tag("pegging", "Pegging"),
|
||||
Tag("petite", "Petite"),
|
||||
Tag("pettanko", "Pettanko"),
|
||||
Tag("ponytail", "Ponytail"),
|
||||
Tag("pregnant", "Pregnant"),
|
||||
Tag("prositution", "Prositution"),
|
||||
Tag("pubic-hair", "Pubic Hair"),
|
||||
Tag("qipao", "Qipao"),
|
||||
Tag("rape", "Rape"),
|
||||
Tag("reverse-rape", "Reverse rape"),
|
||||
Tag("rimjob", "Rimjob"),
|
||||
Tag("schoolgirl", "Schoolgirl"),
|
||||
Tag("schoolgirl-outfit", "Schoolgirl outfit"),
|
||||
Tag("sci-fi", "Sci-fi"),
|
||||
Tag("senpai", "Senpai"),
|
||||
Tag("sex", "Sex"),
|
||||
Tag("sex-toys", "Sex toys"),
|
||||
Tag("shimapan", "Shimapan"),
|
||||
Tag("shota", "Shota"),
|
||||
Tag("shouta", "Shouta"),
|
||||
Tag("sister", "Sister"),
|
||||
Tag("sleeping", "Sleeping"),
|
||||
Tag("small-breast", "Small breast"),
|
||||
Tag("socks", "Socks"),
|
||||
Tag("spats", "Spats"),
|
||||
Tag("spread", "Spread"),
|
||||
Tag("squirting", "Squirting"),
|
||||
Tag("stocking", "Stocking"),
|
||||
Tag("stockings", "Stockings"),
|
||||
Tag("succubus", "Succubus"),
|
||||
Tag("swimsuit", "Swimsuit"),
|
||||
Tag("swinging", "Swinging"),
|
||||
Tag("tall-girl", "Tall-girl"),
|
||||
Tag("tanlines", "Tanlines"),
|
||||
Tag("teacher", "Teacher"),
|
||||
Tag("tentacles", "Tentacles"),
|
||||
Tag("threesome", "Threesome"),
|
||||
Tag("time-stop", "Time stop"),
|
||||
Tag("tomboy", "Tomboy"),
|
||||
Tag("toys", "Toys"),
|
||||
Tag("trans", "Trans"),
|
||||
Tag("tsundere", "Tsundere"),
|
||||
Tag("twin", "Twin"),
|
||||
Tag("twintails", "Twintails"),
|
||||
Tag("ugly-bastard", "Ugly bastard"),
|
||||
Tag("uncensored", "Uncensored"),
|
||||
Tag("unlimited", "Unlimited"),
|
||||
Tag("urination", "Urination"),
|
||||
Tag("vanilla", "Vanilla"),
|
||||
Tag("virgin", "Virgin"),
|
||||
Tag("vomit", "Vomit"),
|
||||
Tag("voyeurism", "Voyeurism"),
|
||||
Tag("waitress", "Waitress"),
|
||||
Tag("x-ray", "X-Ray"),
|
||||
Tag("yandere", "Yandere"),
|
||||
Tag("yukata", "Yukata"),
|
||||
Tag("yuri", "Yuri")
|
||||
))
|
||||
class TagFilter : Filter.Select<Tag>(
|
||||
"Tag",
|
||||
arrayOf(
|
||||
Tag("", "<select>"),
|
||||
Tag("ahegao", "Ahegao"),
|
||||
Tag("anal", "Anal"),
|
||||
Tag("apron", "Apron"),
|
||||
Tag("ashioki", "Ashioki"),
|
||||
Tag("bakunyuu", "Bakunyuu"),
|
||||
Tag("bathroom-sex", "Bathroom sex"),
|
||||
Tag("beauty-mark", "Beauty mark"),
|
||||
Tag("big-ass", "Big ass"),
|
||||
Tag("big-breast", "Big breast"),
|
||||
Tag("big-dick", "Big dick"),
|
||||
Tag("biting", "Biting"),
|
||||
Tag("black-mail", "Blackmail"),
|
||||
Tag("blindfold", "Blindfold"),
|
||||
Tag("blowjob", "Blowjob"),
|
||||
Tag("body-swap", "Body swap"),
|
||||
Tag("bondage", "Bondage"),
|
||||
Tag("booty", "Booty"),
|
||||
Tag("bride", "Bride"),
|
||||
Tag("bukkake", "Bukkake"),
|
||||
Tag("bunny-girl", "Bunny girl"),
|
||||
Tag("busty", "Busty"),
|
||||
Tag("cat", "Cat"),
|
||||
Tag("cat-girl", "Cat girl"),
|
||||
Tag("catgirl", "Catgirl"),
|
||||
Tag("cheating", "Cheating"),
|
||||
Tag("cheerleader", "Cheerleader"),
|
||||
Tag("chikan", "Chikan"),
|
||||
Tag("christmas", "Christmas"),
|
||||
Tag("chubby", "Chubby"),
|
||||
Tag("color", "Color"),
|
||||
Tag("comedy", "Comedy"),
|
||||
Tag("condom", "Condom"),
|
||||
Tag("cosplay", "Cosplay"),
|
||||
Tag("creampie", "Creampie"),
|
||||
Tag("crossdressing", "Crossdressing"),
|
||||
Tag("crotch-tattoo", "Crotch tattoo"),
|
||||
Tag("cunnilingus", "Cunnilingus"),
|
||||
Tag("dark-skin", "Dark skin"),
|
||||
Tag("deepthroat", "Deepthroat"),
|
||||
Tag("defloration", "Defloration"),
|
||||
Tag("devil", "Devil"),
|
||||
Tag("double-penetration", "Double penetration"),
|
||||
Tag("doujin", "Doujin"),
|
||||
Tag("doujinshi", "Doujinshi"),
|
||||
Tag("drama", "Drama"),
|
||||
Tag("drug", "Drug"),
|
||||
Tag("drunk", "Drunk"),
|
||||
Tag("elf", "Elf"),
|
||||
Tag("exhibitionism", "Exhibitionism"),
|
||||
Tag("eyebrows", "Eyebrows"),
|
||||
Tag("eyepatch", "Eyepatch"),
|
||||
Tag("facesitting", "Facesitting"),
|
||||
Tag("fangs", "Fangs"),
|
||||
Tag("fantasy", "Fantasy"),
|
||||
Tag("fellatio", "Fellatio"),
|
||||
Tag("femboy", "Femboy"),
|
||||
Tag("femdom", "Femdom"),
|
||||
Tag("filming", "Filming"),
|
||||
Tag("flat-chest", "Flat chest"),
|
||||
Tag("footjob", "Footjob"),
|
||||
Tag("freckles", "Freckles"),
|
||||
Tag("full-color", "Full color"),
|
||||
Tag("furry", "Furry"),
|
||||
Tag("futanari", "Futanari"),
|
||||
Tag("gangbang", "Gangbang"),
|
||||
Tag("gender-bender", "Gender bender"),
|
||||
Tag("genderbend", "Genderbend"),
|
||||
Tag("girls4m", "Girls4m"),
|
||||
Tag("glasses", "Glasses"),
|
||||
Tag("group", "Group"),
|
||||
Tag("gyaru", "Gyaru"),
|
||||
Tag("hairy", "Hairy"),
|
||||
Tag("hairy-armpit", "Hairy armpit"),
|
||||
Tag("handjob", "Handjob"),
|
||||
Tag("harem", "Harem"),
|
||||
Tag("headphones", "Headphones"),
|
||||
Tag("heart-pupils", "Heart pupils"),
|
||||
Tag("hentai", "Hentai"),
|
||||
Tag("historical", "Historical"),
|
||||
Tag("horns", "Horns"),
|
||||
Tag("horror", "Horror"),
|
||||
Tag("housewife", "Housewife"),
|
||||
Tag("huge-boobs", "Huge-boobs"),
|
||||
Tag("humiliation", "Humiliation"),
|
||||
Tag("idol", "Idol"),
|
||||
Tag("imouto", "Imouto"),
|
||||
Tag("impregnation", "Impregnation"),
|
||||
Tag("incest", "Incest"),
|
||||
Tag("inseki", "Inseki"),
|
||||
Tag("inverted-nipples", "Inverted nipples"),
|
||||
Tag("irrumatio", "Irrumatio"),
|
||||
Tag("isekai", "Isekai"),
|
||||
Tag("kemono-mimi", "Kemono mimi"),
|
||||
Tag("kimono", "Kimono"),
|
||||
Tag("kogal", "Kogal"),
|
||||
Tag("lactation", "Lactation"),
|
||||
Tag("large-breast", "Large breast"),
|
||||
Tag("lingerie", "Lingerie"),
|
||||
Tag("loli", "Loli"),
|
||||
Tag("love-hotel", "Love hotel"),
|
||||
Tag("magical-girl", "Magical girl"),
|
||||
Tag("maid", "Maid"),
|
||||
Tag("masturbation", "Masturbation"),
|
||||
Tag("miko", "Miko"),
|
||||
Tag("milf", "Milf"),
|
||||
Tag("mind-break", "Mind break"),
|
||||
Tag("mind-control", "Mind control"),
|
||||
Tag("monster-girl", "Monster girl"),
|
||||
Tag("muscles", "Muscles"),
|
||||
Tag("nakadashi", "Nakadashi"),
|
||||
Tag("naked-apron", "Naked apron"),
|
||||
Tag("netorare", "Netorare"),
|
||||
Tag("netorase", "Netorase"),
|
||||
Tag("netori", "Netori"),
|
||||
Tag("ninja", "Ninja"),
|
||||
Tag("nun", "Nun"),
|
||||
Tag("nurse", "Nurse"),
|
||||
Tag("office-lady", "Office lady"),
|
||||
Tag("ojousama", "Ojousama"),
|
||||
Tag("old-man", "Old man"),
|
||||
Tag("onani", "Onani"),
|
||||
Tag("oni", "Oni"),
|
||||
Tag("orgasm-denial", "Orgasm denial"),
|
||||
Tag("osananajimi", "Osananajimi"),
|
||||
Tag("pailoli", "Pailoli"),
|
||||
Tag("paizuri", "Paizuri"),
|
||||
Tag("pegging", "Pegging"),
|
||||
Tag("petite", "Petite"),
|
||||
Tag("pettanko", "Pettanko"),
|
||||
Tag("ponytail", "Ponytail"),
|
||||
Tag("pregnant", "Pregnant"),
|
||||
Tag("prositution", "Prositution"),
|
||||
Tag("pubic-hair", "Pubic Hair"),
|
||||
Tag("qipao", "Qipao"),
|
||||
Tag("rape", "Rape"),
|
||||
Tag("reverse-rape", "Reverse rape"),
|
||||
Tag("rimjob", "Rimjob"),
|
||||
Tag("schoolgirl", "Schoolgirl"),
|
||||
Tag("schoolgirl-outfit", "Schoolgirl outfit"),
|
||||
Tag("sci-fi", "Sci-fi"),
|
||||
Tag("senpai", "Senpai"),
|
||||
Tag("sex", "Sex"),
|
||||
Tag("sex-toys", "Sex toys"),
|
||||
Tag("shimapan", "Shimapan"),
|
||||
Tag("shota", "Shota"),
|
||||
Tag("shouta", "Shouta"),
|
||||
Tag("sister", "Sister"),
|
||||
Tag("sleeping", "Sleeping"),
|
||||
Tag("small-breast", "Small breast"),
|
||||
Tag("socks", "Socks"),
|
||||
Tag("spats", "Spats"),
|
||||
Tag("spread", "Spread"),
|
||||
Tag("squirting", "Squirting"),
|
||||
Tag("stocking", "Stocking"),
|
||||
Tag("stockings", "Stockings"),
|
||||
Tag("succubus", "Succubus"),
|
||||
Tag("swimsuit", "Swimsuit"),
|
||||
Tag("swinging", "Swinging"),
|
||||
Tag("tall-girl", "Tall-girl"),
|
||||
Tag("tanlines", "Tanlines"),
|
||||
Tag("teacher", "Teacher"),
|
||||
Tag("tentacles", "Tentacles"),
|
||||
Tag("threesome", "Threesome"),
|
||||
Tag("time-stop", "Time stop"),
|
||||
Tag("tomboy", "Tomboy"),
|
||||
Tag("toys", "Toys"),
|
||||
Tag("trans", "Trans"),
|
||||
Tag("tsundere", "Tsundere"),
|
||||
Tag("twin", "Twin"),
|
||||
Tag("twintails", "Twintails"),
|
||||
Tag("ugly-bastard", "Ugly bastard"),
|
||||
Tag("uncensored", "Uncensored"),
|
||||
Tag("unlimited", "Unlimited"),
|
||||
Tag("urination", "Urination"),
|
||||
Tag("vanilla", "Vanilla"),
|
||||
Tag("virgin", "Virgin"),
|
||||
Tag("vomit", "Vomit"),
|
||||
Tag("voyeurism", "Voyeurism"),
|
||||
Tag("waitress", "Waitress"),
|
||||
Tag("x-ray", "X-Ray"),
|
||||
Tag("yandere", "Yandere"),
|
||||
Tag("yukata", "Yukata"),
|
||||
Tag("yuri", "Yuri")
|
||||
)
|
||||
)
|
||||
|
||||
class Tag(val name: String, private val displayName: String) {
|
||||
override fun toString() = displayName
|
||||
|
|
|
@ -8,15 +8,15 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import org.jsoup.select.Elements
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
abstract class Genkan(
|
||||
override val name: String,
|
||||
|
|
|
@ -4,8 +4,6 @@ import android.app.Application
|
|||
import android.content.SharedPreferences
|
||||
import android.support.v7.preference.CheckBoxPreference
|
||||
import android.support.v7.preference.PreferenceScreen
|
||||
import androidx.preference.CheckBoxPreference as AndroidXCheckBoxPreference
|
||||
import androidx.preference.PreferenceScreen as AndroidXPreferenceScreen
|
||||
import com.github.salomonbrys.kotson.array
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.string
|
||||
|
@ -28,6 +26,8 @@ import rx.Single
|
|||
import rx.schedulers.Schedulers
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import androidx.preference.CheckBoxPreference as AndroidXCheckBoxPreference
|
||||
import androidx.preference.PreferenceScreen as AndroidXPreferenceScreen
|
||||
|
||||
/**
|
||||
* Ported from TachiyomiSy
|
||||
|
@ -190,13 +190,13 @@ open class Hitomi(override val lang: String, private val nozomiLang: String) : H
|
|||
}
|
||||
}
|
||||
|
||||
return base.flatMap { (_, ids) ->
|
||||
val chunks = ids.chunked(PAGE_SIZE)
|
||||
return base.flatMap { (_, ids) ->
|
||||
val chunks = ids.chunked(PAGE_SIZE)
|
||||
|
||||
nozomiIdsToMangas(chunks[page - 1]).map { mangas ->
|
||||
MangasPage(mangas, page < chunks.size)
|
||||
}
|
||||
}.toObservable()
|
||||
nozomiIdsToMangas(chunks[page - 1]).map { mangas ->
|
||||
MangasPage(mangas, page < chunks.size)
|
||||
}
|
||||
}.toObservable()
|
||||
}
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw UnsupportedOperationException("Not used")
|
||||
|
|
|
@ -4,12 +4,12 @@ import eu.kanade.tachiyomi.extension.all.hitomi.Hitomi.Companion.LTN_BASE_URL
|
|||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservable
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import java.security.MessageDigest
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import rx.Observable
|
||||
import rx.Single
|
||||
import java.security.MessageDigest
|
||||
|
||||
private typealias HashedTerm = ByteArray
|
||||
|
||||
|
|
|
@ -24,9 +24,6 @@ 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 java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import okhttp3.Credentials
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
|
@ -38,6 +35,9 @@ import rx.android.schedulers.AndroidSchedulers
|
|||
import rx.schedulers.Schedulers
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
||||
override fun popularMangaRequest(page: Int): Request =
|
||||
|
@ -215,8 +215,10 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|||
else -> SManga.UNKNOWN
|
||||
}
|
||||
// TODO: remove safe calls in next iteration
|
||||
genre = (metadata.genres?.plus(metadata.tags ?: emptySet())
|
||||
?: emptySet()).joinToString(", ")
|
||||
genre = (
|
||||
metadata.genres?.plus(metadata.tags ?: emptySet())
|
||||
?: emptySet()
|
||||
).joinToString(", ")
|
||||
description = metadata.summary
|
||||
}
|
||||
|
||||
|
@ -225,10 +227,10 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|||
Date().time
|
||||
else {
|
||||
try {
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US).parse(date).time
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US).parse(date)?.time ?: 0L
|
||||
} catch (ex: Exception) {
|
||||
try {
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S", Locale.US).parse(date).time
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S", Locale.US).parse(date)?.time ?: 0L
|
||||
} catch (ex: Exception) {
|
||||
Date().time
|
||||
}
|
||||
|
@ -370,65 +372,80 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ response ->
|
||||
libraries = try {
|
||||
gson.fromJson(response.body()?.charStream()!!)
|
||||
} catch (e: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
}, {})
|
||||
.subscribe(
|
||||
{ response ->
|
||||
libraries = try {
|
||||
gson.fromJson(response.body()?.charStream()!!)
|
||||
} catch (e: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
Single.fromCallable {
|
||||
client.newCall(GET("$baseUrl/api/v1/collections?unpaged=true", headers)).execute()
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ response ->
|
||||
collections = try {
|
||||
gson.fromJson<PageWrapperDto<CollectionDto>>(response.body()?.charStream()!!).content
|
||||
} catch (e: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
}, {})
|
||||
.subscribe(
|
||||
{ response ->
|
||||
collections = try {
|
||||
gson.fromJson<PageWrapperDto<CollectionDto>>(response.body()?.charStream()!!).content
|
||||
} catch (e: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
Single.fromCallable {
|
||||
client.newCall(GET("$baseUrl/api/v1/genres", headers)).execute()
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ response ->
|
||||
genres = try {
|
||||
gson.fromJson(response.body()?.charStream()!!)
|
||||
} catch (e: Exception) {
|
||||
emptySet()
|
||||
}
|
||||
}, {})
|
||||
.subscribe(
|
||||
{ response ->
|
||||
genres = try {
|
||||
gson.fromJson(response.body()?.charStream()!!)
|
||||
} catch (e: Exception) {
|
||||
emptySet()
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
Single.fromCallable {
|
||||
client.newCall(GET("$baseUrl/api/v1/tags", headers)).execute()
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ response ->
|
||||
tags = try {
|
||||
gson.fromJson(response.body()?.charStream()!!)
|
||||
} catch (e: Exception) {
|
||||
emptySet()
|
||||
}
|
||||
}, {})
|
||||
.subscribe(
|
||||
{ response ->
|
||||
tags = try {
|
||||
gson.fromJson(response.body()?.charStream()!!)
|
||||
} catch (e: Exception) {
|
||||
emptySet()
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
|
||||
Single.fromCallable {
|
||||
client.newCall(GET("$baseUrl/api/v1/publishers", headers)).execute()
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ response ->
|
||||
publishers = try {
|
||||
gson.fromJson(response.body()?.charStream()!!)
|
||||
} catch (e: Exception) {
|
||||
emptySet()
|
||||
}
|
||||
}, {})
|
||||
.subscribe(
|
||||
{ response ->
|
||||
publishers = try {
|
||||
gson.fromJson(response.body()?.charStream()!!)
|
||||
} catch (e: Exception) {
|
||||
emptySet()
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -59,7 +59,8 @@ open class LANraragi : ConfigurableSource, HttpSource() {
|
|||
url = "${uriBuild.encodedPath}?${uriBuild.encodedQuery}"
|
||||
chapter_number = 1F
|
||||
name = "Chapter"
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
|
@ -118,7 +119,9 @@ open class LANraragi : ConfigurableSource, HttpSource() {
|
|||
artist = getArtist(it.tags)
|
||||
author = artist
|
||||
}
|
||||
}, currentStart + jsonResult.data.size < jsonResult.recordsFiltered)
|
||||
},
|
||||
currentStart + jsonResult.data.size < jsonResult.recordsFiltered
|
||||
)
|
||||
}
|
||||
|
||||
// Preferences
|
||||
|
|
|
@ -11,13 +11,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.random.Random
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Headers
|
||||
|
@ -29,6 +22,13 @@ import okhttp3.Response
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.random.Random
|
||||
|
||||
abstract class Madara(
|
||||
override val name: String,
|
||||
|
@ -189,19 +189,25 @@ abstract class Madara(
|
|||
private class ArtistFilter : Filter.Text("Artist")
|
||||
private class YearFilter : Filter.Text("Year of Released")
|
||||
private class StatusFilter(status: List<Tag>) : Filter.Group<Tag>("Status", status)
|
||||
private class OrderByFilter : UriPartFilter("Order By", arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("Latest", "latest"),
|
||||
Pair("A-Z", "alphabet"),
|
||||
Pair("Rating", "rating"),
|
||||
Pair("Trending", "trending"),
|
||||
Pair("Most Views", "views"),
|
||||
Pair("New", "new-manga")
|
||||
))
|
||||
private class GenreConditionFilter : UriPartFilter("Genre condition", arrayOf(
|
||||
Pair("or", ""),
|
||||
Pair("and", "1")
|
||||
))
|
||||
private class OrderByFilter : UriPartFilter(
|
||||
"Order By",
|
||||
arrayOf(
|
||||
Pair("<select>", ""),
|
||||
Pair("Latest", "latest"),
|
||||
Pair("A-Z", "alphabet"),
|
||||
Pair("Rating", "rating"),
|
||||
Pair("Trending", "trending"),
|
||||
Pair("Most Views", "views"),
|
||||
Pair("New", "new-manga")
|
||||
)
|
||||
)
|
||||
private class GenreConditionFilter : UriPartFilter(
|
||||
"Genre condition",
|
||||
arrayOf(
|
||||
Pair("or", ""),
|
||||
Pair("and", "1")
|
||||
)
|
||||
)
|
||||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
|
||||
class Genre(name: String, val id: String = name) : Filter.CheckBox(name)
|
||||
|
||||
|
@ -385,7 +391,7 @@ abstract class Madara(
|
|||
.let { elements ->
|
||||
if (elements.isEmpty() && !document.select(dataIdSelector).isNullOrEmpty())
|
||||
getXhrChapters(document.select(dataIdSelector).attr("data-id")).select(chapterListSelector())
|
||||
else elements
|
||||
else elements
|
||||
}
|
||||
.map { chapterFromElement(it) }
|
||||
}
|
||||
|
@ -491,9 +497,13 @@ abstract class Madara(
|
|||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
return document.select(pageListParseSelector).mapIndexed { index, element ->
|
||||
Page(index, document.location(), element.select("img").first()?.let {
|
||||
it.absUrl(if (it.hasAttr("data-src")) "data-src" else "src")
|
||||
})
|
||||
Page(
|
||||
index,
|
||||
document.location(),
|
||||
element.select("img").first()?.let {
|
||||
it.absUrl(if (it.hasAttr("data-src")) "data-src" else "src")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ 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.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Headers
|
||||
|
@ -23,6 +21,8 @@ import okhttp3.Request
|
|||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class MadaraFactory : SourceFactory {
|
||||
override fun createSources(): List<Source> = listOf(
|
||||
|
@ -197,13 +197,21 @@ class MangaRawr : Madara("MangaRawr", "https://mangarawr.com", "en")
|
|||
|
||||
class NinjaScans : Madara("NinjaScans", "https://ninjascans.com", "en")
|
||||
|
||||
class ReadManhua : Madara("ReadManhua", "https://readmanhua.net", "en",
|
||||
dateFormat = SimpleDateFormat("dd MMM yy", Locale.US))
|
||||
class ReadManhua : Madara(
|
||||
"ReadManhua",
|
||||
"https://readmanhua.net",
|
||||
"en",
|
||||
dateFormat = SimpleDateFormat("dd MMM yy", Locale.US)
|
||||
)
|
||||
|
||||
class IsekaiScanCom : Madara("IsekaiScan.com", "https://isekaiscan.com", "en")
|
||||
|
||||
class JustForFun : Madara("Just For Fun", "https://just-for-fun.ru", "ru",
|
||||
dateFormat = SimpleDateFormat("yy.MM.dd", Locale.US))
|
||||
class JustForFun : Madara(
|
||||
"Just For Fun",
|
||||
"https://just-for-fun.ru",
|
||||
"ru",
|
||||
dateFormat = SimpleDateFormat("yy.MM.dd", Locale.US)
|
||||
)
|
||||
|
||||
class AoCTranslations : Madara("Agent of Change Translations", "https://aoc.moe", "en") {
|
||||
override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", baseUrl)
|
||||
|
@ -243,11 +251,19 @@ class KomikGo : Madara("KomikGo", "https://komikgo.com", "id")
|
|||
|
||||
class LuxyScans : Madara("Luxy Scans", "https://luxyscans.com", "en")
|
||||
|
||||
class TsubakiNoScan : Madara("Tsubaki No Scan", "https://tsubakinoscan.com", "fr",
|
||||
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US))
|
||||
class TsubakiNoScan : Madara(
|
||||
"Tsubaki No Scan",
|
||||
"https://tsubakinoscan.com",
|
||||
"fr",
|
||||
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
|
||||
)
|
||||
|
||||
class YokaiJump : Madara("Yokai Jump", "https://yokaijump.fr", "fr",
|
||||
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US))
|
||||
class YokaiJump : Madara(
|
||||
"Yokai Jump",
|
||||
"https://yokaijump.fr",
|
||||
"fr",
|
||||
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
|
||||
)
|
||||
|
||||
class ZManga : Madara("ZManga", "https://zmanga.org", "es")
|
||||
|
||||
|
@ -261,8 +277,12 @@ class MangazukiClubJP : Madara("Mangazuki.club", "https://mangazuki.club", "ja")
|
|||
|
||||
class MangazukiClubKO : Madara("Mangazuki.club", "https://mangazuki.club", "ko")
|
||||
|
||||
class FirstKissManga : Madara("1st Kiss", "https://1stkissmanga.com", "en",
|
||||
dateFormat = SimpleDateFormat("dd MMM yyyy", Locale.US)) {
|
||||
class FirstKissManga : Madara(
|
||||
"1st Kiss",
|
||||
"https://1stkissmanga.com",
|
||||
"en",
|
||||
dateFormat = SimpleDateFormat("dd MMM yyyy", Locale.US)
|
||||
) {
|
||||
override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", baseUrl)
|
||||
}
|
||||
|
||||
|
@ -287,8 +307,12 @@ class ManyToonMe : Madara("ManyToon.me", "https://manytoon.me", "en")
|
|||
|
||||
class BoysLove : Madara("BoysLove", "https://boyslove.me", "en")
|
||||
|
||||
class ChibiManga : Madara("Chibi Manga", "http://www.cmreader.info", "en",
|
||||
dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)) {
|
||||
class ChibiManga : Madara(
|
||||
"Chibi Manga",
|
||||
"http://www.cmreader.info",
|
||||
"en",
|
||||
dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||
) {
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
response.asJsoup().let { documet ->
|
||||
documet.select("li.parent.has-child").let { volumes ->
|
||||
|
@ -562,41 +586,43 @@ class DoujinHentai : Madara("DoujinHentai", "https://doujinhentai.net", "es", Si
|
|||
GenreSelectFilter()
|
||||
)
|
||||
|
||||
class GenreSelectFilter : UriPartFilter("Búsqueda de género", arrayOf(
|
||||
Pair("<seleccionar>", ""),
|
||||
Pair("Ecchi", "ecchi"),
|
||||
Pair("Yaoi", "yaoi"),
|
||||
Pair("Yuri", "yuri"),
|
||||
Pair("Anal", "anal"),
|
||||
Pair("Tetonas", "tetonas"),
|
||||
Pair("Escolares", "escolares"),
|
||||
Pair("Incesto", "incesto"),
|
||||
Pair("Virgenes", "virgenes"),
|
||||
Pair("Masturbacion", "masturbacion"),
|
||||
Pair("Maduras", "maduras"),
|
||||
Pair("Lolicon", "lolicon"),
|
||||
Pair("Bikini", "bikini"),
|
||||
Pair("Sirvientas", "sirvientas"),
|
||||
Pair("Enfermera", "enfermera"),
|
||||
Pair("Embarazada", "embarazada"),
|
||||
Pair("Ahegao", "ahegao"),
|
||||
Pair("Casadas", "casadas"),
|
||||
Pair("Chica Con Pene", "chica-con-pene"),
|
||||
Pair("Juguetes Sexuales", "juguetes-sexuales"),
|
||||
Pair("Orgias", "orgias"),
|
||||
Pair("Harem", "harem"),
|
||||
Pair("Romance", "romance"),
|
||||
Pair("Profesores", "profesores"),
|
||||
Pair("Tentaculos", "tentaculos"),
|
||||
Pair("Mamadas", "mamadas"),
|
||||
Pair("Shota", "shota"),
|
||||
Pair("Interracial", "interracial"),
|
||||
Pair("Full Color", "full-colo"),
|
||||
Pair("Sin Censura", "sin-censura"),
|
||||
Pair("Futanari", "futanari"),
|
||||
Pair("Doble Penetracion", "doble-penetracion"),
|
||||
Pair("Cosplay", "cosplay")
|
||||
)
|
||||
class GenreSelectFilter : UriPartFilter(
|
||||
"Búsqueda de género",
|
||||
arrayOf(
|
||||
Pair("<seleccionar>", ""),
|
||||
Pair("Ecchi", "ecchi"),
|
||||
Pair("Yaoi", "yaoi"),
|
||||
Pair("Yuri", "yuri"),
|
||||
Pair("Anal", "anal"),
|
||||
Pair("Tetonas", "tetonas"),
|
||||
Pair("Escolares", "escolares"),
|
||||
Pair("Incesto", "incesto"),
|
||||
Pair("Virgenes", "virgenes"),
|
||||
Pair("Masturbacion", "masturbacion"),
|
||||
Pair("Maduras", "maduras"),
|
||||
Pair("Lolicon", "lolicon"),
|
||||
Pair("Bikini", "bikini"),
|
||||
Pair("Sirvientas", "sirvientas"),
|
||||
Pair("Enfermera", "enfermera"),
|
||||
Pair("Embarazada", "embarazada"),
|
||||
Pair("Ahegao", "ahegao"),
|
||||
Pair("Casadas", "casadas"),
|
||||
Pair("Chica Con Pene", "chica-con-pene"),
|
||||
Pair("Juguetes Sexuales", "juguetes-sexuales"),
|
||||
Pair("Orgias", "orgias"),
|
||||
Pair("Harem", "harem"),
|
||||
Pair("Romance", "romance"),
|
||||
Pair("Profesores", "profesores"),
|
||||
Pair("Tentaculos", "tentaculos"),
|
||||
Pair("Mamadas", "mamadas"),
|
||||
Pair("Shota", "shota"),
|
||||
Pair("Interracial", "interracial"),
|
||||
Pair("Full Color", "full-colo"),
|
||||
Pair("Sin Censura", "sin-censura"),
|
||||
Pair("Futanari", "futanari"),
|
||||
Pair("Doble Penetracion", "doble-penetracion"),
|
||||
Pair("Cosplay", "cosplay")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -21,6 +16,11 @@ import okhttp3.Request
|
|||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// Based off of Mangakakalot 1.2.8
|
||||
|
||||
|
|
|
@ -7,12 +7,12 @@ import eu.kanade.tachiyomi.source.model.FilterList
|
|||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class MangaBoxFactory : SourceFactory {
|
||||
override fun createSources(): List<Source> = listOf(
|
||||
|
|
|
@ -28,10 +28,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.net.URLEncoder
|
||||
import java.util.Date
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.collections.set
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
|
@ -45,6 +41,10 @@ import org.jsoup.parser.Parser
|
|||
import rx.Observable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.net.URLEncoder
|
||||
import java.util.Date
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.collections.set
|
||||
|
||||
abstract class MangaDex(
|
||||
override val lang: String,
|
||||
|
@ -421,7 +421,8 @@ abstract class MangaDex(
|
|||
|
||||
// Remove bbcode tags as well as parses any html characters in description or chapter name to actual characters for example ♥ will show ♥
|
||||
private fun cleanString(string: String): String {
|
||||
val bbRegex = """\[(\w+)[^]]*](.*?)\[/\1]""".toRegex()
|
||||
val bbRegex =
|
||||
"""\[(\w+)[^]]*](.*?)\[/\1]""".toRegex()
|
||||
var intermediate = string
|
||||
.replace("[list]", "")
|
||||
.replace("[/list]", "")
|
||||
|
@ -801,9 +802,11 @@ abstract class MangaDex(
|
|||
private class TagExclusionMode : Filter.Select<String>("Tag exclusion mode", arrayOf("All (and)", "Any (or)"), 1)
|
||||
|
||||
// default selection (Rating Descending) matches popularMangaRequest url
|
||||
class SortFilter : Filter.Sort("Sort",
|
||||
class SortFilter : Filter.Sort(
|
||||
"Sort",
|
||||
sortables.map { it.first }.toTypedArray(),
|
||||
Selection(3, false))
|
||||
Selection(3, false)
|
||||
)
|
||||
|
||||
private class OriginalLanguage : Filter.Select<String>("Original Language", SOURCE_LANG_LIST.map { it.first }.toTypedArray())
|
||||
|
||||
|
@ -955,7 +958,8 @@ abstract class MangaDex(
|
|||
Triple("Number of comments", 4, 5),
|
||||
Triple("Rating", 6, 7),
|
||||
Triple("Views", 8, 9),
|
||||
Triple("Follows", 10, 11))
|
||||
Triple("Follows", 10, 11)
|
||||
)
|
||||
|
||||
private val SOURCE_LANG_LIST = listOf(
|
||||
Pair("All", "0"),
|
||||
|
@ -970,7 +974,8 @@ abstract class MangaDex(
|
|||
Pair("Korean", "28"),
|
||||
Pair("Spanish (LATAM)", "29"),
|
||||
Pair("Thai", "32"),
|
||||
Pair("Filipino", "34"))
|
||||
Pair("Filipino", "34")
|
||||
)
|
||||
|
||||
private var hasMangaPlus = false
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@ 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 java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
* MangAdventure base source.
|
||||
|
@ -88,9 +88,11 @@ abstract class MangAdventure(
|
|||
when (it) {
|
||||
is Person -> uri.appendQueryParameter("author", it.state)
|
||||
is Status -> uri.appendQueryParameter("status", it.string())
|
||||
is CategoryList -> cat.addAll(it.state.mapNotNull { c ->
|
||||
Uri.encode(c.optString())
|
||||
})
|
||||
is CategoryList -> cat.addAll(
|
||||
it.state.mapNotNull { c ->
|
||||
Uri.encode(c.optString())
|
||||
}
|
||||
)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
@ -99,18 +101,21 @@ abstract class MangAdventure(
|
|||
|
||||
override fun latestUpdatesParse(response: Response) =
|
||||
JSONArray(response.asString()).run {
|
||||
MangasPage((0 until length()).map {
|
||||
val obj = getJSONObject(it)
|
||||
SManga.create().apply {
|
||||
url = obj.getString("url")
|
||||
title = obj.getString("title")
|
||||
thumbnail_url = obj.getString("cover")
|
||||
// A bit of a hack to sort by date
|
||||
description = httpDateToTimestamp(
|
||||
obj.getJSONObject("latest_chapter").getString("date")
|
||||
).toString()
|
||||
}
|
||||
}.sortedByDescending(SManga::description), false)
|
||||
MangasPage(
|
||||
(0 until length()).map {
|
||||
val obj = getJSONObject(it)
|
||||
SManga.create().apply {
|
||||
url = obj.getString("url")
|
||||
title = obj.getString("title")
|
||||
thumbnail_url = obj.getString("cover")
|
||||
// A bit of a hack to sort by date
|
||||
description = httpDateToTimestamp(
|
||||
obj.getJSONObject("latest_chapter").getString("date")
|
||||
).toString()
|
||||
}
|
||||
}.sortedByDescending(SManga::description),
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response) =
|
||||
|
@ -143,9 +148,12 @@ abstract class MangAdventure(
|
|||
|
||||
override fun searchMangaParse(response: Response) =
|
||||
JSONArray(response.asString()).run {
|
||||
MangasPage((0 until length()).map {
|
||||
SManga.create().fromJSON(getJSONObject(it))
|
||||
}.sortedBy(SManga::title), false)
|
||||
MangasPage(
|
||||
(0 until length()).map {
|
||||
SManga.create().fromJSON(getJSONObject(it))
|
||||
}.sortedBy(SManga::title),
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFilterList() =
|
||||
|
@ -226,7 +234,7 @@ abstract class MangAdventure(
|
|||
* @return The timestamp of the date.
|
||||
*/
|
||||
fun httpDateToTimestamp(date: String) =
|
||||
SimpleDateFormat(HTTP_DATE, Locale.US).parse(date).time
|
||||
SimpleDateFormat(HTTP_DATE, Locale.US).parse(date)?.time ?: 0L
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,7 +268,8 @@ abstract class MangAdventure(
|
|||
* @constructor Creates a [Filter.Group] object with categories.
|
||||
*/
|
||||
inner class CategoryList : Filter.Group<Category>(
|
||||
"Categories", categories.map(::Category)
|
||||
"Categories",
|
||||
categories.map(::Category)
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,11 +16,13 @@ class MangAdventureActivity : Activity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
intent?.data?.pathSegments?.takeIf { it.size > 1 }?.let {
|
||||
try {
|
||||
startActivity(Intent().apply {
|
||||
action = "eu.kanade.tachiyomi.SEARCH"
|
||||
putExtra("query", MangAdventure.SLUG_QUERY + it[1])
|
||||
putExtra("filter", packageName)
|
||||
})
|
||||
startActivity(
|
||||
Intent().apply {
|
||||
action = "eu.kanade.tachiyomi.SEARCH"
|
||||
putExtra("query", MangAdventure.SLUG_QUERY + it[1])
|
||||
putExtra("filter", packageName)
|
||||
}
|
||||
)
|
||||
} catch (ex: ActivityNotFoundException) {
|
||||
Log.e("MangAdventureActivity", ex.message, ex)
|
||||
}
|
||||
|
@ -30,6 +32,7 @@ class MangAdventureActivity : Activity() {
|
|||
}
|
||||
|
||||
private fun logInvalidIntent(intent: Intent) = Log.e(
|
||||
"MangAdventureActivity", "Failed to parse URI from intent: $intent"
|
||||
"MangAdventureActivity",
|
||||
"Failed to parse URI from intent: $intent"
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ package eu.kanade.tachiyomi.extension.all.mangadventure
|
|||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import java.text.DecimalFormat
|
||||
import okhttp3.Response
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.text.DecimalFormat
|
||||
|
||||
/** Returns the body of a response as a `String`. */
|
||||
fun Response.asString(): String = body()!!.string()
|
||||
|
@ -62,9 +62,9 @@ fun SManga.fromJSON(obj: JSONObject) = apply {
|
|||
title = obj.getString("title")
|
||||
description = obj.getString("description")
|
||||
thumbnail_url = obj.getString("cover")
|
||||
author = obj.getJSONArray("authors")?.joinField(0)
|
||||
artist = obj.getJSONArray("artists")?.joinField(0)
|
||||
genre = obj.getJSONArray("categories")?.joinField("name")
|
||||
author = obj.getJSONArray("authors").joinField(0)
|
||||
artist = obj.getJSONArray("artists").joinField(0)
|
||||
genre = obj.getJSONArray("categories").joinField("name")
|
||||
status = if (obj.getBoolean("completed"))
|
||||
SManga.COMPLETED else SManga.ONGOING
|
||||
}
|
||||
|
@ -82,11 +82,14 @@ fun SChapter.fromJSON(obj: JSONObject) = apply {
|
|||
url = obj.getString("url")
|
||||
chapter_number = obj.optString("chapter", "0").toFloat()
|
||||
date_upload = MangAdventure.httpDateToTimestamp(obj.getString("date"))
|
||||
scanlator = obj.getJSONArray("groups")?.joinField("name", " & ")
|
||||
name = obj.optString("full_title", buildString {
|
||||
obj.optInt("volume").let { if (it != 0) append("Vol. $it, ") }
|
||||
append("Ch. ${chapter_number.format("#.#")}: ")
|
||||
append(obj.getString("title"))
|
||||
})
|
||||
scanlator = obj.getJSONArray("groups").joinField("name", " & ")
|
||||
name = obj.optString(
|
||||
"full_title",
|
||||
buildString {
|
||||
obj.optInt("volume").let { if (it != 0) append("Vol. $it, ") }
|
||||
append("Ch. ${chapter_number.format("#.#")}: ")
|
||||
append(obj.getString("title"))
|
||||
}
|
||||
)
|
||||
if (obj.getBoolean("final")) name += " [END]"
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@ class MangAdventureFactory : SourceFactory {
|
|||
|
||||
/** Arc-Relight source. */
|
||||
class ArcRelight : MangAdventure(
|
||||
"Arc-Relight", "https://arc-relight.com", arrayOf(
|
||||
"Arc-Relight",
|
||||
"https://arc-relight.com",
|
||||
arrayOf(
|
||||
"4-Koma",
|
||||
"Chaos;Head",
|
||||
"Collection",
|
||||
|
|
|
@ -6,13 +6,14 @@ ext {
|
|||
extName = 'MANGA Plus by SHUEISHA'
|
||||
pkgNameSuffix = 'all.mangaplus'
|
||||
extClass = '.MangaPlusFactory'
|
||||
extVersionCode = 11
|
||||
extVersionCode = 12
|
||||
libVersion = '1.2'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-protobuf:0.20.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0'
|
||||
final serialization_version = '1.0.0-RC'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$serialization_version"
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
|
|
@ -6,9 +6,6 @@ import android.os.Build
|
|||
import android.support.v7.preference.CheckBoxPreference
|
||||
import android.support.v7.preference.ListPreference
|
||||
import android.support.v7.preference.PreferenceScreen
|
||||
import androidx.preference.CheckBoxPreference as AndroidXCheckBoxPreference
|
||||
import androidx.preference.ListPreference as AndroidXListPreference
|
||||
import androidx.preference.PreferenceScreen as AndroidXPreferenceScreen
|
||||
import com.google.gson.Gson
|
||||
import com.squareup.duktape.Duktape
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
|
@ -20,7 +17,6 @@ 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 java.util.UUID
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
|
@ -33,6 +29,10 @@ import okhttp3.ResponseBody
|
|||
import rx.Observable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.UUID
|
||||
import androidx.preference.CheckBoxPreference as AndroidXCheckBoxPreference
|
||||
import androidx.preference.ListPreference as AndroidXListPreference
|
||||
import androidx.preference.PreferenceScreen as AndroidXPreferenceScreen
|
||||
|
||||
abstract class MangaPlus(
|
||||
override val lang: String,
|
||||
|
@ -428,7 +428,7 @@ abstract class MangaPlus(
|
|||
|
||||
private fun Response.asProto(): MangaPlusResponse {
|
||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
|
||||
return ProtoBuf.load(MangaPlusSerializer, body()!!.bytes())
|
||||
return ProtoBuf.decodeFromByteArray(MangaPlusSerializer, body()!!.bytes())
|
||||
|
||||
// Apparently, the version used of Kotlinx Serialization lib causes a crash
|
||||
// on KitKat devices (see #1678). So, if the device is running KitKat or lower,
|
||||
|
@ -438,9 +438,13 @@ abstract class MangaPlus(
|
|||
val messageBytes = "var BYTE_ARR = new Uint8Array([${bytes.joinToString()}]);"
|
||||
|
||||
val res = Duktape.create().use {
|
||||
it.set("helper", DuktapeHelper::class.java, object : DuktapeHelper {
|
||||
override fun getProtobuf(): String = protobufJs
|
||||
})
|
||||
it.set(
|
||||
"helper",
|
||||
DuktapeHelper::class.java,
|
||||
object : DuktapeHelper {
|
||||
override fun getProtobuf(): String = protobufJs
|
||||
}
|
||||
)
|
||||
it.evaluate(messageBytes + DECODE_SCRIPT) as String
|
||||
}
|
||||
|
||||
|
|
|
@ -3,128 +3,129 @@ package eu.kanade.tachiyomi.extension.all.mangaplus
|
|||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Serializer
|
||||
import kotlinx.serialization.protobuf.ProtoId
|
||||
import kotlinx.serialization.protobuf.ProtoNumber
|
||||
|
||||
@Serializer(forClass = MangaPlusResponse::class)
|
||||
object MangaPlusSerializer
|
||||
|
||||
@Serializable
|
||||
data class MangaPlusResponse(
|
||||
@ProtoId(1) val success: SuccessResult? = null,
|
||||
@ProtoId(2) val error: ErrorResult? = null
|
||||
@ProtoNumber(1) val success: SuccessResult? = null,
|
||||
@ProtoNumber(2) val error: ErrorResult? = null
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ErrorResult(
|
||||
@ProtoId(1) val action: Action,
|
||||
@ProtoId(2) val englishPopup: Popup,
|
||||
@ProtoId(3) val spanishPopup: Popup
|
||||
@ProtoNumber(1) val action: Action,
|
||||
@ProtoNumber(2) val englishPopup: Popup,
|
||||
@ProtoNumber(3) val spanishPopup: Popup
|
||||
)
|
||||
|
||||
enum class Action { DEFAULT, UNAUTHORIZED, MAINTAINENCE, GEOIP_BLOCKING }
|
||||
|
||||
@Serializable
|
||||
data class Popup(
|
||||
@ProtoId(1) val subject: String,
|
||||
@ProtoId(2) val body: String
|
||||
@ProtoNumber(1) val subject: String,
|
||||
@ProtoNumber(2) val body: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class SuccessResult(
|
||||
@ProtoId(1) val isFeaturedUpdated: Boolean? = false,
|
||||
@ProtoId(5) val allTitlesView: AllTitlesView? = null,
|
||||
@ProtoId(6) val titleRankingView: TitleRankingView? = null,
|
||||
@ProtoId(8) val titleDetailView: TitleDetailView? = null,
|
||||
@ProtoId(10) val mangaViewer: MangaViewer? = null,
|
||||
@ProtoId(11) val webHomeView: WebHomeView? = null
|
||||
@ProtoNumber(1) val isFeaturedUpdated: Boolean? = false,
|
||||
@ProtoNumber(5) val allTitlesView: AllTitlesView? = null,
|
||||
@ProtoNumber(6) val titleRankingView: TitleRankingView? = null,
|
||||
@ProtoNumber(8) val titleDetailView: TitleDetailView? = null,
|
||||
@ProtoNumber(10) val mangaViewer: MangaViewer? = null,
|
||||
@ProtoNumber(11) val webHomeView: WebHomeView? = null
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TitleRankingView(@ProtoId(1) val titles: List<Title> = emptyList())
|
||||
data class TitleRankingView(@ProtoNumber(1) val titles: List<Title> = emptyList())
|
||||
|
||||
@Serializable
|
||||
data class AllTitlesView(@ProtoId(1) val titles: List<Title> = emptyList())
|
||||
data class AllTitlesView(@ProtoNumber(1) val titles: List<Title> = emptyList())
|
||||
|
||||
@Serializable
|
||||
data class WebHomeView(@ProtoId(2) val groups: List<UpdatedTitleGroup> = emptyList())
|
||||
data class WebHomeView(@ProtoNumber(2) val groups: List<UpdatedTitleGroup> = emptyList())
|
||||
|
||||
@Serializable
|
||||
data class TitleDetailView(
|
||||
@ProtoId(1) val title: Title,
|
||||
@ProtoId(2) val titleImageUrl: String,
|
||||
@ProtoId(3) val overview: String,
|
||||
@ProtoId(4) val backgroundImageUrl: String,
|
||||
@ProtoId(5) val nextTimeStamp: Int = 0,
|
||||
@ProtoId(6) val updateTiming: UpdateTiming? = UpdateTiming.DAY,
|
||||
@ProtoId(7) val viewingPeriodDescription: String = "",
|
||||
@ProtoId(8) val nonAppearanceInfo: String = "",
|
||||
@ProtoId(9) val firstChapterList: List<Chapter> = emptyList(),
|
||||
@ProtoId(10) val lastChapterList: List<Chapter> = emptyList(),
|
||||
@ProtoId(14) val isSimulReleased: Boolean = true,
|
||||
@ProtoId(17) val chaptersDescending: Boolean = true
|
||||
@ProtoNumber(1) val title: Title,
|
||||
@ProtoNumber(2) val titleImageUrl: String,
|
||||
@ProtoNumber(3) val overview: String,
|
||||
@ProtoNumber(4) val backgroundImageUrl: String,
|
||||
@ProtoNumber(5) val nextTimeStamp: Int = 0,
|
||||
@ProtoNumber(6) val updateTiming: UpdateTiming? = UpdateTiming.DAY,
|
||||
@ProtoNumber(7) val viewingPeriodDescription: String = "",
|
||||
@ProtoNumber(8) val nonAppearanceInfo: String = "",
|
||||
@ProtoNumber(9) val firstChapterList: List<Chapter> = emptyList(),
|
||||
@ProtoNumber(10) val lastChapterList: List<Chapter> = emptyList(),
|
||||
@ProtoNumber(14) val isSimulReleased: Boolean = true,
|
||||
@ProtoNumber(17) val chaptersDescending: Boolean = true
|
||||
)
|
||||
|
||||
enum class UpdateTiming { NOT_REGULARLY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY, DAY }
|
||||
|
||||
@Serializable
|
||||
data class MangaViewer(@ProtoId(1) val pages: List<MangaPlusPage> = emptyList())
|
||||
data class MangaViewer(@ProtoNumber(1) val pages: List<MangaPlusPage> = emptyList())
|
||||
|
||||
@Serializable
|
||||
data class Title(
|
||||
@ProtoId(1) val titleId: Int,
|
||||
@ProtoId(2) val name: String,
|
||||
@ProtoId(3) val author: String,
|
||||
@ProtoId(4) val portraitImageUrl: String,
|
||||
@ProtoId(5) val landscapeImageUrl: String,
|
||||
@ProtoId(6) val viewCount: Int = 0,
|
||||
@ProtoId(7) val language: Language? = Language.ENGLISH
|
||||
@ProtoNumber(1) val titleId: Int,
|
||||
@ProtoNumber(2) val name: String,
|
||||
@ProtoNumber(3) val author: String,
|
||||
@ProtoNumber(4) val portraitImageUrl: String,
|
||||
@ProtoNumber(5) val landscapeImageUrl: String,
|
||||
@ProtoNumber(6) val viewCount: Int = 0,
|
||||
@ProtoNumber(7) val language: Language? = Language.ENGLISH
|
||||
)
|
||||
|
||||
@Serializable
|
||||
enum class Language(val id: Int) {
|
||||
@ProtoId(0)
|
||||
@ProtoNumber(0)
|
||||
@SerializedName("0")
|
||||
ENGLISH(0),
|
||||
|
||||
@ProtoId(1)
|
||||
@ProtoNumber(1)
|
||||
@SerializedName("1")
|
||||
SPANISH(1)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class UpdatedTitleGroup(
|
||||
@ProtoId(1) val groupName: String,
|
||||
@ProtoId(2) val titles: List<UpdatedTitle> = emptyList()
|
||||
@ProtoNumber(1) val groupName: String,
|
||||
@ProtoNumber(2) val titles: List<UpdatedTitle> = emptyList()
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class UpdatedTitle(
|
||||
@ProtoId(1) val title: Title? = null
|
||||
@ProtoNumber(1) val title: Title? = null
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Chapter(
|
||||
@ProtoId(1) val titleId: Int,
|
||||
@ProtoId(2) val chapterId: Int,
|
||||
@ProtoId(3) val name: String,
|
||||
@ProtoId(4) val subTitle: String? = null,
|
||||
@ProtoId(6) val startTimeStamp: Int,
|
||||
@ProtoId(7) val endTimeStamp: Int
|
||||
@ProtoNumber(1) val titleId: Int,
|
||||
@ProtoNumber(2) val chapterId: Int,
|
||||
@ProtoNumber(3) val name: String,
|
||||
@ProtoNumber(4) val subTitle: String? = null,
|
||||
@ProtoNumber(6) val startTimeStamp: Int,
|
||||
@ProtoNumber(7) val endTimeStamp: Int
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MangaPlusPage(@ProtoId(1) val page: MangaPage? = null)
|
||||
data class MangaPlusPage(@ProtoNumber(1) val page: MangaPage? = null)
|
||||
|
||||
@Serializable
|
||||
data class MangaPage(
|
||||
@ProtoId(1) val imageUrl: String,
|
||||
@ProtoId(2) val width: Int,
|
||||
@ProtoId(3) val height: Int,
|
||||
@ProtoId(5) val encryptionKey: String? = null
|
||||
@ProtoNumber(1) val imageUrl: String,
|
||||
@ProtoNumber(2) val width: Int,
|
||||
@ProtoNumber(3) val height: Int,
|
||||
@ProtoNumber(5) val encryptionKey: String? = null
|
||||
)
|
||||
|
||||
// Used for the deserialization on KitKat devices.
|
||||
const val DECODE_SCRIPT: String = """
|
||||
const val DECODE_SCRIPT: String =
|
||||
"""
|
||||
Duktape.modSearch = function(id) {
|
||||
if (id == "protobufjs")
|
||||
return helper.getProtobuf();
|
||||
|
|
|
@ -7,13 +7,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
open class MangaToon(
|
||||
override val lang: String,
|
||||
|
@ -73,16 +73,16 @@ open class MangaToon(
|
|||
|
||||
override fun chapterFromElement(element: Element): SChapter {
|
||||
val chapter = SChapter.create()
|
||||
chapter.url = element.select("a").first().attr("href")
|
||||
chapter.chapter_number = element.select("div.item-left").text().trim().toFloat()
|
||||
chapter.url = element.select("a").first().attr("href")
|
||||
chapter.chapter_number = element.select("div.item-left").text().trim().toFloat()
|
||||
val date = element.select("div.episode-date").text()
|
||||
chapter.date_upload = parseDate(date)
|
||||
chapter.name = if (chapter.chapter_number> 20) { "\uD83D\uDD12 " } else { "" } + element.select("div.episode-title").text().trim()
|
||||
chapter.date_upload = parseDate(date)
|
||||
chapter.name = if (chapter.chapter_number> 20) { "\uD83D\uDD12 " } else { "" } + element.select("div.episode-title").text().trim()
|
||||
return chapter
|
||||
}
|
||||
|
||||
private fun parseDate(date: String): Long {
|
||||
return SimpleDateFormat("yyyy-MM-dd", Locale.US).parse(date).time
|
||||
return SimpleDateFormat("yyyy-MM-dd", Locale.US).parse(date)?.time ?: 0L
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga {
|
||||
|
|
|
@ -14,11 +14,11 @@ class MangaToonFactory : SourceFactory {
|
|||
TH()
|
||||
)
|
||||
|
||||
class ZH : MangaToon("zh", "cn")
|
||||
class EN : MangaToon("en", "en")
|
||||
class ID : MangaToon("id", "id")
|
||||
class VI : MangaToon("vi", "vi")
|
||||
class ES : MangaToon("es", "es")
|
||||
class PT : MangaToon("pt", "pt")
|
||||
class TH : MangaToon("th", "th")
|
||||
class ZH : MangaToon("zh", "cn")
|
||||
class EN : MangaToon("en", "en")
|
||||
class ID : MangaToon("id", "id")
|
||||
class VI : MangaToon("vi", "vi")
|
||||
class ES : MangaToon("es", "es")
|
||||
class PT : MangaToon("pt", "pt")
|
||||
class TH : MangaToon("th", "th")
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ import android.annotation.SuppressLint
|
|||
import android.annotation.TargetApi
|
||||
import android.os.Build
|
||||
import com.google.gson.Gson
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.security.cert.CertificateException
|
||||
|
@ -13,10 +17,6 @@ import java.util.concurrent.TimeUnit
|
|||
import javax.net.ssl.SSLContext
|
||||
import javax.net.ssl.TrustManager
|
||||
import javax.net.ssl.X509TrustManager
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
|
||||
/**
|
||||
* This class generates the sources for MMRCMS.
|
||||
|
@ -195,21 +195,23 @@ class Generator {
|
|||
|
||||
@Throws(Exception::class)
|
||||
private fun getOkHttpClient(): OkHttpClient {
|
||||
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
|
||||
@SuppressLint("TrustAllX509TrustManager")
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
|
||||
}
|
||||
val trustAllCerts = arrayOf<TrustManager>(
|
||||
object : X509TrustManager {
|
||||
@SuppressLint("TrustAllX509TrustManager")
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
|
||||
}
|
||||
|
||||
@SuppressLint("TrustAllX509TrustManager")
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkServerTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
|
||||
}
|
||||
@SuppressLint("TrustAllX509TrustManager")
|
||||
@Throws(CertificateException::class)
|
||||
override fun checkServerTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
|
||||
}
|
||||
|
||||
override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> {
|
||||
return arrayOf()
|
||||
override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> {
|
||||
return arrayOf()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
// Install the all-trusting trust manager
|
||||
|
||||
|
@ -272,61 +274,62 @@ class Generator {
|
|||
SourceData("fr", "Op-VF", "https://www.op-vf.com"),
|
||||
SourceData("fr", "FR Scan", "https://www.frscan.me"),
|
||||
// NOTE: THIS SOURCE CONTAINS A CUSTOM LANGUAGE SYSTEM (which will be ignored)!
|
||||
SourceData("other", "HentaiShark", "https://www.hentaishark.com", true))
|
||||
// Changed CMS
|
||||
// SourceData("en", "MangaTreat Scans", "http://www.mangatreat.com"),
|
||||
// SourceData("en", "Chibi Manga Reader", "https://www.cmreader.info"),
|
||||
// SourceData("tr", "Epikmanga", "https://www.epikmanga.com"),
|
||||
// SourceData("en", "Hatigarm Scans", "https://hatigarmscans.net"),
|
||||
// Went offline
|
||||
// SourceData("en", "Mangawww Reader", "https://mangawww.club"),
|
||||
// SourceData("ru", "Anigai clan", "http://anigai.ru"),
|
||||
// SourceData("en", "ZXComic", "http://zxcomic.com"),
|
||||
// SourceData("es", "SOS Scanlation", "https://sosscanlation.com"),
|
||||
// SourceData("es", "MangaCasa", "https://mangacasa.com"))
|
||||
// SourceData("ja", "RAW MANGA READER", "https://rawmanga.site"),
|
||||
// SourceData("ar", "Manga FYI", "http://mangafyi.com/manga/arabic"),
|
||||
// SourceData("en", "MangaRoot", "http://mangaroot.com"),
|
||||
// SourceData("en", "MangaForLife", "http://manga4ever.com"),
|
||||
// SourceData("en", "Manga Spoil", "http://mangaspoil.com"),
|
||||
// SourceData("en", "MangaBlue", "http://mangablue.com"),
|
||||
// SourceData("en", "Manga Forest", "https://mangaforest.com"),
|
||||
// SourceData("en", "DManga", "http://dmanga.website"),
|
||||
// SourceData("en", "DB Manga", "http://dbmanga.com"),
|
||||
// SourceData("en", "Mangacox", "http://mangacox.com"),
|
||||
// SourceData("en", "GO Manhwa", "http://gomanhwa.xyz"),
|
||||
// SourceData("en", "KoManga", "https://komanga.net"),
|
||||
// SourceData("en", "Manganimecan", "http://manganimecan.com"),
|
||||
// SourceData("en", "Hentai2Manga", "http://hentai2manga.com"),
|
||||
// SourceData("en", "4 Manga", "http://4-manga.com"),
|
||||
// SourceData("en", "XYXX.INFO", "http://xyxx.info"),
|
||||
// SourceData("en", "Isekai Manga Reader", "https://isekaimanga.club"),
|
||||
// SourceData("fa", "TrinityReader", "http://trinityreader.pw"),
|
||||
// SourceData("fr", "Manga-LEL", "https://www.manga-lel.com"),
|
||||
// SourceData("fr", "Manga Etonnia", "https://www.etonnia.com"),
|
||||
// SourceData("fr", "ScanFR.com"), "http://scanfr.com"),
|
||||
// SourceData("fr", "Manga FYI", "http://mangafyi.com/manga/french"),
|
||||
// SourceData("fr", "scans-manga", "http://scans-manga.com"),
|
||||
// SourceData("fr", "Henka no Kaze", "http://henkanokazelel.esy.es/upload"),
|
||||
// SourceData("fr", "Tous Vos Scans", "http://www.tous-vos-scans.com"),
|
||||
// SourceData("id", "Manga Desu", "http://mangadesu.net"),
|
||||
// SourceData("id", "Komik Mangafire.ID", "http://go.mangafire.id"),
|
||||
// SourceData("id", "MangaOnline", "https://mangaonline.web.id"),
|
||||
// SourceData("id", "MangaNesia", "https://manganesia.com"),
|
||||
// SourceData("id", "MangaID", "https://mangaid.me"
|
||||
// SourceData("id", "Manga Seru", "http://www.mangaseru.top"
|
||||
// SourceData("id", "Manga FYI", "http://mangafyi.com/manga/indonesian"
|
||||
// SourceData("id", "Bacamangaku", "http://www.bacamangaku.com"),
|
||||
// SourceData("id", "Indo Manga Reader", "http://indomangareader.com"),
|
||||
// SourceData("it", "Kingdom Italia Reader", "http://kireader.altervista.org"),
|
||||
// SourceData("ja", "IchigoBook", "http://ichigobook.com"),
|
||||
// SourceData("ja", "Mangaraw Online", "http://mangaraw.online"
|
||||
// SourceData("ja", "Mangazuki RAWS", "https://raws.mangazuki.co"),
|
||||
// SourceData("ja", "MangaRAW", "https://www.mgraw.com"),
|
||||
// SourceData("ja", "マンガ/漫画 マガジン/雑誌 raw", "http://netabare-manga-raw.com"),
|
||||
// SourceData("ru", "NAKAMA", "http://nakama.ru"),
|
||||
// SourceData("tr", "MangAoi", "http://mangaoi.com"),
|
||||
// SourceData("tr", "ManhuaTR", "http://www.manhua-tr.com"),
|
||||
SourceData("other", "HentaiShark", "https://www.hentaishark.com", true)
|
||||
)
|
||||
// Changed CMS
|
||||
// SourceData("en", "MangaTreat Scans", "http://www.mangatreat.com"),
|
||||
// SourceData("en", "Chibi Manga Reader", "https://www.cmreader.info"),
|
||||
// SourceData("tr", "Epikmanga", "https://www.epikmanga.com"),
|
||||
// SourceData("en", "Hatigarm Scans", "https://hatigarmscans.net"),
|
||||
// Went offline
|
||||
// SourceData("en", "Mangawww Reader", "https://mangawww.club"),
|
||||
// SourceData("ru", "Anigai clan", "http://anigai.ru"),
|
||||
// SourceData("en", "ZXComic", "http://zxcomic.com"),
|
||||
// SourceData("es", "SOS Scanlation", "https://sosscanlation.com"),
|
||||
// SourceData("es", "MangaCasa", "https://mangacasa.com"))
|
||||
// SourceData("ja", "RAW MANGA READER", "https://rawmanga.site"),
|
||||
// SourceData("ar", "Manga FYI", "http://mangafyi.com/manga/arabic"),
|
||||
// SourceData("en", "MangaRoot", "http://mangaroot.com"),
|
||||
// SourceData("en", "MangaForLife", "http://manga4ever.com"),
|
||||
// SourceData("en", "Manga Spoil", "http://mangaspoil.com"),
|
||||
// SourceData("en", "MangaBlue", "http://mangablue.com"),
|
||||
// SourceData("en", "Manga Forest", "https://mangaforest.com"),
|
||||
// SourceData("en", "DManga", "http://dmanga.website"),
|
||||
// SourceData("en", "DB Manga", "http://dbmanga.com"),
|
||||
// SourceData("en", "Mangacox", "http://mangacox.com"),
|
||||
// SourceData("en", "GO Manhwa", "http://gomanhwa.xyz"),
|
||||
// SourceData("en", "KoManga", "https://komanga.net"),
|
||||
// SourceData("en", "Manganimecan", "http://manganimecan.com"),
|
||||
// SourceData("en", "Hentai2Manga", "http://hentai2manga.com"),
|
||||
// SourceData("en", "4 Manga", "http://4-manga.com"),
|
||||
// SourceData("en", "XYXX.INFO", "http://xyxx.info"),
|
||||
// SourceData("en", "Isekai Manga Reader", "https://isekaimanga.club"),
|
||||
// SourceData("fa", "TrinityReader", "http://trinityreader.pw"),
|
||||
// SourceData("fr", "Manga-LEL", "https://www.manga-lel.com"),
|
||||
// SourceData("fr", "Manga Etonnia", "https://www.etonnia.com"),
|
||||
// SourceData("fr", "ScanFR.com"), "http://scanfr.com"),
|
||||
// SourceData("fr", "Manga FYI", "http://mangafyi.com/manga/french"),
|
||||
// SourceData("fr", "scans-manga", "http://scans-manga.com"),
|
||||
// SourceData("fr", "Henka no Kaze", "http://henkanokazelel.esy.es/upload"),
|
||||
// SourceData("fr", "Tous Vos Scans", "http://www.tous-vos-scans.com"),
|
||||
// SourceData("id", "Manga Desu", "http://mangadesu.net"),
|
||||
// SourceData("id", "Komik Mangafire.ID", "http://go.mangafire.id"),
|
||||
// SourceData("id", "MangaOnline", "https://mangaonline.web.id"),
|
||||
// SourceData("id", "MangaNesia", "https://manganesia.com"),
|
||||
// SourceData("id", "MangaID", "https://mangaid.me"
|
||||
// SourceData("id", "Manga Seru", "http://www.mangaseru.top"
|
||||
// SourceData("id", "Manga FYI", "http://mangafyi.com/manga/indonesian"
|
||||
// SourceData("id", "Bacamangaku", "http://www.bacamangaku.com"),
|
||||
// SourceData("id", "Indo Manga Reader", "http://indomangareader.com"),
|
||||
// SourceData("it", "Kingdom Italia Reader", "http://kireader.altervista.org"),
|
||||
// SourceData("ja", "IchigoBook", "http://ichigobook.com"),
|
||||
// SourceData("ja", "Mangaraw Online", "http://mangaraw.online"
|
||||
// SourceData("ja", "Mangazuki RAWS", "https://raws.mangazuki.co"),
|
||||
// SourceData("ja", "MangaRAW", "https://www.mgraw.com"),
|
||||
// SourceData("ja", "マンガ/漫画 マガジン/雑誌 raw", "http://netabare-manga-raw.com"),
|
||||
// SourceData("ru", "NAKAMA", "http://nakama.ru"),
|
||||
// SourceData("tr", "MangAoi", "http://mangaoi.com"),
|
||||
// SourceData("tr", "ManhuaTR", "http://www.manhua-tr.com"),
|
||||
|
||||
val relativePath = System.getProperty("user.dir") + "/src/all/mmrcms/src/eu/kanade/tachiyomi/extension/all/mmrcms/GeneratedSources.kt"
|
||||
|
||||
|
|
|
@ -18,16 +18,16 @@ 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 java.net.URLDecoder
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.net.URLDecoder
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
open class MyMangaReaderCMSSource(
|
||||
final override val lang: String,
|
||||
|
@ -114,17 +114,20 @@ open class MyMangaReaderCMSSource(
|
|||
val jsonArray = jsonParser.parse(response.body()!!.string()).let {
|
||||
if (name == "Mangas.pw") it.array else it["suggestions"].array
|
||||
}
|
||||
MangasPage(jsonArray
|
||||
.map {
|
||||
SManga.create().apply {
|
||||
val segment = it["data"].string
|
||||
url = getUrlWithoutBaseUrl(itemUrl + segment)
|
||||
title = it["value"].string
|
||||
MangasPage(
|
||||
jsonArray
|
||||
.map {
|
||||
SManga.create().apply {
|
||||
val segment = it["data"].string
|
||||
url = getUrlWithoutBaseUrl(itemUrl + segment)
|
||||
title = it["value"].string
|
||||
|
||||
// Guess thumbnails
|
||||
// thumbnail_url = "$baseUrl/uploads/manga/$segment/cover/cover_250x350.jpg"
|
||||
}
|
||||
}, false)
|
||||
// Guess thumbnails
|
||||
// thumbnail_url = "$baseUrl/uploads/manga/$segment/cover/cover_250x350.jpg"
|
||||
}
|
||||
},
|
||||
false
|
||||
)
|
||||
} else {
|
||||
internalMangaParse(response)
|
||||
}
|
||||
|
@ -184,27 +187,30 @@ open class MyMangaReaderCMSSource(
|
|||
"Utsukushii" -> "div.content div.col-sm-6"
|
||||
else -> "div[class^=col-sm], div.col-xs-6"
|
||||
}
|
||||
return MangasPage(document.select(internalMangaSelector).map {
|
||||
SManga.create().apply {
|
||||
val urlElement = it.getElementsByClass("chart-title")
|
||||
if (urlElement.size == 0) {
|
||||
url = getUrlWithoutBaseUrl(it.select("a").attr("href"))
|
||||
title = it.select("div.caption").text()
|
||||
it.select("div.caption div").text().let { if (it.isNotEmpty()) title = title.substringBefore(it) } // To clean submanga's titles without breaking hentaishark's
|
||||
} else {
|
||||
url = getUrlWithoutBaseUrl(urlElement.attr("href"))
|
||||
title = urlElement.text().trim()
|
||||
}
|
||||
return MangasPage(
|
||||
document.select(internalMangaSelector).map {
|
||||
SManga.create().apply {
|
||||
val urlElement = it.getElementsByClass("chart-title")
|
||||
if (urlElement.size == 0) {
|
||||
url = getUrlWithoutBaseUrl(it.select("a").attr("href"))
|
||||
title = it.select("div.caption").text()
|
||||
it.select("div.caption div").text().let { if (it.isNotEmpty()) title = title.substringBefore(it) } // To clean submanga's titles without breaking hentaishark's
|
||||
} else {
|
||||
url = getUrlWithoutBaseUrl(urlElement.attr("href"))
|
||||
title = urlElement.text().trim()
|
||||
}
|
||||
|
||||
it.select("img").let { img ->
|
||||
thumbnail_url = when {
|
||||
it.hasAttr("data-background-image") -> it.attr("data-background-image") // Utsukushii
|
||||
img.hasAttr("data-src") -> coverGuess(img.attr("abs:data-src"), url)
|
||||
else -> coverGuess(img.attr("abs:src"), url)
|
||||
it.select("img").let { img ->
|
||||
thumbnail_url = when {
|
||||
it.hasAttr("data-background-image") -> it.attr("data-background-image") // Utsukushii
|
||||
img.hasAttr("data-src") -> coverGuess(img.attr("abs:data-src"), url)
|
||||
else -> coverGuess(img.attr("abs:src"), url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, document.select(".pagination a[rel=next]").isNotEmpty())
|
||||
},
|
||||
document.select(".pagination a[rel=next]").isNotEmpty()
|
||||
)
|
||||
}
|
||||
|
||||
// Guess thumbnails on broken websites
|
||||
|
@ -364,39 +370,43 @@ open class MyMangaReaderCMSSource(
|
|||
}
|
||||
|
||||
override fun pageListParse(response: Response) = response.asJsoup().select("#all > .img-responsive")
|
||||
.mapIndexed { i, e ->
|
||||
var url = (if (e.hasAttr("data-src")) e.attr("abs:data-src") else e.attr("abs:src")).trim()
|
||||
.mapIndexed { i, e ->
|
||||
var url = (if (e.hasAttr("data-src")) e.attr("abs:data-src") else e.attr("abs:src")).trim()
|
||||
|
||||
// Mangas.pw encodes some of their urls, decode them
|
||||
if (name.contains("Mangas.pw") && !url.contains(".")) {
|
||||
url = Base64.decode(url.substringAfter("//"), Base64.DEFAULT).toString(Charsets.UTF_8).substringBefore("=")
|
||||
url = URLDecoder.decode(url, "UTF-8")
|
||||
}
|
||||
|
||||
Page(i, "", url)
|
||||
// Mangas.pw encodes some of their urls, decode them
|
||||
if (name.contains("Mangas.pw") && !url.contains(".")) {
|
||||
url = Base64.decode(url.substringAfter("//"), Base64.DEFAULT).toString(Charsets.UTF_8).substringBefore("=")
|
||||
url = URLDecoder.decode(url, "UTF-8")
|
||||
}
|
||||
|
||||
Page(i, "", url)
|
||||
}
|
||||
|
||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Unused method called!")
|
||||
|
||||
private fun getInitialFilterList() = listOf<Filter<*>>(
|
||||
Filter.Header("NOTE: Ignored if using text search!"),
|
||||
Filter.Separator(),
|
||||
AuthorFilter(),
|
||||
UriSelectFilter("Category",
|
||||
"cat",
|
||||
arrayOf("" to "Any",
|
||||
*categoryMappings.toTypedArray()
|
||||
)
|
||||
),
|
||||
UriSelectFilter("Begins with",
|
||||
"alpha",
|
||||
arrayOf("" to "Any",
|
||||
*"#ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray().map {
|
||||
Pair(it.toString(), it.toString())
|
||||
}.toTypedArray()
|
||||
)
|
||||
),
|
||||
SortFilter()
|
||||
Filter.Header("NOTE: Ignored if using text search!"),
|
||||
Filter.Separator(),
|
||||
AuthorFilter(),
|
||||
UriSelectFilter(
|
||||
"Category",
|
||||
"cat",
|
||||
arrayOf(
|
||||
"" to "Any",
|
||||
*categoryMappings.toTypedArray()
|
||||
)
|
||||
),
|
||||
UriSelectFilter(
|
||||
"Begins with",
|
||||
"alpha",
|
||||
arrayOf(
|
||||
"" to "Any",
|
||||
*"#ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray().map {
|
||||
Pair(it.toString(), it.toString())
|
||||
}.toTypedArray()
|
||||
)
|
||||
),
|
||||
SortFilter()
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -406,11 +416,16 @@ open class MyMangaReaderCMSSource(
|
|||
return when {
|
||||
name == "Mangas.pw" -> FilterList()
|
||||
tagMappings != null -> {
|
||||
FilterList(getInitialFilterList() + UriSelectFilter("Tag",
|
||||
"tag",
|
||||
arrayOf("" to "Any",
|
||||
*tagMappings.toTypedArray()
|
||||
)))
|
||||
FilterList(
|
||||
getInitialFilterList() + UriSelectFilter(
|
||||
"Tag",
|
||||
"tag",
|
||||
arrayOf(
|
||||
"" to "Any",
|
||||
*tagMappings.toTypedArray()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
else -> FilterList(getInitialFilterList())
|
||||
}
|
||||
|
@ -429,7 +444,7 @@ open class MyMangaReaderCMSSource(
|
|||
private val firstIsUnspecified: Boolean = true,
|
||||
defaultValue: Int = 0
|
||||
) :
|
||||
Filter.Select<String>(displayName, vals.map { it.second }.toTypedArray(), defaultValue), UriFilter {
|
||||
Filter.Select<String>(displayName, vals.map { it.second }.toTypedArray(), defaultValue), UriFilter {
|
||||
override fun addToUri(uri: Uri.Builder) {
|
||||
if (state != 0 || !firstIsUnspecified)
|
||||
uri.appendQueryParameter(uriParam, vals[state].first)
|
||||
|
@ -442,9 +457,13 @@ open class MyMangaReaderCMSSource(
|
|||
}
|
||||
}
|
||||
|
||||
class SortFilter : Filter.Sort("Sort",
|
||||
class SortFilter :
|
||||
Filter.Sort(
|
||||
"Sort",
|
||||
sortables.map { it.second }.toTypedArray(),
|
||||
Selection(0, true)), UriFilter {
|
||||
Selection(0, true)
|
||||
),
|
||||
UriFilter {
|
||||
override fun addToUri(uri: Uri.Builder) {
|
||||
uri.appendQueryParameter("sortBy", sortables[state!!.index].first)
|
||||
uri.appendQueryParameter("asc", state!!.ascending.toString())
|
||||
|
@ -452,9 +471,9 @@ open class MyMangaReaderCMSSource(
|
|||
|
||||
companion object {
|
||||
private val sortables = arrayOf(
|
||||
"name" to "Name",
|
||||
"views" to "Popularity",
|
||||
"last_release" to "Last update"
|
||||
"name" to "Name",
|
||||
"views" to "Popularity",
|
||||
"last_release" to "Last update"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -24,6 +21,9 @@ import okhttp3.Response
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
open class MyReadingManga(override val lang: String, private val siteLang: String, private val latestLang: String) : ParsedHttpSource() {
|
||||
|
||||
|
@ -159,8 +159,12 @@ open class MyReadingManga(override val lang: String, private val siteLang: Strin
|
|||
}
|
||||
|
||||
if (needCover) {
|
||||
thumbnail_url = getThumbnail(getImage(client.newCall(GET("$baseUrl/search/?search=${document.location()}", headers))
|
||||
.execute().asJsoup().select("div.wdm_results div.p_content img").first()))
|
||||
thumbnail_url = getThumbnail(
|
||||
getImage(
|
||||
client.newCall(GET("$baseUrl/search/?search=${document.location()}", headers))
|
||||
.execute().asJsoup().select("div.wdm_results div.p_content img").first()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package eu.kanade.tachiyomi.extension.all.nhentai
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
object NHUtils {
|
||||
fun getArtists(document: Document): String {
|
||||
|
@ -57,7 +57,7 @@ object NHUtils {
|
|||
fun getTime(document: Document): Long {
|
||||
val timeString = document.toString().substringAfter("datetime=\"").substringBefore("\">").replace("T", " ")
|
||||
|
||||
return SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSZ").parse(timeString).time
|
||||
return SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSZ").parse(timeString)?.time ?: 0L
|
||||
}
|
||||
|
||||
private fun Element.cleanTag(): String = text().replace(Regex("\\(.*\\)"), "").trim()
|
||||
|
|
|
@ -251,12 +251,14 @@ open class NHentai(
|
|||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
return listOf(SChapter.create().apply {
|
||||
name = "Chapter"
|
||||
scanlator = getGroups(document)
|
||||
date_upload = getTime(document)
|
||||
setUrlWithoutDomain(response.request().url().encodedPath())
|
||||
})
|
||||
return listOf(
|
||||
SChapter.create().apply {
|
||||
name = "Chapter"
|
||||
scanlator = getGroups(document)
|
||||
date_upload = getTime(document)
|
||||
setUrlWithoutDomain(response.request().url().encodedPath())
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun chapterFromElement(element: Element) = throw UnsupportedOperationException("Not used")
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,13 +18,13 @@ 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 java.util.Date
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.Response
|
||||
import rx.Observable
|
||||
import java.util.Date
|
||||
|
||||
@Nsfw
|
||||
class NineHentai : HttpSource() {
|
||||
|
@ -51,26 +51,26 @@ class NineHentai : HttpSource() {
|
|||
|
||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||
return client.newCall(popularMangaRequest(page))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
getMangaList(response, page)
|
||||
}
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
getMangaList(response, page)
|
||||
}
|
||||
}
|
||||
|
||||
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
|
||||
return client.newCall(latestUpdatesRequest(page))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
getMangaList(response, page)
|
||||
}
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
getMangaList(response, page)
|
||||
}
|
||||
}
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||
return client.newCall(searchMangaRequest(page, query, filters))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
getMangaList(response, page)
|
||||
}
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
getMangaList(response, page)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMangaList(response: Response, page: Int): MangasPage {
|
||||
|
@ -180,13 +180,15 @@ class NineHentai : HttpSource() {
|
|||
|
||||
private class GenreList(tags: List<Tag>) : Filter.Group<Tag>("Tags", tags)
|
||||
|
||||
private class Sorting : Filter.Sort("Sorting",
|
||||
arrayOf("Newest", "Popular Right now", "Most Fapped", "Most Viewed", "By Title"),
|
||||
Selection(1, false))
|
||||
private class Sorting : Filter.Sort(
|
||||
"Sorting",
|
||||
arrayOf("Newest", "Popular Right now", "Most Fapped", "Most Viewed", "By Title"),
|
||||
Selection(1, false)
|
||||
)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
Sorting(),
|
||||
GenreList(NHTags.getTagsList())
|
||||
Sorting(),
|
||||
GenreList(NHTags.getTagsList())
|
||||
)
|
||||
|
||||
override fun imageUrlParse(response: Response): String = throw Exception("Not Used")
|
||||
|
|
|
@ -7,15 +7,15 @@ 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.ParsedHttpSource
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
open class NineManga(override val name: String, override val baseUrl: String, override val lang: String) : ParsedHttpSource() {
|
||||
|
||||
|
@ -84,7 +84,7 @@ open class NineManga(override val name: String, override val baseUrl: String, ov
|
|||
if (dateWords.size == 3) {
|
||||
if (dateWords[1].contains(",")) {
|
||||
return try {
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
|
||||
} catch (e: ParseException) {
|
||||
0L
|
||||
}
|
||||
|
@ -161,21 +161,27 @@ open class NineManga(override val name: String, override val baseUrl: String, ov
|
|||
fun toUriPart() = vals[state].second
|
||||
}
|
||||
|
||||
protected open class ContainBeginEndFilter(name: String) : UriPartFilter(name, arrayOf(
|
||||
Pair("Contain", "contain"),
|
||||
Pair("Begin", "begin"),
|
||||
Pair("End", "end")
|
||||
))
|
||||
protected open class ContainBeginEndFilter(name: String) : UriPartFilter(
|
||||
name,
|
||||
arrayOf(
|
||||
Pair("Contain", "contain"),
|
||||
Pair("Begin", "begin"),
|
||||
Pair("End", "end")
|
||||
)
|
||||
)
|
||||
|
||||
private class QueryCBEFilter : ContainBeginEndFilter("Query")
|
||||
private class AuthorCBEFilter : ContainBeginEndFilter("Author")
|
||||
private class ArtistCBEFilter : ContainBeginEndFilter("Artist")
|
||||
|
||||
private class CompletedFilter : UriPartFilter("Completed", arrayOf(
|
||||
Pair("Either", "either"),
|
||||
Pair("Yes", "yes"),
|
||||
Pair("No", "no")
|
||||
))
|
||||
private class CompletedFilter : UriPartFilter(
|
||||
"Completed",
|
||||
arrayOf(
|
||||
Pair("Either", "either"),
|
||||
Pair("Yes", "yes"),
|
||||
Pair("No", "no")
|
||||
)
|
||||
)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
QueryCBEFilter(),
|
||||
|
|
|
@ -4,12 +4,12 @@ import eu.kanade.tachiyomi.source.Source
|
|||
import eu.kanade.tachiyomi.source.SourceFactory
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class NineMangaFactory : SourceFactory {
|
||||
override fun createSources(): List<Source> = listOf(
|
||||
|
@ -756,7 +756,7 @@ fun parseChapterDateByLang(date: String): Long {
|
|||
if (dateWords.size == 3) {
|
||||
if (dateWords[1].contains(",")) {
|
||||
return try {
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
|
||||
} catch (e: ParseException) {
|
||||
0L
|
||||
}
|
||||
|
|
|
@ -8,9 +8,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
@ -18,6 +15,9 @@ import okhttp3.Response
|
|||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
abstract class Paprika(
|
||||
override val name: String,
|
||||
|
@ -161,8 +161,9 @@ abstract class Paprika(
|
|||
else -> null
|
||||
}?.timeInMillis ?: 0L
|
||||
}
|
||||
else -> SimpleDateFormat("MMM d yy", Locale.US)
|
||||
.parse("${this.substringBefore(",")} $currentYear")?.time ?: 0
|
||||
else ->
|
||||
SimpleDateFormat("MMM d yy", Locale.US)
|
||||
.parse("${this.substringBefore(",")} $currentYear")?.time ?: 0
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
0L
|
||||
|
|
|
@ -9,14 +9,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class TheLibraryOfOhara(override val lang: String, private val siteLang: String) : ParsedHttpSource() {
|
||||
|
||||
|
@ -36,15 +36,16 @@ class TheLibraryOfOhara(override val lang: String, private val siteLang: String)
|
|||
|
||||
// only show entries which contain pictures only.
|
||||
override fun popularMangaSelector() = when (lang) {
|
||||
"en" -> "#categories-7 ul li.cat-item-589813936," + // Chapter Secrets
|
||||
"#categories-7 ul li.cat-item-607613583, " + // Chapter Secrets Specials
|
||||
"#categories-7 ul li.cat-item-43972770, " + // Charlotte Family
|
||||
"#categories-7 ul li.cat-item-9363667, " + // Complete Guides
|
||||
"#categories-7 ul li.cat-item-634609261, " + // Parody Chapter
|
||||
"#categories-7 ul li.cat-item-699200615, " + // Return to the Reverie
|
||||
"#categories-7 ul li.cat-item-139757, " + // SBS
|
||||
"#categories-7 ul li.cat-item-22695, " + // Timeline
|
||||
"#categories-7 ul li.cat-item-648324575" // Vivre Card Databook
|
||||
"en" ->
|
||||
"#categories-7 ul li.cat-item-589813936," + // Chapter Secrets
|
||||
"#categories-7 ul li.cat-item-607613583, " + // Chapter Secrets Specials
|
||||
"#categories-7 ul li.cat-item-43972770, " + // Charlotte Family
|
||||
"#categories-7 ul li.cat-item-9363667, " + // Complete Guides
|
||||
"#categories-7 ul li.cat-item-634609261, " + // Parody Chapter
|
||||
"#categories-7 ul li.cat-item-699200615, " + // Return to the Reverie
|
||||
"#categories-7 ul li.cat-item-139757, " + // SBS
|
||||
"#categories-7 ul li.cat-item-22695, " + // Timeline
|
||||
"#categories-7 ul li.cat-item-648324575" // Vivre Card Databook
|
||||
"id" -> "#categories-7 ul li.cat-item-702404482, #categories-7 ul li.cat-item-699200615" // Chapter Secrets Bahasa Indonesia, Return to the Reverie
|
||||
"fr" -> "#categories-7 ul li.cat-item-699200615" // Return to the Reverie
|
||||
"ar" -> "#categories-7 ul li.cat-item-699200615" // Return to the Reverie
|
||||
|
@ -144,7 +145,7 @@ class TheLibraryOfOhara(override val lang: String, private val siteLang: String)
|
|||
|
||||
private fun parseChapterDate(date: String): Long {
|
||||
val parsedDate = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault()).parse(date.replace("+00:00", "+0000"))
|
||||
return parsedDate?.time ?: 0L
|
||||
return parsedDate?.time ?: 0L
|
||||
}
|
||||
|
||||
private fun chapterNextPageSelector() = "div.nav-previous a"
|
||||
|
@ -180,7 +181,8 @@ class TheLibraryOfOhara(override val lang: String, private val siteLang: String)
|
|||
!it.name.contains("Arabic") &&
|
||||
!it.name.contains("Italian") &&
|
||||
!it.name.contains("Indonesia") &&
|
||||
!it.name.contains("Spanish") }.toMutableList()
|
||||
!it.name.contains("Spanish")
|
||||
}.toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,10 +7,6 @@ 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.ParsedHttpSource
|
||||
import java.net.URLDecoder
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
@ -18,6 +14,10 @@ import okhttp3.RequestBody
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.net.URLDecoder
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
abstract class ToomicsGlobal(
|
||||
private val siteLang: String,
|
||||
|
@ -153,7 +153,7 @@ abstract class ToomicsGlobal(
|
|||
|
||||
private fun parseChapterDate(date: String): Long {
|
||||
return try {
|
||||
dateFormat.parse(date).time
|
||||
dateFormat.parse(date)?.time ?: 0L
|
||||
} catch (e: ParseException) {
|
||||
0L
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@ import eu.kanade.tachiyomi.source.model.FilterList
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class DongmanManhua : WebtoonsDefault("zh", "", dateFormat = SimpleDateFormat("yyyy-M-d", Locale.ENGLISH)) {
|
||||
override val baseUrl = "https://www.dongmanmanhua.cn"
|
||||
|
|
|
@ -9,7 +9,6 @@ import eu.kanade.tachiyomi.source.model.MangasPage
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.util.Calendar
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.Headers
|
||||
|
@ -19,6 +18,7 @@ import okhttp3.Request
|
|||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.Calendar
|
||||
|
||||
abstract class Webtoons(
|
||||
override val lang: String,
|
||||
|
@ -33,21 +33,23 @@ abstract class Webtoons(
|
|||
override val supportsLatest = true
|
||||
|
||||
override val client: OkHttpClient = super.client.newBuilder()
|
||||
.cookieJar(object : CookieJar {
|
||||
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {}
|
||||
override fun loadForRequest(url: HttpUrl): List<Cookie> {
|
||||
return listOf<Cookie>(
|
||||
Cookie.Builder()
|
||||
.domain("www.webtoons.com")
|
||||
.path("/")
|
||||
.name("ageGatePass")
|
||||
.value("true")
|
||||
.name("locale")
|
||||
.value(localeForCookie)
|
||||
.build()
|
||||
)
|
||||
.cookieJar(
|
||||
object : CookieJar {
|
||||
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {}
|
||||
override fun loadForRequest(url: HttpUrl): List<Cookie> {
|
||||
return listOf<Cookie>(
|
||||
Cookie.Builder()
|
||||
.domain("www.webtoons.com")
|
||||
.path("/")
|
||||
.name("ageGatePass")
|
||||
.value("true")
|
||||
.name("locale")
|
||||
.value(localeForCookie)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
.build()
|
||||
|
||||
private val day: String
|
||||
|
@ -71,11 +73,11 @@ abstract class Webtoons(
|
|||
override fun latestUpdatesSelector() = "div#dailyList > $day li > a"
|
||||
|
||||
override fun headersBuilder(): Headers.Builder = super.headersBuilder()
|
||||
.add("Referer", "https://www.webtoons.com/$langCode/")
|
||||
.add("Referer", "https://www.webtoons.com/$langCode/")
|
||||
|
||||
protected val mobileHeaders: Headers = super.headersBuilder()
|
||||
.add("Referer", "https://m.webtoons.com")
|
||||
.build()
|
||||
.add("Referer", "https://m.webtoons.com")
|
||||
.build()
|
||||
|
||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/$langCode/dailySchedule", headers)
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ import eu.kanade.tachiyomi.network.GET
|
|||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
open class WebtoonsDefault(
|
||||
override val lang: String,
|
||||
|
|
|
@ -58,7 +58,8 @@ class WebtoonsIndonesian : WebtoonsDefault("in", "id") {
|
|||
// Android seems to be unable to parse Indonesian dates; we'll use a short hard-coded table
|
||||
// instead.
|
||||
private val dateMap: Array<String> = arrayOf(
|
||||
"Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agu", "Sep", "Okt", "Nov", "Des")
|
||||
"Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agu", "Sep", "Okt", "Nov", "Des"
|
||||
)
|
||||
|
||||
override fun chapterParseDate(date: String): Long {
|
||||
val expr = Regex("""(\d{4}) ([A-Z][a-z]{2}) (\d+)""").find(date) ?: return 0
|
||||
|
|
|
@ -7,7 +7,6 @@ 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 java.util.ArrayList
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Request
|
||||
|
@ -16,6 +15,7 @@ import org.json.JSONObject
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.util.ArrayList
|
||||
|
||||
open class WebtoonsTranslate(override val lang: String, private val translateLangCode: String, languageNameExtra: String = "") : Webtoons(lang) {
|
||||
// popularMangaRequest already returns manga sorted by latest update
|
||||
|
@ -80,20 +80,20 @@ open class WebtoonsTranslate(override val lang: String, private val translateLan
|
|||
?: json.getString("thumbnailMobileUrl")
|
||||
|
||||
return SManga.create().apply {
|
||||
title = json.getString("representTitle")
|
||||
author = json.getString("writeAuthorName")
|
||||
artist = json.getString("pictureAuthorName") ?: author
|
||||
thumbnail_url = if (relativeThumnailURL != null) "$thumbnailBaseUrl$relativeThumnailURL" else null
|
||||
status = SManga.UNKNOWN
|
||||
url = mobileBaseUrl
|
||||
.resolve("/translate/episodeList")!!
|
||||
.newBuilder()
|
||||
.addQueryParameter("titleNo", json.getInt("titleNo").toString())
|
||||
.addQueryParameter("languageCode", translateLangCode)
|
||||
.addQueryParameter("teamVersion", json.optInt("teamVersion", 0).toString())
|
||||
.build()
|
||||
.toString()
|
||||
}
|
||||
title = json.getString("representTitle")
|
||||
author = json.getString("writeAuthorName")
|
||||
artist = json.getString("pictureAuthorName") ?: author
|
||||
thumbnail_url = if (relativeThumnailURL != null) "$thumbnailBaseUrl$relativeThumnailURL" else null
|
||||
status = SManga.UNKNOWN
|
||||
url = mobileBaseUrl
|
||||
.resolve("/translate/episodeList")!!
|
||||
.newBuilder()
|
||||
.addQueryParameter("titleNo", json.getInt("titleNo").toString())
|
||||
.addQueryParameter("languageCode", translateLangCode)
|
||||
.addQueryParameter("teamVersion", json.optInt("teamVersion", 0).toString())
|
||||
.build()
|
||||
.toString()
|
||||
}
|
||||
}
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||
|
|
|
@ -7,14 +7,14 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
abstract class WPComics(
|
||||
override val name: String,
|
||||
|
|
|
@ -9,12 +9,12 @@ 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.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class WPComicsFactory : SourceFactory {
|
||||
override fun createSources(): List<Source> = listOf(
|
||||
|
@ -113,9 +113,9 @@ private class ComicLatest : WPComics("ComicLatest", "https://comiclatest.com", "
|
|||
|
||||
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
|
||||
element.select("h3 a").let {
|
||||
title = it.text()
|
||||
setUrlWithoutDomain(it.attr("href"))
|
||||
}
|
||||
title = it.text()
|
||||
setUrlWithoutDomain(it.attr("href"))
|
||||
}
|
||||
thumbnail_url = element.select("img").attr("data-original")
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,6 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -26,6 +22,10 @@ import org.jsoup.nodes.Element
|
|||
import org.jsoup.select.Elements
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
abstract class WPMangaStream(
|
||||
override val name: String,
|
||||
|
@ -273,28 +273,37 @@ abstract class WPMangaStream(
|
|||
|
||||
private class YearFilter : Filter.Text("Year")
|
||||
|
||||
protected class TypeFilter : UriPartFilter("Type", arrayOf(
|
||||
Pair("Default", ""),
|
||||
Pair("Manga", "Manga"),
|
||||
Pair("Manhwa", "Manhwa"),
|
||||
Pair("Manhua", "Manhua"),
|
||||
Pair("Comic", "Comic")
|
||||
))
|
||||
protected class TypeFilter : UriPartFilter(
|
||||
"Type",
|
||||
arrayOf(
|
||||
Pair("Default", ""),
|
||||
Pair("Manga", "Manga"),
|
||||
Pair("Manhwa", "Manhwa"),
|
||||
Pair("Manhua", "Manhua"),
|
||||
Pair("Comic", "Comic")
|
||||
)
|
||||
)
|
||||
|
||||
protected class SortByFilter : UriPartFilter("Sort By", arrayOf(
|
||||
Pair("Default", ""),
|
||||
Pair("A-Z", "title"),
|
||||
Pair("Z-A", "titlereverse"),
|
||||
Pair("Latest Update", "update"),
|
||||
Pair("Latest Added", "latest"),
|
||||
Pair("Popular", "popular")
|
||||
))
|
||||
protected class SortByFilter : UriPartFilter(
|
||||
"Sort By",
|
||||
arrayOf(
|
||||
Pair("Default", ""),
|
||||
Pair("A-Z", "title"),
|
||||
Pair("Z-A", "titlereverse"),
|
||||
Pair("Latest Update", "update"),
|
||||
Pair("Latest Added", "latest"),
|
||||
Pair("Popular", "popular")
|
||||
)
|
||||
)
|
||||
|
||||
protected class StatusFilter : UriPartFilter("Status", arrayOf(
|
||||
Pair("All", ""),
|
||||
Pair("Ongoing", "ongoing"),
|
||||
Pair("Completed", "completed")
|
||||
))
|
||||
protected class StatusFilter : UriPartFilter(
|
||||
"Status",
|
||||
arrayOf(
|
||||
Pair("All", ""),
|
||||
Pair("Ongoing", "ongoing"),
|
||||
Pair("Completed", "completed")
|
||||
)
|
||||
)
|
||||
|
||||
protected class Genre(name: String, val id: String = name) : Filter.TriState(name)
|
||||
protected class GenreListFilter(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres)
|
||||
|
|
|
@ -10,7 +10,6 @@ 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.util.asJsoup
|
||||
import java.io.IOException
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Interceptor
|
||||
|
@ -20,6 +19,7 @@ import okhttp3.Response
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.io.IOException
|
||||
|
||||
class WPMangaStreamFactory : SourceFactory {
|
||||
override fun createSources(): List<Source> = listOf(
|
||||
|
@ -198,66 +198,72 @@ class WestManga : WPMangaStream("West Manga (WP Manga Stream)", "https://westman
|
|||
return manga
|
||||
}
|
||||
|
||||
private class SortByFilter : UriPartFilter("Sort By", arrayOf(
|
||||
Pair("Default", ""),
|
||||
Pair("A-Z", "A-Z"),
|
||||
Pair("Latest Added", "latest"),
|
||||
Pair("Popular", "popular")
|
||||
))
|
||||
private class SortByFilter : UriPartFilter(
|
||||
"Sort By",
|
||||
arrayOf(
|
||||
Pair("Default", ""),
|
||||
Pair("A-Z", "A-Z"),
|
||||
Pair("Latest Added", "latest"),
|
||||
Pair("Popular", "popular")
|
||||
)
|
||||
)
|
||||
|
||||
private class GenreListFilter : UriPartFilter("Genre", arrayOf(
|
||||
Pair("Default", ""),
|
||||
Pair("4-Koma", "4-koma"),
|
||||
Pair("Action", "action"),
|
||||
Pair("Adventure", "adventure"),
|
||||
Pair("Comedy", "comedy"),
|
||||
Pair("Cooking", "cooking"),
|
||||
Pair("Demons", "demons"),
|
||||
Pair("Drama", "drama"),
|
||||
Pair("Ecchi", "ecchi"),
|
||||
Pair("Fantasy", "fantasy"),
|
||||
Pair("FantasyAction", "fantasyaction"),
|
||||
Pair("Game", "game"),
|
||||
Pair("Gender Bender", "gender-bender"),
|
||||
Pair("Gore", "gore"),
|
||||
Pair("Harem", "harem"),
|
||||
Pair("Historical", "historical"),
|
||||
Pair("Horro", "horro"),
|
||||
Pair("Horror", "horror"),
|
||||
Pair("Isekai", "isekai"),
|
||||
Pair("Isekai Action", "isekai-action"),
|
||||
Pair("Josei", "josei"),
|
||||
Pair("Magic", "magic"),
|
||||
Pair("Manga", "manga"),
|
||||
Pair("Manhua", "manhua"),
|
||||
Pair("Martial arts", "martial-arts"),
|
||||
Pair("Mature", "mature"),
|
||||
Pair("Mecha", "mecha"),
|
||||
Pair("Medical", "medical"),
|
||||
Pair("Music", "music"),
|
||||
Pair("Mystery", "mystery"),
|
||||
Pair("Oneshot", "oneshot"),
|
||||
Pair("Project", "project"),
|
||||
Pair("Psychological", "psychological"),
|
||||
Pair("Romance", "romance"),
|
||||
Pair("School", "school"),
|
||||
Pair("School life", "school-life"),
|
||||
Pair("Sci fi", "sci-fi"),
|
||||
Pair("Seinen", "seinen"),
|
||||
Pair("Shoujo", "shoujo"),
|
||||
Pair("Shoujo Ai", "shoujo-ai"),
|
||||
Pair("Shounen", "shounen"),
|
||||
Pair("Slice of Life", "slice-of-life"),
|
||||
Pair("Sports", "sports"),
|
||||
Pair("Super Power", "super-power"),
|
||||
Pair("Supernatural", "supernatural"),
|
||||
Pair("Suspense", "suspense"),
|
||||
Pair("Thriller", "thriller"),
|
||||
Pair("Tragedy", "tragedy"),
|
||||
Pair("Vampire", "vampire"),
|
||||
Pair("Webtoons", "webtoons"),
|
||||
Pair("Yuri", "yuri")
|
||||
))
|
||||
private class GenreListFilter : UriPartFilter(
|
||||
"Genre",
|
||||
arrayOf(
|
||||
Pair("Default", ""),
|
||||
Pair("4-Koma", "4-koma"),
|
||||
Pair("Action", "action"),
|
||||
Pair("Adventure", "adventure"),
|
||||
Pair("Comedy", "comedy"),
|
||||
Pair("Cooking", "cooking"),
|
||||
Pair("Demons", "demons"),
|
||||
Pair("Drama", "drama"),
|
||||
Pair("Ecchi", "ecchi"),
|
||||
Pair("Fantasy", "fantasy"),
|
||||
Pair("FantasyAction", "fantasyaction"),
|
||||
Pair("Game", "game"),
|
||||
Pair("Gender Bender", "gender-bender"),
|
||||
Pair("Gore", "gore"),
|
||||
Pair("Harem", "harem"),
|
||||
Pair("Historical", "historical"),
|
||||
Pair("Horro", "horro"),
|
||||
Pair("Horror", "horror"),
|
||||
Pair("Isekai", "isekai"),
|
||||
Pair("Isekai Action", "isekai-action"),
|
||||
Pair("Josei", "josei"),
|
||||
Pair("Magic", "magic"),
|
||||
Pair("Manga", "manga"),
|
||||
Pair("Manhua", "manhua"),
|
||||
Pair("Martial arts", "martial-arts"),
|
||||
Pair("Mature", "mature"),
|
||||
Pair("Mecha", "mecha"),
|
||||
Pair("Medical", "medical"),
|
||||
Pair("Music", "music"),
|
||||
Pair("Mystery", "mystery"),
|
||||
Pair("Oneshot", "oneshot"),
|
||||
Pair("Project", "project"),
|
||||
Pair("Psychological", "psychological"),
|
||||
Pair("Romance", "romance"),
|
||||
Pair("School", "school"),
|
||||
Pair("School life", "school-life"),
|
||||
Pair("Sci fi", "sci-fi"),
|
||||
Pair("Seinen", "seinen"),
|
||||
Pair("Shoujo", "shoujo"),
|
||||
Pair("Shoujo Ai", "shoujo-ai"),
|
||||
Pair("Shounen", "shounen"),
|
||||
Pair("Slice of Life", "slice-of-life"),
|
||||
Pair("Sports", "sports"),
|
||||
Pair("Super Power", "super-power"),
|
||||
Pair("Supernatural", "supernatural"),
|
||||
Pair("Suspense", "suspense"),
|
||||
Pair("Thriller", "thriller"),
|
||||
Pair("Tragedy", "tragedy"),
|
||||
Pair("Vampire", "vampire"),
|
||||
Pair("Webtoons", "webtoons"),
|
||||
Pair("Yuri", "yuri")
|
||||
)
|
||||
)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
Filter.Header("NOTE: sort and genre can't be combined and ignored when using text search!"),
|
||||
|
@ -384,15 +390,18 @@ class KomikGo : WPMangaStream("Komik GO (WP Manga Stream)", "https://komikgo.com
|
|||
|
||||
private class TextField(name: String, val key: String) : Filter.Text(name)
|
||||
|
||||
private class SortBy : UriPartFilter("Sort by", arrayOf(
|
||||
Pair("Relevance", ""),
|
||||
Pair("Latest", "latest"),
|
||||
Pair("A-Z", "alphabet"),
|
||||
Pair("Rating", "rating"),
|
||||
Pair("Trending", "trending"),
|
||||
Pair("Most View", "views"),
|
||||
Pair("New", "new-manga")
|
||||
))
|
||||
private class SortBy : UriPartFilter(
|
||||
"Sort by",
|
||||
arrayOf(
|
||||
Pair("Relevance", ""),
|
||||
Pair("Latest", "latest"),
|
||||
Pair("A-Z", "alphabet"),
|
||||
Pair("Rating", "rating"),
|
||||
Pair("Trending", "trending"),
|
||||
Pair("Most View", "views"),
|
||||
Pair("New", "new-manga")
|
||||
)
|
||||
)
|
||||
|
||||
private class Status(name: String, val id: String = name) : Filter.TriState(name)
|
||||
private class StatusList(statuses: List<Status>) : Filter.Group<Status>("Status", statuses)
|
||||
|
|
|
@ -8,15 +8,15 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
abstract class Zbulu(
|
||||
override val name: String,
|
||||
|
@ -82,9 +82,9 @@ abstract class Zbulu(
|
|||
filters.forEach { filter ->
|
||||
when (filter) {
|
||||
is AuthorField -> {
|
||||
if (filter.state.isNotBlank()) {
|
||||
ret = "$baseUrl/author/${filter.state.replace(" ", "-")}/page-$page"
|
||||
}
|
||||
if (filter.state.isNotBlank()) {
|
||||
ret = "$baseUrl/author/${filter.state.replace(" ", "-")}/page-$page"
|
||||
}
|
||||
}
|
||||
is GenreFilter -> {
|
||||
if (filter.toUriPart().isNotBlank() && filter.state != 0) {
|
||||
|
@ -193,7 +193,8 @@ abstract class Zbulu(
|
|||
|
||||
// [...document.querySelectorAll('.sub-menu li a')].map(a => `Pair("${a.textContent}", "${a.getAttribute('href')}")`).join(',\n')
|
||||
// from $baseUrl
|
||||
private class GenreFilter : UriPartFilter("Genres",
|
||||
private class GenreFilter : UriPartFilter(
|
||||
"Genres",
|
||||
arrayOf(
|
||||
Pair("Choose a genre", ""),
|
||||
Pair("Action", "action"),
|
||||
|
|
|
@ -7,13 +7,13 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class AndromedaScans : ParsedHttpSource() {
|
||||
override val name = "AndromedaScans"
|
||||
|
|
|
@ -147,13 +147,16 @@ class MangaAe : ParsedHttpSource() {
|
|||
fun toUriPart() = vals[state].second
|
||||
}
|
||||
|
||||
private class OrderByFilter : UriPartFilter("الترتيب حسب", arrayOf(
|
||||
Pair("اختيار", ""),
|
||||
Pair("اسم المانجا", "english_name"),
|
||||
Pair("تاريخ النشر", "release_date"),
|
||||
Pair("عدد الفصول", "chapter_count"),
|
||||
Pair("الحالة", "status")
|
||||
))
|
||||
private class OrderByFilter : UriPartFilter(
|
||||
"الترتيب حسب",
|
||||
arrayOf(
|
||||
Pair("اختيار", ""),
|
||||
Pair("اسم المانجا", "english_name"),
|
||||
Pair("تاريخ النشر", "release_date"),
|
||||
Pair("عدد الفصول", "chapter_count"),
|
||||
Pair("الحالة", "status")
|
||||
)
|
||||
)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
OrderByFilter()
|
||||
|
|
|
@ -6,10 +6,10 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class MangaZen : ParsedHttpSource() {
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class TeamX : ParsedHttpSource() {
|
||||
|
||||
|
@ -44,8 +44,10 @@ class TeamX : ParsedHttpSource() {
|
|||
return SManga.create().apply {
|
||||
title = element.select(titleSelector).text()
|
||||
setUrlWithoutDomain(element.select("a").first().attr("href"))
|
||||
thumbnail_url = element.select("img").let { if (it.hasAttr("data-src"))
|
||||
it.attr("abs:data-src") else it.attr("abs:src") }
|
||||
thumbnail_url = element.select("img").let {
|
||||
if (it.hasAttr("data-src"))
|
||||
it.attr("abs:data-src") else it.attr("abs:src")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,8 +108,10 @@ class TeamX : ParsedHttpSource() {
|
|||
title = info.select("div.col-md-9").text()
|
||||
description = info.select("div.story p").text()
|
||||
genre = info.select("div.genre a").joinToString { it.text() }
|
||||
thumbnail_url = info.select("img").let { if (it.hasAttr("data-src"))
|
||||
it.attr("abs:data-src") else it.attr("abs:src") }
|
||||
thumbnail_url = info.select("img").let {
|
||||
if (it.hasAttr("data-src"))
|
||||
it.attr("abs:data-src") else it.attr("abs:src")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,8 +132,14 @@ class TeamX : ParsedHttpSource() {
|
|||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
return document.select("div#translationPageall img").mapIndexed { i, img ->
|
||||
Page(i, "", img.let { if (it.hasAttr("data-src"))
|
||||
it.attr("abs:data-src") else it.attr("abs:src") })
|
||||
Page(
|
||||
i,
|
||||
"",
|
||||
img.let {
|
||||
if (it.hasAttr("data-src"))
|
||||
it.attr("abs:data-src") else it.attr("abs:src")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,6 @@ 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.ParsedHttpSource
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
@ -26,6 +22,10 @@ import okhttp3.Response
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class MangaTube : ParsedHttpSource() {
|
||||
|
||||
|
@ -156,7 +156,7 @@ class MangaTube : ParsedHttpSource() {
|
|||
}
|
||||
date_upload = element.select("p.chapter-date").text().let {
|
||||
try {
|
||||
SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()).parse(it.substringAfter(" ")).time
|
||||
SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()).parse(it.substringAfter(" "))?.time ?: 0L
|
||||
} catch (_: ParseException) {
|
||||
0L
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class WieManga : ParsedHttpSource() {
|
||||
|
||||
|
@ -119,7 +119,7 @@ class WieManga : ParsedHttpSource() {
|
|||
}
|
||||
|
||||
private fun parseChapterDate(date: String): Long {
|
||||
return SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault()).parse(date).time
|
||||
return SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault()).parse(date)?.time ?: 0L
|
||||
}
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
|
|
|
@ -47,8 +47,10 @@ class CloneManga : ParsedHttpSource() {
|
|||
status = SManga.UNKNOWN
|
||||
url = element.select("a").first().attr("href")
|
||||
description = element.select("h4").first()?.text() ?: ""
|
||||
thumbnail_url = baseUrl + attr.substring(attr.indexOf("site/themes"),
|
||||
attr.indexOf(")"))
|
||||
thumbnail_url = baseUrl + attr.substring(
|
||||
attr.indexOf("site/themes"),
|
||||
attr.indexOf(")")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,8 +67,10 @@ class CloneManga : ParsedHttpSource() {
|
|||
val document = response.asJsoup()
|
||||
val series = document.location()
|
||||
val numChapters = Regex(
|
||||
pattern = "&page=(.*)&lang=").findAll(
|
||||
input = document.getElementsByTag("script")[3].toString())
|
||||
pattern = "&page=(.*)&lang="
|
||||
).findAll(
|
||||
input = document.getElementsByTag("script")[3].toString()
|
||||
)
|
||||
.elementAt(3).destructured.component1()
|
||||
.toInt()
|
||||
val chapters = ArrayList<SChapter>()
|
||||
|
|
|
@ -8,9 +8,6 @@ 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.ParsedHttpSource
|
||||
import java.net.URLEncoder
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -19,6 +16,9 @@ import okhttp3.RequestBody
|
|||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.net.URLEncoder
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class Comicastle : ParsedHttpSource() {
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.ArrayList
|
||||
|
@ -15,11 +20,6 @@ import java.util.Calendar
|
|||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.regex.Pattern
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class ComicExtra : ParsedHttpSource() {
|
||||
|
||||
|
@ -141,15 +141,13 @@ class ComicExtra : ParsedHttpSource() {
|
|||
}
|
||||
|
||||
private fun dateParse(dateAsString: String): Long {
|
||||
val date: Date
|
||||
date = try {
|
||||
val date: Date? = try {
|
||||
SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH).parse(dateAsString.replace(Regex("(st|nd|rd|th)"), ""))
|
||||
} catch (e: ParseException) {
|
||||
val m = datePattern.matcher(dateAsString)
|
||||
|
||||
if (dateAsString != "Today" && m.matches()) {
|
||||
val amount = m.group(1).toInt()
|
||||
|
||||
val amount = m.group(1)!!.toInt()
|
||||
Calendar.getInstance().apply {
|
||||
add(Calendar.DATE, -amount)
|
||||
}.time
|
||||
|
@ -158,7 +156,7 @@ class ComicExtra : ParsedHttpSource() {
|
|||
} else return 0
|
||||
}
|
||||
|
||||
return date.time
|
||||
return date?.time ?: 0L
|
||||
}
|
||||
|
||||
override fun pageListRequest(chapter: SChapter): Request {
|
||||
|
|
|
@ -11,14 +11,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class Dilbert : ParsedHttpSource() {
|
||||
|
||||
|
@ -46,20 +46,26 @@ class Dilbert : ParsedHttpSource() {
|
|||
|
||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||
val currentYear = Calendar.getInstance().get(Calendar.YEAR)
|
||||
return Observable.just(MangasPage((currentYear downTo 1989).map {
|
||||
SManga.create().apply {
|
||||
url = "?$it"
|
||||
title = "$name ($it)"
|
||||
artist = "Scott Adams"
|
||||
author = "Scott Adams"
|
||||
status = if (it < currentYear) SManga.COMPLETED else SManga.ONGOING
|
||||
description = """
|
||||
return Observable.just(
|
||||
MangasPage(
|
||||
(currentYear downTo 1989).map {
|
||||
SManga.create().apply {
|
||||
url = "?$it"
|
||||
title = "$name ($it)"
|
||||
artist = "Scott Adams"
|
||||
author = "Scott Adams"
|
||||
status = if (it < currentYear) SManga.COMPLETED else SManga.ONGOING
|
||||
description =
|
||||
"""
|
||||
A satirical comic strip featuring Dilbert, a competent, but seldom recognized engineer.
|
||||
(This entry includes all the chapters published in $it.)
|
||||
""".trimIndent()
|
||||
thumbnail_url = "https://dilbert.com/assets/favicon/favicon-196x196-cf4d86b485e628a034ab8b961c1c3520b5969252400a80b9eed544d99403e037.png"
|
||||
}
|
||||
}, false))
|
||||
""".trimIndent()
|
||||
thumbnail_url = "https://dilbert.com/assets/favicon/favicon-196x196-cf4d86b485e628a034ab8b961c1c3520b5969252400a80b9eed544d99403e037.png"
|
||||
}
|
||||
},
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList) = fetchPopularManga(page)
|
||||
|
@ -74,7 +80,7 @@ class Dilbert : ParsedHttpSource() {
|
|||
val date = element.first(".comic-title-date").text()
|
||||
url = element.first(".img-comic-link").attr("href")
|
||||
name = element.first(".comic-title-name").text().ifBlank { date }
|
||||
date_upload = dateFormat.parse(date).time
|
||||
date_upload = dateFormat.parse(date)?.time ?: 0L
|
||||
}
|
||||
|
||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||
|
@ -93,7 +99,8 @@ class Dilbert : ParsedHttpSource() {
|
|||
if (pages != null) for (page in 2..pages) getChapters(page)
|
||||
return Observable.just(
|
||||
chapters.sortedBy(SChapter::date_upload).mapIndexed {
|
||||
i, ch -> ch.apply { chapter_number = i + 1f }
|
||||
i, ch ->
|
||||
ch.apply { chapter_number = i + 1f }
|
||||
}.reversed()
|
||||
)
|
||||
}
|
||||
|
|
|
@ -50,10 +50,12 @@ class DynastyDoujins : DynastyScans() {
|
|||
val chapters = document.select(chapterListSelector()).map { chapterFromElement(it) }.toMutableList()
|
||||
|
||||
document.select("a.thumbnail img").let { images ->
|
||||
if (images.isNotEmpty()) chapters.add(SChapter.create().apply {
|
||||
name = "Images"
|
||||
setUrlWithoutDomain(document.location() + "/images")
|
||||
})
|
||||
if (images.isNotEmpty()) chapters.add(
|
||||
SChapter.create().apply {
|
||||
name = "Images"
|
||||
setUrlWithoutDomain(document.location() + "/images")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return chapters
|
||||
|
|
|
@ -8,9 +8,10 @@ class DynastyFactory : SourceFactory {
|
|||
}
|
||||
|
||||
fun getAllDynasty() =
|
||||
listOf(
|
||||
DynastyAnthologies(),
|
||||
DynastyChapters(),
|
||||
DynastyDoujins(),
|
||||
DynastyIssues(),
|
||||
DynastySeries())
|
||||
listOf(
|
||||
DynastyAnthologies(),
|
||||
DynastyChapters(),
|
||||
DynastyDoujins(),
|
||||
DynastyIssues(),
|
||||
DynastySeries()
|
||||
)
|
||||
|
|
|
@ -8,9 +8,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.ArrayList
|
||||
import java.util.Locale
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.json.JSONArray
|
||||
|
@ -19,6 +16,9 @@ import org.jsoup.nodes.Element
|
|||
import org.jsoup.nodes.Node
|
||||
import org.jsoup.nodes.TextNode
|
||||
import org.jsoup.select.Elements
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.ArrayList
|
||||
import java.util.Locale
|
||||
|
||||
abstract class DynastyScans : ParsedHttpSource() {
|
||||
|
||||
|
@ -70,8 +70,10 @@ abstract class DynastyScans : ParsedHttpSource() {
|
|||
override fun searchMangaNextPageSelector() = "div.pagination > ul > li.active + li > a"
|
||||
|
||||
private fun buildListfromResponse(): List<Node> {
|
||||
return client.newCall(Request.Builder().headers(headers)
|
||||
.url(popularMangaInitialUrl()).build()).execute().asJsoup()
|
||||
return client.newCall(
|
||||
Request.Builder().headers(headers)
|
||||
.url(popularMangaInitialUrl()).build()
|
||||
).execute().asJsoup()
|
||||
.select("div#main").first { it.hasText() }.childNodes()
|
||||
}
|
||||
|
||||
|
@ -170,9 +172,9 @@ abstract class DynastyScans : ParsedHttpSource() {
|
|||
val imageUrls = JSONArray("[$imageUrl]")
|
||||
|
||||
(0 until imageUrls.length())
|
||||
.map { imageUrls.getJSONObject(it) }
|
||||
.map { baseUrl + it.get("image") }
|
||||
.forEach { pages.add(Page(pages.size, "", it)) }
|
||||
.map { imageUrls.getJSONObject(it) }
|
||||
.map { baseUrl + it.get("image") }
|
||||
.forEach { pages.add(Page(pages.size, "", it)) }
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
@ -193,32 +195,32 @@ abstract class DynastyScans : ParsedHttpSource() {
|
|||
}
|
||||
if (type == "src") {
|
||||
nodes
|
||||
.filter { it is Element && it.hasClass("thumbnails") }
|
||||
.flatMap { it.childNodes() }
|
||||
.filterIsInstance<Element>()
|
||||
.filter { it.hasClass("span2") }
|
||||
.forEach { this.add(it.child(0).child(0).attr(type)) }
|
||||
.filter { it is Element && it.hasClass("thumbnails") }
|
||||
.flatMap { it.childNodes() }
|
||||
.filterIsInstance<Element>()
|
||||
.filter { it.hasClass("span2") }
|
||||
.forEach { this.add(it.child(0).child(0).attr(type)) }
|
||||
}
|
||||
if (type == "href") {
|
||||
nodes
|
||||
.filter { it is Element && it.hasClass("thumbnails") }
|
||||
.flatMap { it.childNodes() }
|
||||
.filterIsInstance<Element>()
|
||||
.filter { it.hasClass("span2") }
|
||||
.forEach { this.add(it.child(0).attr(type)) }
|
||||
.filter { it is Element && it.hasClass("thumbnails") }
|
||||
.flatMap { it.childNodes() }
|
||||
.filterIsInstance<Element>()
|
||||
.filter { it.hasClass("span2") }
|
||||
.forEach { this.add(it.child(0).attr(type)) }
|
||||
}
|
||||
}
|
||||
|
||||
fun indexOfPartial(partial: String): Int {
|
||||
return (0..this.lastIndex).firstOrNull { this[it].contains(partial) }
|
||||
?: -1
|
||||
?: -1
|
||||
}
|
||||
|
||||
fun getItem(partial: String): String {
|
||||
return (0..this.lastIndex)
|
||||
.firstOrNull { super.get(it).contains(partial) }
|
||||
?.let { super.get(it) }
|
||||
?: ""
|
||||
.firstOrNull { super.get(it).contains(partial) }
|
||||
?.let { super.get(it) }
|
||||
?: ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.util.Calendar
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
@ -19,6 +18,7 @@ import okhttp3.Response
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.util.Calendar
|
||||
|
||||
@Nsfw
|
||||
class Eggporncomics : ParsedHttpSource() {
|
||||
|
@ -129,21 +129,25 @@ class Eggporncomics : ParsedHttpSource() {
|
|||
override fun mangaDetailsParse(document: Document): SManga {
|
||||
return SManga.create().apply {
|
||||
thumbnail_url = document.select(pageListSelector).first().toFullSizeImage()
|
||||
description = document.select("div.links ul").joinToString("\n") { element -> element.select("a")
|
||||
.joinToString(prefix = element.select("span").text().replace(descriptionPrefixRegex, ": ")) { it.text() } }
|
||||
description = document.select("div.links ul").joinToString("\n") { element ->
|
||||
element.select("a")
|
||||
.joinToString(prefix = element.select("span").text().replace(descriptionPrefixRegex, ": ")) { it.text() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Chapters
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return listOf(SChapter.create().apply {
|
||||
setUrlWithoutDomain(response.request().url().toString())
|
||||
name = "Chapter"
|
||||
date_upload = response.asJsoup().select("div.info > div.meta li:contains(days ago)").firstOrNull()
|
||||
?.let { Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, -(it.text().substringBefore(" ").toIntOrNull() ?: 0)) }.timeInMillis }
|
||||
?: 0
|
||||
})
|
||||
return listOf(
|
||||
SChapter.create().apply {
|
||||
setUrlWithoutDomain(response.request().url().toString())
|
||||
name = "Chapter"
|
||||
date_upload = response.asJsoup().select("div.info > div.meta li:contains(days ago)").firstOrNull()
|
||||
?.let { Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, -(it.text().substringBefore(" ").toIntOrNull() ?: 0)) }.timeInMillis }
|
||||
?: 0
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun chapterListSelector() = throw UnsupportedOperationException("Not used")
|
||||
|
|
|
@ -8,14 +8,14 @@ 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 java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class Explosm : HttpSource() {
|
||||
|
||||
|
@ -92,7 +92,7 @@ class Explosm : HttpSource() {
|
|||
element.select("div#comic-author").text().let { cName ->
|
||||
name = cName
|
||||
date_upload = SimpleDateFormat("yyyy.MM.dd", Locale.getDefault())
|
||||
.parse(cName.substringBefore(" ")).time
|
||||
.parse(cName.substringBefore(" "))?.time ?: 0L
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@ class GunnerkriggCourt : ParsedHttpSource() {
|
|||
return Observable.just(manga)
|
||||
}
|
||||
|
||||
override fun chapterListSelector() = """div.chapters option[value~=\d*]"""
|
||||
override fun chapterListSelector() =
|
||||
"""div.chapters option[value~=\d*]"""
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return super.chapterListParse(response).reversed()
|
||||
|
|
|
@ -15,9 +15,6 @@ 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 java.io.IOException
|
||||
import java.util.HashMap
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.Call
|
||||
import okhttp3.Callback
|
||||
import okhttp3.Headers
|
||||
|
@ -29,6 +26,9 @@ import org.json.JSONObject
|
|||
import rx.Observable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.IOException
|
||||
import java.util.HashMap
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
open class Guya : ConfigurableSource, HttpSource() {
|
||||
|
||||
|
@ -40,10 +40,13 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||
private val scanlatorCacheUrl = "$baseUrl/api/get_all_groups"
|
||||
|
||||
override fun headersBuilder() = Headers.Builder().apply {
|
||||
add("User-Agent", "(Android ${Build.VERSION.RELEASE}; " +
|
||||
"${Build.MANUFACTURER} ${Build.MODEL}) " +
|
||||
"Tachiyomi/${BuildConfig.VERSION_NAME} " +
|
||||
Build.ID)
|
||||
add(
|
||||
"User-Agent",
|
||||
"(Android ${Build.VERSION.RELEASE}; " +
|
||||
"${Build.MANUFACTURER} ${Build.MODEL}) " +
|
||||
"Tachiyomi/${BuildConfig.VERSION_NAME} " +
|
||||
Build.ID
|
||||
)
|
||||
}
|
||||
|
||||
private val scanlators: ScanlatorStore = ScanlatorStore()
|
||||
|
@ -131,9 +134,12 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||
metadata.put("chapter", chapterNum)
|
||||
metadata.put("scanlator", scanlators.getKeyFromValue(chapter.scanlator.toString()))
|
||||
metadata.put("slug", json.getString("slug"))
|
||||
metadata.put("folder", json.getJSONObject("chapters")
|
||||
.getJSONObject(chapterNum)
|
||||
.getString("folder"))
|
||||
metadata.put(
|
||||
"folder",
|
||||
json.getJSONObject("chapters")
|
||||
.getJSONObject(chapterNum)
|
||||
.getString("folder")
|
||||
)
|
||||
|
||||
return parsePageFromJson(pages, metadata)
|
||||
}
|
||||
|
@ -320,10 +326,16 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||
val pageArray = ArrayList<Page>()
|
||||
|
||||
for (i in 0 until pages.length()) {
|
||||
val page = Page(i + 1, "", pageBuilder(metadata.getString("slug"),
|
||||
metadata.getString("folder"),
|
||||
pages[i].toString(),
|
||||
metadata.getString("scanlator")))
|
||||
val page = Page(
|
||||
i + 1,
|
||||
"",
|
||||
pageBuilder(
|
||||
metadata.getString("slug"),
|
||||
metadata.getString("folder"),
|
||||
pages[i].toString(),
|
||||
metadata.getString("scanlator")
|
||||
)
|
||||
)
|
||||
pageArray.add(page)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,13 +9,13 @@ 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.ParsedHttpSource
|
||||
import java.io.IOException
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.io.IOException
|
||||
|
||||
@Nsfw
|
||||
class HBrowse : ParsedHttpSource() {
|
||||
|
@ -185,7 +185,7 @@ class HBrowse : ParsedHttpSource() {
|
|||
override fun getFilterList(): FilterList {
|
||||
return FilterList(
|
||||
listOf(Filter.Header("Can't combine with text search!"), Filter.Separator()) +
|
||||
advFilterMap.map { AdvancedFilter(getAdvTriStateList(it.key, it.value.split(", "))) }
|
||||
advFilterMap.map { AdvancedFilter(getAdvTriStateList(it.key, it.value.split(", "))) }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.lang.UnsupportedOperationException
|
||||
import java.util.Calendar
|
||||
import java.util.regex.Pattern
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
@ -22,6 +19,9 @@ import okhttp3.Response
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.lang.UnsupportedOperationException
|
||||
import java.util.Calendar
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@Nsfw
|
||||
class Hentai2Read : ParsedHttpSource() {
|
||||
|
@ -182,7 +182,7 @@ class Hentai2Read : ParsedHttpSource() {
|
|||
chapter.date_upload = element.select("div > small").text()?.let {
|
||||
val matcher = chapterDatePattern.matcher(it)
|
||||
if (matcher.find()) {
|
||||
parseChapterDate(matcher.group(1))
|
||||
parseChapterDate(matcher.group(1)!!)
|
||||
} else {
|
||||
0L
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ class Hentai2Read : ParsedHttpSource() {
|
|||
val m = pagesUrlPattern.matcher(response.body()!!.string())
|
||||
var i = 0
|
||||
while (m.find()) {
|
||||
m.group(1).split(",").forEach {
|
||||
m.group(1)?.split(",")?.forEach {
|
||||
pages.add(Page(i++, "", imageBaseUrl + it.trim('"').replace("""\/""", "/")))
|
||||
}
|
||||
}
|
||||
|
@ -245,27 +245,27 @@ class Hentai2Read : ParsedHttpSource() {
|
|||
}
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
SortOrder(getSortOrder()),
|
||||
MangaNameSelect(),
|
||||
Filter.Separator(),
|
||||
ArtistName(),
|
||||
ArtistNameSelect(),
|
||||
Filter.Separator(),
|
||||
CharacterName(),
|
||||
CharacterNameSelect(),
|
||||
Filter.Separator(),
|
||||
ReleaseYear(),
|
||||
ReleaseYearSelect(),
|
||||
Filter.Separator(),
|
||||
Status(),
|
||||
Filter.Separator(),
|
||||
TagSearchMode(),
|
||||
Filter.Separator(),
|
||||
TagList("Categories", getCategoryList()),
|
||||
Filter.Separator(),
|
||||
TagList("Tags", getTagList()),
|
||||
Filter.Separator(),
|
||||
TagList("Doujins", getDoujinList())
|
||||
SortOrder(getSortOrder()),
|
||||
MangaNameSelect(),
|
||||
Filter.Separator(),
|
||||
ArtistName(),
|
||||
ArtistNameSelect(),
|
||||
Filter.Separator(),
|
||||
CharacterName(),
|
||||
CharacterNameSelect(),
|
||||
Filter.Separator(),
|
||||
ReleaseYear(),
|
||||
ReleaseYearSelect(),
|
||||
Filter.Separator(),
|
||||
Status(),
|
||||
Filter.Separator(),
|
||||
TagSearchMode(),
|
||||
Filter.Separator(),
|
||||
TagList("Categories", getCategoryList()),
|
||||
Filter.Separator(),
|
||||
TagList("Tags", getTagList()),
|
||||
Filter.Separator(),
|
||||
TagList("Doujins", getDoujinList())
|
||||
)
|
||||
|
||||
private fun getSortOrder() = arrayOf(
|
||||
|
|
|
@ -109,13 +109,15 @@ class HentaiFox : ParsedHttpSource() {
|
|||
// Chapters
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return listOf(SChapter.create().apply {
|
||||
name = "Chapter"
|
||||
// page path with a marker at the end
|
||||
url = "${response.request().url().toString().replace("/gallery/", "/g/")}#"
|
||||
// number of pages
|
||||
url += response.asJsoup().select("[id=load_pages]").attr("value")
|
||||
})
|
||||
return listOf(
|
||||
SChapter.create().apply {
|
||||
name = "Chapter"
|
||||
// page path with a marker at the end
|
||||
url = "${response.request().url().toString().replace("/gallery/", "/g/")}#"
|
||||
// number of pages
|
||||
url += response.asJsoup().select("[id=load_pages]").attr("value")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun chapterListSelector() = throw UnsupportedOperationException("Not used")
|
||||
|
@ -146,59 +148,62 @@ class HentaiFox : ParsedHttpSource() {
|
|||
)
|
||||
|
||||
// Top 50 tags
|
||||
private class GenreFilter : UriPartFilter("Category", arrayOf(
|
||||
Pair("<select>", "---"),
|
||||
Pair("Big breasts", "big-breasts"),
|
||||
Pair("Sole female", "sole-female"),
|
||||
Pair("Sole male", "sole-male"),
|
||||
Pair("Anal", "anal"),
|
||||
Pair("Nakadashi", "nakadashi"),
|
||||
Pair("Group", "group"),
|
||||
Pair("Stockings", "stockings"),
|
||||
Pair("Blowjob", "blowjob"),
|
||||
Pair("Schoolgirl uniform", "schoolgirl-uniform"),
|
||||
Pair("Rape", "rape"),
|
||||
Pair("Lolicon", "lolicon"),
|
||||
Pair("Glasses", "glasses"),
|
||||
Pair("Defloration", "defloration"),
|
||||
Pair("Ahegao", "ahegao"),
|
||||
Pair("Incest", "incest"),
|
||||
Pair("Shotacon", "shotacon"),
|
||||
Pair("X-ray", "x-ray"),
|
||||
Pair("Bondage", "bondage"),
|
||||
Pair("Full color", "full-color"),
|
||||
Pair("Double penetration", "double-penetration"),
|
||||
Pair("Femdom", "femdom"),
|
||||
Pair("Milf", "milf"),
|
||||
Pair("Yaoi", "yaoi"),
|
||||
Pair("Multi-work series", "multi-work-series"),
|
||||
Pair("Schoolgirl", "schoolgirl"),
|
||||
Pair("Mind break", "mind-break"),
|
||||
Pair("Paizuri", "paizuri"),
|
||||
Pair("Mosaic censorship", "mosaic-censorship"),
|
||||
Pair("Impregnation", "impregnation"),
|
||||
Pair("Males only", "males-only"),
|
||||
Pair("Sex toys", "sex-toys"),
|
||||
Pair("Sister", "sister"),
|
||||
Pair("Dark skin", "dark-skin"),
|
||||
Pair("Ffm threesome", "ffm-threesome"),
|
||||
Pair("Hairy", "hairy"),
|
||||
Pair("Cheating", "cheating"),
|
||||
Pair("Sweating", "sweating"),
|
||||
Pair("Yuri", "yuri"),
|
||||
Pair("Netorare", "netorare"),
|
||||
Pair("Full censorship", "full-censorship"),
|
||||
Pair("Schoolboy uniform", "schoolboy-uniform"),
|
||||
Pair("Dilf", "dilf"),
|
||||
Pair("Big penis", "big-penis"),
|
||||
Pair("Futanari", "futanari"),
|
||||
Pair("Swimsuit", "swimsuit"),
|
||||
Pair("Collar", "collar"),
|
||||
Pair("Uncensored", "uncensored"),
|
||||
Pair("Big ass", "big-ass"),
|
||||
Pair("Story arc", "story-arc"),
|
||||
Pair("Teacher", "teacher")
|
||||
))
|
||||
private class GenreFilter : UriPartFilter(
|
||||
"Category",
|
||||
arrayOf(
|
||||
Pair("<select>", "---"),
|
||||
Pair("Big breasts", "big-breasts"),
|
||||
Pair("Sole female", "sole-female"),
|
||||
Pair("Sole male", "sole-male"),
|
||||
Pair("Anal", "anal"),
|
||||
Pair("Nakadashi", "nakadashi"),
|
||||
Pair("Group", "group"),
|
||||
Pair("Stockings", "stockings"),
|
||||
Pair("Blowjob", "blowjob"),
|
||||
Pair("Schoolgirl uniform", "schoolgirl-uniform"),
|
||||
Pair("Rape", "rape"),
|
||||
Pair("Lolicon", "lolicon"),
|
||||
Pair("Glasses", "glasses"),
|
||||
Pair("Defloration", "defloration"),
|
||||
Pair("Ahegao", "ahegao"),
|
||||
Pair("Incest", "incest"),
|
||||
Pair("Shotacon", "shotacon"),
|
||||
Pair("X-ray", "x-ray"),
|
||||
Pair("Bondage", "bondage"),
|
||||
Pair("Full color", "full-color"),
|
||||
Pair("Double penetration", "double-penetration"),
|
||||
Pair("Femdom", "femdom"),
|
||||
Pair("Milf", "milf"),
|
||||
Pair("Yaoi", "yaoi"),
|
||||
Pair("Multi-work series", "multi-work-series"),
|
||||
Pair("Schoolgirl", "schoolgirl"),
|
||||
Pair("Mind break", "mind-break"),
|
||||
Pair("Paizuri", "paizuri"),
|
||||
Pair("Mosaic censorship", "mosaic-censorship"),
|
||||
Pair("Impregnation", "impregnation"),
|
||||
Pair("Males only", "males-only"),
|
||||
Pair("Sex toys", "sex-toys"),
|
||||
Pair("Sister", "sister"),
|
||||
Pair("Dark skin", "dark-skin"),
|
||||
Pair("Ffm threesome", "ffm-threesome"),
|
||||
Pair("Hairy", "hairy"),
|
||||
Pair("Cheating", "cheating"),
|
||||
Pair("Sweating", "sweating"),
|
||||
Pair("Yuri", "yuri"),
|
||||
Pair("Netorare", "netorare"),
|
||||
Pair("Full censorship", "full-censorship"),
|
||||
Pair("Schoolboy uniform", "schoolboy-uniform"),
|
||||
Pair("Dilf", "dilf"),
|
||||
Pair("Big penis", "big-penis"),
|
||||
Pair("Futanari", "futanari"),
|
||||
Pair("Swimsuit", "swimsuit"),
|
||||
Pair("Collar", "collar"),
|
||||
Pair("Uncensored", "uncensored"),
|
||||
Pair("Big ass", "big-ass"),
|
||||
Pair("Story arc", "story-arc"),
|
||||
Pair("Teacher", "teacher")
|
||||
)
|
||||
)
|
||||
|
||||
private open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) :
|
||||
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||
|
|
|
@ -8,11 +8,11 @@ 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.ParsedHttpSource
|
||||
import java.net.URLEncoder
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.net.URLEncoder
|
||||
|
||||
@Nsfw
|
||||
class HentaiNexus : ParsedHttpSource() {
|
||||
|
|
|
@ -11,10 +11,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.Call
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
@ -22,6 +18,10 @@ import okhttp3.Response
|
|||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class Hiveworks : ParsedHttpSource() {
|
||||
|
||||
|
@ -290,84 +290,104 @@ class Hiveworks : ParsedHttpSource() {
|
|||
fun addToUri(uri: Uri.Builder)
|
||||
}
|
||||
|
||||
private class UpdateDay : UriSelectFilter("Update Day", "update-day", arrayOf(
|
||||
Pair("all", "All"),
|
||||
Pair("monday", "Monday"),
|
||||
Pair("tuesday", "Tuesday"),
|
||||
Pair("wednesday", "Wednesday"),
|
||||
Pair("thursday", "Thursday"),
|
||||
Pair("friday", "Friday"),
|
||||
Pair("saturday", "Saturday"),
|
||||
Pair("sunday", "Sunday")
|
||||
))
|
||||
private class UpdateDay : UriSelectFilter(
|
||||
"Update Day",
|
||||
"update-day",
|
||||
arrayOf(
|
||||
Pair("all", "All"),
|
||||
Pair("monday", "Monday"),
|
||||
Pair("tuesday", "Tuesday"),
|
||||
Pair("wednesday", "Wednesday"),
|
||||
Pair("thursday", "Thursday"),
|
||||
Pair("friday", "Friday"),
|
||||
Pair("saturday", "Saturday"),
|
||||
Pair("sunday", "Sunday")
|
||||
)
|
||||
)
|
||||
|
||||
private class RatingFilter : UriSelectFilter("Rating", "age", arrayOf(
|
||||
Pair("all", "All"),
|
||||
Pair("everyone", "Everyone"),
|
||||
Pair("teen", "Teen"),
|
||||
Pair("young-adult", "Young Adult"),
|
||||
Pair("mature", "Mature")
|
||||
))
|
||||
private class RatingFilter : UriSelectFilter(
|
||||
"Rating",
|
||||
"age",
|
||||
arrayOf(
|
||||
Pair("all", "All"),
|
||||
Pair("everyone", "Everyone"),
|
||||
Pair("teen", "Teen"),
|
||||
Pair("young-adult", "Young Adult"),
|
||||
Pair("mature", "Mature")
|
||||
)
|
||||
)
|
||||
|
||||
private class GenreFilter : UriSelectFilter("Genre", "genre", arrayOf(
|
||||
Pair("all", "All"),
|
||||
Pair("action/adventure", "Action/Adventure"),
|
||||
Pair("animated", "Animated"),
|
||||
Pair("autobio", "Autobio"),
|
||||
Pair("comedy", "Comedy"),
|
||||
Pair("drama", "Drama"),
|
||||
Pair("dystopian", "Dystopian"),
|
||||
Pair("fairytale", "Fairytale"),
|
||||
Pair("fantasy", "Fantasy"),
|
||||
Pair("finished", "Finished"),
|
||||
Pair("historical-fiction", "Historical Fiction"),
|
||||
Pair("horror", "Horror"),
|
||||
Pair("lgbt", "LGBT"),
|
||||
Pair("mystery", "Mystery"),
|
||||
Pair("romance", "Romance"),
|
||||
Pair("sci-fi", "Science Fiction"),
|
||||
Pair("slice-of-life", "Slice of Life"),
|
||||
Pair("steampunk", "Steampunk"),
|
||||
Pair("superhero", "Superhero"),
|
||||
Pair("urban-fantasy", "Urban Fantasy")
|
||||
))
|
||||
private class GenreFilter : UriSelectFilter(
|
||||
"Genre",
|
||||
"genre",
|
||||
arrayOf(
|
||||
Pair("all", "All"),
|
||||
Pair("action/adventure", "Action/Adventure"),
|
||||
Pair("animated", "Animated"),
|
||||
Pair("autobio", "Autobio"),
|
||||
Pair("comedy", "Comedy"),
|
||||
Pair("drama", "Drama"),
|
||||
Pair("dystopian", "Dystopian"),
|
||||
Pair("fairytale", "Fairytale"),
|
||||
Pair("fantasy", "Fantasy"),
|
||||
Pair("finished", "Finished"),
|
||||
Pair("historical-fiction", "Historical Fiction"),
|
||||
Pair("horror", "Horror"),
|
||||
Pair("lgbt", "LGBT"),
|
||||
Pair("mystery", "Mystery"),
|
||||
Pair("romance", "Romance"),
|
||||
Pair("sci-fi", "Science Fiction"),
|
||||
Pair("slice-of-life", "Slice of Life"),
|
||||
Pair("steampunk", "Steampunk"),
|
||||
Pair("superhero", "Superhero"),
|
||||
Pair("urban-fantasy", "Urban Fantasy")
|
||||
)
|
||||
)
|
||||
|
||||
private class TitleFilter : UriSelectFilter("Title", "alpha", arrayOf(
|
||||
Pair("all", "All"),
|
||||
Pair("a", "A"),
|
||||
Pair("b", "B"),
|
||||
Pair("c", "C"),
|
||||
Pair("d", "D"),
|
||||
Pair("e", "E"),
|
||||
Pair("f", "F"),
|
||||
Pair("g", "G"),
|
||||
Pair("h", "H"),
|
||||
Pair("i", "I"),
|
||||
Pair("j", "J"),
|
||||
Pair("k", "K"),
|
||||
Pair("l", "L"),
|
||||
Pair("m", "M"),
|
||||
Pair("n", "N"),
|
||||
Pair("o", "O"),
|
||||
Pair("p", "P"),
|
||||
Pair("q", "Q"),
|
||||
Pair("r", "R"),
|
||||
Pair("s", "S"),
|
||||
Pair("t", "T"),
|
||||
Pair("u", "U"),
|
||||
Pair("v", "V"),
|
||||
Pair("w", "W"),
|
||||
Pair("x", "X"),
|
||||
Pair("y", "Y"),
|
||||
Pair("z", "Z"),
|
||||
Pair("numbers-symbols", "Numbers / Symbols")
|
||||
))
|
||||
private class TitleFilter : UriSelectFilter(
|
||||
"Title",
|
||||
"alpha",
|
||||
arrayOf(
|
||||
Pair("all", "All"),
|
||||
Pair("a", "A"),
|
||||
Pair("b", "B"),
|
||||
Pair("c", "C"),
|
||||
Pair("d", "D"),
|
||||
Pair("e", "E"),
|
||||
Pair("f", "F"),
|
||||
Pair("g", "G"),
|
||||
Pair("h", "H"),
|
||||
Pair("i", "I"),
|
||||
Pair("j", "J"),
|
||||
Pair("k", "K"),
|
||||
Pair("l", "L"),
|
||||
Pair("m", "M"),
|
||||
Pair("n", "N"),
|
||||
Pair("o", "O"),
|
||||
Pair("p", "P"),
|
||||
Pair("q", "Q"),
|
||||
Pair("r", "R"),
|
||||
Pair("s", "S"),
|
||||
Pair("t", "T"),
|
||||
Pair("u", "U"),
|
||||
Pair("v", "V"),
|
||||
Pair("w", "W"),
|
||||
Pair("x", "X"),
|
||||
Pair("y", "Y"),
|
||||
Pair("z", "Z"),
|
||||
Pair("numbers-symbols", "Numbers / Symbols")
|
||||
)
|
||||
)
|
||||
|
||||
private class SortFilter : UriSelectFilter("Sort By", "sortby", arrayOf(
|
||||
Pair("none", "None"),
|
||||
Pair("a-z", "A-Z"),
|
||||
Pair("z-a", "Z-A")
|
||||
))
|
||||
private class SortFilter : UriSelectFilter(
|
||||
"Sort By",
|
||||
"sortby",
|
||||
arrayOf(
|
||||
Pair("none", "None"),
|
||||
Pair("a-z", "A-Z"),
|
||||
Pair("z-a", "Z-A")
|
||||
)
|
||||
)
|
||||
|
||||
// Other Code
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class Honkaiimpact : ParsedHttpSource() {
|
||||
|
||||
|
|
|
@ -15,12 +15,6 @@ 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.ParsedHttpSource
|
||||
import java.io.IOException
|
||||
import java.net.URLDecoder
|
||||
import java.net.URLEncoder
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.Credentials
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -30,6 +24,12 @@ import org.jsoup.nodes.Document
|
|||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.IOException
|
||||
import java.net.URLDecoder
|
||||
import java.net.URLEncoder
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class Madokami : ConfigurableSource, ParsedHttpSource() {
|
||||
override val name = "Madokami"
|
||||
|
@ -145,7 +145,7 @@ class Madokami : ConfigurableSource, ParsedHttpSource() {
|
|||
}
|
||||
chapter.date_upload = newDate.time.time
|
||||
} else {
|
||||
chapter.date_upload = dateFormat.parse(date).time
|
||||
chapter.date_upload = dateFormat.parse(date)?.time ?: 0L
|
||||
}
|
||||
return chapter
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class mangacruzers : ParsedHttpSource() {
|
||||
|
||||
|
@ -70,16 +70,16 @@ class mangacruzers : ParsedHttpSource() {
|
|||
override fun latestUpdatesFromElement(element: Element) = mangaFromElement(element)
|
||||
override fun searchMangaFromElement(element: Element) = mangaFromElement(element)
|
||||
|
||||
private fun mangaFromElement(element: Element): SManga {
|
||||
val manga = SManga.create()
|
||||
manga.url = element.select("a").attr("abs:href")
|
||||
manga.title = element.select("td").first().text().trim()
|
||||
private fun mangaFromElement(element: Element): SManga {
|
||||
val manga = SManga.create()
|
||||
manga.url = element.select("a").attr("abs:href")
|
||||
manga.title = element.select("td").first().text().trim()
|
||||
|
||||
return manga
|
||||
}
|
||||
|
||||
private fun parseDate(date: String): Long {
|
||||
return SimpleDateFormat("MMM dd, yyyy", Locale.US).parse(date).time
|
||||
return SimpleDateFormat("MMM dd, yyyy", Locale.US).parse(date)?.time ?: 0L
|
||||
}
|
||||
|
||||
override fun chapterFromElement(element: Element) = SChapter.create().apply {
|
||||
|
|
|
@ -13,11 +13,11 @@ 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 java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class Mangadog : HttpSource() {
|
||||
|
||||
|
@ -32,7 +32,7 @@ class Mangadog : HttpSource() {
|
|||
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/index/latestupdate/getUpdateResult?page=$page", headers)
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val uri = Uri.parse("$baseUrl/index/keywordsearch/index").buildUpon()
|
||||
.appendQueryParameter("query", query)
|
||||
.appendQueryParameter("query", query)
|
||||
return GET(uri.toString(), headers)
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ class Mangadog : HttpSource() {
|
|||
}
|
||||
|
||||
private fun parseDate(date: String): Long {
|
||||
return SimpleDateFormat("yyyy-MM-dd", Locale.US).parse(date).time
|
||||
return SimpleDateFormat("yyyy-MM-dd", Locale.US).parse(date)?.time ?: 0L
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
|
|
|
@ -7,15 +7,15 @@ 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.ParsedHttpSource
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class Mangaeden : ParsedHttpSource() {
|
||||
|
||||
|
@ -52,15 +52,18 @@ class Mangaeden : ParsedHttpSource() {
|
|||
val url = HttpUrl.parse("$baseUrl/en/en-directory/")?.newBuilder()!!.addQueryParameter("title", query)
|
||||
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
||||
when (filter) {
|
||||
is StatusList -> filter.state
|
||||
is StatusList ->
|
||||
filter.state
|
||||
.filter { it.state }
|
||||
.map { it.id.toString() }
|
||||
.forEach { url.addQueryParameter("status", it) }
|
||||
is Types -> filter.state
|
||||
is Types ->
|
||||
filter.state
|
||||
.filter { it.state }
|
||||
.map { it.id.toString() }
|
||||
.forEach { url.addQueryParameter("type", it) }
|
||||
is GenreList -> filter.state
|
||||
is GenreList ->
|
||||
filter.state
|
||||
.filter { !it.isIgnored() }
|
||||
.forEach { genre -> url.addQueryParameter(if (genre.isIncluded()) "categoriesInc" else "categoriesExcl", genre.id) }
|
||||
is TextField -> url.addQueryParameter(filter.key, filter.state)
|
||||
|
@ -129,11 +132,12 @@ class Mangaeden : ParsedHttpSource() {
|
|||
set(Calendar.MILLISECOND, 0)
|
||||
}.timeInMillis
|
||||
}
|
||||
else -> try {
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time
|
||||
} catch (e: ParseException) {
|
||||
0L
|
||||
}
|
||||
else ->
|
||||
try {
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
|
||||
} catch (e: ParseException) {
|
||||
0L
|
||||
}
|
||||
}
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
|
@ -147,69 +151,72 @@ class Mangaeden : ParsedHttpSource() {
|
|||
private class NamedId(name: String, val id: Int) : Filter.CheckBox(name)
|
||||
private class Genre(name: String, val id: String) : Filter.TriState(name)
|
||||
private class TextField(name: String, val key: String) : Filter.Text(name)
|
||||
private class OrderBy : Filter.Sort("Order by", arrayOf("Manga title", "Views", "Chapters", "Latest chapter"),
|
||||
Selection(1, false))
|
||||
private class OrderBy : Filter.Sort(
|
||||
"Order by",
|
||||
arrayOf("Manga title", "Views", "Chapters", "Latest chapter"),
|
||||
Selection(1, false)
|
||||
)
|
||||
|
||||
private class StatusList(statuses: List<NamedId>) : Filter.Group<NamedId>("Stato", statuses)
|
||||
private class Types(types: List<NamedId>) : Filter.Group<NamedId>("Tipo", types)
|
||||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
TextField("Author", "author"),
|
||||
TextField("Artist", "artist"),
|
||||
OrderBy(),
|
||||
Types(types()),
|
||||
StatusList(statuses()),
|
||||
GenreList(genres())
|
||||
TextField("Author", "author"),
|
||||
TextField("Artist", "artist"),
|
||||
OrderBy(),
|
||||
Types(types()),
|
||||
StatusList(statuses()),
|
||||
GenreList(genres())
|
||||
)
|
||||
|
||||
private fun types() = listOf(
|
||||
NamedId("Japanese Manga", 0),
|
||||
NamedId("Korean Manhwa", 1),
|
||||
NamedId("Chinese Manhua", 2),
|
||||
NamedId("Comic", 3),
|
||||
NamedId("Doujinshi", 4)
|
||||
NamedId("Japanese Manga", 0),
|
||||
NamedId("Korean Manhwa", 1),
|
||||
NamedId("Chinese Manhua", 2),
|
||||
NamedId("Comic", 3),
|
||||
NamedId("Doujinshi", 4)
|
||||
)
|
||||
|
||||
private fun statuses() = listOf(
|
||||
NamedId("Ongoing", 1),
|
||||
NamedId("Completed", 2),
|
||||
NamedId("Suspended", 0)
|
||||
NamedId("Ongoing", 1),
|
||||
NamedId("Completed", 2),
|
||||
NamedId("Suspended", 0)
|
||||
)
|
||||
|
||||
private fun genres() = listOf(
|
||||
Genre("Action", "4e70e91bc092255ef70016f8"),
|
||||
Genre("Adult", "4e70e92fc092255ef7001b94"),
|
||||
Genre("Adventure", "4e70e918c092255ef700168e"),
|
||||
Genre("Comedy", "4e70e918c092255ef7001675"),
|
||||
Genre("Doujinshi", "4e70e928c092255ef7001a0a"),
|
||||
Genre("Drama", "4e70e918c092255ef7001693"),
|
||||
Genre("Ecchi", "4e70e91ec092255ef700175e"),
|
||||
Genre("Fantasy", "4e70e918c092255ef7001676"),
|
||||
Genre("Gender Bender", "4e70e921c092255ef700184b"),
|
||||
Genre("Harem", "4e70e91fc092255ef7001783"),
|
||||
Genre("Historical", "4e70e91ac092255ef70016d8"),
|
||||
Genre("Horror", "4e70e919c092255ef70016a8"),
|
||||
Genre("Josei", "4e70e920c092255ef70017de"),
|
||||
Genre("Martial Arts", "4e70e923c092255ef70018d0"),
|
||||
Genre("Mature", "4e70e91bc092255ef7001705"),
|
||||
Genre("Mecha", "4e70e922c092255ef7001877"),
|
||||
Genre("Mystery", "4e70e918c092255ef7001681"),
|
||||
Genre("One Shot", "4e70e91dc092255ef7001747"),
|
||||
Genre("Psychological", "4e70e919c092255ef70016a9"),
|
||||
Genre("Romance", "4e70e918c092255ef7001677"),
|
||||
Genre("School Life", "4e70e918c092255ef7001688"),
|
||||
Genre("Sci-fi", "4e70e91bc092255ef7001706"),
|
||||
Genre("Seinen", "4e70e918c092255ef700168b"),
|
||||
Genre("Shoujo", "4e70e918c092255ef7001667"),
|
||||
Genre("Shounen", "4e70e918c092255ef700166f"),
|
||||
Genre("Slice of Life", "4e70e918c092255ef700167e"),
|
||||
Genre("Smut", "4e70e922c092255ef700185a"),
|
||||
Genre("Sports", "4e70e91dc092255ef700172e"),
|
||||
Genre("Supernatural", "4e70e918c092255ef700166a"),
|
||||
Genre("Tragedy", "4e70e918c092255ef7001672"),
|
||||
Genre("Webtoons", "4e70ea70c092255ef7006d9c"),
|
||||
Genre("Yaoi", "4e70e91ac092255ef70016e5"),
|
||||
Genre("Yuri", "4e70e92ac092255ef7001a57")
|
||||
Genre("Action", "4e70e91bc092255ef70016f8"),
|
||||
Genre("Adult", "4e70e92fc092255ef7001b94"),
|
||||
Genre("Adventure", "4e70e918c092255ef700168e"),
|
||||
Genre("Comedy", "4e70e918c092255ef7001675"),
|
||||
Genre("Doujinshi", "4e70e928c092255ef7001a0a"),
|
||||
Genre("Drama", "4e70e918c092255ef7001693"),
|
||||
Genre("Ecchi", "4e70e91ec092255ef700175e"),
|
||||
Genre("Fantasy", "4e70e918c092255ef7001676"),
|
||||
Genre("Gender Bender", "4e70e921c092255ef700184b"),
|
||||
Genre("Harem", "4e70e91fc092255ef7001783"),
|
||||
Genre("Historical", "4e70e91ac092255ef70016d8"),
|
||||
Genre("Horror", "4e70e919c092255ef70016a8"),
|
||||
Genre("Josei", "4e70e920c092255ef70017de"),
|
||||
Genre("Martial Arts", "4e70e923c092255ef70018d0"),
|
||||
Genre("Mature", "4e70e91bc092255ef7001705"),
|
||||
Genre("Mecha", "4e70e922c092255ef7001877"),
|
||||
Genre("Mystery", "4e70e918c092255ef7001681"),
|
||||
Genre("One Shot", "4e70e91dc092255ef7001747"),
|
||||
Genre("Psychological", "4e70e919c092255ef70016a9"),
|
||||
Genre("Romance", "4e70e918c092255ef7001677"),
|
||||
Genre("School Life", "4e70e918c092255ef7001688"),
|
||||
Genre("Sci-fi", "4e70e91bc092255ef7001706"),
|
||||
Genre("Seinen", "4e70e918c092255ef700168b"),
|
||||
Genre("Shoujo", "4e70e918c092255ef7001667"),
|
||||
Genre("Shounen", "4e70e918c092255ef700166f"),
|
||||
Genre("Slice of Life", "4e70e918c092255ef700167e"),
|
||||
Genre("Smut", "4e70e922c092255ef700185a"),
|
||||
Genre("Sports", "4e70e91dc092255ef700172e"),
|
||||
Genre("Supernatural", "4e70e918c092255ef700166a"),
|
||||
Genre("Tragedy", "4e70e918c092255ef7001672"),
|
||||
Genre("Webtoons", "4e70ea70c092255ef7006d9c"),
|
||||
Genre("Yaoi", "4e70e91ac092255ef70016e5"),
|
||||
Genre("Yuri", "4e70e92ac092255ef7001a57")
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class MangaFast : ParsedHttpSource() {
|
||||
override val name = "MangaFast"
|
||||
|
|
|
@ -8,14 +8,14 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class Mangafreak : ParsedHttpSource() {
|
||||
override val name: String = "Mangafreak"
|
||||
|
@ -76,14 +76,16 @@ class Mangafreak : ParsedHttpSource() {
|
|||
uri.appendPath("Genre")
|
||||
when (filter) {
|
||||
is GenreList -> {
|
||||
uri.appendPath(filter.state.joinToString("") {
|
||||
when (it.state) {
|
||||
Filter.TriState.STATE_IGNORE -> "0"
|
||||
Filter.TriState.STATE_INCLUDE -> "1"
|
||||
Filter.TriState.STATE_EXCLUDE -> "2"
|
||||
else -> "0"
|
||||
uri.appendPath(
|
||||
filter.state.joinToString("") {
|
||||
when (it.state) {
|
||||
Filter.TriState.STATE_IGNORE -> "0"
|
||||
Filter.TriState.STATE_INCLUDE -> "1"
|
||||
Filter.TriState.STATE_EXCLUDE -> "2"
|
||||
else -> "0"
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
uri.appendEncodedPath("Status/0/Type/0")
|
||||
|
@ -120,7 +122,7 @@ class Mangafreak : ParsedHttpSource() {
|
|||
date_upload = parseDate(element.select(" td:eq(1)").text())
|
||||
}
|
||||
private fun parseDate(date: String): Long {
|
||||
return SimpleDateFormat("yyyy/MM/dd", Locale.US).parse(date).time
|
||||
return SimpleDateFormat("yyyy/MM/dd", Locale.US).parse(date)?.time ?: 0L
|
||||
}
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return super.chapterListParse(response).reversed()
|
||||
|
@ -144,7 +146,8 @@ class Mangafreak : ParsedHttpSource() {
|
|||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
GenreList(getGenreList()))
|
||||
GenreList(getGenreList())
|
||||
)
|
||||
private fun getGenreList() = listOf(
|
||||
Genre("Act"),
|
||||
Genre("Adult"),
|
||||
|
@ -185,5 +188,5 @@ class Mangafreak : ParsedHttpSource() {
|
|||
Genre("Vampire"),
|
||||
Genre("Yaoi"),
|
||||
Genre("Yuri")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -13,14 +13,14 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class Mangahasu : ParsedHttpSource() {
|
||||
|
||||
|
@ -195,18 +195,24 @@ class Mangahasu : ParsedHttpSource() {
|
|||
fun toUriPart() = vals[state].second
|
||||
}
|
||||
|
||||
private class TypeFilter : UriPartFilter("Type", arrayOf(
|
||||
Pair("Any", ""),
|
||||
Pair("Manga", "10"),
|
||||
Pair("Manhwa", "12"),
|
||||
Pair("Manhua", "19")
|
||||
))
|
||||
private class TypeFilter : UriPartFilter(
|
||||
"Type",
|
||||
arrayOf(
|
||||
Pair("Any", ""),
|
||||
Pair("Manga", "10"),
|
||||
Pair("Manhwa", "12"),
|
||||
Pair("Manhua", "19")
|
||||
)
|
||||
)
|
||||
|
||||
private class StatusFilter : UriPartFilter("Status", arrayOf(
|
||||
Pair("Any", ""),
|
||||
Pair("Completed", "1"),
|
||||
Pair("Ongoing", "2")
|
||||
))
|
||||
private class StatusFilter : UriPartFilter(
|
||||
"Status",
|
||||
arrayOf(
|
||||
Pair("Any", ""),
|
||||
Pair("Completed", "1"),
|
||||
Pair("Ongoing", "2")
|
||||
)
|
||||
)
|
||||
|
||||
private class Genre(name: String, val id: String) : Filter.TriState(name)
|
||||
private class GenreFilter(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
|
||||
|
|
|
@ -9,10 +9,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.HttpUrl
|
||||
|
@ -20,6 +16,10 @@ import okhttp3.OkHttpClient
|
|||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class Mangahere : ParsedHttpSource() {
|
||||
|
||||
|
@ -34,19 +34,24 @@ class Mangahere : ParsedHttpSource() {
|
|||
override val supportsLatest = true
|
||||
|
||||
override val client: OkHttpClient = super.client.newBuilder()
|
||||
.cookieJar(object : CookieJar {
|
||||
.cookieJar(
|
||||
object : CookieJar {
|
||||
override fun saveFromResponse(url: HttpUrl, cookies: MutableList<Cookie>) {}
|
||||
override fun loadForRequest(url: HttpUrl): MutableList<Cookie> {
|
||||
return ArrayList<Cookie>().apply {
|
||||
add(Cookie.Builder()
|
||||
add(
|
||||
Cookie.Builder()
|
||||
.domain("www.mangahere.cc")
|
||||
.path("/")
|
||||
.name("isAdult")
|
||||
.value("1")
|
||||
.build()) }
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
.build()
|
||||
}
|
||||
)
|
||||
.build()
|
||||
|
||||
override fun popularMangaSelector() = ".manga-list-1-list li"
|
||||
|
||||
|
@ -67,7 +72,7 @@ class Mangahere : ParsedHttpSource() {
|
|||
manga.title = titleElement.attr("title")
|
||||
manga.setUrlWithoutDomain(titleElement.attr("href"))
|
||||
manga.thumbnail_url = element.select("img.manga-list-1-cover")
|
||||
?.first()?.attr("src")
|
||||
?.first()?.attr("src")
|
||||
|
||||
return manga
|
||||
}
|
||||
|
@ -140,7 +145,7 @@ class Mangahere : ParsedHttpSource() {
|
|||
manga.genre = document.select(".detail-info-right-tag-list > a")?.joinToString { it.text() }
|
||||
manga.description = document.select(".fullcontent")?.first()?.text()
|
||||
manga.thumbnail_url = document.select("img.detail-info-cover-img")?.first()
|
||||
?.attr("src")
|
||||
?.attr("src")
|
||||
|
||||
document.select("span.detail-info-right-title-tip")?.first()?.text()?.also { statusText ->
|
||||
when {
|
||||
|
@ -186,7 +191,7 @@ class Mangahere : ParsedHttpSource() {
|
|||
}.timeInMillis
|
||||
} else {
|
||||
try {
|
||||
SimpleDateFormat("MMM dd,yyyy", Locale.ENGLISH).parse(date).time
|
||||
SimpleDateFormat("MMM dd,yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
|
||||
} catch (e: ParseException) {
|
||||
0L
|
||||
}
|
||||
|
@ -232,8 +237,9 @@ class Mangahere : ParsedHttpSource() {
|
|||
|
||||
val chapterIdStartLoc = html.indexOf("chapterid")
|
||||
val chapterId = html.substring(
|
||||
chapterIdStartLoc + 11,
|
||||
html.indexOf(";", chapterIdStartLoc)).trim()
|
||||
chapterIdStartLoc + 11,
|
||||
html.indexOf(";", chapterIdStartLoc)
|
||||
).trim()
|
||||
|
||||
val chapterPagesElement = document.select(".pager-list-left > span").first()
|
||||
val pagesLinksElements = chapterPagesElement.select("a")
|
||||
|
@ -250,15 +256,15 @@ class Mangahere : ParsedHttpSource() {
|
|||
for (tr in 1..3) {
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(pageLink)
|
||||
.addHeader("Referer", link)
|
||||
.addHeader("Accept", "*/*")
|
||||
.addHeader("Accept-Language", "en-US,en;q=0.9")
|
||||
.addHeader("Connection", "keep-alive")
|
||||
.addHeader("Host", "www.mangahere.cc")
|
||||
.addHeader("User-Agent", System.getProperty("http.agent") ?: "")
|
||||
.addHeader("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
.url(pageLink)
|
||||
.addHeader("Referer", link)
|
||||
.addHeader("Accept", "*/*")
|
||||
.addHeader("Accept-Language", "en-US,en;q=0.9")
|
||||
.addHeader("Connection", "keep-alive")
|
||||
.addHeader("Host", "www.mangahere.cc")
|
||||
.addHeader("User-Agent", System.getProperty("http.agent") ?: "")
|
||||
.addHeader("X-Requested-With", "XMLHttpRequest")
|
||||
.build()
|
||||
|
||||
val response = client.newCall(request).execute()
|
||||
responseText = response.body()!!.string()
|
||||
|
@ -298,7 +304,9 @@ class Mangahere : ParsedHttpSource() {
|
|||
val secretKeyEndLoc = secretKeyDeobfuscatedScript.indexOf(";")
|
||||
|
||||
val secretKeyResultScript = secretKeyDeobfuscatedScript.substring(
|
||||
secretKeyStartLoc, secretKeyEndLoc)
|
||||
secretKeyStartLoc,
|
||||
secretKeyEndLoc
|
||||
)
|
||||
|
||||
return duktape.evaluate(secretKeyResultScript).toString()
|
||||
}
|
||||
|
@ -312,56 +320,56 @@ class Mangahere : ParsedHttpSource() {
|
|||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
TypeList(types.keys.toList().sorted().toTypedArray()),
|
||||
CompletionList(completions),
|
||||
GenreList(genres())
|
||||
TypeList(types.keys.toList().sorted().toTypedArray()),
|
||||
CompletionList(completions),
|
||||
GenreList(genres())
|
||||
)
|
||||
|
||||
private val types = hashMapOf(
|
||||
"Japanese Manga" to 1,
|
||||
"Korean Manhwa" to 2,
|
||||
"Other Manga" to 4,
|
||||
"Any" to 0
|
||||
"Japanese Manga" to 1,
|
||||
"Korean Manhwa" to 2,
|
||||
"Other Manga" to 4,
|
||||
"Any" to 0
|
||||
)
|
||||
|
||||
private val completions = arrayOf("Either", "No", "Yes")
|
||||
|
||||
private fun genres() = arrayListOf(
|
||||
Genre("Action", 1),
|
||||
Genre("Adventure", 2),
|
||||
Genre("Comedy", 3),
|
||||
Genre("Fantasy", 4),
|
||||
Genre("Historical", 5),
|
||||
Genre("Horror", 6),
|
||||
Genre("Martial Arts", 7),
|
||||
Genre("Mystery", 8),
|
||||
Genre("Romance", 9),
|
||||
Genre("Shounen Ai", 10),
|
||||
Genre("Supernatural", 11),
|
||||
Genre("Drama", 12),
|
||||
Genre("Shounen", 13),
|
||||
Genre("School Life", 14),
|
||||
Genre("Shoujo", 15),
|
||||
Genre("Gender Bender", 16),
|
||||
Genre("Josei", 17),
|
||||
Genre("Psychological", 18),
|
||||
Genre("Seinen", 19),
|
||||
Genre("Slice of Life", 20),
|
||||
Genre("Sci-fi", 21),
|
||||
Genre("Ecchi", 22),
|
||||
Genre("Harem", 23),
|
||||
Genre("Shoujo Ai", 24),
|
||||
Genre("Yuri", 25),
|
||||
Genre("Mature", 26),
|
||||
Genre("Tragedy", 27),
|
||||
Genre("Yaoi", 28),
|
||||
Genre("Doujinshi", 29),
|
||||
Genre("Sports", 30),
|
||||
Genre("Adult", 31),
|
||||
Genre("One Shot", 32),
|
||||
Genre("Smut", 33),
|
||||
Genre("Mecha", 34),
|
||||
Genre("Shotacon", 35),
|
||||
Genre("Lolicon", 36)
|
||||
Genre("Action", 1),
|
||||
Genre("Adventure", 2),
|
||||
Genre("Comedy", 3),
|
||||
Genre("Fantasy", 4),
|
||||
Genre("Historical", 5),
|
||||
Genre("Horror", 6),
|
||||
Genre("Martial Arts", 7),
|
||||
Genre("Mystery", 8),
|
||||
Genre("Romance", 9),
|
||||
Genre("Shounen Ai", 10),
|
||||
Genre("Supernatural", 11),
|
||||
Genre("Drama", 12),
|
||||
Genre("Shounen", 13),
|
||||
Genre("School Life", 14),
|
||||
Genre("Shoujo", 15),
|
||||
Genre("Gender Bender", 16),
|
||||
Genre("Josei", 17),
|
||||
Genre("Psychological", 18),
|
||||
Genre("Seinen", 19),
|
||||
Genre("Slice of Life", 20),
|
||||
Genre("Sci-fi", 21),
|
||||
Genre("Ecchi", 22),
|
||||
Genre("Harem", 23),
|
||||
Genre("Shoujo Ai", 24),
|
||||
Genre("Yuri", 25),
|
||||
Genre("Mature", 26),
|
||||
Genre("Tragedy", 27),
|
||||
Genre("Yaoi", 28),
|
||||
Genre("Doujinshi", 29),
|
||||
Genre("Sports", 30),
|
||||
Genre("Adult", 31),
|
||||
Genre("One Shot", 32),
|
||||
Genre("Smut", 33),
|
||||
Genre("Mecha", 34),
|
||||
Genre("Shotacon", 35),
|
||||
Genre("Lolicon", 36)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -14,17 +14,17 @@ 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.ParsedHttpSource
|
||||
import java.net.URL
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.net.URL
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class Mangahub : ParsedHttpSource() {
|
||||
|
||||
|
@ -55,7 +55,7 @@ class Mangahub : ParsedHttpSource() {
|
|||
manga.title = titleElement.text()
|
||||
manga.setUrlWithoutDomain(URL(titleElement.attr("href")).path)
|
||||
manga.thumbnail_url = element.select("img.manga-thumb.list-item-thumb")
|
||||
?.first()?.attr("src")
|
||||
?.first()?.attr("src")
|
||||
|
||||
return manga
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ class Mangahub : ParsedHttpSource() {
|
|||
manga.genre = document.select("._3Czbn a")?.joinToString { it.text() }
|
||||
manga.description = document.select("div#noanim-content-tab-pane-99 p.ZyMp7")?.first()?.text()
|
||||
manga.thumbnail_url = document.select("img.img-responsive")?.first()
|
||||
?.attr("src")
|
||||
?.attr("src")
|
||||
|
||||
document.select("._3QCtP > div:nth-child(2) > div:nth-child(3) > span:nth-child(2)")?.first()?.text()?.also { statusText ->
|
||||
when {
|
||||
|
@ -133,7 +133,7 @@ class Mangahub : ParsedHttpSource() {
|
|||
// parses: "12-20-2019" and defaults everything that wasn't taken into account to 0
|
||||
else -> {
|
||||
try {
|
||||
parsedDate = SimpleDateFormat("MM-dd-yyyy", Locale.US).parse(date).time
|
||||
parsedDate = SimpleDateFormat("MM-dd-yyyy", Locale.US).parse(date)?.time ?: 0L
|
||||
} catch (e: ParseException) { /*nothing to do, parsedDate is initialized with 0L*/ }
|
||||
}
|
||||
}
|
||||
|
@ -208,16 +208,16 @@ class Mangahub : ParsedHttpSource() {
|
|||
private class GenreList(genres: Array<Genre>) : Filter.Select<Genre>("Genres", genres, 0)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
OrderBy(orderBy),
|
||||
GenreList(genres)
|
||||
OrderBy(orderBy),
|
||||
GenreList(genres)
|
||||
)
|
||||
|
||||
private val orderBy = arrayOf(
|
||||
Order("Popular", "POPULAR"),
|
||||
Order("Updates", "LATEST"),
|
||||
Order("A-Z", "ALPHABET"),
|
||||
Order("New", "NEW"),
|
||||
Order("Completed", "COMPLETED")
|
||||
Order("Popular", "POPULAR"),
|
||||
Order("Updates", "LATEST"),
|
||||
Order("A-Z", "ALPHABET"),
|
||||
Order("New", "NEW"),
|
||||
Order("Completed", "COMPLETED")
|
||||
)
|
||||
|
||||
private val genres = arrayOf(
|
||||
|
|
|
@ -7,14 +7,14 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class MangaJar : ParsedHttpSource() {
|
||||
|
||||
|
@ -43,8 +43,10 @@ class MangaJar : ParsedHttpSource() {
|
|||
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
|
||||
setUrlWithoutDomain(element.select("a").attr("href"))
|
||||
title = element.select("img").attr("title")
|
||||
thumbnail_url = element.select("img").let { if (it.hasAttr("data-src"))
|
||||
it.attr("data-src") else it.attr("src") }
|
||||
thumbnail_url = element.select("img").let {
|
||||
if (it.hasAttr("data-src"))
|
||||
it.attr("data-src") else it.attr("src")
|
||||
}
|
||||
}
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
|
||||
|
@ -63,16 +65,18 @@ class MangaJar : ParsedHttpSource() {
|
|||
url.addQueryParameter("q", query)
|
||||
url.addQueryParameter("page", page.toString())
|
||||
|
||||
(filters.forEach { filter ->
|
||||
when (filter) {
|
||||
is OrderBy -> {
|
||||
url.addQueryParameter("sortBy", filter.toUriPart())
|
||||
}
|
||||
is SortBy -> {
|
||||
url.addQueryParameter("sortAscending", filter.toUriPart())
|
||||
(
|
||||
filters.forEach { filter ->
|
||||
when (filter) {
|
||||
is OrderBy -> {
|
||||
url.addQueryParameter("sortBy", filter.toUriPart())
|
||||
}
|
||||
is SortBy -> {
|
||||
url.addQueryParameter("sortAscending", filter.toUriPart())
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
return GET(url.toString(), headers)
|
||||
}
|
||||
|
@ -117,7 +121,7 @@ class MangaJar : ParsedHttpSource() {
|
|||
return if ("ago" in string) {
|
||||
parseRelativeDate(string) ?: 0
|
||||
} else {
|
||||
dateFormat.parse(string).time
|
||||
dateFormat.parse(string)?.time ?: 0L
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,25 +150,32 @@ class MangaJar : ParsedHttpSource() {
|
|||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not Used")
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
OrderBy(),
|
||||
SortBy(),
|
||||
GenreList()
|
||||
OrderBy(),
|
||||
SortBy(),
|
||||
GenreList()
|
||||
)
|
||||
|
||||
private class SortBy : UriPartFilter("Sort By", arrayOf(
|
||||
private class SortBy : UriPartFilter(
|
||||
"Sort By",
|
||||
arrayOf(
|
||||
Pair("Descending", "0"),
|
||||
Pair("Ascending", "1")
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private class OrderBy : UriPartFilter("Order By", arrayOf(
|
||||
private class OrderBy : UriPartFilter(
|
||||
"Order By",
|
||||
arrayOf(
|
||||
Pair("Popularity", "popular"),
|
||||
Pair("Year", "year"),
|
||||
Pair("Alphabet", "name"),
|
||||
Pair("Date added", "published_at"),
|
||||
Pair("Date updated", "last_chapter_at")
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private class GenreList : Filter.Select<String>("Select Genre",
|
||||
private class GenreList : Filter.Select<String>(
|
||||
"Select Genre",
|
||||
arrayOf(
|
||||
"",
|
||||
"Fantasy",
|
||||
|
@ -220,7 +231,7 @@ class MangaJar : ParsedHttpSource() {
|
|||
private inline fun <reified T> Iterable<*>.findInstance() = find { it is T } as? T
|
||||
|
||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||
fun toUriPart() = vals[state].second
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.ResponseBody
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class MangaKatana : ParsedHttpSource() {
|
||||
override val name = "MangaKatana"
|
||||
|
|
|
@ -17,14 +17,14 @@ 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 java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Source responds to requests with their full database as a JsonArray, then sorts/filters it client-side
|
||||
|
@ -89,11 +89,13 @@ class MangaLife : HttpSource() {
|
|||
val endRange = ((page * 24) - 1).let { if (it <= directory.lastIndex) it else directory.lastIndex }
|
||||
|
||||
for (i in (((page - 1) * 24)..endRange)) {
|
||||
mangas.add(SManga.create().apply {
|
||||
title = directory[i]["s"].string
|
||||
url = "/manga/${directory[i]["i"].string}"
|
||||
thumbnail_url = "https://cover.mangabeast01.com/cover/${directory[i]["i"].string}.jpg"
|
||||
})
|
||||
mangas.add(
|
||||
SManga.create().apply {
|
||||
title = directory[i]["s"].string
|
||||
url = "/manga/${directory[i]["i"].string}"
|
||||
thumbnail_url = "https://cover.mangabeast01.com/cover/${directory[i]["i"].string}.jpg"
|
||||
}
|
||||
)
|
||||
}
|
||||
return MangasPage(mangas, endRange < directory.lastIndex)
|
||||
}
|
||||
|
@ -281,54 +283,54 @@ class MangaLife : HttpSource() {
|
|||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
YearField(),
|
||||
AuthorField(),
|
||||
SelectField("Scan Status", arrayOf("Any", "Complete", "Discontinued", "Hiatus", "Incomplete", "Ongoing")),
|
||||
SelectField("Publish Status", arrayOf("Any", "Cancelled", "Complete", "Discontinued", "Hiatus", "Incomplete", "Ongoing", "Unfinished")),
|
||||
SelectField("Type", arrayOf("Any", "Doujinshi", "Manga", "Manhua", "Manhwa", "OEL", "One-shot")),
|
||||
SelectField("Translation", arrayOf("Any", "Official Only")),
|
||||
Sort(),
|
||||
GenreList(getGenreList())
|
||||
YearField(),
|
||||
AuthorField(),
|
||||
SelectField("Scan Status", arrayOf("Any", "Complete", "Discontinued", "Hiatus", "Incomplete", "Ongoing")),
|
||||
SelectField("Publish Status", arrayOf("Any", "Cancelled", "Complete", "Discontinued", "Hiatus", "Incomplete", "Ongoing", "Unfinished")),
|
||||
SelectField("Type", arrayOf("Any", "Doujinshi", "Manga", "Manhua", "Manhwa", "OEL", "One-shot")),
|
||||
SelectField("Translation", arrayOf("Any", "Official Only")),
|
||||
Sort(),
|
||||
GenreList(getGenreList())
|
||||
)
|
||||
|
||||
// [...document.querySelectorAll("label.triStateCheckBox input")].map(el => `Filter("${el.getAttribute('name')}", "${el.nextSibling.textContent.trim()}")`).join(',\n')
|
||||
// https://manga4life.com/advanced-search/
|
||||
private fun getGenreList() = listOf(
|
||||
Genre("Action"),
|
||||
Genre("Adult"),
|
||||
Genre("Adventure"),
|
||||
Genre("Comedy"),
|
||||
Genre("Doujinshi"),
|
||||
Genre("Drama"),
|
||||
Genre("Ecchi"),
|
||||
Genre("Fantasy"),
|
||||
Genre("Gender Bender"),
|
||||
Genre("Harem"),
|
||||
Genre("Hentai"),
|
||||
Genre("Historical"),
|
||||
Genre("Horror"),
|
||||
Genre("Josei"),
|
||||
Genre("Lolicon"),
|
||||
Genre("Martial Arts"),
|
||||
Genre("Mature"),
|
||||
Genre("Mecha"),
|
||||
Genre("Mystery"),
|
||||
Genre("Psychological"),
|
||||
Genre("Romance"),
|
||||
Genre("School Life"),
|
||||
Genre("Sci-fi"),
|
||||
Genre("Seinen"),
|
||||
Genre("Shotacon"),
|
||||
Genre("Shoujo"),
|
||||
Genre("Shoujo Ai"),
|
||||
Genre("Shounen"),
|
||||
Genre("Shounen Ai"),
|
||||
Genre("Slice of Life"),
|
||||
Genre("Smut"),
|
||||
Genre("Sports"),
|
||||
Genre("Supernatural"),
|
||||
Genre("Tragedy"),
|
||||
Genre("Yaoi"),
|
||||
Genre("Yuri")
|
||||
Genre("Action"),
|
||||
Genre("Adult"),
|
||||
Genre("Adventure"),
|
||||
Genre("Comedy"),
|
||||
Genre("Doujinshi"),
|
||||
Genre("Drama"),
|
||||
Genre("Ecchi"),
|
||||
Genre("Fantasy"),
|
||||
Genre("Gender Bender"),
|
||||
Genre("Harem"),
|
||||
Genre("Hentai"),
|
||||
Genre("Historical"),
|
||||
Genre("Horror"),
|
||||
Genre("Josei"),
|
||||
Genre("Lolicon"),
|
||||
Genre("Martial Arts"),
|
||||
Genre("Mature"),
|
||||
Genre("Mecha"),
|
||||
Genre("Mystery"),
|
||||
Genre("Psychological"),
|
||||
Genre("Romance"),
|
||||
Genre("School Life"),
|
||||
Genre("Sci-fi"),
|
||||
Genre("Seinen"),
|
||||
Genre("Shotacon"),
|
||||
Genre("Shoujo"),
|
||||
Genre("Shoujo Ai"),
|
||||
Genre("Shounen"),
|
||||
Genre("Shounen Ai"),
|
||||
Genre("Slice of Life"),
|
||||
Genre("Smut"),
|
||||
Genre("Sports"),
|
||||
Genre("Supernatural"),
|
||||
Genre("Tragedy"),
|
||||
Genre("Yaoi"),
|
||||
Genre("Yuri")
|
||||
)
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class MangaLinkz : ParsedHttpSource() {
|
||||
|
||||
|
@ -126,11 +126,12 @@ class MangaLinkz : ParsedHttpSource() {
|
|||
}
|
||||
}
|
||||
}
|
||||
else -> try {
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.US).parse(this).time
|
||||
} catch (_: Exception) {
|
||||
0L
|
||||
}
|
||||
else ->
|
||||
try {
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.US).parse(this)?.time ?: 0L
|
||||
} catch (_: Exception) {
|
||||
0L
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@ 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.ParsedHttpSource
|
||||
import java.util.Calendar
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.util.Calendar
|
||||
|
||||
// MangaManiac is a network of sites built by Animemaniac.co.
|
||||
|
||||
|
|
|
@ -12,14 +12,14 @@ 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 okhttp3.Headers
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import java.lang.Exception
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import kotlin.collections.ArrayList
|
||||
import okhttp3.Headers
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
||||
fun JsonObject.getNullable(key: String): JsonElement? {
|
||||
val value: JsonElement = this.get(key) ?: return null
|
||||
|
@ -72,11 +72,13 @@ class MangaMutiny : HttpSource() {
|
|||
for (singleChapterJsonElement in jsonChapters) {
|
||||
val singleChapterJsonObject = singleChapterJsonElement.asJsonObject
|
||||
|
||||
chapterList.add(SChapter.create().apply {
|
||||
name = chapterTitleBuilder(singleChapterJsonObject)
|
||||
url = singleChapterJsonObject.get("slug").asString
|
||||
date_upload = parseDate(singleChapterJsonObject.get("releasedAt").asString)
|
||||
})
|
||||
chapterList.add(
|
||||
SChapter.create().apply {
|
||||
name = chapterTitleBuilder(singleChapterJsonObject)
|
||||
url = singleChapterJsonObject.get("slug").asString
|
||||
date_upload = parseDate(singleChapterJsonObject.get("releasedAt").asString)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,11 +213,13 @@ class MangaMutiny : HttpSource() {
|
|||
|
||||
for (singleItem in itemsArray) {
|
||||
val mangaObject = singleItem.asJsonObject
|
||||
mangasPage.add(SManga.create().apply {
|
||||
this.title = mangaObject.get("title").asString
|
||||
this.thumbnail_url = mangaObject.getNullable("thumbnail")?.asString
|
||||
this.url = mangaObject.get("slug").asString
|
||||
})
|
||||
mangasPage.add(
|
||||
SManga.create().apply {
|
||||
this.title = mangaObject.get("title").asString
|
||||
this.thumbnail_url = mangaObject.getNullable("thumbnail")?.asString
|
||||
this.url = mangaObject.get("slug").asString
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,19 +307,27 @@ class MangaMutiny : HttpSource() {
|
|||
}
|
||||
}
|
||||
|
||||
private class StatusFilter : UriSelectFilter("Status", "status", arrayOf(
|
||||
Pair("", "All"),
|
||||
Pair("completed", "Completed"),
|
||||
Pair("ongoing", "Ongoing")
|
||||
))
|
||||
private class StatusFilter : UriSelectFilter(
|
||||
"Status",
|
||||
"status",
|
||||
arrayOf(
|
||||
Pair("", "All"),
|
||||
Pair("completed", "Completed"),
|
||||
Pair("ongoing", "Ongoing")
|
||||
)
|
||||
)
|
||||
|
||||
private class CategoryFilter : UriSelectFilter("Category", "tags", arrayOf(
|
||||
Pair("", "All"),
|
||||
Pair("josei", "Josei"),
|
||||
Pair("seinen", "Seinen"),
|
||||
Pair("shoujo", "Shoujo"),
|
||||
Pair("shounen", "Shounen")
|
||||
)) {
|
||||
private class CategoryFilter : UriSelectFilter(
|
||||
"Category",
|
||||
"tags",
|
||||
arrayOf(
|
||||
Pair("", "All"),
|
||||
Pair("josei", "Josei"),
|
||||
Pair("seinen", "Seinen"),
|
||||
Pair("shoujo", "Shoujo"),
|
||||
Pair("shounen", "Shounen")
|
||||
)
|
||||
) {
|
||||
override fun potentiallyAddToUriParameterMap(parameterMap: MutableMap<String, String>) =
|
||||
appendValueToKeyInUriParameterMap(parameterMap, uriParam, vals[state].first)
|
||||
}
|
||||
|
@ -333,92 +345,104 @@ class MangaMutiny : HttpSource() {
|
|||
}
|
||||
}
|
||||
// Actual genere filter list
|
||||
private class GenresFilter : GenreFilterList("Genres", listOf(
|
||||
GenreFilter("action", "action"),
|
||||
GenreFilter("adult", "adult"),
|
||||
GenreFilter("adventure", "adventure"),
|
||||
GenreFilter("aliens", "aliens"),
|
||||
GenreFilter("animals", "animals"),
|
||||
GenreFilter("comedy", "comedy"),
|
||||
GenreFilter("cooking", "cooking"),
|
||||
GenreFilter("crossdressing", "crossdressing"),
|
||||
GenreFilter("delinquents", "delinquents"),
|
||||
GenreFilter("demons", "demons"),
|
||||
GenreFilter("drama", "drama"),
|
||||
GenreFilter("ecchi", "ecchi"),
|
||||
GenreFilter("fantasy", "fantasy"),
|
||||
GenreFilter("gender_bender", "gender bender"),
|
||||
GenreFilter("genderswap", "genderswap"),
|
||||
GenreFilter("ghosts", "ghosts"),
|
||||
GenreFilter("gore", "gore"),
|
||||
GenreFilter("gyaru", "gyaru"),
|
||||
GenreFilter("harem", "harem"),
|
||||
GenreFilter("historical", "historical"),
|
||||
GenreFilter("horror", "horror"),
|
||||
GenreFilter("incest", "incest"),
|
||||
GenreFilter("isekai", "isekai"),
|
||||
GenreFilter("loli", "loli"),
|
||||
GenreFilter("magic", "magic"),
|
||||
GenreFilter("magical_girls", "magical girls"),
|
||||
GenreFilter("mangamutiny", "mangamutiny"),
|
||||
GenreFilter("martial_arts", "martial arts"),
|
||||
GenreFilter("mature", "mature"),
|
||||
GenreFilter("mecha", "mecha"),
|
||||
GenreFilter("medical", "medical"),
|
||||
GenreFilter("military", "military"),
|
||||
GenreFilter("monster_girls", "monster girls"),
|
||||
GenreFilter("monsters", "monsters"),
|
||||
GenreFilter("mystery", "mystery"),
|
||||
GenreFilter("ninja", "ninja"),
|
||||
GenreFilter("office_workers", "office workers"),
|
||||
GenreFilter("philosophical", "philosophical"),
|
||||
GenreFilter("psychological", "psychological"),
|
||||
GenreFilter("reincarnation", "reincarnation"),
|
||||
GenreFilter("reverse_harem", "reverse harem"),
|
||||
GenreFilter("romance", "romance"),
|
||||
GenreFilter("school_life", "school life"),
|
||||
GenreFilter("sci_fi", "sci fi"),
|
||||
GenreFilter("sci-fi", "sci-fi"),
|
||||
GenreFilter("sexual_violence", "sexual violence"),
|
||||
GenreFilter("shota", "shota"),
|
||||
GenreFilter("shoujo_ai", "shoujo ai"),
|
||||
GenreFilter("shounen_ai", "shounen ai"),
|
||||
GenreFilter("slice_of_life", "slice of life"),
|
||||
GenreFilter("smut", "smut"),
|
||||
GenreFilter("sports", "sports"),
|
||||
GenreFilter("superhero", "superhero"),
|
||||
GenreFilter("supernatural", "supernatural"),
|
||||
GenreFilter("survival", "survival"),
|
||||
GenreFilter("time_travel", "time travel"),
|
||||
GenreFilter("tragedy", "tragedy"),
|
||||
GenreFilter("video_games", "video games"),
|
||||
GenreFilter("virtual_reality", "virtual reality"),
|
||||
GenreFilter("webtoons", "webtoons"),
|
||||
GenreFilter("wuxia", "wuxia"),
|
||||
GenreFilter("zombies", "zombies")
|
||||
))
|
||||
private class GenresFilter : GenreFilterList(
|
||||
"Genres",
|
||||
listOf(
|
||||
GenreFilter("action", "action"),
|
||||
GenreFilter("adult", "adult"),
|
||||
GenreFilter("adventure", "adventure"),
|
||||
GenreFilter("aliens", "aliens"),
|
||||
GenreFilter("animals", "animals"),
|
||||
GenreFilter("comedy", "comedy"),
|
||||
GenreFilter("cooking", "cooking"),
|
||||
GenreFilter("crossdressing", "crossdressing"),
|
||||
GenreFilter("delinquents", "delinquents"),
|
||||
GenreFilter("demons", "demons"),
|
||||
GenreFilter("drama", "drama"),
|
||||
GenreFilter("ecchi", "ecchi"),
|
||||
GenreFilter("fantasy", "fantasy"),
|
||||
GenreFilter("gender_bender", "gender bender"),
|
||||
GenreFilter("genderswap", "genderswap"),
|
||||
GenreFilter("ghosts", "ghosts"),
|
||||
GenreFilter("gore", "gore"),
|
||||
GenreFilter("gyaru", "gyaru"),
|
||||
GenreFilter("harem", "harem"),
|
||||
GenreFilter("historical", "historical"),
|
||||
GenreFilter("horror", "horror"),
|
||||
GenreFilter("incest", "incest"),
|
||||
GenreFilter("isekai", "isekai"),
|
||||
GenreFilter("loli", "loli"),
|
||||
GenreFilter("magic", "magic"),
|
||||
GenreFilter("magical_girls", "magical girls"),
|
||||
GenreFilter("mangamutiny", "mangamutiny"),
|
||||
GenreFilter("martial_arts", "martial arts"),
|
||||
GenreFilter("mature", "mature"),
|
||||
GenreFilter("mecha", "mecha"),
|
||||
GenreFilter("medical", "medical"),
|
||||
GenreFilter("military", "military"),
|
||||
GenreFilter("monster_girls", "monster girls"),
|
||||
GenreFilter("monsters", "monsters"),
|
||||
GenreFilter("mystery", "mystery"),
|
||||
GenreFilter("ninja", "ninja"),
|
||||
GenreFilter("office_workers", "office workers"),
|
||||
GenreFilter("philosophical", "philosophical"),
|
||||
GenreFilter("psychological", "psychological"),
|
||||
GenreFilter("reincarnation", "reincarnation"),
|
||||
GenreFilter("reverse_harem", "reverse harem"),
|
||||
GenreFilter("romance", "romance"),
|
||||
GenreFilter("school_life", "school life"),
|
||||
GenreFilter("sci_fi", "sci fi"),
|
||||
GenreFilter("sci-fi", "sci-fi"),
|
||||
GenreFilter("sexual_violence", "sexual violence"),
|
||||
GenreFilter("shota", "shota"),
|
||||
GenreFilter("shoujo_ai", "shoujo ai"),
|
||||
GenreFilter("shounen_ai", "shounen ai"),
|
||||
GenreFilter("slice_of_life", "slice of life"),
|
||||
GenreFilter("smut", "smut"),
|
||||
GenreFilter("sports", "sports"),
|
||||
GenreFilter("superhero", "superhero"),
|
||||
GenreFilter("supernatural", "supernatural"),
|
||||
GenreFilter("survival", "survival"),
|
||||
GenreFilter("time_travel", "time travel"),
|
||||
GenreFilter("tragedy", "tragedy"),
|
||||
GenreFilter("video_games", "video games"),
|
||||
GenreFilter("virtual_reality", "virtual reality"),
|
||||
GenreFilter("webtoons", "webtoons"),
|
||||
GenreFilter("wuxia", "wuxia"),
|
||||
GenreFilter("zombies", "zombies")
|
||||
)
|
||||
)
|
||||
|
||||
// Actual format filter List
|
||||
private class FormatsFilter : GenreFilterList("Formats", listOf(
|
||||
GenreFilter("4-koma", "4-koma"),
|
||||
GenreFilter("adaptation", "adaptation"),
|
||||
GenreFilter("anthology", "anthology"),
|
||||
GenreFilter("award_winning", "award winning"),
|
||||
GenreFilter("doujinshi", "doujinshi"),
|
||||
GenreFilter("fan_colored", "fan colored"),
|
||||
GenreFilter("full_color", "full color"),
|
||||
GenreFilter("long_strip", "long strip"),
|
||||
GenreFilter("official_colored", "official colored"),
|
||||
GenreFilter("oneshot", "oneshot"),
|
||||
GenreFilter("web_comic", "web comic")
|
||||
))
|
||||
private class FormatsFilter : GenreFilterList(
|
||||
"Formats",
|
||||
listOf(
|
||||
GenreFilter("4-koma", "4-koma"),
|
||||
GenreFilter("adaptation", "adaptation"),
|
||||
GenreFilter("anthology", "anthology"),
|
||||
GenreFilter("award_winning", "award winning"),
|
||||
GenreFilter("doujinshi", "doujinshi"),
|
||||
GenreFilter("fan_colored", "fan colored"),
|
||||
GenreFilter("full_color", "full color"),
|
||||
GenreFilter("long_strip", "long strip"),
|
||||
GenreFilter("official_colored", "official colored"),
|
||||
GenreFilter("oneshot", "oneshot"),
|
||||
GenreFilter("web_comic", "web comic")
|
||||
)
|
||||
)
|
||||
|
||||
private class SortFilter : UriSelectFilter("Sort", "sort", arrayOf(
|
||||
Pair("-rating -ratingCount", "Popular"),
|
||||
Pair("-lastReleasedAt", "Last update"),
|
||||
Pair("-createdAt", "Newest"),
|
||||
Pair("title", "Name")
|
||||
), firstIsUnspecified = false, defaultValue = 0)
|
||||
private class SortFilter : UriSelectFilter(
|
||||
"Sort",
|
||||
"sort",
|
||||
arrayOf(
|
||||
Pair("-rating -ratingCount", "Popular"),
|
||||
Pair("-lastReleasedAt", "Last update"),
|
||||
Pair("-createdAt", "Newest"),
|
||||
Pair("title", "Name")
|
||||
),
|
||||
firstIsUnspecified = false,
|
||||
defaultValue = 0
|
||||
)
|
||||
|
||||
private class AuthorFilter : Filter.Text("Manga Author & Artist"), UriFilter {
|
||||
override fun potentiallyAddToUriParameterMap(parameterMap: MutableMap<String, String>) {
|
||||
|
@ -429,8 +453,8 @@ class MangaMutiny : HttpSource() {
|
|||
}
|
||||
|
||||
/**The scanlator filter exists on the mangamutiny website website, however it doesn't work.
|
||||
This should stay disabled in the extension until it's properly implemented on the website,
|
||||
otherwise users may be confused by searches that return no results.**/
|
||||
This should stay disabled in the extension until it's properly implemented on the website,
|
||||
otherwise users may be confused by searches that return no results.**/
|
||||
/*
|
||||
private class ScanlatorFilter : Filter.Text("Scanlator Name"), UriFilter {
|
||||
override fun potentiallyAddToUriParameterMap(parameterMap: MutableMap<String, String>) {
|
||||
|
|
|
@ -6,14 +6,14 @@ 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.ParsedHttpSource
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class MangaOwl : ParsedHttpSource() {
|
||||
|
||||
|
|
|
@ -15,9 +15,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
@ -26,6 +23,9 @@ import org.jsoup.nodes.Document
|
|||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class MangaPark : ConfigurableSource, ParsedHttpSource() {
|
||||
|
||||
|
@ -154,7 +154,7 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
|
|||
return when (getSourcePref()) {
|
||||
// source with most chapters along with chapters that source doesn't have
|
||||
"most" -> {
|
||||
val chapters = mangaBySource.maxBy { it.count() }!!
|
||||
val chapters = mangaBySource.maxByOrNull { it.count() }!!
|
||||
(chapters + chapters.getMissingChapters(mangaBySource.flatten())).sortedByDescending { it.chapter_number }
|
||||
}
|
||||
// "smart list" - try not to miss a chapter and avoid dupes
|
||||
|
@ -280,21 +280,21 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
|
|||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
AuthorArtistText(),
|
||||
SearchTypeFilter("Title query", "name-match"),
|
||||
SearchTypeFilter("Author/Artist query", "autart-match"),
|
||||
SortFilter(),
|
||||
GenreGroup(),
|
||||
GenreInclusionFilter(),
|
||||
ChapterCountFilter(),
|
||||
StatusFilter(),
|
||||
RatingFilter(),
|
||||
TypeFilter(),
|
||||
YearFilter()
|
||||
AuthorArtistText(),
|
||||
SearchTypeFilter("Title query", "name-match"),
|
||||
SearchTypeFilter("Author/Artist query", "autart-match"),
|
||||
SortFilter(),
|
||||
GenreGroup(),
|
||||
GenreInclusionFilter(),
|
||||
ChapterCountFilter(),
|
||||
StatusFilter(),
|
||||
RatingFilter(),
|
||||
TypeFilter(),
|
||||
YearFilter()
|
||||
)
|
||||
|
||||
private class SearchTypeFilter(name: String, val uriParam: String) :
|
||||
Filter.Select<String>(name, STATE_MAP), UriFilter {
|
||||
Filter.Select<String>(name, STATE_MAP), UriFilter {
|
||||
override fun addToUri(uri: Uri.Builder) {
|
||||
if (STATE_MAP[state] != "contain") {
|
||||
uri.appendQueryParameter(uriParam, STATE_MAP[state])
|
||||
|
@ -316,107 +316,112 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
|
|||
|
||||
private class GenreFilter(val uriParam: String, displayName: String) : Filter.TriState(displayName)
|
||||
|
||||
private class GenreGroup : Filter.Group<GenreFilter>("Genres", listOf(
|
||||
GenreFilter("4-koma", "4 koma"),
|
||||
GenreFilter("action", "Action"),
|
||||
GenreFilter("adaptation", "Adaptation"),
|
||||
GenreFilter("adult", "Adult"),
|
||||
GenreFilter("adventure", "Adventure"),
|
||||
GenreFilter("aliens", "Aliens"),
|
||||
GenreFilter("animals", "Animals"),
|
||||
GenreFilter("anthology", "Anthology"),
|
||||
GenreFilter("award-winning", "Award winning"),
|
||||
GenreFilter("comedy", "Comedy"),
|
||||
GenreFilter("cooking", "Cooking"),
|
||||
GenreFilter("crime", "Crime"),
|
||||
GenreFilter("crossdressing", "Crossdressing"),
|
||||
GenreFilter("delinquents", "Delinquents"),
|
||||
GenreFilter("demons", "Demons"),
|
||||
GenreFilter("doujinshi", "Doujinshi"),
|
||||
GenreFilter("drama", "Drama"),
|
||||
GenreFilter("ecchi", "Ecchi"),
|
||||
GenreFilter("fan-colored", "Fan colored"),
|
||||
GenreFilter("fantasy", "Fantasy"),
|
||||
GenreFilter("food", "Food"),
|
||||
GenreFilter("full-color", "Full color"),
|
||||
GenreFilter("game", "Game"),
|
||||
GenreFilter("gender-bender", "Gender bender"),
|
||||
GenreFilter("genderswap", "Genderswap"),
|
||||
GenreFilter("ghosts", "Ghosts"),
|
||||
GenreFilter("gore", "Gore"),
|
||||
GenreFilter("gossip", "Gossip"),
|
||||
GenreFilter("gyaru", "Gyaru"),
|
||||
GenreFilter("harem", "Harem"),
|
||||
GenreFilter("historical", "Historical"),
|
||||
GenreFilter("horror", "Horror"),
|
||||
GenreFilter("incest", "Incest"),
|
||||
GenreFilter("isekai", "Isekai"),
|
||||
GenreFilter("josei", "Josei"),
|
||||
GenreFilter("kids", "Kids"),
|
||||
GenreFilter("loli", "Loli"),
|
||||
GenreFilter("lolicon", "Lolicon"),
|
||||
GenreFilter("long-strip", "Long strip"),
|
||||
GenreFilter("mafia", "Mafia"),
|
||||
GenreFilter("magic", "Magic"),
|
||||
GenreFilter("magical-girls", "Magical girls"),
|
||||
GenreFilter("manhwa", "Manhwa"),
|
||||
GenreFilter("martial-arts", "Martial arts"),
|
||||
GenreFilter("mature", "Mature"),
|
||||
GenreFilter("mecha", "Mecha"),
|
||||
GenreFilter("medical", "Medical"),
|
||||
GenreFilter("military", "Military"),
|
||||
GenreFilter("monster-girls", "Monster girls"),
|
||||
GenreFilter("monsters", "Monsters"),
|
||||
GenreFilter("music", "Music"),
|
||||
GenreFilter("mystery", "Mystery"),
|
||||
GenreFilter("ninja", "Ninja"),
|
||||
GenreFilter("office-workers", "Office workers"),
|
||||
GenreFilter("official-colored", "Official colored"),
|
||||
GenreFilter("one-shot", "One shot"),
|
||||
GenreFilter("parody", "Parody"),
|
||||
GenreFilter("philosophical", "Philosophical"),
|
||||
GenreFilter("police", "Police"),
|
||||
GenreFilter("post-apocalyptic", "Post apocalyptic"),
|
||||
GenreFilter("psychological", "Psychological"),
|
||||
GenreFilter("reincarnation", "Reincarnation"),
|
||||
GenreFilter("reverse-harem", "Reverse harem"),
|
||||
GenreFilter("romance", "Romance"),
|
||||
GenreFilter("samurai", "Samurai"),
|
||||
GenreFilter("school-life", "School life"),
|
||||
GenreFilter("sci-fi", "Sci fi"),
|
||||
GenreFilter("seinen", "Seinen"),
|
||||
GenreFilter("shota", "Shota"),
|
||||
GenreFilter("shotacon", "Shotacon"),
|
||||
GenreFilter("shoujo", "Shoujo"),
|
||||
GenreFilter("shoujo-ai", "Shoujo ai"),
|
||||
GenreFilter("shounen", "Shounen"),
|
||||
GenreFilter("shounen-ai", "Shounen ai"),
|
||||
GenreFilter("slice-of-life", "Slice of life"),
|
||||
GenreFilter("smut", "Smut"),
|
||||
GenreFilter("space", "Space"),
|
||||
GenreFilter("sports", "Sports"),
|
||||
GenreFilter("super-power", "Super power"),
|
||||
GenreFilter("superhero", "Superhero"),
|
||||
GenreFilter("supernatural", "Supernatural"),
|
||||
GenreFilter("survival", "Survival"),
|
||||
GenreFilter("suspense", "Suspense"),
|
||||
GenreFilter("thriller", "Thriller"),
|
||||
GenreFilter("time-travel", "Time travel"),
|
||||
GenreFilter("toomics", "Toomics"),
|
||||
GenreFilter("traditional-games", "Traditional games"),
|
||||
GenreFilter("tragedy", "Tragedy"),
|
||||
GenreFilter("user-created", "User created"),
|
||||
GenreFilter("vampire", "Vampire"),
|
||||
GenreFilter("vampires", "Vampires"),
|
||||
GenreFilter("video-games", "Video games"),
|
||||
GenreFilter("virtual-reality", "Virtual reality"),
|
||||
GenreFilter("web-comic", "Web comic"),
|
||||
GenreFilter("webtoon", "Webtoon"),
|
||||
GenreFilter("wuxia", "Wuxia"),
|
||||
GenreFilter("yaoi", "Yaoi"),
|
||||
GenreFilter("yuri", "Yuri"),
|
||||
GenreFilter("zombies", "Zombies")
|
||||
)), UriFilter {
|
||||
private class GenreGroup :
|
||||
Filter.Group<GenreFilter>(
|
||||
"Genres",
|
||||
listOf(
|
||||
GenreFilter("4-koma", "4 koma"),
|
||||
GenreFilter("action", "Action"),
|
||||
GenreFilter("adaptation", "Adaptation"),
|
||||
GenreFilter("adult", "Adult"),
|
||||
GenreFilter("adventure", "Adventure"),
|
||||
GenreFilter("aliens", "Aliens"),
|
||||
GenreFilter("animals", "Animals"),
|
||||
GenreFilter("anthology", "Anthology"),
|
||||
GenreFilter("award-winning", "Award winning"),
|
||||
GenreFilter("comedy", "Comedy"),
|
||||
GenreFilter("cooking", "Cooking"),
|
||||
GenreFilter("crime", "Crime"),
|
||||
GenreFilter("crossdressing", "Crossdressing"),
|
||||
GenreFilter("delinquents", "Delinquents"),
|
||||
GenreFilter("demons", "Demons"),
|
||||
GenreFilter("doujinshi", "Doujinshi"),
|
||||
GenreFilter("drama", "Drama"),
|
||||
GenreFilter("ecchi", "Ecchi"),
|
||||
GenreFilter("fan-colored", "Fan colored"),
|
||||
GenreFilter("fantasy", "Fantasy"),
|
||||
GenreFilter("food", "Food"),
|
||||
GenreFilter("full-color", "Full color"),
|
||||
GenreFilter("game", "Game"),
|
||||
GenreFilter("gender-bender", "Gender bender"),
|
||||
GenreFilter("genderswap", "Genderswap"),
|
||||
GenreFilter("ghosts", "Ghosts"),
|
||||
GenreFilter("gore", "Gore"),
|
||||
GenreFilter("gossip", "Gossip"),
|
||||
GenreFilter("gyaru", "Gyaru"),
|
||||
GenreFilter("harem", "Harem"),
|
||||
GenreFilter("historical", "Historical"),
|
||||
GenreFilter("horror", "Horror"),
|
||||
GenreFilter("incest", "Incest"),
|
||||
GenreFilter("isekai", "Isekai"),
|
||||
GenreFilter("josei", "Josei"),
|
||||
GenreFilter("kids", "Kids"),
|
||||
GenreFilter("loli", "Loli"),
|
||||
GenreFilter("lolicon", "Lolicon"),
|
||||
GenreFilter("long-strip", "Long strip"),
|
||||
GenreFilter("mafia", "Mafia"),
|
||||
GenreFilter("magic", "Magic"),
|
||||
GenreFilter("magical-girls", "Magical girls"),
|
||||
GenreFilter("manhwa", "Manhwa"),
|
||||
GenreFilter("martial-arts", "Martial arts"),
|
||||
GenreFilter("mature", "Mature"),
|
||||
GenreFilter("mecha", "Mecha"),
|
||||
GenreFilter("medical", "Medical"),
|
||||
GenreFilter("military", "Military"),
|
||||
GenreFilter("monster-girls", "Monster girls"),
|
||||
GenreFilter("monsters", "Monsters"),
|
||||
GenreFilter("music", "Music"),
|
||||
GenreFilter("mystery", "Mystery"),
|
||||
GenreFilter("ninja", "Ninja"),
|
||||
GenreFilter("office-workers", "Office workers"),
|
||||
GenreFilter("official-colored", "Official colored"),
|
||||
GenreFilter("one-shot", "One shot"),
|
||||
GenreFilter("parody", "Parody"),
|
||||
GenreFilter("philosophical", "Philosophical"),
|
||||
GenreFilter("police", "Police"),
|
||||
GenreFilter("post-apocalyptic", "Post apocalyptic"),
|
||||
GenreFilter("psychological", "Psychological"),
|
||||
GenreFilter("reincarnation", "Reincarnation"),
|
||||
GenreFilter("reverse-harem", "Reverse harem"),
|
||||
GenreFilter("romance", "Romance"),
|
||||
GenreFilter("samurai", "Samurai"),
|
||||
GenreFilter("school-life", "School life"),
|
||||
GenreFilter("sci-fi", "Sci fi"),
|
||||
GenreFilter("seinen", "Seinen"),
|
||||
GenreFilter("shota", "Shota"),
|
||||
GenreFilter("shotacon", "Shotacon"),
|
||||
GenreFilter("shoujo", "Shoujo"),
|
||||
GenreFilter("shoujo-ai", "Shoujo ai"),
|
||||
GenreFilter("shounen", "Shounen"),
|
||||
GenreFilter("shounen-ai", "Shounen ai"),
|
||||
GenreFilter("slice-of-life", "Slice of life"),
|
||||
GenreFilter("smut", "Smut"),
|
||||
GenreFilter("space", "Space"),
|
||||
GenreFilter("sports", "Sports"),
|
||||
GenreFilter("super-power", "Super power"),
|
||||
GenreFilter("superhero", "Superhero"),
|
||||
GenreFilter("supernatural", "Supernatural"),
|
||||
GenreFilter("survival", "Survival"),
|
||||
GenreFilter("suspense", "Suspense"),
|
||||
GenreFilter("thriller", "Thriller"),
|
||||
GenreFilter("time-travel", "Time travel"),
|
||||
GenreFilter("toomics", "Toomics"),
|
||||
GenreFilter("traditional-games", "Traditional games"),
|
||||
GenreFilter("tragedy", "Tragedy"),
|
||||
GenreFilter("user-created", "User created"),
|
||||
GenreFilter("vampire", "Vampire"),
|
||||
GenreFilter("vampires", "Vampires"),
|
||||
GenreFilter("video-games", "Video games"),
|
||||
GenreFilter("virtual-reality", "Virtual reality"),
|
||||
GenreFilter("web-comic", "Web comic"),
|
||||
GenreFilter("webtoon", "Webtoon"),
|
||||
GenreFilter("wuxia", "Wuxia"),
|
||||
GenreFilter("yaoi", "Yaoi"),
|
||||
GenreFilter("yuri", "Yuri"),
|
||||
GenreFilter("zombies", "Zombies")
|
||||
)
|
||||
),
|
||||
UriFilter {
|
||||
override fun addToUri(uri: Uri.Builder) {
|
||||
val genresParameterValue = state.filter { it.isIncluded() }.joinToString(",") { it.uriParam }
|
||||
if (genresParameterValue.isNotEmpty()) {
|
||||
|
@ -430,12 +435,19 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
|
|||
}
|
||||
}
|
||||
|
||||
private class GenreInclusionFilter : UriSelectFilter("Genre inclusion", "genres-mode", arrayOf(
|
||||
private class GenreInclusionFilter : UriSelectFilter(
|
||||
"Genre inclusion",
|
||||
"genres-mode",
|
||||
arrayOf(
|
||||
Pair("and", "And mode"),
|
||||
Pair("or", "Or mode")
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private class ChapterCountFilter : UriSelectFilter("Chapter count", "chapters", arrayOf(
|
||||
private class ChapterCountFilter : UriSelectFilter(
|
||||
"Chapter count",
|
||||
"chapters",
|
||||
arrayOf(
|
||||
Pair("any", "Any"),
|
||||
Pair("1", "1 +"),
|
||||
Pair("5", "5 +"),
|
||||
|
@ -447,15 +459,23 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
|
|||
Pair("100", "100 +"),
|
||||
Pair("150", "150 +"),
|
||||
Pair("200", "200 +")
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private class StatusFilter : UriSelectFilter("Status", "status", arrayOf(
|
||||
private class StatusFilter : UriSelectFilter(
|
||||
"Status",
|
||||
"status",
|
||||
arrayOf(
|
||||
Pair("any", "Any"),
|
||||
Pair("completed", "Completed"),
|
||||
Pair("ongoing", "Ongoing")
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private class RatingFilter : UriSelectFilter("Rating", "rating", arrayOf(
|
||||
private class RatingFilter : UriSelectFilter(
|
||||
"Rating",
|
||||
"rating",
|
||||
arrayOf(
|
||||
Pair("any", "Any"),
|
||||
Pair("5", "5 stars"),
|
||||
Pair("4", "4 stars"),
|
||||
|
@ -463,26 +483,37 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
|
|||
Pair("2", "2 stars"),
|
||||
Pair("1", "1 star"),
|
||||
Pair("0", "0 stars")
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private class TypeFilter : UriSelectFilter("Type", "types", arrayOf(
|
||||
private class TypeFilter : UriSelectFilter(
|
||||
"Type",
|
||||
"types",
|
||||
arrayOf(
|
||||
Pair("any", "Any"),
|
||||
Pair("manga", "Japanese Manga"),
|
||||
Pair("manhwa", "Korean Manhwa"),
|
||||
Pair("manhua", "Chinese Manhua"),
|
||||
Pair("unknown", "Unknown")
|
||||
))
|
||||
|
||||
private class YearFilter : UriSelectFilter("Release year", "years",
|
||||
arrayOf(Pair("any", "Any"),
|
||||
// Get all years between today and 1946
|
||||
*(Calendar.getInstance().get(Calendar.YEAR) downTo 1946).map {
|
||||
Pair(it.toString(), it.toString())
|
||||
}.toTypedArray()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
private class SortFilter : UriSelectFilter("Sort", "orderby", arrayOf(
|
||||
private class YearFilter : UriSelectFilter(
|
||||
"Release year",
|
||||
"years",
|
||||
arrayOf(
|
||||
Pair("any", "Any"),
|
||||
// Get all years between today and 1946
|
||||
*(Calendar.getInstance().get(Calendar.YEAR) downTo 1946).map {
|
||||
Pair(it.toString(), it.toString())
|
||||
}.toTypedArray()
|
||||
)
|
||||
)
|
||||
|
||||
private class SortFilter : UriSelectFilter(
|
||||
"Sort",
|
||||
"orderby",
|
||||
arrayOf(
|
||||
Pair("a-z", "A-Z"),
|
||||
Pair("views_a", "Views all-time"),
|
||||
Pair("views_y", "Views last 365 days"),
|
||||
|
@ -491,7 +522,10 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
|
|||
Pair("rating", "Rating"),
|
||||
Pair("update", "Latest"),
|
||||
Pair("create", "New manga")
|
||||
), firstIsUnspecified = false, defaultValue = 1)
|
||||
),
|
||||
firstIsUnspecified = false,
|
||||
defaultValue = 1
|
||||
)
|
||||
|
||||
/**
|
||||
* Class that creates a select filter. Each entry in the dropdown has a name and a display name.
|
||||
|
@ -506,7 +540,7 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
|
|||
val firstIsUnspecified: Boolean = true,
|
||||
defaultValue: Int = 0
|
||||
) :
|
||||
Filter.Select<String>(displayName, vals.map { it.second }.toTypedArray(), defaultValue), UriFilter {
|
||||
Filter.Select<String>(displayName, vals.map { it.second }.toTypedArray(), defaultValue), UriFilter {
|
||||
override fun addToUri(uri: Uri.Builder) {
|
||||
if (state != 0 || !firstIsUnspecified)
|
||||
uri.appendQueryParameter(uriParam, vals[state].first)
|
||||
|
|
|
@ -8,13 +8,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
abstract class MRP(
|
||||
override val name: String,
|
||||
|
|
|
@ -14,8 +14,9 @@ import org.jsoup.nodes.Element
|
|||
|
||||
class MRPFactory : SourceFactory {
|
||||
override fun createSources(): List<Source> = listOf(
|
||||
Mangareader(),
|
||||
Mangapanda())
|
||||
Mangareader(),
|
||||
Mangapanda()
|
||||
)
|
||||
}
|
||||
|
||||
class Mangareader : MRP("Mangareader", "https://www.mangareader.net") {
|
||||
|
|
|
@ -10,11 +10,6 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import kotlin.experimental.and
|
||||
import kotlin.experimental.xor
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -23,6 +18,11 @@ import okhttp3.Response
|
|||
import okhttp3.ResponseBody
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import kotlin.experimental.and
|
||||
import kotlin.experimental.xor
|
||||
|
||||
class MangaRockEs : ParsedHttpSource() {
|
||||
|
||||
|
@ -35,16 +35,18 @@ class MangaRockEs : ParsedHttpSource() {
|
|||
override val supportsLatest = true
|
||||
|
||||
// Handles the page decoding
|
||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder().addInterceptor(fun(chain): Response {
|
||||
val url = chain.request().url().toString()
|
||||
val response = chain.proceed(chain.request())
|
||||
if (!url.endsWith(".mri")) return response
|
||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder().addInterceptor(
|
||||
fun(chain): Response {
|
||||
val url = chain.request().url().toString()
|
||||
val response = chain.proceed(chain.request())
|
||||
if (!url.endsWith(".mri")) return response
|
||||
|
||||
val decoded: ByteArray = decodeMri(response)
|
||||
val mediaType = MediaType.parse("image/webp")
|
||||
val rb = ResponseBody.create(mediaType, decoded)
|
||||
return response.newBuilder().body(rb).build()
|
||||
}).build()
|
||||
val decoded: ByteArray = decodeMri(response)
|
||||
val mediaType = MediaType.parse("image/webp")
|
||||
val rb = ResponseBody.create(mediaType, decoded)
|
||||
return response.newBuilder().body(rb).build()
|
||||
}
|
||||
).build()
|
||||
|
||||
// Popular
|
||||
|
||||
|
@ -150,7 +152,7 @@ class MangaRockEs : ParsedHttpSource() {
|
|||
|
||||
calendar.timeInMillis
|
||||
} else {
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.US).parse(date).time
|
||||
SimpleDateFormat("MMM d, yyyy", Locale.US).parse(date)?.time ?: 0L
|
||||
}
|
||||
} ?: 0
|
||||
}
|
||||
|
@ -215,13 +217,18 @@ class MangaRockEs : ParsedHttpSource() {
|
|||
|
||||
// Filters
|
||||
|
||||
private class StatusFilter : UriPartFilter("Status", arrayOf(
|
||||
Pair("All", "all"),
|
||||
Pair("Completed", "completed"),
|
||||
Pair("Ongoing", "ongoing")
|
||||
))
|
||||
private class StatusFilter : UriPartFilter(
|
||||
"Status",
|
||||
arrayOf(
|
||||
Pair("All", "all"),
|
||||
Pair("Completed", "completed"),
|
||||
Pair("Ongoing", "ongoing")
|
||||
)
|
||||
)
|
||||
|
||||
private class RankFilter : UriPartFilter("Rank", arrayOf(
|
||||
private class RankFilter : UriPartFilter(
|
||||
"Rank",
|
||||
arrayOf(
|
||||
Pair("All", "all"),
|
||||
Pair("1 - 999", "1-999"),
|
||||
Pair("1k - 2k", "1000-2000"),
|
||||
|
@ -234,80 +241,84 @@ class MangaRockEs : ParsedHttpSource() {
|
|||
Pair("8k - 9k", "8000-9000"),
|
||||
Pair("9k - 19k", "9000-10000"),
|
||||
Pair("10k - 11k", "10000-11000")
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private class SortBy : UriPartFilter("Sort by", arrayOf(
|
||||
private class SortBy : UriPartFilter(
|
||||
"Sort by",
|
||||
arrayOf(
|
||||
Pair("Name", "name"),
|
||||
Pair("Rank", "rank")
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
private class Genre(name: String, val uriPart: String) : Filter.CheckBox(name)
|
||||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
// Search and filter don't work at the same time
|
||||
Filter.Header("NOTE: Ignored if using text search!"),
|
||||
Filter.Separator(),
|
||||
StatusFilter(),
|
||||
RankFilter(),
|
||||
SortBy(),
|
||||
GenreList(getGenreList())
|
||||
// Search and filter don't work at the same time
|
||||
Filter.Header("NOTE: Ignored if using text search!"),
|
||||
Filter.Separator(),
|
||||
StatusFilter(),
|
||||
RankFilter(),
|
||||
SortBy(),
|
||||
GenreList(getGenreList())
|
||||
)
|
||||
|
||||
// [...document.querySelectorAll('._2DMqI .mdl-checkbox')].map(n => `Genre("${n.querySelector('.mdl-checkbox__label').innerText}", "${n.querySelector('input').dataset.oid}")`).sort().join(',\n')
|
||||
// on https://mangarock.com/manga
|
||||
private fun getGenreList() = listOf(
|
||||
Genre("4-koma", "4-koma"),
|
||||
Genre("Action", "action"),
|
||||
Genre("Adult", "adult"),
|
||||
Genre("Adventure", "adventure"),
|
||||
Genre("Comedy", "comedy"),
|
||||
Genre("Demons", "demons"),
|
||||
Genre("Doujinshi", "doujinshi"),
|
||||
Genre("Drama", "drama"),
|
||||
Genre("Ecchi", "ecchi"),
|
||||
Genre("Fantasy", "fantasy"),
|
||||
Genre("Gender Bender", "gender-bender"),
|
||||
Genre("Harem", "harem"),
|
||||
Genre("Historical", "historical"),
|
||||
Genre("Horror", "horror"),
|
||||
Genre("Isekai", "isekai"),
|
||||
Genre("Josei", "josei"),
|
||||
Genre("Kids", "kids"),
|
||||
Genre("Magic", "magic"),
|
||||
Genre("Martial Arts", "martial-arts"),
|
||||
Genre("Mature", "mature"),
|
||||
Genre("Mecha", "mecha"),
|
||||
Genre("Military", "military"),
|
||||
Genre("Music", "music"),
|
||||
Genre("Mystery", "mystery"),
|
||||
Genre("One Shot", "one-shot"),
|
||||
Genre("Parody", "parody"),
|
||||
Genre("Police", "police"),
|
||||
Genre("Psychological", "psychological"),
|
||||
Genre("Romance", "romance"),
|
||||
Genre("School Life", "school-life"),
|
||||
Genre("Sci-Fi", "sci-fi"),
|
||||
Genre("Seinen", "seinen"),
|
||||
Genre("Shoujo Ai", "shoujo-ai"),
|
||||
Genre("Shoujo", "shoujo"),
|
||||
Genre("Shounen Ai", "shounen-ai"),
|
||||
Genre("Shounen", "shounen"),
|
||||
Genre("Slice of Life", "slice-of-life"),
|
||||
Genre("Smut", "smut"),
|
||||
Genre("Space", "space"),
|
||||
Genre("Sports", "sports"),
|
||||
Genre("Super Power", "super-power"),
|
||||
Genre("Supernatural", "supernatural"),
|
||||
Genre("Tragedy", "tragedy"),
|
||||
Genre("Vampire", "vampire"),
|
||||
Genre("Webtoons", "webtoons"),
|
||||
Genre("Yaoi", "yaoi"),
|
||||
Genre("Yuri", "yuri")
|
||||
Genre("4-koma", "4-koma"),
|
||||
Genre("Action", "action"),
|
||||
Genre("Adult", "adult"),
|
||||
Genre("Adventure", "adventure"),
|
||||
Genre("Comedy", "comedy"),
|
||||
Genre("Demons", "demons"),
|
||||
Genre("Doujinshi", "doujinshi"),
|
||||
Genre("Drama", "drama"),
|
||||
Genre("Ecchi", "ecchi"),
|
||||
Genre("Fantasy", "fantasy"),
|
||||
Genre("Gender Bender", "gender-bender"),
|
||||
Genre("Harem", "harem"),
|
||||
Genre("Historical", "historical"),
|
||||
Genre("Horror", "horror"),
|
||||
Genre("Isekai", "isekai"),
|
||||
Genre("Josei", "josei"),
|
||||
Genre("Kids", "kids"),
|
||||
Genre("Magic", "magic"),
|
||||
Genre("Martial Arts", "martial-arts"),
|
||||
Genre("Mature", "mature"),
|
||||
Genre("Mecha", "mecha"),
|
||||
Genre("Military", "military"),
|
||||
Genre("Music", "music"),
|
||||
Genre("Mystery", "mystery"),
|
||||
Genre("One Shot", "one-shot"),
|
||||
Genre("Parody", "parody"),
|
||||
Genre("Police", "police"),
|
||||
Genre("Psychological", "psychological"),
|
||||
Genre("Romance", "romance"),
|
||||
Genre("School Life", "school-life"),
|
||||
Genre("Sci-Fi", "sci-fi"),
|
||||
Genre("Seinen", "seinen"),
|
||||
Genre("Shoujo Ai", "shoujo-ai"),
|
||||
Genre("Shoujo", "shoujo"),
|
||||
Genre("Shounen Ai", "shounen-ai"),
|
||||
Genre("Shounen", "shounen"),
|
||||
Genre("Slice of Life", "slice-of-life"),
|
||||
Genre("Smut", "smut"),
|
||||
Genre("Space", "space"),
|
||||
Genre("Sports", "sports"),
|
||||
Genre("Super Power", "super-power"),
|
||||
Genre("Supernatural", "supernatural"),
|
||||
Genre("Tragedy", "tragedy"),
|
||||
Genre("Vampire", "vampire"),
|
||||
Genre("Webtoons", "webtoons"),
|
||||
Genre("Yaoi", "yaoi"),
|
||||
Genre("Yuri", "yuri")
|
||||
)
|
||||
|
||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||
fun toUriPart() = vals[state].second
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,13 +12,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup.parse
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class Mangasail : ParsedHttpSource() {
|
||||
|
||||
|
@ -155,7 +155,7 @@ class Mangasail : ParsedHttpSource() {
|
|||
}
|
||||
|
||||
private fun parseChapterDate(string: String): Long {
|
||||
return dateFormat.parse(string.substringAfter("on ")).time
|
||||
return dateFormat.parse(string.substringAfter("on "))?.time ?: 0L
|
||||
}
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
|
|
|
@ -17,14 +17,14 @@ 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 java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Exact same code as Manga Life except for better chapter names thanks to Regex
|
||||
|
@ -92,11 +92,13 @@ class Mangasee : HttpSource() {
|
|||
val endRange = ((page * 24) - 1).let { if (it <= directory.lastIndex) it else directory.lastIndex }
|
||||
|
||||
for (i in (((page - 1) * 24)..endRange)) {
|
||||
mangas.add(SManga.create().apply {
|
||||
title = directory[i]["s"].string
|
||||
url = "/manga/${directory[i]["i"].string}"
|
||||
thumbnail_url = "https://cover.mangabeast01.com/cover/${directory[i]["i"].string}.jpg"
|
||||
})
|
||||
mangas.add(
|
||||
SManga.create().apply {
|
||||
title = directory[i]["s"].string
|
||||
url = "/manga/${directory[i]["i"].string}"
|
||||
thumbnail_url = "https://cover.mangabeast01.com/cover/${directory[i]["i"].string}.jpg"
|
||||
}
|
||||
)
|
||||
}
|
||||
return MangasPage(mangas, endRange < directory.lastIndex)
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
||||
class Mangatown : ParsedHttpSource() {
|
||||
|
||||
|
@ -110,7 +110,7 @@ class Mangatown : ParsedHttpSource() {
|
|||
date.contains("Yesterday") -> Calendar.getInstance().apply { add(Calendar.DAY_OF_MONTH, -1) }.timeInMillis
|
||||
else -> {
|
||||
try {
|
||||
SimpleDateFormat("MMM dd,yyyy", Locale.US).parse(date).time
|
||||
SimpleDateFormat("MMM dd,yyyy", Locale.US).parse(date)?.time ?: 0L
|
||||
} catch (e: Exception) {
|
||||
0L
|
||||
}
|
||||
|
|
|
@ -6,13 +6,13 @@ 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.ParsedHttpSource
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import org.jsoup.select.Elements
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class ManhwaTime : ParsedHttpSource() {
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue