parent
aea608013b
commit
050efe196b
|
@ -1,7 +0,0 @@
|
||||||
ext {
|
|
||||||
extName = 'Read Comics Book'
|
|
||||||
extClass = '.ReadComicsBook'
|
|
||||||
extVersionCode = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
|
Binary file not shown.
Before Width: | Height: | Size: 7.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
Binary file not shown.
Before Width: | Height: | Size: 24 KiB |
Binary file not shown.
Before Width: | Height: | Size: 41 KiB |
|
@ -1,14 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.readcomicsbook
|
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
class Data<T>(val data: T)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
class Comic(
|
|
||||||
val title: String,
|
|
||||||
val slug: String,
|
|
||||||
@SerialName("img_url") val cover: String? = null,
|
|
||||||
)
|
|
|
@ -1,38 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.readcomicsbook
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
|
||||||
|
|
||||||
class GenreFilter : Filter.Select<String>(
|
|
||||||
"Genres",
|
|
||||||
genres.map { it.first }.toTypedArray(),
|
|
||||||
) {
|
|
||||||
val selected get() = genres[state].second
|
|
||||||
}
|
|
||||||
|
|
||||||
private val genres = listOf(
|
|
||||||
"Marvel" to "marvel",
|
|
||||||
"DC Comics" to "dc-comics",
|
|
||||||
"Action" to "action",
|
|
||||||
"Adventure" to "adventure",
|
|
||||||
"Anthology" to "anthology",
|
|
||||||
"Anthropomorphic" to "anthropomorphic",
|
|
||||||
"Biography" to "biography",
|
|
||||||
"Children" to "children",
|
|
||||||
"Comedy" to "comedy",
|
|
||||||
"Crime" to "crime",
|
|
||||||
"Cyborgs" to "cyborgs",
|
|
||||||
"Dark Horse" to "dark-horse",
|
|
||||||
"Demons" to "demons",
|
|
||||||
"Drama" to "drama",
|
|
||||||
"Fantasy" to "fantasy",
|
|
||||||
"Family" to "family",
|
|
||||||
"Fighting" to "fighting",
|
|
||||||
"Gore" to "gore",
|
|
||||||
"Graphic Novels" to "graphic-novels",
|
|
||||||
"Historical" to "historical",
|
|
||||||
"Horror" to "horror",
|
|
||||||
"Leading Ladies" to "leading-ladies",
|
|
||||||
"Literature" to "literature",
|
|
||||||
"Magic" to "magic",
|
|
||||||
"Manga" to "manga",
|
|
||||||
)
|
|
|
@ -1,207 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.readcomicsbook
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import kotlinx.serialization.json.decodeFromStream
|
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
|
||||||
import okhttp3.Request
|
|
||||||
import okhttp3.Response
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
import java.text.ParseException
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Locale
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class ReadComicsBook : HttpSource() {
|
|
||||||
override val name = "Read Comics Book"
|
|
||||||
override val lang = "en"
|
|
||||||
override val baseUrl = "https://readcomicsplus.net"
|
|
||||||
override val supportsLatest = true
|
|
||||||
override val client = network.cloudflareClient.newBuilder()
|
|
||||||
.readTimeout(1L, TimeUnit.MINUTES)
|
|
||||||
.build()
|
|
||||||
private val json: Json by injectLazy()
|
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request {
|
|
||||||
val url = buildString {
|
|
||||||
append(baseUrl)
|
|
||||||
append("/popular-comics")
|
|
||||||
if (page > 1) {
|
|
||||||
append("?page=")
|
|
||||||
append(page.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GET(url, headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
|
||||||
val doc = response.asJsoup()
|
|
||||||
|
|
||||||
return MangasPage(
|
|
||||||
mangas = doc.select(".manga-list .manga-thumb a").map {
|
|
||||||
SManga.create().apply {
|
|
||||||
setUrlWithoutDomain(it.absUrl("href"))
|
|
||||||
title = it.attr("title")
|
|
||||||
thumbnail_url = it.selectFirst("img")?.attr("data-original")
|
|
||||||
?.replace("http://", "https://")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hasNextPage = doc.selectFirst(".page-pagination .next-page") != null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int): Request {
|
|
||||||
val url = buildString {
|
|
||||||
append(baseUrl)
|
|
||||||
append("/comic-updates")
|
|
||||||
if (page > 1) {
|
|
||||||
append("?page=")
|
|
||||||
append(page.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return GET(url, headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response) = popularMangaParse(response)
|
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
|
||||||
return if (query.isNotBlank()) {
|
|
||||||
val url = "$baseUrl/ajax/search".toHttpUrl().newBuilder()
|
|
||||||
.addQueryParameter("q", query.trim())
|
|
||||||
.build()
|
|
||||||
|
|
||||||
GET(url, headers)
|
|
||||||
} else {
|
|
||||||
val url = buildString {
|
|
||||||
append(baseUrl)
|
|
||||||
append("/genre/")
|
|
||||||
append(
|
|
||||||
filters.filterIsInstance<GenreFilter>().first().selected,
|
|
||||||
)
|
|
||||||
if (page > 1) {
|
|
||||||
append("?page=")
|
|
||||||
append(page.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GET(url, headers)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFilterList(): FilterList {
|
|
||||||
return FilterList(
|
|
||||||
GenreFilter(),
|
|
||||||
Filter.Header("Filters don't work with text search"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage {
|
|
||||||
if (response.request.url.pathSegments[0] == "genre") {
|
|
||||||
return popularMangaParse(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
val res = json.decodeFromStream<Data<List<Comic>>>(response.body.byteStream())
|
|
||||||
|
|
||||||
return MangasPage(
|
|
||||||
mangas = res.data.map {
|
|
||||||
SManga.create().apply {
|
|
||||||
url = "/comic/${it.slug}"
|
|
||||||
title = it.title
|
|
||||||
thumbnail_url = it.cover ?: "$baseUrl/images/sites/default.jpg"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
hasNextPage = false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga {
|
|
||||||
val doc = response.asJsoup()
|
|
||||||
|
|
||||||
return SManga.create().apply {
|
|
||||||
title = doc.selectFirst(".headline h1")!!.text()
|
|
||||||
author = doc.selectFirst("div.meta-data.mt-author")?.ownText()
|
|
||||||
status = with(doc.selectFirst("div.meta-data:has(> label:contains(status))")?.ownText()) {
|
|
||||||
when {
|
|
||||||
equals("ongoing", true) -> SManga.ONGOING
|
|
||||||
equals("completed", true) -> SManga.COMPLETED
|
|
||||||
else -> SManga.UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
thumbnail_url = doc.selectFirst("div.manga-thumb img")?.absUrl("data-original")
|
|
||||||
?.replace("http://", "https://")
|
|
||||||
genre = doc.select("div.meta-data a[href*=/genre/]").eachText().joinToString()
|
|
||||||
description = buildString {
|
|
||||||
doc.selectFirst(".summary-content")?.text()?.let(::append)
|
|
||||||
if (isNotBlank()) {
|
|
||||||
append("\n\n")
|
|
||||||
}
|
|
||||||
doc.selectFirst("div.meta-data:has(> label:contains(Other Names))")
|
|
||||||
?.text()?.let(::appendLine)
|
|
||||||
doc.selectFirst("div.meta-data.view")
|
|
||||||
?.text()?.let(::appendLine)
|
|
||||||
doc.selectFirst("div.rating")?.text()?.let {
|
|
||||||
append("Rating: ")
|
|
||||||
append(it, "\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
|
||||||
val doc = response.asJsoup()
|
|
||||||
|
|
||||||
return doc.select("ul.chapter-list li").drop(1).map {
|
|
||||||
SChapter.create().apply {
|
|
||||||
with(it.selectFirst("a")!!) {
|
|
||||||
setUrlWithoutDomain(absUrl("href"))
|
|
||||||
name = text()
|
|
||||||
}
|
|
||||||
date_upload = it.selectFirst("span.time")?.text().parseDate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String?.parseDate(): Long {
|
|
||||||
if (isNullOrBlank()) return 0L
|
|
||||||
|
|
||||||
return try {
|
|
||||||
dateFormat.parse(this)?.time ?: 0L
|
|
||||||
} catch (_: ParseException) {
|
|
||||||
0L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val dateFormat = SimpleDateFormat("dd/MM/yyy", Locale.ENGLISH)
|
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
|
||||||
val doc = response.asJsoup()
|
|
||||||
|
|
||||||
return doc.select(".page-chapter img").mapIndexed { idx, img ->
|
|
||||||
Page(idx, imageUrl = img.attr("data-original"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun imageRequest(page: Page): Request {
|
|
||||||
var url = page.imageUrl!!
|
|
||||||
|
|
||||||
if (url.toHttpUrl().host.contains("blogspot") && url.contains("s1600")) {
|
|
||||||
url = url.replace("s1600", "s0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return GET(url, headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue