[RU]WebOfComics (#11814)
* WebOfComics * partial image parsing * page img more * typos * mangaDetails * search * popular new page more comics * LICENSED * site remembers last POST request sorting * empty author * date * more work chapter * subPage (more work chapter) * until pages (more work chapter) * another one uploadUrl * control quantity parse * date companion
This commit is contained in:
parent
4e9f670523
commit
4f1d0b6517
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="eu.kanade.tachiyomi.extension" />
|
|
@ -0,0 +1,15 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
extName = 'Web of Comics'
|
||||
pkgNameSuffix = 'ru.webofcomics'
|
||||
extClass = '.WebOfComics'
|
||||
extVersionCode = 1
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':lib-ratelimit')
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
After Width: | Height: | Size: 135 KiB |
|
@ -0,0 +1,254 @@
|
|||
package eu.kanade.tachiyomi.extension.ru.webofcomics
|
||||
|
||||
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
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.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class WebOfComics : ParsedHttpSource() {
|
||||
|
||||
override val name = "Web of Comics"
|
||||
|
||||
override val baseUrl = "https://webofcomics.ru"
|
||||
|
||||
override val lang = "ru"
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
override fun headersBuilder(): Headers.Builder = Headers.Builder()
|
||||
.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.50")
|
||||
.add("Referer", baseUrl)
|
||||
|
||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
||||
.connectTimeout(10, TimeUnit.SECONDS)
|
||||
.readTimeout(30, TimeUnit.SECONDS)
|
||||
.addNetworkInterceptor(RateLimitInterceptor(3))
|
||||
.build()
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
return POST(
|
||||
"$baseUrl/page/$page",
|
||||
body = FormBody.Builder()
|
||||
.add("dlenewssortby", "rating")
|
||||
.add("dledirection", "desc")
|
||||
.add("set_new_sort", "dle_sort_main")
|
||||
.add("set_direction_sort", "dle_direction_main")
|
||||
.build(),
|
||||
headers = headers
|
||||
)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
return POST(
|
||||
"$baseUrl/page/$page",
|
||||
body = FormBody.Builder()
|
||||
.add("dlenewssortby", "date")
|
||||
.add("dledirection", "desc")
|
||||
.add("set_new_sort", "dle_sort_main")
|
||||
.add("set_direction_sort", "dle_direction_main")
|
||||
.build(),
|
||||
headers = headers
|
||||
)
|
||||
}
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
return POST(
|
||||
"$baseUrl/index.php?do=search",
|
||||
body = FormBody.Builder()
|
||||
.add("do", "search")
|
||||
.add("subaction", "search")
|
||||
.add("story", query)
|
||||
.add("search_start", page.toString())
|
||||
.build(),
|
||||
headers = headers
|
||||
)
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup()
|
||||
|
||||
val mangas = document.select(searchMangaSelector()).map { element ->
|
||||
searchMangaFromElement(element)
|
||||
}
|
||||
return MangasPage(mangas, mangas.isNotEmpty())
|
||||
}
|
||||
|
||||
override fun popularMangaSelector() = ".movie-item"
|
||||
|
||||
override fun latestUpdatesSelector() = popularMangaSelector()
|
||||
|
||||
override fun searchMangaSelector() = popularMangaSelector()
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga {
|
||||
val manga = SManga.create()
|
||||
manga.thumbnail_url = baseUrl + element.select(".lazyload").first().attr("data-src").replace("/thumbs", "")
|
||||
element.select(".movie-title").first().let {
|
||||
manga.setUrlWithoutDomain(it.attr("href"))
|
||||
manga.title = it.html().substringBefore("<div>")
|
||||
}
|
||||
return manga
|
||||
}
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element) = popularMangaFromElement(element)
|
||||
|
||||
override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
|
||||
|
||||
override fun popularMangaNextPageSelector() = ".pnext a"
|
||||
|
||||
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
|
||||
|
||||
override fun searchMangaNextPageSelector(): String? = null
|
||||
|
||||
private fun parseStatus(status: String): Int {
|
||||
return when (status) {
|
||||
"Завершён" -> SManga.COMPLETED
|
||||
"Продолжается" -> SManga.ONGOING
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply {
|
||||
val infoElement = document.select(".page-cols").first()
|
||||
val infoElement2 = document.select(".m-info2 .sliceinfo1")
|
||||
title = infoElement.select("h1").first().text()
|
||||
thumbnail_url = baseUrl + infoElement.select(".lazyload").first().attr("data-src")
|
||||
description = document.select(".slice-this").first().text().substringAfter("Описание:").trim()
|
||||
author = infoElement2.select(":contains(Автор) a").joinToString { it.text() }
|
||||
if (author.isNullOrEmpty())
|
||||
author = infoElement.select(".mi-item:contains(Издательство)").first().text()
|
||||
artist = infoElement2.select(":contains(Художник) a").joinToString { it.text() }
|
||||
genre = (infoElement.select(".mi-item:contains(Тип) a") + infoElement.select(".mi-item:contains(Возраст) a") + infoElement.select(".mi-item:contains(Формат) a") + infoElement.select(".mi-item:contains(Жанр) a")).joinToString { it.text() }
|
||||
status = if (document.toString().contains("Удалено по просьбе правообладателя"))
|
||||
SManga.LICENSED
|
||||
else
|
||||
parseStatus(infoElement.select(".mi-item:contains(Перевод) a").first().text())
|
||||
}
|
||||
|
||||
override fun chapterListRequest(manga: SManga): Request {
|
||||
val TypeSeries =
|
||||
with(manga.url) {
|
||||
when {
|
||||
contains("/manga/") -> "xsort='tommanga,glavamanga' template='custom-linkstocomics-xfmanga-guest'"
|
||||
contains("/comics/") -> "xsort='number' template='custom-linkstocomics-xfcomics-guest'"
|
||||
else -> "error"
|
||||
}
|
||||
}
|
||||
return POST(
|
||||
baseUrl + "/engine/ajax/customajax.php",
|
||||
body = FormBody.Builder()
|
||||
.add("castom", "custom senxf='fastnavigation|${manga.url.substringAfterLast("/").substringBefore("-")}' $TypeSeries limit='3000' sort='asc' cache='yes'")
|
||||
.build(),
|
||||
headers = headers
|
||||
)
|
||||
}
|
||||
|
||||
override fun chapterListSelector() = ".ltcitems:has(a:not(.alttranslatelink))"
|
||||
|
||||
override fun chapterFromElement(element: Element): SChapter {
|
||||
val chapter = SChapter.create()
|
||||
element.select("a").first().let {
|
||||
chapter.name = it.text().substringAfterLast(":")
|
||||
chapter.chapter_number = it.text().substringAfter("Глава").substringAfter("#").substringBefore("-").toFloatOrNull() ?: -1f
|
||||
chapter.setUrlWithoutDomain(it.attr("href"))
|
||||
}
|
||||
chapter.date_upload = simpleDateFormat.parse(element.select("div").first().text().trim())?.time ?: 0L
|
||||
return chapter
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return super.chapterListParse(response).reversed()
|
||||
}
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
var baseImgUrl = document.select("link[rel='image_src']").last().attr("href")
|
||||
|
||||
val publicUrl = "/public_html"
|
||||
val uploadUrl =
|
||||
with(baseImgUrl) {
|
||||
when {
|
||||
contains("/uploads/") -> "/uploads/"
|
||||
contains("/manga/") -> "/manga/"
|
||||
contains("/mangaparser/") -> "/mangaparser/"
|
||||
else -> "errorUploads"
|
||||
}
|
||||
}
|
||||
baseImgUrl = baseImgUrl.substringBefore(uploadUrl)
|
||||
if (baseImgUrl.contains(publicUrl))
|
||||
baseImgUrl =
|
||||
baseImgUrl.substringBefore(publicUrl) + "/www/" +
|
||||
baseUrl.substringAfter("://") + publicUrl +
|
||||
baseImgUrl.substringAfter(publicUrl)
|
||||
|
||||
if (document.select(".readtab .lazyload").isNotEmpty()) {
|
||||
return document.select(".readtab .lazyload").mapIndexed { index, element ->
|
||||
Page(
|
||||
index,
|
||||
"",
|
||||
baseImgUrl + uploadUrl + element.attr("data-src").substringAfter(uploadUrl)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val counterPageStr = document.select("#comics script").toString()
|
||||
|
||||
val startPageStr = counterPageStr
|
||||
.substringAfter("for(var i =")
|
||||
.substringBefore("; i <")
|
||||
.trim()
|
||||
var endPageStr = counterPageStr
|
||||
.substringAfter("; i <")
|
||||
.substringBefore("; i++)")
|
||||
.trim()
|
||||
|
||||
if (endPageStr.contains("="))
|
||||
endPageStr = (endPageStr.replace("=", "").trim().toInt() + 1).toString()
|
||||
|
||||
if (baseImgUrl.contains("/share."))
|
||||
baseImgUrl = counterPageStr
|
||||
.substringAfter("data-src=\"")
|
||||
.substringBefore("' + i")
|
||||
.trim().replace("https://feik.domain.ru/", "https://read.webofcomics.ru/webofcomics.ru/www/webofcomics.ru/public_html/") +
|
||||
counterPageStr
|
||||
.substringAfter("i + '")
|
||||
.substringBefore("\">")
|
||||
.trim()
|
||||
|
||||
var subPage = ""
|
||||
|
||||
return (startPageStr.toInt() until endPageStr.toInt()).mapIndexed { index, page ->
|
||||
if (startPageStr == "0") {
|
||||
subPage = when {
|
||||
page < 10 -> "00"
|
||||
page < 100 -> "0"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
Page(
|
||||
index,
|
||||
"",
|
||||
baseImgUrl.substringBeforeLast("/") + "/$subPage$page." + baseImgUrl.substringAfterLast(".")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun imageUrlParse(document: Document) = ""
|
||||
|
||||
companion object {
|
||||
private val simpleDateFormat by lazy { SimpleDateFormat("dd.MM.yyyy", Locale.US) }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue