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:
arkon 2020-09-13 18:33:59 -04:00 committed by GitHub
parent 19a3cd2367
commit 016653bdc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
229 changed files with 9702 additions and 8853 deletions

View File

@ -1,6 +1,6 @@
buildscript { buildscript {
ext.kotlin_version = '1.3.72' ext.kotlin_version = '1.4.10'
ext.coroutines_version = '1.3.5' ext.coroutines_version = '1.3.9'
repositories { repositories {
google() google()
maven { url 'https://plugins.gradle.org/m2/' } maven { url 'https://plugins.gradle.org/m2/' }
@ -10,7 +10,7 @@ buildscript {
classpath 'com.android.tools.build:gradle:4.0.1' classpath 'com.android.tools.build:gradle:4.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$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'
} }
} }

View File

@ -1,6 +1,6 @@
object Deps { object Deps {
object kotlin { object kotlin {
const val version = "1.3.72" const val version = "1.4.10"
const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version" const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version"
} }

View File

@ -7,13 +7,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
open class BoomManga( open class BoomManga(
override val name: String, override val name: String,
@ -84,7 +84,7 @@ open class BoomManga(
} }
private fun parseDate(date: String): Long { 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 { override fun mangaDetailsParse(document: Document): SManga {

View File

@ -10,14 +10,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.Headers import okhttp3.Headers
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import rx.Observable import rx.Observable
import java.text.SimpleDateFormat
import java.util.Locale
abstract class ComiCake( abstract class ComiCake(
override val name: String, override val name: String,
@ -146,7 +146,7 @@ abstract class ComiCake(
private fun parseChapterJson(obj: JSONObject) = SChapter.create().apply { private fun parseChapterJson(obj: JSONObject) = SChapter.create().apply {
name = obj.getString("title") // title will always have content, vs. name that's an optional field 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() 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) // TODO scanlator field by adding team to expandable in CC (low priority given the use case of CC)
url = obj.getString("manifest") url = obj.getString("manifest")
} }

View File

@ -4,8 +4,6 @@ import android.annotation.SuppressLint
import android.app.Application import android.app.Application
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri 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.CheckBoxPreference
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.network.GET 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.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.net.URLEncoder
import okhttp3.CacheControl import okhttp3.CacheControl
import okhttp3.CookieJar import okhttp3.CookieJar
import okhttp3.Headers import okhttp3.Headers
@ -34,6 +31,9 @@ import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get 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() { 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) return MangasPage(parsedMangas, hasNextPage)
} }
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.just(listOf(SChapter.create().apply { override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.just(
listOf(
SChapter.create().apply {
url = manga.url url = manga.url
name = "Chapter" name = "Chapter"
chapter_number = 1f chapter_number = 1f
})) }
)
)
override fun fetchPageList(chapter: SChapter) = fetchChapterPage(chapter, "$baseUrl/${chapter.url}").map { override fun fetchPageList(chapter: SChapter) = fetchChapterPage(chapter, "$baseUrl/${chapter.url}").map {
it.mapIndexed { i, s -> it.mapIndexed { i, s ->
@ -218,8 +222,10 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
?.trim() ?.trim()
?.let { right -> ?.let { right ->
ignore { ignore {
when (left.removeSuffix(":") when (
.toLowerCase()) { left.removeSuffix(":")
.toLowerCase()
) {
"posted" -> datePosted = EX_DATE_FORMAT.parse(right)?.time ?: 0 "posted" -> datePosted = EX_DATE_FORMAT.parse(right)?.time ?: 0
"visible" -> visible = right.nullIfBlank() "visible" -> visible = right.nullIfBlank()
"language" -> { "language" -> {
@ -255,8 +261,10 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
select("#taglist tr").forEach { select("#taglist tr").forEach {
val namespace = it.select(".tc").text().removeSuffix(":") val namespace = it.select(".tc").text().removeSuffix(":")
val currentTags = it.select("div").map { element -> val currentTags = it.select("div").map { element ->
Tag(element.text().trim(), Tag(
element.hasClass("gtl")) element.text().trim(),
element.hasClass("gtl")
)
} }
tags[namespace] = currentTags tags[namespace] = currentTags
} }
@ -367,7 +375,9 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
} }
} }
class GenreGroup : UriGroup<GenreOption>("Genres", listOf( class GenreGroup : UriGroup<GenreOption>(
"Genres",
listOf(
GenreOption("Dōjinshi", "doujinshi"), GenreOption("Dōjinshi", "doujinshi"),
GenreOption("Manga", "manga"), GenreOption("Manga", "manga"),
GenreOption("Artist CG", "artistcg"), GenreOption("Artist CG", "artistcg"),
@ -378,7 +388,8 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
GenreOption("Cosplay", "cosplay"), GenreOption("Cosplay", "cosplay"),
GenreOption("Asian Porn", "asianporn"), GenreOption("Asian Porn", "asianporn"),
GenreOption("Misc", "misc") GenreOption("Misc", "misc")
)) )
)
class AdvancedOption(name: String, private val param: String, defValue: Boolean = false) : CheckBox(name, defValue), UriFilter { class AdvancedOption(name: String, private val param: String, defValue: Boolean = false) : CheckBox(name, defValue), UriFilter {
override fun addToUri(builder: Uri.Builder) { override fun addToUri(builder: Uri.Builder) {
@ -423,7 +434,9 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
} }
// Explicit type arg for listOf() to workaround this: KT-16570 // Explicit type arg for listOf() to workaround this: KT-16570
class AdvancedGroup : UriGroup<Filter<*>>("Advanced Options", listOf( class AdvancedGroup : UriGroup<Filter<*>>(
"Advanced Options",
listOf(
AdvancedOption("Search Gallery Name", "f_sname", true), AdvancedOption("Search Gallery Name", "f_sname", true),
AdvancedOption("Search Gallery Tags", "f_stags", true), AdvancedOption("Search Gallery Tags", "f_stags", true),
AdvancedOption("Search Gallery Description", "f_sdesc"), AdvancedOption("Search Gallery Description", "f_sdesc"),
@ -435,7 +448,8 @@ open class EHentai(override val lang: String, private val ehLang: String) : Conf
RatingOption(), RatingOption(),
MinPagesOption(), MinPagesOption(),
MaxPagesOption() MaxPagesOption()
)) )
)
private class EnforceLanguageFilter(default: Boolean) : CheckBox("Enforce language", default) private class EnforceLanguageFilter(default: Boolean) : CheckBox("Enforce language", default)

View File

@ -39,7 +39,8 @@ fun ExGalleryMetadata.copyTo(manga: SManga) {
title?.let { t -> title?.let { t ->
if (ONGOING_SUFFIX.any { if (ONGOING_SUFFIX.any {
t.endsWith(it, ignoreCase = true) t.endsWith(it, ignoreCase = true)
}) manga.status = SManga.ONGOING }
) manga.status = SManga.ONGOING
} }
// Build a nice looking description out of what we know // Build a nice looking description out of what we know

View File

@ -37,14 +37,17 @@ open class EliMangasProvider(
override fun popularMangaParse(response: Response): MangasPage { override fun popularMangaParse(response: Response): MangasPage {
val json = gson.fromJson<JsonArray>(response.body()!!.string()).asJsonArray val json = gson.fromJson<JsonArray>(response.body()!!.string()).asJsonArray
return MangasPage(json.map { return MangasPage(
json.map {
SManga.create().apply { SManga.create().apply {
val id = it["id"].asString val id = it["id"].asString
url = id url = id
title = it["name"].asString title = it["name"].asString
thumbnail_url = "https://www.elimangas.com/images/$id.jpg" thumbnail_url = "https://www.elimangas.com/images/$id.jpg"
} }
}, json.size() >= 30) },
json.size() >= 30
)
} }
// Latest // Latest

View File

@ -7,14 +7,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.util.Calendar
import java.util.concurrent.TimeUnit
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.json.JSONObject import org.json.JSONObject
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.Calendar
import java.util.concurrent.TimeUnit
open class Emerald( open class Emerald(
override val name: String, override val name: String,
@ -76,8 +76,11 @@ open class Emerald(
} }
} }
if (styleToInclude.isNotEmpty()) { if (styleToInclude.isNotEmpty()) {
url.addQueryParameter("styles", styleToInclude url.addQueryParameter(
.joinToString(",")) "styles",
styleToInclude
.joinToString(",")
)
} }
} }
is DemographicFilter -> { is DemographicFilter -> {
@ -88,8 +91,11 @@ open class Emerald(
} }
} }
if (demographicToInclude.isNotEmpty()) { if (demographicToInclude.isNotEmpty()) {
url.addQueryParameter("demogs", demographicToInclude url.addQueryParameter(
.joinToString(",")) "demogs",
demographicToInclude
.joinToString(",")
)
} }
} }
is StatusFilter -> { is StatusFilter -> {
@ -110,8 +116,11 @@ open class Emerald(
} }
} }
if (genreToInclude.isNotEmpty()) { if (genreToInclude.isNotEmpty()) {
url.addQueryParameter("genres", genreToInclude url.addQueryParameter(
.joinToString(",")) "genres",
genreToInclude
.joinToString(",")
)
} }
} }
is StarFilter -> { is StarFilter -> {
@ -154,8 +163,10 @@ open class Emerald(
val manga = SManga.create() val manga = SManga.create()
val genres = mutableListOf<String>() val genres = mutableListOf<String>()
val status = infoElement.select("div.attr-item:contains(status) span").text() val status = infoElement.select("div.attr-item:contains(status) span").text()
infoElement.select("div.attr-item:contains(genres) span").text().split(" / " infoElement.select("div.attr-item:contains(genres) span").text().split(
.toRegex()).forEach { element -> " / "
.toRegex()
).forEach { element ->
genres.add(element) genres.add(element)
} }
manga.title = infoElement.select("h3").text() manga.title = infoElement.select("h3").text()
@ -259,11 +270,13 @@ open class Emerald(
val imgJson = JSONObject(script) val imgJson = JSONObject(script)
val imgNames = imgJson.names() val imgNames = imgJson.names()
if (imgNames != null) {
for (i in 0 until imgNames.length()) { for (i in 0 until imgNames.length()) {
val imgKey = imgNames.getString(i) val imgKey = imgNames.getString(i)
val imgUrl = imgJson.getString(imgKey) val imgUrl = imgJson.getString(imgKey)
pages.add(Page(i, "", imgUrl)) pages.add(Page(i, "", imgUrl))
} }
}
return pages return pages
} }
@ -276,16 +289,21 @@ open class Emerald(
private class GenreFilter(genres: List<Tag>) : Filter.Group<Tag>("Genres", genres) private class GenreFilter(genres: List<Tag>) : Filter.Group<Tag>("Genres", genres)
private class StatusFilter : Filter.TriState("Completed") private class StatusFilter : Filter.TriState("Completed")
private class StarFilter : UriPartFilter("Stars", arrayOf( private class StarFilter : UriPartFilter(
"Stars",
arrayOf(
Pair("<select>", ""), Pair("<select>", ""),
Pair("5 Stars", "5"), Pair("5 Stars", "5"),
Pair("4 Stars", "4"), Pair("4 Stars", "4"),
Pair("3 Stars", "3"), Pair("3 Stars", "3"),
Pair("2 Stars", "2"), Pair("2 Stars", "2"),
Pair("1 Stars", "1") Pair("1 Stars", "1")
)) )
)
private class ChapterFilter : UriPartFilter("Chapters", arrayOf( private class ChapterFilter : UriPartFilter(
"Chapters",
arrayOf(
Pair("<select>", ""), Pair("<select>", ""),
Pair("1 ~ 9", "1-9"), Pair("1 ~ 9", "1-9"),
Pair("10 ~ 29", "10-29"), Pair("10 ~ 29", "10-29"),
@ -296,9 +314,12 @@ open class Emerald(
Pair("50+", "50"), Pair("50+", "50"),
Pair("10+", "10"), Pair("10+", "10"),
Pair("1+", "1") Pair("1+", "1")
)) )
)
private class SortBy : UriPartFilter("Sorts By", arrayOf( private class SortBy : UriPartFilter(
"Sorts By",
arrayOf(
Pair("<select>", ""), Pair("<select>", ""),
Pair("Totally", "views_t"), Pair("Totally", "views_t"),
Pair("365 days", "views_y"), Pair("365 days", "views_y"),
@ -309,7 +330,8 @@ open class Emerald(
Pair("A-Z", "title"), Pair("A-Z", "title"),
Pair("Update time", "update"), Pair("Update time", "update"),
Pair("Add time", "create") Pair("Add time", "create")
)) )
)
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
Filter.Header("NOTE: Ignored if using text search!"), Filter.Header("NOTE: Ignored if using text search!"),

View File

@ -10,8 +10,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.nio.charset.Charset
import java.util.Calendar
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -20,6 +18,8 @@ import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import org.jsoup.select.Elements import org.jsoup.select.Elements
import java.nio.charset.Charset
import java.util.Calendar
/** /**
* For sites based on the Flat-Manga CMS * For sites based on the Flat-Manga CMS
@ -81,11 +81,14 @@ abstract class FMReader(
url.addQueryParameter("ungenre", ungenre) url.addQueryParameter("ungenre", ungenre)
} }
is SortBy -> { is SortBy -> {
url.addQueryParameter("sort", when (filter.state?.index) { url.addQueryParameter(
"sort",
when (filter.state?.index) {
0 -> "name" 0 -> "name"
1 -> "views" 1 -> "views"
else -> "last_update" else -> "last_update"
}) }
)
if (filter.state?.ascending == true) if (filter.state?.ascending == true)
url.addQueryParameter("sort_type", "ASC") url.addQueryParameter("sort_type", "ASC")
} }

View File

@ -11,7 +11,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.net.URLEncoder
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -20,6 +19,7 @@ import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.net.URLEncoder
class FMReaderFactory : SourceFactory { class FMReaderFactory : SourceFactory {
override fun createSources(): List<Source> = listOf( 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> { override fun chapterListParse(response: Response): List<SChapter> {
return response.asJsoup().let { document -> return response.asJsoup().let { document ->
document.select(chapterListSelector()).map { chapterFromElement(it).apply { document.select(chapterListSelector()).map {
chapterFromElement(it).apply {
scanlator = document.select("div.row li:has(b:contains(Nhóm dịch)) small").text() 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() } override fun pageListParse(document: Document): List<Page> = super.pageListParse(document).onEach { it.imageUrl!!.trim() }

View File

@ -10,17 +10,17 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.HashSet import java.util.HashSet
import java.util.Locale 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( abstract class FoolSlide(
override val name: String, override val name: String,
@ -138,9 +138,12 @@ abstract class FoolSlide(
private fun allowAdult(request: Request) = allowAdult(request.url().toString()) private fun allowAdult(request: Request) = allowAdult(request.url().toString())
private fun allowAdult(url: String): Request { private fun allowAdult(url: String): Request {
return POST(url, body = FormBody.Builder() return POST(
url,
body = FormBody.Builder()
.add("adult", "true") .add("adult", "true")
.build()) .build()
)
} }
override fun chapterListRequest(manga: SManga) = allowAdult(super.chapterListRequest(manga)) override fun chapterListRequest(manga: SManga) = allowAdult(super.chapterListRequest(manga))
@ -216,7 +219,7 @@ abstract class FoolSlide(
if (result != null) { if (result != null) {
// Result parsed but no year, copy current year over // Result parsed but no year, copy current year over
result = Calendar.getInstance().apply { result = Calendar.getInstance().apply {
time = result time = result!!
set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR)) set(Calendar.YEAR, Calendar.getInstance().get(Calendar.YEAR))
}.time }.time
} }

View File

@ -9,12 +9,12 @@ import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.net.URLEncoder
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.net.URLEncoder
@Nsfw @Nsfw
class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga") { 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() response.close()
// Better error message for invalid artist // Better error message for invalid artist
if (response.code() == 404 && if (response.code() == 404 &&
!filters.findInstance<ArtistFilter>()?.state.isNullOrBlank()) !filters.findInstance<ArtistFilter>()?.state.isNullOrBlank()
)
error("Invalid artist!") error("Invalid artist!")
else throw Exception("HTTP error ${response.code()}") else throw Exception("HTTP error ${response.code()}")
} }
@ -145,7 +146,9 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
class ArtistFilter : Filter.Text("Artist (must be exact match)") class ArtistFilter : Filter.Text("Artist (must be exact match)")
class BookFilter : Filter.CheckBox("Show books only", false) class BookFilter : Filter.CheckBox("Show books only", false)
class TagFilter : Filter.Select<Tag>("Tag", arrayOf( class TagFilter : Filter.Select<Tag>(
"Tag",
arrayOf(
Tag("", "<select>"), Tag("", "<select>"),
Tag("ahegao", "Ahegao"), Tag("ahegao", "Ahegao"),
Tag("anal", "Anal"), Tag("anal", "Anal"),
@ -330,7 +333,8 @@ class HentaiCafe : FoolSlide("Hentai Cafe", "https://hentai.cafe", "en", "/manga
Tag("yandere", "Yandere"), Tag("yandere", "Yandere"),
Tag("yukata", "Yukata"), Tag("yukata", "Yukata"),
Tag("yuri", "Yuri") Tag("yuri", "Yuri")
)) )
)
class Tag(val name: String, private val displayName: String) { class Tag(val name: String, private val displayName: String) {
override fun toString() = displayName override fun toString() = displayName

View File

@ -8,15 +8,15 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import org.jsoup.select.Elements import org.jsoup.select.Elements
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
abstract class Genkan( abstract class Genkan(
override val name: String, override val name: String,

View File

@ -4,8 +4,6 @@ import android.app.Application
import android.content.SharedPreferences import android.content.SharedPreferences
import android.support.v7.preference.CheckBoxPreference import android.support.v7.preference.CheckBoxPreference
import android.support.v7.preference.PreferenceScreen 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.array
import com.github.salomonbrys.kotson.get import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.string import com.github.salomonbrys.kotson.string
@ -28,6 +26,8 @@ import rx.Single
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import androidx.preference.CheckBoxPreference as AndroidXCheckBoxPreference
import androidx.preference.PreferenceScreen as AndroidXPreferenceScreen
/** /**
* Ported from TachiyomiSy * Ported from TachiyomiSy

View File

@ -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.GET
import eu.kanade.tachiyomi.network.asObservable import eu.kanade.tachiyomi.network.asObservable
import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.network.asObservableSuccess
import java.security.MessageDigest
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import rx.Observable import rx.Observable
import rx.Single import rx.Single
import java.security.MessageDigest
private typealias HashedTerm = ByteArray private typealias HashedTerm = ByteArray

View File

@ -24,9 +24,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import okhttp3.Credentials import okhttp3.Credentials
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
@ -38,6 +35,9 @@ import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get 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() { open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
override fun popularMangaRequest(page: Int): Request = override fun popularMangaRequest(page: Int): Request =
@ -215,8 +215,10 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
else -> SManga.UNKNOWN else -> SManga.UNKNOWN
} }
// TODO: remove safe calls in next iteration // TODO: remove safe calls in next iteration
genre = (metadata.genres?.plus(metadata.tags ?: emptySet()) genre = (
?: emptySet()).joinToString(", ") metadata.genres?.plus(metadata.tags ?: emptySet())
?: emptySet()
).joinToString(", ")
description = metadata.summary description = metadata.summary
} }
@ -225,10 +227,10 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
Date().time Date().time
else { else {
try { 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) { } catch (ex: Exception) {
try { 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) { } catch (ex: Exception) {
Date().time Date().time
} }
@ -370,65 +372,80 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ response -> .subscribe(
{ response ->
libraries = try { libraries = try {
gson.fromJson(response.body()?.charStream()!!) gson.fromJson(response.body()?.charStream()!!)
} catch (e: Exception) { } catch (e: Exception) {
emptyList() emptyList()
} }
}, {}) },
{}
)
Single.fromCallable { Single.fromCallable {
client.newCall(GET("$baseUrl/api/v1/collections?unpaged=true", headers)).execute() client.newCall(GET("$baseUrl/api/v1/collections?unpaged=true", headers)).execute()
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ response -> .subscribe(
{ response ->
collections = try { collections = try {
gson.fromJson<PageWrapperDto<CollectionDto>>(response.body()?.charStream()!!).content gson.fromJson<PageWrapperDto<CollectionDto>>(response.body()?.charStream()!!).content
} catch (e: Exception) { } catch (e: Exception) {
emptyList() emptyList()
} }
}, {}) },
{}
)
Single.fromCallable { Single.fromCallable {
client.newCall(GET("$baseUrl/api/v1/genres", headers)).execute() client.newCall(GET("$baseUrl/api/v1/genres", headers)).execute()
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ response -> .subscribe(
{ response ->
genres = try { genres = try {
gson.fromJson(response.body()?.charStream()!!) gson.fromJson(response.body()?.charStream()!!)
} catch (e: Exception) { } catch (e: Exception) {
emptySet() emptySet()
} }
}, {}) },
{}
)
Single.fromCallable { Single.fromCallable {
client.newCall(GET("$baseUrl/api/v1/tags", headers)).execute() client.newCall(GET("$baseUrl/api/v1/tags", headers)).execute()
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ response -> .subscribe(
{ response ->
tags = try { tags = try {
gson.fromJson(response.body()?.charStream()!!) gson.fromJson(response.body()?.charStream()!!)
} catch (e: Exception) { } catch (e: Exception) {
emptySet() emptySet()
} }
}, {}) },
{}
)
Single.fromCallable { Single.fromCallable {
client.newCall(GET("$baseUrl/api/v1/publishers", headers)).execute() client.newCall(GET("$baseUrl/api/v1/publishers", headers)).execute()
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe({ response -> .subscribe(
{ response ->
publishers = try { publishers = try {
gson.fromJson(response.body()?.charStream()!!) gson.fromJson(response.body()?.charStream()!!)
} catch (e: Exception) { } catch (e: Exception) {
emptySet() emptySet()
} }
}, {}) },
{}
)
} }
companion object { companion object {

View File

@ -59,7 +59,8 @@ open class LANraragi : ConfigurableSource, HttpSource() {
url = "${uriBuild.encodedPath}?${uriBuild.encodedQuery}" url = "${uriBuild.encodedPath}?${uriBuild.encodedQuery}"
chapter_number = 1F chapter_number = 1F
name = "Chapter" name = "Chapter"
}) }
)
} }
override fun pageListParse(response: Response): List<Page> { override fun pageListParse(response: Response): List<Page> {
@ -118,7 +119,9 @@ open class LANraragi : ConfigurableSource, HttpSource() {
artist = getArtist(it.tags) artist = getArtist(it.tags)
author = artist author = artist
} }
}, currentStart + jsonResult.data.size < jsonResult.recordsFiltered) },
currentStart + jsonResult.data.size < jsonResult.recordsFiltered
)
} }
// Preferences // Preferences

View File

@ -11,13 +11,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup 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.CacheControl
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.Headers import okhttp3.Headers
@ -29,6 +22,13 @@ import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable 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( abstract class Madara(
override val name: String, override val name: String,
@ -189,7 +189,9 @@ abstract class Madara(
private class ArtistFilter : Filter.Text("Artist") private class ArtistFilter : Filter.Text("Artist")
private class YearFilter : Filter.Text("Year of Released") private class YearFilter : Filter.Text("Year of Released")
private class StatusFilter(status: List<Tag>) : Filter.Group<Tag>("Status", status) private class StatusFilter(status: List<Tag>) : Filter.Group<Tag>("Status", status)
private class OrderByFilter : UriPartFilter("Order By", arrayOf( private class OrderByFilter : UriPartFilter(
"Order By",
arrayOf(
Pair("<select>", ""), Pair("<select>", ""),
Pair("Latest", "latest"), Pair("Latest", "latest"),
Pair("A-Z", "alphabet"), Pair("A-Z", "alphabet"),
@ -197,11 +199,15 @@ abstract class Madara(
Pair("Trending", "trending"), Pair("Trending", "trending"),
Pair("Most Views", "views"), Pair("Most Views", "views"),
Pair("New", "new-manga") Pair("New", "new-manga")
)) )
private class GenreConditionFilter : UriPartFilter("Genre condition", arrayOf( )
private class GenreConditionFilter : UriPartFilter(
"Genre condition",
arrayOf(
Pair("or", ""), Pair("or", ""),
Pair("and", "1") Pair("and", "1")
)) )
)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres) private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
class Genre(name: String, val id: String = name) : Filter.CheckBox(name) class Genre(name: String, val id: String = name) : Filter.CheckBox(name)
@ -491,9 +497,13 @@ abstract class Madara(
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
return document.select(pageListParseSelector).mapIndexed { index, element -> return document.select(pageListParseSelector).mapIndexed { index, element ->
Page(index, document.location(), element.select("img").first()?.let { Page(
index,
document.location(),
element.select("img").first()?.let {
it.absUrl(if (it.hasAttr("data-src")) "data-src" else "src") it.absUrl(if (it.hasAttr("data-src")) "data-src" else "src")
}) }
)
} }
} }

View File

@ -12,8 +12,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.CacheControl import okhttp3.CacheControl
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.Headers import okhttp3.Headers
@ -23,6 +21,8 @@ import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class MadaraFactory : SourceFactory { class MadaraFactory : SourceFactory {
override fun createSources(): List<Source> = listOf( 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 NinjaScans : Madara("NinjaScans", "https://ninjascans.com", "en")
class ReadManhua : Madara("ReadManhua", "https://readmanhua.net", "en", class ReadManhua : Madara(
dateFormat = SimpleDateFormat("dd MMM yy", Locale.US)) "ReadManhua",
"https://readmanhua.net",
"en",
dateFormat = SimpleDateFormat("dd MMM yy", Locale.US)
)
class IsekaiScanCom : Madara("IsekaiScan.com", "https://isekaiscan.com", "en") class IsekaiScanCom : Madara("IsekaiScan.com", "https://isekaiscan.com", "en")
class JustForFun : Madara("Just For Fun", "https://just-for-fun.ru", "ru", class JustForFun : Madara(
dateFormat = SimpleDateFormat("yy.MM.dd", Locale.US)) "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") { class AoCTranslations : Madara("Agent of Change Translations", "https://aoc.moe", "en") {
override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", baseUrl) 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 LuxyScans : Madara("Luxy Scans", "https://luxyscans.com", "en")
class TsubakiNoScan : Madara("Tsubaki No Scan", "https://tsubakinoscan.com", "fr", class TsubakiNoScan : Madara(
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)) "Tsubaki No Scan",
"https://tsubakinoscan.com",
"fr",
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
)
class YokaiJump : Madara("Yokai Jump", "https://yokaijump.fr", "fr", class YokaiJump : Madara(
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)) "Yokai Jump",
"https://yokaijump.fr",
"fr",
dateFormat = SimpleDateFormat("dd/MM/yy", Locale.US)
)
class ZManga : Madara("ZManga", "https://zmanga.org", "es") 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 MangazukiClubKO : Madara("Mangazuki.club", "https://mangazuki.club", "ko")
class FirstKissManga : Madara("1st Kiss", "https://1stkissmanga.com", "en", class FirstKissManga : Madara(
dateFormat = SimpleDateFormat("dd MMM yyyy", Locale.US)) { "1st Kiss",
"https://1stkissmanga.com",
"en",
dateFormat = SimpleDateFormat("dd MMM yyyy", Locale.US)
) {
override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", baseUrl) 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 BoysLove : Madara("BoysLove", "https://boyslove.me", "en")
class ChibiManga : Madara("Chibi Manga", "http://www.cmreader.info", "en", class ChibiManga : Madara(
dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)) { "Chibi Manga",
"http://www.cmreader.info",
"en",
dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US)
) {
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
response.asJsoup().let { documet -> response.asJsoup().let { documet ->
documet.select("li.parent.has-child").let { volumes -> documet.select("li.parent.has-child").let { volumes ->
@ -562,7 +586,9 @@ class DoujinHentai : Madara("DoujinHentai", "https://doujinhentai.net", "es", Si
GenreSelectFilter() GenreSelectFilter()
) )
class GenreSelectFilter : UriPartFilter("Búsqueda de género", arrayOf( class GenreSelectFilter : UriPartFilter(
"Búsqueda de género",
arrayOf(
Pair("<seleccionar>", ""), Pair("<seleccionar>", ""),
Pair("Ecchi", "ecchi"), Pair("Ecchi", "ecchi"),
Pair("Yaoi", "yaoi"), Pair("Yaoi", "yaoi"),

View File

@ -9,11 +9,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup 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.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -21,6 +16,11 @@ import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element 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 // Based off of Mangakakalot 1.2.8

View File

@ -7,12 +7,12 @@ import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.Headers import okhttp3.Headers
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class MangaBoxFactory : SourceFactory { class MangaBoxFactory : SourceFactory {
override fun createSources(): List<Source> = listOf( override fun createSources(): List<Source> = listOf(

View File

@ -28,10 +28,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup 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.CacheControl
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
@ -45,6 +41,10 @@ import org.jsoup.parser.Parser
import rx.Observable import rx.Observable
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get 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( abstract class MangaDex(
override val lang: String, 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 &hearts; will show ♥ // Remove bbcode tags as well as parses any html characters in description or chapter name to actual characters for example &hearts; will show ♥
private fun cleanString(string: String): String { private fun cleanString(string: String): String {
val bbRegex = """\[(\w+)[^]]*](.*?)\[/\1]""".toRegex() val bbRegex =
"""\[(\w+)[^]]*](.*?)\[/\1]""".toRegex()
var intermediate = string var intermediate = string
.replace("[list]", "") .replace("[list]", "")
.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) private class TagExclusionMode : Filter.Select<String>("Tag exclusion mode", arrayOf("All (and)", "Any (or)"), 1)
// default selection (Rating Descending) matches popularMangaRequest url // default selection (Rating Descending) matches popularMangaRequest url
class SortFilter : Filter.Sort("Sort", class SortFilter : Filter.Sort(
"Sort",
sortables.map { it.first }.toTypedArray(), 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()) 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("Number of comments", 4, 5),
Triple("Rating", 6, 7), Triple("Rating", 6, 7),
Triple("Views", 8, 9), Triple("Views", 8, 9),
Triple("Follows", 10, 11)) Triple("Follows", 10, 11)
)
private val SOURCE_LANG_LIST = listOf( private val SOURCE_LANG_LIST = listOf(
Pair("All", "0"), Pair("All", "0"),
@ -970,7 +974,8 @@ abstract class MangaDex(
Pair("Korean", "28"), Pair("Korean", "28"),
Pair("Spanish (LATAM)", "29"), Pair("Spanish (LATAM)", "29"),
Pair("Thai", "32"), Pair("Thai", "32"),
Pair("Filipino", "34")) Pair("Filipino", "34")
)
private var hasMangaPlus = false private var hasMangaPlus = false
} }

View File

@ -12,14 +12,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.Headers import okhttp3.Headers
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import rx.Observable import rx.Observable
import java.text.SimpleDateFormat
import java.util.Locale
/** /**
* MangAdventure base source. * MangAdventure base source.
@ -88,9 +88,11 @@ abstract class MangAdventure(
when (it) { when (it) {
is Person -> uri.appendQueryParameter("author", it.state) is Person -> uri.appendQueryParameter("author", it.state)
is Status -> uri.appendQueryParameter("status", it.string()) is Status -> uri.appendQueryParameter("status", it.string())
is CategoryList -> cat.addAll(it.state.mapNotNull { c -> is CategoryList -> cat.addAll(
it.state.mapNotNull { c ->
Uri.encode(c.optString()) Uri.encode(c.optString())
}) }
)
else -> Unit else -> Unit
} }
} }
@ -99,7 +101,8 @@ abstract class MangAdventure(
override fun latestUpdatesParse(response: Response) = override fun latestUpdatesParse(response: Response) =
JSONArray(response.asString()).run { JSONArray(response.asString()).run {
MangasPage((0 until length()).map { MangasPage(
(0 until length()).map {
val obj = getJSONObject(it) val obj = getJSONObject(it)
SManga.create().apply { SManga.create().apply {
url = obj.getString("url") url = obj.getString("url")
@ -110,7 +113,9 @@ abstract class MangAdventure(
obj.getJSONObject("latest_chapter").getString("date") obj.getJSONObject("latest_chapter").getString("date")
).toString() ).toString()
} }
}.sortedByDescending(SManga::description), false) }.sortedByDescending(SManga::description),
false
)
} }
override fun chapterListParse(response: Response) = override fun chapterListParse(response: Response) =
@ -143,9 +148,12 @@ abstract class MangAdventure(
override fun searchMangaParse(response: Response) = override fun searchMangaParse(response: Response) =
JSONArray(response.asString()).run { JSONArray(response.asString()).run {
MangasPage((0 until length()).map { MangasPage(
(0 until length()).map {
SManga.create().fromJSON(getJSONObject(it)) SManga.create().fromJSON(getJSONObject(it))
}.sortedBy(SManga::title), false) }.sortedBy(SManga::title),
false
)
} }
override fun getFilterList() = override fun getFilterList() =
@ -226,7 +234,7 @@ abstract class MangAdventure(
* @return The timestamp of the date. * @return The timestamp of the date.
*/ */
fun httpDateToTimestamp(date: String) = 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. * @constructor Creates a [Filter.Group] object with categories.
*/ */
inner class CategoryList : Filter.Group<Category>( inner class CategoryList : Filter.Group<Category>(
"Categories", categories.map(::Category) "Categories",
categories.map(::Category)
) )
/** /**

View File

@ -16,11 +16,13 @@ class MangAdventureActivity : Activity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
intent?.data?.pathSegments?.takeIf { it.size > 1 }?.let { intent?.data?.pathSegments?.takeIf { it.size > 1 }?.let {
try { try {
startActivity(Intent().apply { startActivity(
Intent().apply {
action = "eu.kanade.tachiyomi.SEARCH" action = "eu.kanade.tachiyomi.SEARCH"
putExtra("query", MangAdventure.SLUG_QUERY + it[1]) putExtra("query", MangAdventure.SLUG_QUERY + it[1])
putExtra("filter", packageName) putExtra("filter", packageName)
}) }
)
} catch (ex: ActivityNotFoundException) { } catch (ex: ActivityNotFoundException) {
Log.e("MangAdventureActivity", ex.message, ex) Log.e("MangAdventureActivity", ex.message, ex)
} }
@ -30,6 +32,7 @@ class MangAdventureActivity : Activity() {
} }
private fun logInvalidIntent(intent: Intent) = Log.e( private fun logInvalidIntent(intent: Intent) = Log.e(
"MangAdventureActivity", "Failed to parse URI from intent: $intent" "MangAdventureActivity",
"Failed to parse URI from intent: $intent"
) )
} }

View File

@ -3,10 +3,10 @@ package eu.kanade.tachiyomi.extension.all.mangadventure
import android.net.Uri import android.net.Uri
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import java.text.DecimalFormat
import okhttp3.Response import okhttp3.Response
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import java.text.DecimalFormat
/** Returns the body of a response as a `String`. */ /** Returns the body of a response as a `String`. */
fun Response.asString(): String = body()!!.string() fun Response.asString(): String = body()!!.string()
@ -62,9 +62,9 @@ fun SManga.fromJSON(obj: JSONObject) = apply {
title = obj.getString("title") title = obj.getString("title")
description = obj.getString("description") description = obj.getString("description")
thumbnail_url = obj.getString("cover") thumbnail_url = obj.getString("cover")
author = obj.getJSONArray("authors")?.joinField(0) author = obj.getJSONArray("authors").joinField(0)
artist = obj.getJSONArray("artists")?.joinField(0) artist = obj.getJSONArray("artists").joinField(0)
genre = obj.getJSONArray("categories")?.joinField("name") genre = obj.getJSONArray("categories").joinField("name")
status = if (obj.getBoolean("completed")) status = if (obj.getBoolean("completed"))
SManga.COMPLETED else SManga.ONGOING SManga.COMPLETED else SManga.ONGOING
} }
@ -82,11 +82,14 @@ fun SChapter.fromJSON(obj: JSONObject) = apply {
url = obj.getString("url") url = obj.getString("url")
chapter_number = obj.optString("chapter", "0").toFloat() chapter_number = obj.optString("chapter", "0").toFloat()
date_upload = MangAdventure.httpDateToTimestamp(obj.getString("date")) date_upload = MangAdventure.httpDateToTimestamp(obj.getString("date"))
scanlator = obj.getJSONArray("groups")?.joinField("name", " & ") scanlator = obj.getJSONArray("groups").joinField("name", " & ")
name = obj.optString("full_title", buildString { name = obj.optString(
"full_title",
buildString {
obj.optInt("volume").let { if (it != 0) append("Vol. $it, ") } obj.optInt("volume").let { if (it != 0) append("Vol. $it, ") }
append("Ch. ${chapter_number.format("#.#")}: ") append("Ch. ${chapter_number.format("#.#")}: ")
append(obj.getString("title")) append(obj.getString("title"))
}) }
)
if (obj.getBoolean("final")) name += " [END]" if (obj.getBoolean("final")) name += " [END]"
} }

View File

@ -10,7 +10,9 @@ class MangAdventureFactory : SourceFactory {
/** Arc-Relight source. */ /** Arc-Relight source. */
class ArcRelight : MangAdventure( class ArcRelight : MangAdventure(
"Arc-Relight", "https://arc-relight.com", arrayOf( "Arc-Relight",
"https://arc-relight.com",
arrayOf(
"4-Koma", "4-Koma",
"Chaos;Head", "Chaos;Head",
"Collection", "Collection",

View File

@ -6,13 +6,14 @@ ext {
extName = 'MANGA Plus by SHUEISHA' extName = 'MANGA Plus by SHUEISHA'
pkgNameSuffix = 'all.mangaplus' pkgNameSuffix = 'all.mangaplus'
extClass = '.MangaPlusFactory' extClass = '.MangaPlusFactory'
extVersionCode = 11 extVersionCode = 12
libVersion = '1.2' libVersion = '1.2'
} }
dependencies { dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-protobuf:0.20.0' final serialization_version = '1.0.0-RC'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0' implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:$serialization_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$serialization_version"
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -6,9 +6,6 @@ import android.os.Build
import android.support.v7.preference.CheckBoxPreference import android.support.v7.preference.CheckBoxPreference
import android.support.v7.preference.ListPreference import android.support.v7.preference.ListPreference
import android.support.v7.preference.PreferenceScreen 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.google.gson.Gson
import com.squareup.duktape.Duktape import com.squareup.duktape.Duktape
import eu.kanade.tachiyomi.network.GET 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.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import java.util.UUID
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoBuf
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
@ -33,6 +29,10 @@ import okhttp3.ResponseBody
import rx.Observable import rx.Observable
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get 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( abstract class MangaPlus(
override val lang: String, override val lang: String,
@ -428,7 +428,7 @@ abstract class MangaPlus(
private fun Response.asProto(): MangaPlusResponse { private fun Response.asProto(): MangaPlusResponse {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) 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 // 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, // 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 messageBytes = "var BYTE_ARR = new Uint8Array([${bytes.joinToString()}]);"
val res = Duktape.create().use { val res = Duktape.create().use {
it.set("helper", DuktapeHelper::class.java, object : DuktapeHelper { it.set(
"helper",
DuktapeHelper::class.java,
object : DuktapeHelper {
override fun getProtobuf(): String = protobufJs override fun getProtobuf(): String = protobufJs
}) }
)
it.evaluate(messageBytes + DECODE_SCRIPT) as String it.evaluate(messageBytes + DECODE_SCRIPT) as String
} }

View File

@ -3,128 +3,129 @@ package eu.kanade.tachiyomi.extension.all.mangaplus
import com.google.gson.annotations.SerializedName import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Serializer import kotlinx.serialization.Serializer
import kotlinx.serialization.protobuf.ProtoId import kotlinx.serialization.protobuf.ProtoNumber
@Serializer(forClass = MangaPlusResponse::class) @Serializer(forClass = MangaPlusResponse::class)
object MangaPlusSerializer object MangaPlusSerializer
@Serializable @Serializable
data class MangaPlusResponse( data class MangaPlusResponse(
@ProtoId(1) val success: SuccessResult? = null, @ProtoNumber(1) val success: SuccessResult? = null,
@ProtoId(2) val error: ErrorResult? = null @ProtoNumber(2) val error: ErrorResult? = null
) )
@Serializable @Serializable
data class ErrorResult( data class ErrorResult(
@ProtoId(1) val action: Action, @ProtoNumber(1) val action: Action,
@ProtoId(2) val englishPopup: Popup, @ProtoNumber(2) val englishPopup: Popup,
@ProtoId(3) val spanishPopup: Popup @ProtoNumber(3) val spanishPopup: Popup
) )
enum class Action { DEFAULT, UNAUTHORIZED, MAINTAINENCE, GEOIP_BLOCKING } enum class Action { DEFAULT, UNAUTHORIZED, MAINTAINENCE, GEOIP_BLOCKING }
@Serializable @Serializable
data class Popup( data class Popup(
@ProtoId(1) val subject: String, @ProtoNumber(1) val subject: String,
@ProtoId(2) val body: String @ProtoNumber(2) val body: String
) )
@Serializable @Serializable
data class SuccessResult( data class SuccessResult(
@ProtoId(1) val isFeaturedUpdated: Boolean? = false, @ProtoNumber(1) val isFeaturedUpdated: Boolean? = false,
@ProtoId(5) val allTitlesView: AllTitlesView? = null, @ProtoNumber(5) val allTitlesView: AllTitlesView? = null,
@ProtoId(6) val titleRankingView: TitleRankingView? = null, @ProtoNumber(6) val titleRankingView: TitleRankingView? = null,
@ProtoId(8) val titleDetailView: TitleDetailView? = null, @ProtoNumber(8) val titleDetailView: TitleDetailView? = null,
@ProtoId(10) val mangaViewer: MangaViewer? = null, @ProtoNumber(10) val mangaViewer: MangaViewer? = null,
@ProtoId(11) val webHomeView: WebHomeView? = null @ProtoNumber(11) val webHomeView: WebHomeView? = null
) )
@Serializable @Serializable
data class TitleRankingView(@ProtoId(1) val titles: List<Title> = emptyList()) data class TitleRankingView(@ProtoNumber(1) val titles: List<Title> = emptyList())
@Serializable @Serializable
data class AllTitlesView(@ProtoId(1) val titles: List<Title> = emptyList()) data class AllTitlesView(@ProtoNumber(1) val titles: List<Title> = emptyList())
@Serializable @Serializable
data class WebHomeView(@ProtoId(2) val groups: List<UpdatedTitleGroup> = emptyList()) data class WebHomeView(@ProtoNumber(2) val groups: List<UpdatedTitleGroup> = emptyList())
@Serializable @Serializable
data class TitleDetailView( data class TitleDetailView(
@ProtoId(1) val title: Title, @ProtoNumber(1) val title: Title,
@ProtoId(2) val titleImageUrl: String, @ProtoNumber(2) val titleImageUrl: String,
@ProtoId(3) val overview: String, @ProtoNumber(3) val overview: String,
@ProtoId(4) val backgroundImageUrl: String, @ProtoNumber(4) val backgroundImageUrl: String,
@ProtoId(5) val nextTimeStamp: Int = 0, @ProtoNumber(5) val nextTimeStamp: Int = 0,
@ProtoId(6) val updateTiming: UpdateTiming? = UpdateTiming.DAY, @ProtoNumber(6) val updateTiming: UpdateTiming? = UpdateTiming.DAY,
@ProtoId(7) val viewingPeriodDescription: String = "", @ProtoNumber(7) val viewingPeriodDescription: String = "",
@ProtoId(8) val nonAppearanceInfo: String = "", @ProtoNumber(8) val nonAppearanceInfo: String = "",
@ProtoId(9) val firstChapterList: List<Chapter> = emptyList(), @ProtoNumber(9) val firstChapterList: List<Chapter> = emptyList(),
@ProtoId(10) val lastChapterList: List<Chapter> = emptyList(), @ProtoNumber(10) val lastChapterList: List<Chapter> = emptyList(),
@ProtoId(14) val isSimulReleased: Boolean = true, @ProtoNumber(14) val isSimulReleased: Boolean = true,
@ProtoId(17) val chaptersDescending: Boolean = true @ProtoNumber(17) val chaptersDescending: Boolean = true
) )
enum class UpdateTiming { NOT_REGULARLY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY, DAY } enum class UpdateTiming { NOT_REGULARLY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY, DAY }
@Serializable @Serializable
data class MangaViewer(@ProtoId(1) val pages: List<MangaPlusPage> = emptyList()) data class MangaViewer(@ProtoNumber(1) val pages: List<MangaPlusPage> = emptyList())
@Serializable @Serializable
data class Title( data class Title(
@ProtoId(1) val titleId: Int, @ProtoNumber(1) val titleId: Int,
@ProtoId(2) val name: String, @ProtoNumber(2) val name: String,
@ProtoId(3) val author: String, @ProtoNumber(3) val author: String,
@ProtoId(4) val portraitImageUrl: String, @ProtoNumber(4) val portraitImageUrl: String,
@ProtoId(5) val landscapeImageUrl: String, @ProtoNumber(5) val landscapeImageUrl: String,
@ProtoId(6) val viewCount: Int = 0, @ProtoNumber(6) val viewCount: Int = 0,
@ProtoId(7) val language: Language? = Language.ENGLISH @ProtoNumber(7) val language: Language? = Language.ENGLISH
) )
@Serializable @Serializable
enum class Language(val id: Int) { enum class Language(val id: Int) {
@ProtoId(0) @ProtoNumber(0)
@SerializedName("0") @SerializedName("0")
ENGLISH(0), ENGLISH(0),
@ProtoId(1) @ProtoNumber(1)
@SerializedName("1") @SerializedName("1")
SPANISH(1) SPANISH(1)
} }
@Serializable @Serializable
data class UpdatedTitleGroup( data class UpdatedTitleGroup(
@ProtoId(1) val groupName: String, @ProtoNumber(1) val groupName: String,
@ProtoId(2) val titles: List<UpdatedTitle> = emptyList() @ProtoNumber(2) val titles: List<UpdatedTitle> = emptyList()
) )
@Serializable @Serializable
data class UpdatedTitle( data class UpdatedTitle(
@ProtoId(1) val title: Title? = null @ProtoNumber(1) val title: Title? = null
) )
@Serializable @Serializable
data class Chapter( data class Chapter(
@ProtoId(1) val titleId: Int, @ProtoNumber(1) val titleId: Int,
@ProtoId(2) val chapterId: Int, @ProtoNumber(2) val chapterId: Int,
@ProtoId(3) val name: String, @ProtoNumber(3) val name: String,
@ProtoId(4) val subTitle: String? = null, @ProtoNumber(4) val subTitle: String? = null,
@ProtoId(6) val startTimeStamp: Int, @ProtoNumber(6) val startTimeStamp: Int,
@ProtoId(7) val endTimeStamp: Int @ProtoNumber(7) val endTimeStamp: Int
) )
@Serializable @Serializable
data class MangaPlusPage(@ProtoId(1) val page: MangaPage? = null) data class MangaPlusPage(@ProtoNumber(1) val page: MangaPage? = null)
@Serializable @Serializable
data class MangaPage( data class MangaPage(
@ProtoId(1) val imageUrl: String, @ProtoNumber(1) val imageUrl: String,
@ProtoId(2) val width: Int, @ProtoNumber(2) val width: Int,
@ProtoId(3) val height: Int, @ProtoNumber(3) val height: Int,
@ProtoId(5) val encryptionKey: String? = null @ProtoNumber(5) val encryptionKey: String? = null
) )
// Used for the deserialization on KitKat devices. // Used for the deserialization on KitKat devices.
const val DECODE_SCRIPT: String = """ const val DECODE_SCRIPT: String =
"""
Duktape.modSearch = function(id) { Duktape.modSearch = function(id) {
if (id == "protobufjs") if (id == "protobufjs")
return helper.getProtobuf(); return helper.getProtobuf();

View File

@ -7,13 +7,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
open class MangaToon( open class MangaToon(
override val lang: String, override val lang: String,
@ -82,7 +82,7 @@ open class MangaToon(
} }
private fun parseDate(date: String): Long { 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 { override fun mangaDetailsParse(document: Document): SManga {

View File

@ -14,11 +14,11 @@ class MangaToonFactory : SourceFactory {
TH() TH()
) )
class ZH : MangaToon("zh", "cn") class ZH : MangaToon("zh", "cn")
class EN : MangaToon("en", "en") class EN : MangaToon("en", "en")
class ID : MangaToon("id", "id") class ID : MangaToon("id", "id")
class VI : MangaToon("vi", "vi") class VI : MangaToon("vi", "vi")
class ES : MangaToon("es", "es") class ES : MangaToon("es", "es")
class PT : MangaToon("pt", "pt") class PT : MangaToon("pt", "pt")
class TH : MangaToon("th", "th") class TH : MangaToon("th", "th")
} }

View File

@ -4,6 +4,10 @@ import android.annotation.SuppressLint
import android.annotation.TargetApi import android.annotation.TargetApi
import android.os.Build import android.os.Build
import com.google.gson.Gson 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.File
import java.io.PrintWriter import java.io.PrintWriter
import java.security.cert.CertificateException import java.security.cert.CertificateException
@ -13,10 +17,6 @@ import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager 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. * This class generates the sources for MMRCMS.
@ -195,7 +195,8 @@ class Generator {
@Throws(Exception::class) @Throws(Exception::class)
private fun getOkHttpClient(): OkHttpClient { private fun getOkHttpClient(): OkHttpClient {
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager { val trustAllCerts = arrayOf<TrustManager>(
object : X509TrustManager {
@SuppressLint("TrustAllX509TrustManager") @SuppressLint("TrustAllX509TrustManager")
@Throws(CertificateException::class) @Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) { override fun checkClientTrusted(chain: Array<java.security.cert.X509Certificate>, authType: String) {
@ -209,7 +210,8 @@ class Generator {
override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> { override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> {
return arrayOf() return arrayOf()
} }
}) }
)
// Install the all-trusting trust manager // Install the all-trusting trust manager
@ -272,7 +274,8 @@ class Generator {
SourceData("fr", "Op-VF", "https://www.op-vf.com"), SourceData("fr", "Op-VF", "https://www.op-vf.com"),
SourceData("fr", "FR Scan", "https://www.frscan.me"), SourceData("fr", "FR Scan", "https://www.frscan.me"),
// NOTE: THIS SOURCE CONTAINS A CUSTOM LANGUAGE SYSTEM (which will be ignored)! // NOTE: THIS SOURCE CONTAINS A CUSTOM LANGUAGE SYSTEM (which will be ignored)!
SourceData("other", "HentaiShark", "https://www.hentaishark.com", true)) SourceData("other", "HentaiShark", "https://www.hentaishark.com", true)
)
// Changed CMS // Changed CMS
// SourceData("en", "MangaTreat Scans", "http://www.mangatreat.com"), // SourceData("en", "MangaTreat Scans", "http://www.mangatreat.com"),
// SourceData("en", "Chibi Manga Reader", "https://www.cmreader.info"), // SourceData("en", "Chibi Manga Reader", "https://www.cmreader.info"),

View File

@ -18,16 +18,16 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup 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.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable 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( open class MyMangaReaderCMSSource(
final override val lang: String, final override val lang: String,
@ -114,7 +114,8 @@ open class MyMangaReaderCMSSource(
val jsonArray = jsonParser.parse(response.body()!!.string()).let { val jsonArray = jsonParser.parse(response.body()!!.string()).let {
if (name == "Mangas.pw") it.array else it["suggestions"].array if (name == "Mangas.pw") it.array else it["suggestions"].array
} }
MangasPage(jsonArray MangasPage(
jsonArray
.map { .map {
SManga.create().apply { SManga.create().apply {
val segment = it["data"].string val segment = it["data"].string
@ -124,7 +125,9 @@ open class MyMangaReaderCMSSource(
// Guess thumbnails // Guess thumbnails
// thumbnail_url = "$baseUrl/uploads/manga/$segment/cover/cover_250x350.jpg" // thumbnail_url = "$baseUrl/uploads/manga/$segment/cover/cover_250x350.jpg"
} }
}, false) },
false
)
} else { } else {
internalMangaParse(response) internalMangaParse(response)
} }
@ -184,7 +187,8 @@ open class MyMangaReaderCMSSource(
"Utsukushii" -> "div.content div.col-sm-6" "Utsukushii" -> "div.content div.col-sm-6"
else -> "div[class^=col-sm], div.col-xs-6" else -> "div[class^=col-sm], div.col-xs-6"
} }
return MangasPage(document.select(internalMangaSelector).map { return MangasPage(
document.select(internalMangaSelector).map {
SManga.create().apply { SManga.create().apply {
val urlElement = it.getElementsByClass("chart-title") val urlElement = it.getElementsByClass("chart-title")
if (urlElement.size == 0) { if (urlElement.size == 0) {
@ -204,7 +208,9 @@ open class MyMangaReaderCMSSource(
} }
} }
} }
}, document.select(".pagination a[rel=next]").isNotEmpty()) },
document.select(".pagination a[rel=next]").isNotEmpty()
)
} }
// Guess thumbnails on broken websites // Guess thumbnails on broken websites
@ -382,15 +388,19 @@ open class MyMangaReaderCMSSource(
Filter.Header("NOTE: Ignored if using text search!"), Filter.Header("NOTE: Ignored if using text search!"),
Filter.Separator(), Filter.Separator(),
AuthorFilter(), AuthorFilter(),
UriSelectFilter("Category", UriSelectFilter(
"Category",
"cat", "cat",
arrayOf("" to "Any", arrayOf(
"" to "Any",
*categoryMappings.toTypedArray() *categoryMappings.toTypedArray()
) )
), ),
UriSelectFilter("Begins with", UriSelectFilter(
"Begins with",
"alpha", "alpha",
arrayOf("" to "Any", arrayOf(
"" to "Any",
*"#ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray().map { *"#ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray().map {
Pair(it.toString(), it.toString()) Pair(it.toString(), it.toString())
}.toTypedArray() }.toTypedArray()
@ -406,11 +416,16 @@ open class MyMangaReaderCMSSource(
return when { return when {
name == "Mangas.pw" -> FilterList() name == "Mangas.pw" -> FilterList()
tagMappings != null -> { tagMappings != null -> {
FilterList(getInitialFilterList() + UriSelectFilter("Tag", FilterList(
getInitialFilterList() + UriSelectFilter(
"Tag",
"tag", "tag",
arrayOf("" to "Any", arrayOf(
"" to "Any",
*tagMappings.toTypedArray() *tagMappings.toTypedArray()
))) )
)
)
} }
else -> FilterList(getInitialFilterList()) else -> FilterList(getInitialFilterList())
} }
@ -442,9 +457,13 @@ open class MyMangaReaderCMSSource(
} }
} }
class SortFilter : Filter.Sort("Sort", class SortFilter :
Filter.Sort(
"Sort",
sortables.map { it.second }.toTypedArray(), sortables.map { it.second }.toTypedArray(),
Selection(0, true)), UriFilter { Selection(0, true)
),
UriFilter {
override fun addToUri(uri: Uri.Builder) { override fun addToUri(uri: Uri.Builder) {
uri.appendQueryParameter("sortBy", sortables[state!!.index].first) uri.appendQueryParameter("sortBy", sortables[state!!.index].first)
uri.appendQueryParameter("asc", state!!.ascending.toString()) uri.appendQueryParameter("asc", state!!.ascending.toString())

View File

@ -13,9 +13,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import okhttp3.CacheControl import okhttp3.CacheControl
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -24,6 +21,9 @@ import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable 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() { 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) { if (needCover) {
thumbnail_url = getThumbnail(getImage(client.newCall(GET("$baseUrl/search/?search=${document.location()}", headers)) thumbnail_url = getThumbnail(
.execute().asJsoup().select("div.wdm_results div.p_content img").first())) getImage(
client.newCall(GET("$baseUrl/search/?search=${document.location()}", headers))
.execute().asJsoup().select("div.wdm_results div.p_content img").first()
)
)
} }
} }
} }

View File

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.extension.all.nhentai package eu.kanade.tachiyomi.extension.all.nhentai
import java.text.SimpleDateFormat
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
object NHUtils { object NHUtils {
fun getArtists(document: Document): String { fun getArtists(document: Document): String {
@ -57,7 +57,7 @@ object NHUtils {
fun getTime(document: Document): Long { fun getTime(document: Document): Long {
val timeString = document.toString().substringAfter("datetime=\"").substringBefore("\">").replace("T", " ") 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() private fun Element.cleanTag(): String = text().replace(Regex("\\(.*\\)"), "").trim()

View File

@ -251,12 +251,14 @@ open class NHentai(
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
val document = response.asJsoup() val document = response.asJsoup()
return listOf(SChapter.create().apply { return listOf(
SChapter.create().apply {
name = "Chapter" name = "Chapter"
scanlator = getGroups(document) scanlator = getGroups(document)
date_upload = getTime(document) date_upload = getTime(document)
setUrlWithoutDomain(response.request().url().encodedPath()) setUrlWithoutDomain(response.request().url().encodedPath())
}) }
)
} }
override fun chapterFromElement(element: Element) = throw UnsupportedOperationException("Not used") override fun chapterFromElement(element: Element) = throw UnsupportedOperationException("Not used")

View File

@ -18,13 +18,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.util.Date
import okhttp3.MediaType import okhttp3.MediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody import okhttp3.RequestBody
import okhttp3.Response import okhttp3.Response
import rx.Observable import rx.Observable
import java.util.Date
@Nsfw @Nsfw
class NineHentai : HttpSource() { class NineHentai : HttpSource() {
@ -180,9 +180,11 @@ class NineHentai : HttpSource() {
private class GenreList(tags: List<Tag>) : Filter.Group<Tag>("Tags", tags) private class GenreList(tags: List<Tag>) : Filter.Group<Tag>("Tags", tags)
private class Sorting : Filter.Sort("Sorting", private class Sorting : Filter.Sort(
"Sorting",
arrayOf("Newest", "Popular Right now", "Most Fapped", "Most Viewed", "By Title"), arrayOf("Newest", "Popular Right now", "Most Fapped", "Most Viewed", "By Title"),
Selection(1, false)) Selection(1, false)
)
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
Sorting(), Sorting(),

View File

@ -7,15 +7,15 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element 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() { 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.size == 3) {
if (dateWords[1].contains(",")) { if (dateWords[1].contains(",")) {
return try { return try {
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
} catch (e: ParseException) { } catch (e: ParseException) {
0L 0L
} }
@ -161,21 +161,27 @@ open class NineManga(override val name: String, override val baseUrl: String, ov
fun toUriPart() = vals[state].second fun toUriPart() = vals[state].second
} }
protected open class ContainBeginEndFilter(name: String) : UriPartFilter(name, arrayOf( protected open class ContainBeginEndFilter(name: String) : UriPartFilter(
name,
arrayOf(
Pair("Contain", "contain"), Pair("Contain", "contain"),
Pair("Begin", "begin"), Pair("Begin", "begin"),
Pair("End", "end") Pair("End", "end")
)) )
)
private class QueryCBEFilter : ContainBeginEndFilter("Query") private class QueryCBEFilter : ContainBeginEndFilter("Query")
private class AuthorCBEFilter : ContainBeginEndFilter("Author") private class AuthorCBEFilter : ContainBeginEndFilter("Author")
private class ArtistCBEFilter : ContainBeginEndFilter("Artist") private class ArtistCBEFilter : ContainBeginEndFilter("Artist")
private class CompletedFilter : UriPartFilter("Completed", arrayOf( private class CompletedFilter : UriPartFilter(
"Completed",
arrayOf(
Pair("Either", "either"), Pair("Either", "either"),
Pair("Yes", "yes"), Pair("Yes", "yes"),
Pair("No", "no") Pair("No", "no")
)) )
)
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
QueryCBEFilter(), QueryCBEFilter(),

View File

@ -4,12 +4,12 @@ import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory import eu.kanade.tachiyomi.source.SourceFactory
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.Request
import org.jsoup.nodes.Element
import java.text.ParseException import java.text.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
import okhttp3.Request
import org.jsoup.nodes.Element
class NineMangaFactory : SourceFactory { class NineMangaFactory : SourceFactory {
override fun createSources(): List<Source> = listOf( override fun createSources(): List<Source> = listOf(
@ -756,7 +756,7 @@ fun parseChapterDateByLang(date: String): Long {
if (dateWords.size == 3) { if (dateWords.size == 3) {
if (dateWords[1].contains(",")) { if (dateWords[1].contains(",")) {
return try { return try {
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
} catch (e: ParseException) { } catch (e: ParseException) {
0L 0L
} }

View File

@ -8,9 +8,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -18,6 +15,9 @@ import okhttp3.Response
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
abstract class Paprika( abstract class Paprika(
override val name: String, override val name: String,
@ -161,7 +161,8 @@ abstract class Paprika(
else -> null else -> null
}?.timeInMillis ?: 0L }?.timeInMillis ?: 0L
} }
else -> SimpleDateFormat("MMM d yy", Locale.US) else ->
SimpleDateFormat("MMM d yy", Locale.US)
.parse("${this.substringBefore(",")} $currentYear")?.time ?: 0 .parse("${this.substringBefore(",")} $currentYear")?.time ?: 0
} }
} catch (_: Exception) { } catch (_: Exception) {

View File

@ -9,14 +9,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.text.SimpleDateFormat
import java.util.Locale
class TheLibraryOfOhara(override val lang: String, private val siteLang: String) : ParsedHttpSource() { class TheLibraryOfOhara(override val lang: String, private val siteLang: String) : ParsedHttpSource() {
@ -36,7 +36,8 @@ class TheLibraryOfOhara(override val lang: String, private val siteLang: String)
// only show entries which contain pictures only. // only show entries which contain pictures only.
override fun popularMangaSelector() = when (lang) { override fun popularMangaSelector() = when (lang) {
"en" -> "#categories-7 ul li.cat-item-589813936," + // Chapter Secrets "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-607613583, " + // Chapter Secrets Specials
"#categories-7 ul li.cat-item-43972770, " + // Charlotte Family "#categories-7 ul li.cat-item-43972770, " + // Charlotte Family
"#categories-7 ul li.cat-item-9363667, " + // Complete Guides "#categories-7 ul li.cat-item-9363667, " + // Complete Guides
@ -180,7 +181,8 @@ class TheLibraryOfOhara(override val lang: String, private val siteLang: String)
!it.name.contains("Arabic") && !it.name.contains("Arabic") &&
!it.name.contains("Italian") && !it.name.contains("Italian") &&
!it.name.contains("Indonesia") && !it.name.contains("Indonesia") &&
!it.name.contains("Spanish") }.toMutableList() !it.name.contains("Spanish")
}.toMutableList()
} }
} }

View File

@ -7,10 +7,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -18,6 +14,10 @@ import okhttp3.RequestBody
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.net.URLDecoder
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.concurrent.TimeUnit
abstract class ToomicsGlobal( abstract class ToomicsGlobal(
private val siteLang: String, private val siteLang: String,
@ -153,7 +153,7 @@ abstract class ToomicsGlobal(
private fun parseChapterDate(date: String): Long { private fun parseChapterDate(date: String): Long {
return try { return try {
dateFormat.parse(date).time dateFormat.parse(date)?.time ?: 0L
} catch (e: ParseException) { } catch (e: ParseException) {
0L 0L
} }

View File

@ -5,13 +5,13 @@ import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.Headers import okhttp3.Headers
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class DongmanManhua : WebtoonsDefault("zh", "", dateFormat = SimpleDateFormat("yyyy-M-d", Locale.ENGLISH)) { class DongmanManhua : WebtoonsDefault("zh", "", dateFormat = SimpleDateFormat("yyyy-M-d", Locale.ENGLISH)) {
override val baseUrl = "https://www.dongmanmanhua.cn" override val baseUrl = "https://www.dongmanmanhua.cn"

View File

@ -9,7 +9,6 @@ import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.util.Calendar
import okhttp3.Cookie import okhttp3.Cookie
import okhttp3.CookieJar import okhttp3.CookieJar
import okhttp3.Headers import okhttp3.Headers
@ -19,6 +18,7 @@ import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.Calendar
abstract class Webtoons( abstract class Webtoons(
override val lang: String, override val lang: String,
@ -33,7 +33,8 @@ abstract class Webtoons(
override val supportsLatest = true override val supportsLatest = true
override val client: OkHttpClient = super.client.newBuilder() override val client: OkHttpClient = super.client.newBuilder()
.cookieJar(object : CookieJar { .cookieJar(
object : CookieJar {
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {} override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {}
override fun loadForRequest(url: HttpUrl): List<Cookie> { override fun loadForRequest(url: HttpUrl): List<Cookie> {
return listOf<Cookie>( return listOf<Cookie>(
@ -47,7 +48,8 @@ abstract class Webtoons(
.build() .build()
) )
} }
}) }
)
.build() .build()
private val day: String private val day: String

View File

@ -4,11 +4,11 @@ import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import java.text.SimpleDateFormat
import java.util.Locale
import org.json.JSONObject import org.json.JSONObject
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
open class WebtoonsDefault( open class WebtoonsDefault(
override val lang: String, override val lang: String,

View File

@ -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 // Android seems to be unable to parse Indonesian dates; we'll use a short hard-coded table
// instead. // instead.
private val dateMap: Array<String> = arrayOf( 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 { override fun chapterParseDate(date: String): Long {
val expr = Regex("""(\d{4}) ([A-Z][a-z]{2}) (\d+)""").find(date) ?: return 0 val expr = Regex("""(\d{4}) ([A-Z][a-z]{2}) (\d+)""").find(date) ?: return 0

View File

@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import java.util.ArrayList
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.Request import okhttp3.Request
@ -16,6 +15,7 @@ import org.json.JSONObject
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.util.ArrayList
open class WebtoonsTranslate(override val lang: String, private val translateLangCode: String, languageNameExtra: String = "") : Webtoons(lang) { open class WebtoonsTranslate(override val lang: String, private val translateLangCode: String, languageNameExtra: String = "") : Webtoons(lang) {
// popularMangaRequest already returns manga sorted by latest update // popularMangaRequest already returns manga sorted by latest update

View File

@ -7,14 +7,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
abstract class WPComics( abstract class WPComics(
override val name: String, override val name: String,

View File

@ -9,12 +9,12 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class WPComicsFactory : SourceFactory { class WPComicsFactory : SourceFactory {
override fun createSources(): List<Source> = listOf( override fun createSources(): List<Source> = listOf(

View File

@ -13,10 +13,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -26,6 +22,10 @@ import org.jsoup.nodes.Element
import org.jsoup.select.Elements import org.jsoup.select.Elements
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get 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( abstract class WPMangaStream(
override val name: String, override val name: String,
@ -273,28 +273,37 @@ abstract class WPMangaStream(
private class YearFilter : Filter.Text("Year") private class YearFilter : Filter.Text("Year")
protected class TypeFilter : UriPartFilter("Type", arrayOf( protected class TypeFilter : UriPartFilter(
"Type",
arrayOf(
Pair("Default", ""), Pair("Default", ""),
Pair("Manga", "Manga"), Pair("Manga", "Manga"),
Pair("Manhwa", "Manhwa"), Pair("Manhwa", "Manhwa"),
Pair("Manhua", "Manhua"), Pair("Manhua", "Manhua"),
Pair("Comic", "Comic") Pair("Comic", "Comic")
)) )
)
protected class SortByFilter : UriPartFilter("Sort By", arrayOf( protected class SortByFilter : UriPartFilter(
"Sort By",
arrayOf(
Pair("Default", ""), Pair("Default", ""),
Pair("A-Z", "title"), Pair("A-Z", "title"),
Pair("Z-A", "titlereverse"), Pair("Z-A", "titlereverse"),
Pair("Latest Update", "update"), Pair("Latest Update", "update"),
Pair("Latest Added", "latest"), Pair("Latest Added", "latest"),
Pair("Popular", "popular") Pair("Popular", "popular")
)) )
)
protected class StatusFilter : UriPartFilter("Status", arrayOf( protected class StatusFilter : UriPartFilter(
"Status",
arrayOf(
Pair("All", ""), Pair("All", ""),
Pair("Ongoing", "ongoing"), Pair("Ongoing", "ongoing"),
Pair("Completed", "completed") Pair("Completed", "completed")
)) )
)
protected class Genre(name: String, val id: String = name) : Filter.TriState(name) protected class Genre(name: String, val id: String = name) : Filter.TriState(name)
protected class GenreListFilter(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres) protected class GenreListFilter(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres)

View File

@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.io.IOException
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.Interceptor import okhttp3.Interceptor
@ -20,6 +19,7 @@ import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.io.IOException
class WPMangaStreamFactory : SourceFactory { class WPMangaStreamFactory : SourceFactory {
override fun createSources(): List<Source> = listOf( override fun createSources(): List<Source> = listOf(
@ -198,14 +198,19 @@ class WestManga : WPMangaStream("West Manga (WP Manga Stream)", "https://westman
return manga return manga
} }
private class SortByFilter : UriPartFilter("Sort By", arrayOf( private class SortByFilter : UriPartFilter(
"Sort By",
arrayOf(
Pair("Default", ""), Pair("Default", ""),
Pair("A-Z", "A-Z"), Pair("A-Z", "A-Z"),
Pair("Latest Added", "latest"), Pair("Latest Added", "latest"),
Pair("Popular", "popular") Pair("Popular", "popular")
)) )
)
private class GenreListFilter : UriPartFilter("Genre", arrayOf( private class GenreListFilter : UriPartFilter(
"Genre",
arrayOf(
Pair("Default", ""), Pair("Default", ""),
Pair("4-Koma", "4-koma"), Pair("4-Koma", "4-koma"),
Pair("Action", "action"), Pair("Action", "action"),
@ -257,7 +262,8 @@ class WestManga : WPMangaStream("West Manga (WP Manga Stream)", "https://westman
Pair("Vampire", "vampire"), Pair("Vampire", "vampire"),
Pair("Webtoons", "webtoons"), Pair("Webtoons", "webtoons"),
Pair("Yuri", "yuri") Pair("Yuri", "yuri")
)) )
)
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
Filter.Header("NOTE: sort and genre can't be combined and ignored when using text search!"), Filter.Header("NOTE: sort and genre can't be combined and ignored when using text search!"),
@ -384,7 +390,9 @@ class KomikGo : WPMangaStream("Komik GO (WP Manga Stream)", "https://komikgo.com
private class TextField(name: String, val key: String) : Filter.Text(name) private class TextField(name: String, val key: String) : Filter.Text(name)
private class SortBy : UriPartFilter("Sort by", arrayOf( private class SortBy : UriPartFilter(
"Sort by",
arrayOf(
Pair("Relevance", ""), Pair("Relevance", ""),
Pair("Latest", "latest"), Pair("Latest", "latest"),
Pair("A-Z", "alphabet"), Pair("A-Z", "alphabet"),
@ -392,7 +400,8 @@ class KomikGo : WPMangaStream("Komik GO (WP Manga Stream)", "https://komikgo.com
Pair("Trending", "trending"), Pair("Trending", "trending"),
Pair("Most View", "views"), Pair("Most View", "views"),
Pair("New", "new-manga") Pair("New", "new-manga")
)) )
)
private class Status(name: String, val id: String = name) : Filter.TriState(name) private class Status(name: String, val id: String = name) : Filter.TriState(name)
private class StatusList(statuses: List<Status>) : Filter.Group<Status>("Status", statuses) private class StatusList(statuses: List<Status>) : Filter.Group<Status>("Status", statuses)

View File

@ -8,15 +8,15 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
abstract class Zbulu( abstract class Zbulu(
override val name: String, override val name: String,
@ -193,7 +193,8 @@ abstract class Zbulu(
// [...document.querySelectorAll('.sub-menu li a')].map(a => `Pair("${a.textContent}", "${a.getAttribute('href')}")`).join(',\n') // [...document.querySelectorAll('.sub-menu li a')].map(a => `Pair("${a.textContent}", "${a.getAttribute('href')}")`).join(',\n')
// from $baseUrl // from $baseUrl
private class GenreFilter : UriPartFilter("Genres", private class GenreFilter : UriPartFilter(
"Genres",
arrayOf( arrayOf(
Pair("Choose a genre", ""), Pair("Choose a genre", ""),
Pair("Action", "action"), Pair("Action", "action"),

View File

@ -7,13 +7,13 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.MediaType import okhttp3.MediaType
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody import okhttp3.RequestBody
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class AndromedaScans : ParsedHttpSource() { class AndromedaScans : ParsedHttpSource() {
override val name = "AndromedaScans" override val name = "AndromedaScans"

View File

@ -147,13 +147,16 @@ class MangaAe : ParsedHttpSource() {
fun toUriPart() = vals[state].second fun toUriPart() = vals[state].second
} }
private class OrderByFilter : UriPartFilter("الترتيب حسب", arrayOf( private class OrderByFilter : UriPartFilter(
"الترتيب حسب",
arrayOf(
Pair("اختيار", ""), Pair("اختيار", ""),
Pair("اسم المانجا", "english_name"), Pair("اسم المانجا", "english_name"),
Pair("تاريخ النشر", "release_date"), Pair("تاريخ النشر", "release_date"),
Pair("عدد الفصول", "chapter_count"), Pair("عدد الفصول", "chapter_count"),
Pair("الحالة", "status") Pair("الحالة", "status")
)) )
)
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
OrderByFilter() OrderByFilter()

View File

@ -6,10 +6,10 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Locale
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class MangaZen : ParsedHttpSource() { class MangaZen : ParsedHttpSource() {

View File

@ -8,12 +8,12 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.util.concurrent.TimeUnit
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.concurrent.TimeUnit
class TeamX : ParsedHttpSource() { class TeamX : ParsedHttpSource() {
@ -44,8 +44,10 @@ class TeamX : ParsedHttpSource() {
return SManga.create().apply { return SManga.create().apply {
title = element.select(titleSelector).text() title = element.select(titleSelector).text()
setUrlWithoutDomain(element.select("a").first().attr("href")) setUrlWithoutDomain(element.select("a").first().attr("href"))
thumbnail_url = element.select("img").let { if (it.hasAttr("data-src")) thumbnail_url = element.select("img").let {
it.attr("abs:data-src") else it.attr("abs:src") } 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() title = info.select("div.col-md-9").text()
description = info.select("div.story p").text() description = info.select("div.story p").text()
genre = info.select("div.genre a").joinToString { it.text() } genre = info.select("div.genre a").joinToString { it.text() }
thumbnail_url = info.select("img").let { if (it.hasAttr("data-src")) thumbnail_url = info.select("img").let {
it.attr("abs:data-src") else it.attr("abs:src") } 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> { override fun pageListParse(document: Document): List<Page> {
return document.select("div#translationPageall img").mapIndexed { i, img -> return document.select("div#translationPageall img").mapIndexed { i, img ->
Page(i, "", img.let { if (it.hasAttr("data-src")) Page(
it.attr("abs:data-src") else it.attr("abs:src") }) i,
"",
img.let {
if (it.hasAttr("data-src"))
it.attr("abs:data-src") else it.attr("abs:src")
}
)
} }
} }

View File

@ -14,10 +14,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -26,6 +22,10 @@ import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class MangaTube : ParsedHttpSource() { class MangaTube : ParsedHttpSource() {
@ -156,7 +156,7 @@ class MangaTube : ParsedHttpSource() {
} }
date_upload = element.select("p.chapter-date").text().let { date_upload = element.select("p.chapter-date").text().let {
try { try {
SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()).parse(it.substringAfter(" ")).time SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()).parse(it.substringAfter(" "))?.time ?: 0L
} catch (_: ParseException) { } catch (_: ParseException) {
0L 0L
} }

View File

@ -6,13 +6,13 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class WieManga : ParsedHttpSource() { class WieManga : ParsedHttpSource() {
@ -119,7 +119,7 @@ class WieManga : ParsedHttpSource() {
} }
private fun parseChapterDate(date: String): Long { 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> { override fun pageListParse(document: Document): List<Page> {

View File

@ -47,8 +47,10 @@ class CloneManga : ParsedHttpSource() {
status = SManga.UNKNOWN status = SManga.UNKNOWN
url = element.select("a").first().attr("href") url = element.select("a").first().attr("href")
description = element.select("h4").first()?.text() ?: "" description = element.select("h4").first()?.text() ?: ""
thumbnail_url = baseUrl + attr.substring(attr.indexOf("site/themes"), thumbnail_url = baseUrl + attr.substring(
attr.indexOf(")")) attr.indexOf("site/themes"),
attr.indexOf(")")
)
} }
} }
@ -65,8 +67,10 @@ class CloneManga : ParsedHttpSource() {
val document = response.asJsoup() val document = response.asJsoup()
val series = document.location() val series = document.location()
val numChapters = Regex( val numChapters = Regex(
pattern = "&page=(.*)&lang=").findAll( pattern = "&page=(.*)&lang="
input = document.getElementsByTag("script")[3].toString()) ).findAll(
input = document.getElementsByTag("script")[3].toString()
)
.elementAt(3).destructured.component1() .elementAt(3).destructured.component1()
.toInt() .toInt()
val chapters = ArrayList<SChapter>() val chapters = ArrayList<SChapter>()

View File

@ -8,9 +8,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.net.URLEncoder
import java.util.Calendar
import java.util.Locale
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.MediaType import okhttp3.MediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -19,6 +16,9 @@ import okhttp3.RequestBody
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.net.URLEncoder
import java.util.Calendar
import java.util.Locale
class Comicastle : ParsedHttpSource() { class Comicastle : ParsedHttpSource() {

View File

@ -8,6 +8,11 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup 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.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.ArrayList import java.util.ArrayList
@ -15,11 +20,6 @@ import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
import java.util.regex.Pattern 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() { class ComicExtra : ParsedHttpSource() {
@ -141,15 +141,13 @@ class ComicExtra : ParsedHttpSource() {
} }
private fun dateParse(dateAsString: String): Long { private fun dateParse(dateAsString: String): Long {
val date: Date val date: Date? = try {
date = try {
SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH).parse(dateAsString.replace(Regex("(st|nd|rd|th)"), "")) SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH).parse(dateAsString.replace(Regex("(st|nd|rd|th)"), ""))
} catch (e: ParseException) { } catch (e: ParseException) {
val m = datePattern.matcher(dateAsString) val m = datePattern.matcher(dateAsString)
if (dateAsString != "Today" && m.matches()) { if (dateAsString != "Today" && m.matches()) {
val amount = m.group(1).toInt() val amount = m.group(1)!!.toInt()
Calendar.getInstance().apply { Calendar.getInstance().apply {
add(Calendar.DATE, -amount) add(Calendar.DATE, -amount)
}.time }.time
@ -158,7 +156,7 @@ class ComicExtra : ParsedHttpSource() {
} else return 0 } else return 0
} }
return date.time return date?.time ?: 0L
} }
override fun pageListRequest(chapter: SChapter): Request { override fun pageListRequest(chapter: SChapter): Request {

View File

@ -11,14 +11,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class Dilbert : ParsedHttpSource() { class Dilbert : ParsedHttpSource() {
@ -46,20 +46,26 @@ class Dilbert : ParsedHttpSource() {
override fun fetchPopularManga(page: Int): Observable<MangasPage> { override fun fetchPopularManga(page: Int): Observable<MangasPage> {
val currentYear = Calendar.getInstance().get(Calendar.YEAR) val currentYear = Calendar.getInstance().get(Calendar.YEAR)
return Observable.just(MangasPage((currentYear downTo 1989).map { return Observable.just(
MangasPage(
(currentYear downTo 1989).map {
SManga.create().apply { SManga.create().apply {
url = "?$it" url = "?$it"
title = "$name ($it)" title = "$name ($it)"
artist = "Scott Adams" artist = "Scott Adams"
author = "Scott Adams" author = "Scott Adams"
status = if (it < currentYear) SManga.COMPLETED else SManga.ONGOING status = if (it < currentYear) SManga.COMPLETED else SManga.ONGOING
description = """ description =
"""
A satirical comic strip featuring Dilbert, a competent, but seldom recognized engineer. A satirical comic strip featuring Dilbert, a competent, but seldom recognized engineer.
(This entry includes all the chapters published in $it.) (This entry includes all the chapters published in $it.)
""".trimIndent() """.trimIndent()
thumbnail_url = "https://dilbert.com/assets/favicon/favicon-196x196-cf4d86b485e628a034ab8b961c1c3520b5969252400a80b9eed544d99403e037.png" thumbnail_url = "https://dilbert.com/assets/favicon/favicon-196x196-cf4d86b485e628a034ab8b961c1c3520b5969252400a80b9eed544d99403e037.png"
} }
}, false)) },
false
)
)
} }
override fun fetchSearchManga(page: Int, query: String, filters: FilterList) = fetchPopularManga(page) 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() val date = element.first(".comic-title-date").text()
url = element.first(".img-comic-link").attr("href") url = element.first(".img-comic-link").attr("href")
name = element.first(".comic-title-name").text().ifBlank { date } 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>> { 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) if (pages != null) for (page in 2..pages) getChapters(page)
return Observable.just( return Observable.just(
chapters.sortedBy(SChapter::date_upload).mapIndexed { chapters.sortedBy(SChapter::date_upload).mapIndexed {
i, ch -> ch.apply { chapter_number = i + 1f } i, ch ->
ch.apply { chapter_number = i + 1f }
}.reversed() }.reversed()
) )
} }

View File

@ -50,10 +50,12 @@ class DynastyDoujins : DynastyScans() {
val chapters = document.select(chapterListSelector()).map { chapterFromElement(it) }.toMutableList() val chapters = document.select(chapterListSelector()).map { chapterFromElement(it) }.toMutableList()
document.select("a.thumbnail img").let { images -> document.select("a.thumbnail img").let { images ->
if (images.isNotEmpty()) chapters.add(SChapter.create().apply { if (images.isNotEmpty()) chapters.add(
SChapter.create().apply {
name = "Images" name = "Images"
setUrlWithoutDomain(document.location() + "/images") setUrlWithoutDomain(document.location() + "/images")
}) }
)
} }
return chapters return chapters

View File

@ -13,4 +13,5 @@ fun getAllDynasty() =
DynastyChapters(), DynastyChapters(),
DynastyDoujins(), DynastyDoujins(),
DynastyIssues(), DynastyIssues(),
DynastySeries()) DynastySeries()
)

View File

@ -8,9 +8,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.ArrayList
import java.util.Locale
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.json.JSONArray import org.json.JSONArray
@ -19,6 +16,9 @@ import org.jsoup.nodes.Element
import org.jsoup.nodes.Node import org.jsoup.nodes.Node
import org.jsoup.nodes.TextNode import org.jsoup.nodes.TextNode
import org.jsoup.select.Elements import org.jsoup.select.Elements
import java.text.SimpleDateFormat
import java.util.ArrayList
import java.util.Locale
abstract class DynastyScans : ParsedHttpSource() { abstract class DynastyScans : ParsedHttpSource() {
@ -70,8 +70,10 @@ abstract class DynastyScans : ParsedHttpSource() {
override fun searchMangaNextPageSelector() = "div.pagination > ul > li.active + li > a" override fun searchMangaNextPageSelector() = "div.pagination > ul > li.active + li > a"
private fun buildListfromResponse(): List<Node> { private fun buildListfromResponse(): List<Node> {
return client.newCall(Request.Builder().headers(headers) return client.newCall(
.url(popularMangaInitialUrl()).build()).execute().asJsoup() Request.Builder().headers(headers)
.url(popularMangaInitialUrl()).build()
).execute().asJsoup()
.select("div#main").first { it.hasText() }.childNodes() .select("div#main").first { it.hasText() }.childNodes()
} }

View File

@ -11,7 +11,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.util.Calendar
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -19,6 +18,7 @@ import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.util.Calendar
@Nsfw @Nsfw
class Eggporncomics : ParsedHttpSource() { class Eggporncomics : ParsedHttpSource() {
@ -129,21 +129,25 @@ class Eggporncomics : ParsedHttpSource() {
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
return SManga.create().apply { return SManga.create().apply {
thumbnail_url = document.select(pageListSelector).first().toFullSizeImage() thumbnail_url = document.select(pageListSelector).first().toFullSizeImage()
description = document.select("div.links ul").joinToString("\n") { element -> element.select("a") description = document.select("div.links ul").joinToString("\n") { element ->
.joinToString(prefix = element.select("span").text().replace(descriptionPrefixRegex, ": ")) { it.text() } } element.select("a")
.joinToString(prefix = element.select("span").text().replace(descriptionPrefixRegex, ": ")) { it.text() }
}
} }
} }
// Chapters // Chapters
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
return listOf(SChapter.create().apply { return listOf(
SChapter.create().apply {
setUrlWithoutDomain(response.request().url().toString()) setUrlWithoutDomain(response.request().url().toString())
name = "Chapter" name = "Chapter"
date_upload = response.asJsoup().select("div.info > div.meta li:contains(days ago)").firstOrNull() 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 } ?.let { Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, -(it.text().substringBefore(" ").toIntOrNull() ?: 0)) }.timeInMillis }
?: 0 ?: 0
}) }
)
} }
override fun chapterListSelector() = throw UnsupportedOperationException("Not used") override fun chapterListSelector() = throw UnsupportedOperationException("Not used")

View File

@ -8,14 +8,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.text.SimpleDateFormat
import java.util.Locale
class Explosm : HttpSource() { class Explosm : HttpSource() {
@ -92,7 +92,7 @@ class Explosm : HttpSource() {
element.select("div#comic-author").text().let { cName -> element.select("div#comic-author").text().let { cName ->
name = cName name = cName
date_upload = SimpleDateFormat("yyyy.MM.dd", Locale.getDefault()) date_upload = SimpleDateFormat("yyyy.MM.dd", Locale.getDefault())
.parse(cName.substringBefore(" ")).time .parse(cName.substringBefore(" "))?.time ?: 0L
} }
} }
} }

View File

@ -46,7 +46,8 @@ class GunnerkriggCourt : ParsedHttpSource() {
return Observable.just(manga) 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> { override fun chapterListParse(response: Response): List<SChapter> {
return super.chapterListParse(response).reversed() return super.chapterListParse(response).reversed()

View File

@ -15,9 +15,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import java.io.IOException
import java.util.HashMap
import java.util.concurrent.TimeUnit
import okhttp3.Call import okhttp3.Call
import okhttp3.Callback import okhttp3.Callback
import okhttp3.Headers import okhttp3.Headers
@ -29,6 +26,9 @@ import org.json.JSONObject
import rx.Observable import rx.Observable
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.IOException
import java.util.HashMap
import java.util.concurrent.TimeUnit
open class Guya : ConfigurableSource, HttpSource() { open class Guya : ConfigurableSource, HttpSource() {
@ -40,10 +40,13 @@ open class Guya : ConfigurableSource, HttpSource() {
private val scanlatorCacheUrl = "$baseUrl/api/get_all_groups" private val scanlatorCacheUrl = "$baseUrl/api/get_all_groups"
override fun headersBuilder() = Headers.Builder().apply { override fun headersBuilder() = Headers.Builder().apply {
add("User-Agent", "(Android ${Build.VERSION.RELEASE}; " + add(
"User-Agent",
"(Android ${Build.VERSION.RELEASE}; " +
"${Build.MANUFACTURER} ${Build.MODEL}) " + "${Build.MANUFACTURER} ${Build.MODEL}) " +
"Tachiyomi/${BuildConfig.VERSION_NAME} " + "Tachiyomi/${BuildConfig.VERSION_NAME} " +
Build.ID) Build.ID
)
} }
private val scanlators: ScanlatorStore = ScanlatorStore() private val scanlators: ScanlatorStore = ScanlatorStore()
@ -131,9 +134,12 @@ open class Guya : ConfigurableSource, HttpSource() {
metadata.put("chapter", chapterNum) metadata.put("chapter", chapterNum)
metadata.put("scanlator", scanlators.getKeyFromValue(chapter.scanlator.toString())) metadata.put("scanlator", scanlators.getKeyFromValue(chapter.scanlator.toString()))
metadata.put("slug", json.getString("slug")) metadata.put("slug", json.getString("slug"))
metadata.put("folder", json.getJSONObject("chapters") metadata.put(
"folder",
json.getJSONObject("chapters")
.getJSONObject(chapterNum) .getJSONObject(chapterNum)
.getString("folder")) .getString("folder")
)
return parsePageFromJson(pages, metadata) return parsePageFromJson(pages, metadata)
} }
@ -320,10 +326,16 @@ open class Guya : ConfigurableSource, HttpSource() {
val pageArray = ArrayList<Page>() val pageArray = ArrayList<Page>()
for (i in 0 until pages.length()) { for (i in 0 until pages.length()) {
val page = Page(i + 1, "", pageBuilder(metadata.getString("slug"), val page = Page(
i + 1,
"",
pageBuilder(
metadata.getString("slug"),
metadata.getString("folder"), metadata.getString("folder"),
pages[i].toString(), pages[i].toString(),
metadata.getString("scanlator"))) metadata.getString("scanlator")
)
)
pageArray.add(page) pageArray.add(page)
} }

View File

@ -9,13 +9,13 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.io.IOException
import okhttp3.CookieJar import okhttp3.CookieJar
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.io.IOException
@Nsfw @Nsfw
class HBrowse : ParsedHttpSource() { class HBrowse : ParsedHttpSource() {

View File

@ -12,9 +12,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.lang.UnsupportedOperationException
import java.util.Calendar
import java.util.regex.Pattern
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -22,6 +19,9 @@ import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.lang.UnsupportedOperationException
import java.util.Calendar
import java.util.regex.Pattern
@Nsfw @Nsfw
class Hentai2Read : ParsedHttpSource() { class Hentai2Read : ParsedHttpSource() {
@ -182,7 +182,7 @@ class Hentai2Read : ParsedHttpSource() {
chapter.date_upload = element.select("div > small").text()?.let { chapter.date_upload = element.select("div > small").text()?.let {
val matcher = chapterDatePattern.matcher(it) val matcher = chapterDatePattern.matcher(it)
if (matcher.find()) { if (matcher.find()) {
parseChapterDate(matcher.group(1)) parseChapterDate(matcher.group(1)!!)
} else { } else {
0L 0L
} }
@ -216,7 +216,7 @@ class Hentai2Read : ParsedHttpSource() {
val m = pagesUrlPattern.matcher(response.body()!!.string()) val m = pagesUrlPattern.matcher(response.body()!!.string())
var i = 0 var i = 0
while (m.find()) { while (m.find()) {
m.group(1).split(",").forEach { m.group(1)?.split(",")?.forEach {
pages.add(Page(i++, "", imageBaseUrl + it.trim('"').replace("""\/""", "/"))) pages.add(Page(i++, "", imageBaseUrl + it.trim('"').replace("""\/""", "/")))
} }
} }

View File

@ -109,13 +109,15 @@ class HentaiFox : ParsedHttpSource() {
// Chapters // Chapters
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
return listOf(SChapter.create().apply { return listOf(
SChapter.create().apply {
name = "Chapter" name = "Chapter"
// page path with a marker at the end // page path with a marker at the end
url = "${response.request().url().toString().replace("/gallery/", "/g/")}#" url = "${response.request().url().toString().replace("/gallery/", "/g/")}#"
// number of pages // number of pages
url += response.asJsoup().select("[id=load_pages]").attr("value") url += response.asJsoup().select("[id=load_pages]").attr("value")
}) }
)
} }
override fun chapterListSelector() = throw UnsupportedOperationException("Not used") override fun chapterListSelector() = throw UnsupportedOperationException("Not used")
@ -146,7 +148,9 @@ class HentaiFox : ParsedHttpSource() {
) )
// Top 50 tags // Top 50 tags
private class GenreFilter : UriPartFilter("Category", arrayOf( private class GenreFilter : UriPartFilter(
"Category",
arrayOf(
Pair("<select>", "---"), Pair("<select>", "---"),
Pair("Big breasts", "big-breasts"), Pair("Big breasts", "big-breasts"),
Pair("Sole female", "sole-female"), Pair("Sole female", "sole-female"),
@ -198,7 +202,8 @@ class HentaiFox : ParsedHttpSource() {
Pair("Big ass", "big-ass"), Pair("Big ass", "big-ass"),
Pair("Story arc", "story-arc"), Pair("Story arc", "story-arc"),
Pair("Teacher", "teacher") Pair("Teacher", "teacher")
)) )
)
private open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) : private open class UriPartFilter(displayName: String, private val vals: Array<Pair<String, String>>) :
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) { Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {

View File

@ -8,11 +8,11 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.net.URLEncoder
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.net.URLEncoder
@Nsfw @Nsfw
class HentaiNexus : ParsedHttpSource() { class HentaiNexus : ParsedHttpSource() {

View File

@ -11,10 +11,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup 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.Call
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@ -22,6 +18,10 @@ import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.concurrent.TimeUnit
class Hiveworks : ParsedHttpSource() { class Hiveworks : ParsedHttpSource() {
@ -290,7 +290,10 @@ class Hiveworks : ParsedHttpSource() {
fun addToUri(uri: Uri.Builder) fun addToUri(uri: Uri.Builder)
} }
private class UpdateDay : UriSelectFilter("Update Day", "update-day", arrayOf( private class UpdateDay : UriSelectFilter(
"Update Day",
"update-day",
arrayOf(
Pair("all", "All"), Pair("all", "All"),
Pair("monday", "Monday"), Pair("monday", "Monday"),
Pair("tuesday", "Tuesday"), Pair("tuesday", "Tuesday"),
@ -299,17 +302,25 @@ class Hiveworks : ParsedHttpSource() {
Pair("friday", "Friday"), Pair("friday", "Friday"),
Pair("saturday", "Saturday"), Pair("saturday", "Saturday"),
Pair("sunday", "Sunday") Pair("sunday", "Sunday")
)) )
)
private class RatingFilter : UriSelectFilter("Rating", "age", arrayOf( private class RatingFilter : UriSelectFilter(
"Rating",
"age",
arrayOf(
Pair("all", "All"), Pair("all", "All"),
Pair("everyone", "Everyone"), Pair("everyone", "Everyone"),
Pair("teen", "Teen"), Pair("teen", "Teen"),
Pair("young-adult", "Young Adult"), Pair("young-adult", "Young Adult"),
Pair("mature", "Mature") Pair("mature", "Mature")
)) )
)
private class GenreFilter : UriSelectFilter("Genre", "genre", arrayOf( private class GenreFilter : UriSelectFilter(
"Genre",
"genre",
arrayOf(
Pair("all", "All"), Pair("all", "All"),
Pair("action/adventure", "Action/Adventure"), Pair("action/adventure", "Action/Adventure"),
Pair("animated", "Animated"), Pair("animated", "Animated"),
@ -330,9 +341,13 @@ class Hiveworks : ParsedHttpSource() {
Pair("steampunk", "Steampunk"), Pair("steampunk", "Steampunk"),
Pair("superhero", "Superhero"), Pair("superhero", "Superhero"),
Pair("urban-fantasy", "Urban Fantasy") Pair("urban-fantasy", "Urban Fantasy")
)) )
)
private class TitleFilter : UriSelectFilter("Title", "alpha", arrayOf( private class TitleFilter : UriSelectFilter(
"Title",
"alpha",
arrayOf(
Pair("all", "All"), Pair("all", "All"),
Pair("a", "A"), Pair("a", "A"),
Pair("b", "B"), Pair("b", "B"),
@ -361,13 +376,18 @@ class Hiveworks : ParsedHttpSource() {
Pair("y", "Y"), Pair("y", "Y"),
Pair("z", "Z"), Pair("z", "Z"),
Pair("numbers-symbols", "Numbers / Symbols") Pair("numbers-symbols", "Numbers / Symbols")
)) )
)
private class SortFilter : UriSelectFilter("Sort By", "sortby", arrayOf( private class SortFilter : UriSelectFilter(
"Sort By",
"sortby",
arrayOf(
Pair("none", "None"), Pair("none", "None"),
Pair("a-z", "A-Z"), Pair("a-z", "A-Z"),
Pair("z-a", "Z-A") Pair("z-a", "Z-A")
)) )
)
// Other Code // Other Code

View File

@ -13,13 +13,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class Honkaiimpact : ParsedHttpSource() { class Honkaiimpact : ParsedHttpSource() {

View File

@ -15,12 +15,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.Credentials
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -30,6 +24,12 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get 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() { class Madokami : ConfigurableSource, ParsedHttpSource() {
override val name = "Madokami" override val name = "Madokami"
@ -145,7 +145,7 @@ class Madokami : ConfigurableSource, ParsedHttpSource() {
} }
chapter.date_upload = newDate.time.time chapter.date_upload = newDate.time.time
} else { } else {
chapter.date_upload = dateFormat.parse(date).time chapter.date_upload = dateFormat.parse(date)?.time ?: 0L
} }
return chapter return chapter
} }

View File

@ -8,14 +8,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class mangacruzers : ParsedHttpSource() { class mangacruzers : ParsedHttpSource() {
@ -79,7 +79,7 @@ class mangacruzers : ParsedHttpSource() {
} }
private fun parseDate(date: String): Long { 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 { override fun chapterFromElement(element: Element) = SChapter.create().apply {

View File

@ -13,11 +13,11 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import java.text.SimpleDateFormat
import java.util.Locale
class Mangadog : HttpSource() { class Mangadog : HttpSource() {
@ -122,7 +122,7 @@ class Mangadog : HttpSource() {
} }
private fun parseDate(date: String): Long { 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 { override fun mangaDetailsParse(response: Response): SManga {

View File

@ -7,15 +7,15 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class Mangaeden : ParsedHttpSource() { class Mangaeden : ParsedHttpSource() {
@ -52,15 +52,18 @@ class Mangaeden : ParsedHttpSource() {
val url = HttpUrl.parse("$baseUrl/en/en-directory/")?.newBuilder()!!.addQueryParameter("title", query) val url = HttpUrl.parse("$baseUrl/en/en-directory/")?.newBuilder()!!.addQueryParameter("title", query)
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> (if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
when (filter) { when (filter) {
is StatusList -> filter.state is StatusList ->
filter.state
.filter { it.state } .filter { it.state }
.map { it.id.toString() } .map { it.id.toString() }
.forEach { url.addQueryParameter("status", it) } .forEach { url.addQueryParameter("status", it) }
is Types -> filter.state is Types ->
filter.state
.filter { it.state } .filter { it.state }
.map { it.id.toString() } .map { it.id.toString() }
.forEach { url.addQueryParameter("type", it) } .forEach { url.addQueryParameter("type", it) }
is GenreList -> filter.state is GenreList ->
filter.state
.filter { !it.isIgnored() } .filter { !it.isIgnored() }
.forEach { genre -> url.addQueryParameter(if (genre.isIncluded()) "categoriesInc" else "categoriesExcl", genre.id) } .forEach { genre -> url.addQueryParameter(if (genre.isIncluded()) "categoriesInc" else "categoriesExcl", genre.id) }
is TextField -> url.addQueryParameter(filter.key, filter.state) is TextField -> url.addQueryParameter(filter.key, filter.state)
@ -129,8 +132,9 @@ class Mangaeden : ParsedHttpSource() {
set(Calendar.MILLISECOND, 0) set(Calendar.MILLISECOND, 0)
}.timeInMillis }.timeInMillis
} }
else -> try { else ->
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date).time try {
SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
} catch (e: ParseException) { } catch (e: ParseException) {
0L 0L
} }
@ -147,8 +151,11 @@ class Mangaeden : ParsedHttpSource() {
private class NamedId(name: String, val id: Int) : Filter.CheckBox(name) private class NamedId(name: String, val id: Int) : Filter.CheckBox(name)
private class Genre(name: String, val id: String) : Filter.TriState(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 TextField(name: String, val key: String) : Filter.Text(name)
private class OrderBy : Filter.Sort("Order by", arrayOf("Manga title", "Views", "Chapters", "Latest chapter"), private class OrderBy : Filter.Sort(
Selection(1, false)) "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 StatusList(statuses: List<NamedId>) : Filter.Group<NamedId>("Stato", statuses)
private class Types(types: List<NamedId>) : Filter.Group<NamedId>("Tipo", types) private class Types(types: List<NamedId>) : Filter.Group<NamedId>("Tipo", types)

View File

@ -6,10 +6,10 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Locale
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class MangaFast : ParsedHttpSource() { class MangaFast : ParsedHttpSource() {
override val name = "MangaFast" override val name = "MangaFast"

View File

@ -8,14 +8,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class Mangafreak : ParsedHttpSource() { class Mangafreak : ParsedHttpSource() {
override val name: String = "Mangafreak" override val name: String = "Mangafreak"
@ -76,14 +76,16 @@ class Mangafreak : ParsedHttpSource() {
uri.appendPath("Genre") uri.appendPath("Genre")
when (filter) { when (filter) {
is GenreList -> { is GenreList -> {
uri.appendPath(filter.state.joinToString("") { uri.appendPath(
filter.state.joinToString("") {
when (it.state) { when (it.state) {
Filter.TriState.STATE_IGNORE -> "0" Filter.TriState.STATE_IGNORE -> "0"
Filter.TriState.STATE_INCLUDE -> "1" Filter.TriState.STATE_INCLUDE -> "1"
Filter.TriState.STATE_EXCLUDE -> "2" Filter.TriState.STATE_EXCLUDE -> "2"
else -> "0" else -> "0"
} }
}) }
)
} }
} }
uri.appendEncodedPath("Status/0/Type/0") uri.appendEncodedPath("Status/0/Type/0")
@ -120,7 +122,7 @@ class Mangafreak : ParsedHttpSource() {
date_upload = parseDate(element.select(" td:eq(1)").text()) date_upload = parseDate(element.select(" td:eq(1)").text())
} }
private fun parseDate(date: String): Long { 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> { override fun chapterListParse(response: Response): List<SChapter> {
return super.chapterListParse(response).reversed() return super.chapterListParse(response).reversed()
@ -144,7 +146,8 @@ class Mangafreak : ParsedHttpSource() {
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres) private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
GenreList(getGenreList())) GenreList(getGenreList())
)
private fun getGenreList() = listOf( private fun getGenreList() = listOf(
Genre("Act"), Genre("Act"),
Genre("Adult"), Genre("Adult"),

View File

@ -13,14 +13,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class Mangahasu : ParsedHttpSource() { class Mangahasu : ParsedHttpSource() {
@ -195,18 +195,24 @@ class Mangahasu : ParsedHttpSource() {
fun toUriPart() = vals[state].second fun toUriPart() = vals[state].second
} }
private class TypeFilter : UriPartFilter("Type", arrayOf( private class TypeFilter : UriPartFilter(
"Type",
arrayOf(
Pair("Any", ""), Pair("Any", ""),
Pair("Manga", "10"), Pair("Manga", "10"),
Pair("Manhwa", "12"), Pair("Manhwa", "12"),
Pair("Manhua", "19") Pair("Manhua", "19")
)) )
)
private class StatusFilter : UriPartFilter("Status", arrayOf( private class StatusFilter : UriPartFilter(
"Status",
arrayOf(
Pair("Any", ""), Pair("Any", ""),
Pair("Completed", "1"), Pair("Completed", "1"),
Pair("Ongoing", "2") Pair("Ongoing", "2")
)) )
)
private class Genre(name: String, val id: String) : Filter.TriState(name) private class Genre(name: String, val id: String) : Filter.TriState(name)
private class GenreFilter(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres) private class GenreFilter(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)

View File

@ -9,10 +9,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup 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.Cookie
import okhttp3.CookieJar import okhttp3.CookieJar
import okhttp3.HttpUrl import okhttp3.HttpUrl
@ -20,6 +16,10 @@ import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class Mangahere : ParsedHttpSource() { class Mangahere : ParsedHttpSource() {
@ -34,18 +34,23 @@ class Mangahere : ParsedHttpSource() {
override val supportsLatest = true override val supportsLatest = true
override val client: OkHttpClient = super.client.newBuilder() override val client: OkHttpClient = super.client.newBuilder()
.cookieJar(object : CookieJar { .cookieJar(
object : CookieJar {
override fun saveFromResponse(url: HttpUrl, cookies: MutableList<Cookie>) {} override fun saveFromResponse(url: HttpUrl, cookies: MutableList<Cookie>) {}
override fun loadForRequest(url: HttpUrl): MutableList<Cookie> { override fun loadForRequest(url: HttpUrl): MutableList<Cookie> {
return ArrayList<Cookie>().apply { return ArrayList<Cookie>().apply {
add(Cookie.Builder() add(
Cookie.Builder()
.domain("www.mangahere.cc") .domain("www.mangahere.cc")
.path("/") .path("/")
.name("isAdult") .name("isAdult")
.value("1") .value("1")
.build()) } .build()
)
} }
}) }
}
)
.build() .build()
override fun popularMangaSelector() = ".manga-list-1-list li" override fun popularMangaSelector() = ".manga-list-1-list li"
@ -186,7 +191,7 @@ class Mangahere : ParsedHttpSource() {
}.timeInMillis }.timeInMillis
} else { } else {
try { try {
SimpleDateFormat("MMM dd,yyyy", Locale.ENGLISH).parse(date).time SimpleDateFormat("MMM dd,yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
} catch (e: ParseException) { } catch (e: ParseException) {
0L 0L
} }
@ -233,7 +238,8 @@ class Mangahere : ParsedHttpSource() {
val chapterIdStartLoc = html.indexOf("chapterid") val chapterIdStartLoc = html.indexOf("chapterid")
val chapterId = html.substring( val chapterId = html.substring(
chapterIdStartLoc + 11, chapterIdStartLoc + 11,
html.indexOf(";", chapterIdStartLoc)).trim() html.indexOf(";", chapterIdStartLoc)
).trim()
val chapterPagesElement = document.select(".pager-list-left > span").first() val chapterPagesElement = document.select(".pager-list-left > span").first()
val pagesLinksElements = chapterPagesElement.select("a") val pagesLinksElements = chapterPagesElement.select("a")
@ -298,7 +304,9 @@ class Mangahere : ParsedHttpSource() {
val secretKeyEndLoc = secretKeyDeobfuscatedScript.indexOf(";") val secretKeyEndLoc = secretKeyDeobfuscatedScript.indexOf(";")
val secretKeyResultScript = secretKeyDeobfuscatedScript.substring( val secretKeyResultScript = secretKeyDeobfuscatedScript.substring(
secretKeyStartLoc, secretKeyEndLoc) secretKeyStartLoc,
secretKeyEndLoc
)
return duktape.evaluate(secretKeyResultScript).toString() return duktape.evaluate(secretKeyResultScript).toString()
} }

View File

@ -14,17 +14,17 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.HttpUrl
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody import okhttp3.RequestBody
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element 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() { class Mangahub : ParsedHttpSource() {
@ -133,7 +133,7 @@ class Mangahub : ParsedHttpSource() {
// parses: "12-20-2019" and defaults everything that wasn't taken into account to 0 // parses: "12-20-2019" and defaults everything that wasn't taken into account to 0
else -> { else -> {
try { 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*/ } } catch (e: ParseException) { /*nothing to do, parsedDate is initialized with 0L*/ }
} }
} }

View File

@ -7,14 +7,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class MangaJar : ParsedHttpSource() { class MangaJar : ParsedHttpSource() {
@ -43,8 +43,10 @@ class MangaJar : ParsedHttpSource() {
override fun popularMangaFromElement(element: Element) = SManga.create().apply { override fun popularMangaFromElement(element: Element) = SManga.create().apply {
setUrlWithoutDomain(element.select("a").attr("href")) setUrlWithoutDomain(element.select("a").attr("href"))
title = element.select("img").attr("title") title = element.select("img").attr("title")
thumbnail_url = element.select("img").let { if (it.hasAttr("data-src")) thumbnail_url = element.select("img").let {
it.attr("data-src") else it.attr("src") } if (it.hasAttr("data-src"))
it.attr("data-src") else it.attr("src")
}
} }
override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element) override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
@ -63,7 +65,8 @@ class MangaJar : ParsedHttpSource() {
url.addQueryParameter("q", query) url.addQueryParameter("q", query)
url.addQueryParameter("page", page.toString()) url.addQueryParameter("page", page.toString())
(filters.forEach { filter -> (
filters.forEach { filter ->
when (filter) { when (filter) {
is OrderBy -> { is OrderBy -> {
url.addQueryParameter("sortBy", filter.toUriPart()) url.addQueryParameter("sortBy", filter.toUriPart())
@ -72,7 +75,8 @@ class MangaJar : ParsedHttpSource() {
url.addQueryParameter("sortAscending", filter.toUriPart()) url.addQueryParameter("sortAscending", filter.toUriPart())
} }
} }
}) }
)
return GET(url.toString(), headers) return GET(url.toString(), headers)
} }
@ -117,7 +121,7 @@ class MangaJar : ParsedHttpSource() {
return if ("ago" in string) { return if ("ago" in string) {
parseRelativeDate(string) ?: 0 parseRelativeDate(string) ?: 0
} else { } else {
dateFormat.parse(string).time dateFormat.parse(string)?.time ?: 0L
} }
} }
@ -151,20 +155,27 @@ class MangaJar : ParsedHttpSource() {
GenreList() GenreList()
) )
private class SortBy : UriPartFilter("Sort By", arrayOf( private class SortBy : UriPartFilter(
"Sort By",
arrayOf(
Pair("Descending", "0"), Pair("Descending", "0"),
Pair("Ascending", "1") Pair("Ascending", "1")
)) )
)
private class OrderBy : UriPartFilter("Order By", arrayOf( private class OrderBy : UriPartFilter(
"Order By",
arrayOf(
Pair("Popularity", "popular"), Pair("Popularity", "popular"),
Pair("Year", "year"), Pair("Year", "year"),
Pair("Alphabet", "name"), Pair("Alphabet", "name"),
Pair("Date added", "published_at"), Pair("Date added", "published_at"),
Pair("Date updated", "last_chapter_at") Pair("Date updated", "last_chapter_at")
)) )
)
private class GenreList : Filter.Select<String>("Select Genre", private class GenreList : Filter.Select<String>(
"Select Genre",
arrayOf( arrayOf(
"", "",
"Fantasy", "Fantasy",

View File

@ -6,13 +6,13 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.MediaType import okhttp3.MediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.ResponseBody import okhttp3.ResponseBody
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class MangaKatana : ParsedHttpSource() { class MangaKatana : ParsedHttpSource() {
override val name = "MangaKatana" override val name = "MangaKatana"

View File

@ -17,14 +17,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import rx.Observable 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 * 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 } val endRange = ((page * 24) - 1).let { if (it <= directory.lastIndex) it else directory.lastIndex }
for (i in (((page - 1) * 24)..endRange)) { for (i in (((page - 1) * 24)..endRange)) {
mangas.add(SManga.create().apply { mangas.add(
SManga.create().apply {
title = directory[i]["s"].string title = directory[i]["s"].string
url = "/manga/${directory[i]["i"].string}" url = "/manga/${directory[i]["i"].string}"
thumbnail_url = "https://cover.mangabeast01.com/cover/${directory[i]["i"].string}.jpg" thumbnail_url = "https://cover.mangabeast01.com/cover/${directory[i]["i"].string}.jpg"
}) }
)
} }
return MangasPage(mangas, endRange < directory.lastIndex) return MangasPage(mangas, endRange < directory.lastIndex)
} }

View File

@ -11,13 +11,13 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class MangaLinkz : ParsedHttpSource() { class MangaLinkz : ParsedHttpSource() {
@ -126,8 +126,9 @@ class MangaLinkz : ParsedHttpSource() {
} }
} }
} }
else -> try { else ->
SimpleDateFormat("MMM d, yyyy", Locale.US).parse(this).time try {
SimpleDateFormat("MMM d, yyyy", Locale.US).parse(this)?.time ?: 0L
} catch (_: Exception) { } catch (_: Exception) {
0L 0L
} }

View File

@ -7,11 +7,11 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.util.Calendar
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.util.Calendar
// MangaManiac is a network of sites built by Animemaniac.co. // MangaManiac is a network of sites built by Animemaniac.co.

View File

@ -12,14 +12,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import okhttp3.Headers
import okhttp3.Request
import okhttp3.Response
import java.lang.Exception import java.lang.Exception
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import java.util.TimeZone import java.util.TimeZone
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import okhttp3.Headers
import okhttp3.Request
import okhttp3.Response
fun JsonObject.getNullable(key: String): JsonElement? { fun JsonObject.getNullable(key: String): JsonElement? {
val value: JsonElement = this.get(key) ?: return null val value: JsonElement = this.get(key) ?: return null
@ -72,11 +72,13 @@ class MangaMutiny : HttpSource() {
for (singleChapterJsonElement in jsonChapters) { for (singleChapterJsonElement in jsonChapters) {
val singleChapterJsonObject = singleChapterJsonElement.asJsonObject val singleChapterJsonObject = singleChapterJsonElement.asJsonObject
chapterList.add(SChapter.create().apply { chapterList.add(
SChapter.create().apply {
name = chapterTitleBuilder(singleChapterJsonObject) name = chapterTitleBuilder(singleChapterJsonObject)
url = singleChapterJsonObject.get("slug").asString url = singleChapterJsonObject.get("slug").asString
date_upload = parseDate(singleChapterJsonObject.get("releasedAt").asString) date_upload = parseDate(singleChapterJsonObject.get("releasedAt").asString)
}) }
)
} }
} }
@ -211,11 +213,13 @@ class MangaMutiny : HttpSource() {
for (singleItem in itemsArray) { for (singleItem in itemsArray) {
val mangaObject = singleItem.asJsonObject val mangaObject = singleItem.asJsonObject
mangasPage.add(SManga.create().apply { mangasPage.add(
SManga.create().apply {
this.title = mangaObject.get("title").asString this.title = mangaObject.get("title").asString
this.thumbnail_url = mangaObject.getNullable("thumbnail")?.asString this.thumbnail_url = mangaObject.getNullable("thumbnail")?.asString
this.url = mangaObject.get("slug").asString this.url = mangaObject.get("slug").asString
}) }
)
} }
} }
@ -303,19 +307,27 @@ class MangaMutiny : HttpSource() {
} }
} }
private class StatusFilter : UriSelectFilter("Status", "status", arrayOf( private class StatusFilter : UriSelectFilter(
"Status",
"status",
arrayOf(
Pair("", "All"), Pair("", "All"),
Pair("completed", "Completed"), Pair("completed", "Completed"),
Pair("ongoing", "Ongoing") Pair("ongoing", "Ongoing")
)) )
)
private class CategoryFilter : UriSelectFilter("Category", "tags", arrayOf( private class CategoryFilter : UriSelectFilter(
"Category",
"tags",
arrayOf(
Pair("", "All"), Pair("", "All"),
Pair("josei", "Josei"), Pair("josei", "Josei"),
Pair("seinen", "Seinen"), Pair("seinen", "Seinen"),
Pair("shoujo", "Shoujo"), Pair("shoujo", "Shoujo"),
Pair("shounen", "Shounen") Pair("shounen", "Shounen")
)) { )
) {
override fun potentiallyAddToUriParameterMap(parameterMap: MutableMap<String, String>) = override fun potentiallyAddToUriParameterMap(parameterMap: MutableMap<String, String>) =
appendValueToKeyInUriParameterMap(parameterMap, uriParam, vals[state].first) appendValueToKeyInUriParameterMap(parameterMap, uriParam, vals[state].first)
} }
@ -333,7 +345,9 @@ class MangaMutiny : HttpSource() {
} }
} }
// Actual genere filter list // Actual genere filter list
private class GenresFilter : GenreFilterList("Genres", listOf( private class GenresFilter : GenreFilterList(
"Genres",
listOf(
GenreFilter("action", "action"), GenreFilter("action", "action"),
GenreFilter("adult", "adult"), GenreFilter("adult", "adult"),
GenreFilter("adventure", "adventure"), GenreFilter("adventure", "adventure"),
@ -396,10 +410,13 @@ class MangaMutiny : HttpSource() {
GenreFilter("webtoons", "webtoons"), GenreFilter("webtoons", "webtoons"),
GenreFilter("wuxia", "wuxia"), GenreFilter("wuxia", "wuxia"),
GenreFilter("zombies", "zombies") GenreFilter("zombies", "zombies")
)) )
)
// Actual format filter List // Actual format filter List
private class FormatsFilter : GenreFilterList("Formats", listOf( private class FormatsFilter : GenreFilterList(
"Formats",
listOf(
GenreFilter("4-koma", "4-koma"), GenreFilter("4-koma", "4-koma"),
GenreFilter("adaptation", "adaptation"), GenreFilter("adaptation", "adaptation"),
GenreFilter("anthology", "anthology"), GenreFilter("anthology", "anthology"),
@ -411,14 +428,21 @@ class MangaMutiny : HttpSource() {
GenreFilter("official_colored", "official colored"), GenreFilter("official_colored", "official colored"),
GenreFilter("oneshot", "oneshot"), GenreFilter("oneshot", "oneshot"),
GenreFilter("web_comic", "web comic") GenreFilter("web_comic", "web comic")
)) )
)
private class SortFilter : UriSelectFilter("Sort", "sort", arrayOf( private class SortFilter : UriSelectFilter(
"Sort",
"sort",
arrayOf(
Pair("-rating -ratingCount", "Popular"), Pair("-rating -ratingCount", "Popular"),
Pair("-lastReleasedAt", "Last update"), Pair("-lastReleasedAt", "Last update"),
Pair("-createdAt", "Newest"), Pair("-createdAt", "Newest"),
Pair("title", "Name") Pair("title", "Name")
), firstIsUnspecified = false, defaultValue = 0) ),
firstIsUnspecified = false,
defaultValue = 0
)
private class AuthorFilter : Filter.Text("Manga Author & Artist"), UriFilter { private class AuthorFilter : Filter.Text("Manga Author & Artist"), UriFilter {
override fun potentiallyAddToUriParameterMap(parameterMap: MutableMap<String, String>) { override fun potentiallyAddToUriParameterMap(parameterMap: MutableMap<String, String>) {

View File

@ -6,14 +6,14 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element 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() { class MangaOwl : ParsedHttpSource() {

View File

@ -15,9 +15,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import okhttp3.CacheControl import okhttp3.CacheControl
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@ -26,6 +23,9 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class MangaPark : ConfigurableSource, ParsedHttpSource() { class MangaPark : ConfigurableSource, ParsedHttpSource() {
@ -154,7 +154,7 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
return when (getSourcePref()) { return when (getSourcePref()) {
// source with most chapters along with chapters that source doesn't have // source with most chapters along with chapters that source doesn't have
"most" -> { "most" -> {
val chapters = mangaBySource.maxBy { it.count() }!! val chapters = mangaBySource.maxByOrNull { it.count() }!!
(chapters + chapters.getMissingChapters(mangaBySource.flatten())).sortedByDescending { it.chapter_number } (chapters + chapters.getMissingChapters(mangaBySource.flatten())).sortedByDescending { it.chapter_number }
} }
// "smart list" - try not to miss a chapter and avoid dupes // "smart list" - try not to miss a chapter and avoid dupes
@ -316,7 +316,10 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
private class GenreFilter(val uriParam: String, displayName: String) : Filter.TriState(displayName) private class GenreFilter(val uriParam: String, displayName: String) : Filter.TriState(displayName)
private class GenreGroup : Filter.Group<GenreFilter>("Genres", listOf( private class GenreGroup :
Filter.Group<GenreFilter>(
"Genres",
listOf(
GenreFilter("4-koma", "4 koma"), GenreFilter("4-koma", "4 koma"),
GenreFilter("action", "Action"), GenreFilter("action", "Action"),
GenreFilter("adaptation", "Adaptation"), GenreFilter("adaptation", "Adaptation"),
@ -416,7 +419,9 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
GenreFilter("yaoi", "Yaoi"), GenreFilter("yaoi", "Yaoi"),
GenreFilter("yuri", "Yuri"), GenreFilter("yuri", "Yuri"),
GenreFilter("zombies", "Zombies") GenreFilter("zombies", "Zombies")
)), UriFilter { )
),
UriFilter {
override fun addToUri(uri: Uri.Builder) { override fun addToUri(uri: Uri.Builder) {
val genresParameterValue = state.filter { it.isIncluded() }.joinToString(",") { it.uriParam } val genresParameterValue = state.filter { it.isIncluded() }.joinToString(",") { it.uriParam }
if (genresParameterValue.isNotEmpty()) { 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("and", "And mode"),
Pair("or", "Or 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("any", "Any"),
Pair("1", "1 +"), Pair("1", "1 +"),
Pair("5", "5 +"), Pair("5", "5 +"),
@ -447,15 +459,23 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
Pair("100", "100 +"), Pair("100", "100 +"),
Pair("150", "150 +"), Pair("150", "150 +"),
Pair("200", "200 +") Pair("200", "200 +")
)) )
)
private class StatusFilter : UriSelectFilter("Status", "status", arrayOf( private class StatusFilter : UriSelectFilter(
"Status",
"status",
arrayOf(
Pair("any", "Any"), Pair("any", "Any"),
Pair("completed", "Completed"), Pair("completed", "Completed"),
Pair("ongoing", "Ongoing") Pair("ongoing", "Ongoing")
)) )
)
private class RatingFilter : UriSelectFilter("Rating", "rating", arrayOf( private class RatingFilter : UriSelectFilter(
"Rating",
"rating",
arrayOf(
Pair("any", "Any"), Pair("any", "Any"),
Pair("5", "5 stars"), Pair("5", "5 stars"),
Pair("4", "4 stars"), Pair("4", "4 stars"),
@ -463,18 +483,26 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
Pair("2", "2 stars"), Pair("2", "2 stars"),
Pair("1", "1 star"), Pair("1", "1 star"),
Pair("0", "0 stars") Pair("0", "0 stars")
)) )
)
private class TypeFilter : UriSelectFilter("Type", "types", arrayOf( private class TypeFilter : UriSelectFilter(
"Type",
"types",
arrayOf(
Pair("any", "Any"), Pair("any", "Any"),
Pair("manga", "Japanese Manga"), Pair("manga", "Japanese Manga"),
Pair("manhwa", "Korean Manhwa"), Pair("manhwa", "Korean Manhwa"),
Pair("manhua", "Chinese Manhua"), Pair("manhua", "Chinese Manhua"),
Pair("unknown", "Unknown") Pair("unknown", "Unknown")
)) )
)
private class YearFilter : UriSelectFilter("Release year", "years", private class YearFilter : UriSelectFilter(
arrayOf(Pair("any", "Any"), "Release year",
"years",
arrayOf(
Pair("any", "Any"),
// Get all years between today and 1946 // Get all years between today and 1946
*(Calendar.getInstance().get(Calendar.YEAR) downTo 1946).map { *(Calendar.getInstance().get(Calendar.YEAR) downTo 1946).map {
Pair(it.toString(), it.toString()) Pair(it.toString(), it.toString())
@ -482,7 +510,10 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
) )
) )
private class SortFilter : UriSelectFilter("Sort", "orderby", arrayOf( private class SortFilter : UriSelectFilter(
"Sort",
"orderby",
arrayOf(
Pair("a-z", "A-Z"), Pair("a-z", "A-Z"),
Pair("views_a", "Views all-time"), Pair("views_a", "Views all-time"),
Pair("views_y", "Views last 365 days"), Pair("views_y", "Views last 365 days"),
@ -491,7 +522,10 @@ class MangaPark : ConfigurableSource, ParsedHttpSource() {
Pair("rating", "Rating"), Pair("rating", "Rating"),
Pair("update", "Latest"), Pair("update", "Latest"),
Pair("create", "New manga") 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. * Class that creates a select filter. Each entry in the dropdown has a name and a display name.

View File

@ -8,13 +8,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
abstract class MRP( abstract class MRP(
override val name: String, override val name: String,

View File

@ -15,7 +15,8 @@ import org.jsoup.nodes.Element
class MRPFactory : SourceFactory { class MRPFactory : SourceFactory {
override fun createSources(): List<Source> = listOf( override fun createSources(): List<Source> = listOf(
Mangareader(), Mangareader(),
Mangapanda()) Mangapanda()
)
} }
class Mangareader : MRP("Mangareader", "https://www.mangareader.net") { class Mangareader : MRP("Mangareader", "https://www.mangareader.net") {

View File

@ -10,11 +10,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource 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.HttpUrl
import okhttp3.MediaType import okhttp3.MediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -23,6 +18,11 @@ import okhttp3.Response
import okhttp3.ResponseBody import okhttp3.ResponseBody
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element 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() { class MangaRockEs : ParsedHttpSource() {
@ -35,7 +35,8 @@ class MangaRockEs : ParsedHttpSource() {
override val supportsLatest = true override val supportsLatest = true
// Handles the page decoding // Handles the page decoding
override val client: OkHttpClient = network.cloudflareClient.newBuilder().addInterceptor(fun(chain): Response { override val client: OkHttpClient = network.cloudflareClient.newBuilder().addInterceptor(
fun(chain): Response {
val url = chain.request().url().toString() val url = chain.request().url().toString()
val response = chain.proceed(chain.request()) val response = chain.proceed(chain.request())
if (!url.endsWith(".mri")) return response if (!url.endsWith(".mri")) return response
@ -44,7 +45,8 @@ class MangaRockEs : ParsedHttpSource() {
val mediaType = MediaType.parse("image/webp") val mediaType = MediaType.parse("image/webp")
val rb = ResponseBody.create(mediaType, decoded) val rb = ResponseBody.create(mediaType, decoded)
return response.newBuilder().body(rb).build() return response.newBuilder().body(rb).build()
}).build() }
).build()
// Popular // Popular
@ -150,7 +152,7 @@ class MangaRockEs : ParsedHttpSource() {
calendar.timeInMillis calendar.timeInMillis
} else { } else {
SimpleDateFormat("MMM d, yyyy", Locale.US).parse(date).time SimpleDateFormat("MMM d, yyyy", Locale.US).parse(date)?.time ?: 0L
} }
} ?: 0 } ?: 0
} }
@ -215,13 +217,18 @@ class MangaRockEs : ParsedHttpSource() {
// Filters // Filters
private class StatusFilter : UriPartFilter("Status", arrayOf( private class StatusFilter : UriPartFilter(
"Status",
arrayOf(
Pair("All", "all"), Pair("All", "all"),
Pair("Completed", "completed"), Pair("Completed", "completed"),
Pair("Ongoing", "ongoing") Pair("Ongoing", "ongoing")
)) )
)
private class RankFilter : UriPartFilter("Rank", arrayOf( private class RankFilter : UriPartFilter(
"Rank",
arrayOf(
Pair("All", "all"), Pair("All", "all"),
Pair("1 - 999", "1-999"), Pair("1 - 999", "1-999"),
Pair("1k - 2k", "1000-2000"), Pair("1k - 2k", "1000-2000"),
@ -234,12 +241,16 @@ class MangaRockEs : ParsedHttpSource() {
Pair("8k - 9k", "8000-9000"), Pair("8k - 9k", "8000-9000"),
Pair("9k - 19k", "9000-10000"), Pair("9k - 19k", "9000-10000"),
Pair("10k - 11k", "10000-11000") Pair("10k - 11k", "10000-11000")
)) )
)
private class SortBy : UriPartFilter("Sort by", arrayOf( private class SortBy : UriPartFilter(
"Sort by",
arrayOf(
Pair("Name", "name"), Pair("Name", "name"),
Pair("Rank", "rank") Pair("Rank", "rank")
)) )
)
private class Genre(name: String, val uriPart: String) : Filter.CheckBox(name) private class Genre(name: String, val uriPart: String) : Filter.CheckBox(name)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres) private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Genres", genres)

View File

@ -12,13 +12,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.Jsoup.parse import org.jsoup.Jsoup.parse
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
class Mangasail : ParsedHttpSource() { class Mangasail : ParsedHttpSource() {
@ -155,7 +155,7 @@ class Mangasail : ParsedHttpSource() {
} }
private fun parseChapterDate(string: String): Long { 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> { override fun pageListParse(document: Document): List<Page> {

View File

@ -17,14 +17,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import rx.Observable 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 * 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 } val endRange = ((page * 24) - 1).let { if (it <= directory.lastIndex) it else directory.lastIndex }
for (i in (((page - 1) * 24)..endRange)) { for (i in (((page - 1) * 24)..endRange)) {
mangas.add(SManga.create().apply { mangas.add(
SManga.create().apply {
title = directory[i]["s"].string title = directory[i]["s"].string
url = "/manga/${directory[i]["i"].string}" url = "/manga/${directory[i]["i"].string}"
thumbnail_url = "https://cover.mangabeast01.com/cover/${directory[i]["i"].string}.jpg" thumbnail_url = "https://cover.mangabeast01.com/cover/${directory[i]["i"].string}.jpg"
}) }
)
} }
return MangasPage(mangas, endRange < directory.lastIndex) return MangasPage(mangas, endRange < directory.lastIndex)
} }

View File

@ -8,14 +8,14 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class Mangatown : ParsedHttpSource() { class Mangatown : ParsedHttpSource() {
@ -110,7 +110,7 @@ class Mangatown : ParsedHttpSource() {
date.contains("Yesterday") -> Calendar.getInstance().apply { add(Calendar.DAY_OF_MONTH, -1) }.timeInMillis date.contains("Yesterday") -> Calendar.getInstance().apply { add(Calendar.DAY_OF_MONTH, -1) }.timeInMillis
else -> { else -> {
try { try {
SimpleDateFormat("MMM dd,yyyy", Locale.US).parse(date).time SimpleDateFormat("MMM dd,yyyy", Locale.US).parse(date)?.time ?: 0L
} catch (e: Exception) { } catch (e: Exception) {
0L 0L
} }

View File

@ -6,13 +6,13 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import java.text.SimpleDateFormat
import java.util.Locale
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import org.jsoup.select.Elements import org.jsoup.select.Elements
import java.text.SimpleDateFormat
import java.util.Locale
class ManhwaTime : ParsedHttpSource() { class ManhwaTime : ParsedHttpSource() {

View File

@ -9,12 +9,12 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import java.text.SimpleDateFormat
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import rx.Observable import rx.Observable
import java.text.SimpleDateFormat
class ManManga : ParsedHttpSource() { class ManManga : ParsedHttpSource() {
override val name = "Man Manga" override val name = "Man Manga"

Some files were not shown because too many files have changed in this diff Show More