GigaViewer: show all chapters, fix Corocoro, cleanup (#12321)
* GigaViewer: show all chapters, fix Corocoro, cleanup * optimize icon assets * throw exception if chapter is not available
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 59 KiB |
|
@ -23,8 +23,8 @@ class ComicGardo : GigaViewer(
|
|||
override fun popularMangaSelector(): String = "ul.series-section-list li.series-section-item > a"
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.select("h5.series-title").text()
|
||||
thumbnail_url = element.select("div.thumb img").attr("data-src")
|
||||
title = element.selectFirst("h5.series-title").text()
|
||||
thumbnail_url = element.selectFirst("div.thumb img").attr("data-src")
|
||||
setUrlWithoutDomain(element.attr("href"))
|
||||
}
|
||||
|
||||
|
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 655 B |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 43 KiB |
|
@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.extension.ja.corocoroonline
|
|||
|
||||
import eu.kanade.tachiyomi.multisrc.gigaviewer.GigaViewer
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
|
@ -19,6 +18,8 @@ class CorocoroOnline : GigaViewer(
|
|||
"https://cdn-img.www.corocoro.jp/public/page"
|
||||
) {
|
||||
|
||||
override val supportsLatest: Boolean = false
|
||||
|
||||
override val client: OkHttpClient = super.client.newBuilder()
|
||||
.addInterceptor(::imageIntercept)
|
||||
.build()
|
||||
|
@ -27,23 +28,18 @@ class CorocoroOnline : GigaViewer(
|
|||
|
||||
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/manga", headers)
|
||||
|
||||
override fun popularMangaSelector(): String = "ul.p-list-manga li.p-wp-list-item > a"
|
||||
override fun popularMangaSelector(): String = "a.p-article-wrap"
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.selectFirst("h3.p-article-title")!!.text()
|
||||
.substringBefore("第")
|
||||
.trim()
|
||||
thumbnail_url = element.selectFirst("img")!!.attr("src")
|
||||
.substringAfter(']')
|
||||
thumbnail_url = element.selectFirst("> .p-article-image > img")!!.attr("src")
|
||||
setUrlWithoutDomain(element.attr("href"))
|
||||
}
|
||||
|
||||
override fun latestUpdatesSelector(): String = "div.p-manga-today a.p-article-wrap"
|
||||
|
||||
// Site doesn't have a manga search and only returns news in search results.
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||
return client.newCall(popularMangaRequest(page))
|
||||
.asObservableSuccess()
|
||||
.map(::popularMangaParse)
|
||||
return fetchPopularManga(page)
|
||||
.map { allManga ->
|
||||
val filteredManga = allManga.mangas.filter { manga ->
|
||||
manga.title.contains(query, true)
|
||||
|
@ -65,6 +61,8 @@ class CorocoroOnline : GigaViewer(
|
|||
// All chapters seems to be free.
|
||||
override fun chapterListSelector(): String = "li.episode"
|
||||
|
||||
override val chapterListMode = CHAPTER_LIST_LOCKED
|
||||
|
||||
// The source have no collections, so no need to have filters.
|
||||
override fun getFilterList(): FilterList = FilterList()
|
||||
|
||||
|
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 913 B |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 995 B |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 19 KiB |
|
@ -27,9 +27,9 @@ class KurageBunch : GigaViewer(
|
|||
override fun popularMangaSelector(): String = "ul.page-series-list li div.item-box"
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.select("a.series-data-container h4").text()
|
||||
thumbnail_url = element.select("a.series-thumb img").attr("data-src")
|
||||
setUrlWithoutDomain(element.select("a").first()!!.attr("href"))
|
||||
title = element.selectFirst("a.series-data-container h4").text()
|
||||
thumbnail_url = element.selectFirst("a.series-thumb img").attr("data-src")
|
||||
setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||
}
|
||||
|
||||
override fun chapterListSelector(): String = "li.episode"
|
||||
|
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 105 KiB |
|
@ -21,8 +21,8 @@ class MagazinePocket : GigaViewer(
|
|||
override fun popularMangaSelector(): String = "ul.daily-series li.daily-series-item > a"
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.select("h4.daily-series-title").text()
|
||||
thumbnail_url = element.select("div.daily-series-thumb img").attr("data-src")
|
||||
title = element.selectFirst("h4.daily-series-title").text()
|
||||
thumbnail_url = element.selectFirst("div.daily-series-thumb img").attr("data-src")
|
||||
setUrlWithoutDomain(element.attr("href"))
|
||||
}
|
||||
|
||||
|
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 22 KiB |
|
@ -28,7 +28,7 @@ class SundayWebEvery : GigaViewer(
|
|||
|
||||
override fun latestUpdatesSelector(): String = "h3#series-$dayOfWeek + section " + popularMangaSelector()
|
||||
|
||||
override fun chapterListSelector(): String = "li.episode:not(.private)"
|
||||
override val chapterListMode = CHAPTER_LIST_LOCKED
|
||||
|
||||
override fun getCollections(): List<Collection> = listOf(
|
||||
Collection("連載作品", ""),
|
||||
|
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 19 KiB |
|
@ -23,14 +23,14 @@ class TonariNoYoungJump : GigaViewer(
|
|||
override fun popularMangaSelector(): String = "ul.series-table-list li.subpage-table-list-item > a"
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.select("h4.title").text()
|
||||
thumbnail_url = element.select("div.subpage-image-wrapper img").attr("data-src")
|
||||
title = element.selectFirst("h4.title").text()
|
||||
thumbnail_url = element.selectFirst("div.subpage-image-wrapper img").attr("data-src")
|
||||
.replace("{width}", "528")
|
||||
.replace("{height}", "528")
|
||||
setUrlWithoutDomain(element.attr("href"))
|
||||
}
|
||||
|
||||
override fun chapterListSelector(): String = "li.episode"
|
||||
override val chapterListMode = CHAPTER_LIST_LOCKED
|
||||
|
||||
override fun getCollections(): List<Collection> = listOf(
|
||||
Collection("連載中", ""),
|
||||
|
|
|
@ -14,6 +14,7 @@ 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 kotlinx.serialization.SerializationException
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
|
@ -22,7 +23,7 @@ import okhttp3.Call
|
|||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
|
@ -66,8 +67,8 @@ abstract class GigaViewer(
|
|||
override fun popularMangaSelector(): String = "ul.series-list li a"
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.select("h2.series-list-title").text()
|
||||
thumbnail_url = element.select("div.series-list-thumb img")
|
||||
title = element.selectFirst("h2.series-list-title").text()
|
||||
thumbnail_url = element.selectFirst("div.series-list-thumb img")
|
||||
.attr("data-src")
|
||||
setUrlWithoutDomain(element.attr("href"))
|
||||
}
|
||||
|
@ -112,9 +113,9 @@ abstract class GigaViewer(
|
|||
override fun searchMangaSelector() = "ul.search-series-list li, ul.series-list li"
|
||||
|
||||
override fun searchMangaFromElement(element: Element): SManga = SManga.create().apply {
|
||||
title = element.select("div.title-box p.series-title").text()
|
||||
thumbnail_url = element.select("div.thmb-container a img").attr("src")
|
||||
setUrlWithoutDomain(element.select("div.thmb-container a").attr("href"))
|
||||
title = element.selectFirst("div.title-box p.series-title").text()
|
||||
thumbnail_url = element.selectFirst("div.thmb-container a img").attr("src")
|
||||
setUrlWithoutDomain(element.selectFirst("div.thmb-container a").attr("href"))
|
||||
}
|
||||
|
||||
override fun searchMangaNextPageSelector(): String? = null
|
||||
|
@ -122,19 +123,19 @@ abstract class GigaViewer(
|
|||
protected open fun mangaDetailsInfoSelector(): String = "section.series-information div.series-header"
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply {
|
||||
val infoElement = document.select(mangaDetailsInfoSelector()).first()!!
|
||||
val infoElement = document.selectFirst(mangaDetailsInfoSelector())!!
|
||||
|
||||
title = infoElement.select("h1.series-header-title").text()
|
||||
author = infoElement.select("h2.series-header-author").text()
|
||||
title = infoElement.selectFirst("h1.series-header-title").text()
|
||||
author = infoElement.selectFirst("h2.series-header-author").text()
|
||||
artist = author
|
||||
description = infoElement.select("p.series-header-description").text()
|
||||
thumbnail_url = infoElement.select("div.series-header-image-wrapper img")
|
||||
description = infoElement.selectFirst("p.series-header-description").text()
|
||||
thumbnail_url = infoElement.selectFirst("div.series-header-image-wrapper img")
|
||||
.attr("data-src")
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
val readableProductList = document.select("div.js-readable-product-list").first()!!
|
||||
val readableProductList = document.selectFirst("div.js-readable-product-list")!!
|
||||
val firstListEndpoint = readableProductList.attr("data-first-list-endpoint")
|
||||
.toHttpUrlOrNull()!!
|
||||
val latestListEndpoint = readableProductList.attr("data-latest-list-endpoint")
|
||||
|
@ -162,9 +163,9 @@ abstract class GigaViewer(
|
|||
response.request.url.toString()
|
||||
)
|
||||
|
||||
chapters += tempDocument
|
||||
tempDocument
|
||||
.select("ul.series-episode-list " + chapterListSelector())
|
||||
.map { element -> chapterFromElement(element) }
|
||||
.mapTo(chapters) { element -> chapterFromElement(element) }
|
||||
|
||||
request = GET(readMoreEndpoint, newHeaders)
|
||||
result = client.newCall(request).execute()
|
||||
|
@ -175,15 +176,22 @@ abstract class GigaViewer(
|
|||
return chapters
|
||||
}
|
||||
|
||||
override fun chapterListSelector() = "li.episode:has(span.series-episode-list-is-free)"
|
||||
override fun chapterListSelector() = "li.episode"
|
||||
|
||||
protected open val chapterListMode = CHAPTER_LIST_PAID
|
||||
|
||||
override fun chapterFromElement(element: Element): SChapter {
|
||||
val info = element.select("a.series-episode-list-container").first() ?: element
|
||||
val info = element.selectFirst("a.series-episode-list-container") ?: element
|
||||
val mangaUrl = element.ownerDocument().location()
|
||||
|
||||
return SChapter.create().apply {
|
||||
name = info.select("h4.series-episode-list-title").text()
|
||||
date_upload = info.select("span.series-episode-list-date").first()
|
||||
name = info.selectFirst("h4.series-episode-list-title").text()
|
||||
if (chapterListMode == CHAPTER_LIST_PAID && element.selectFirst("span.series-episode-list-is-free") == null) {
|
||||
name = YEN_BANKNOTE + name
|
||||
} else if (chapterListMode == CHAPTER_LIST_LOCKED && element.hasClass("private")) {
|
||||
name = LOCK + name
|
||||
}
|
||||
date_upload = info.selectFirst("span.series-episode-list-date")
|
||||
?.text().orEmpty()
|
||||
.toDate()
|
||||
scanlator = publisher
|
||||
|
@ -192,9 +200,15 @@ abstract class GigaViewer(
|
|||
}
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
val episode = document.select("script#episode-json")
|
||||
val episode = document.selectFirst("script#episode-json")
|
||||
.attr("data-value")
|
||||
.let { json.decodeFromString<GigaViewerEpisodeDto>(it) }
|
||||
.let {
|
||||
try {
|
||||
json.decodeFromString<GigaViewerEpisodeDto>(it)
|
||||
} catch (e: SerializationException) {
|
||||
throw Exception("このチャプターは非公開です\nChapter is not available!")
|
||||
}
|
||||
}
|
||||
|
||||
return episode.readableProduct.pageStructure.pages
|
||||
.filter { it.type == "main" }
|
||||
|
@ -251,7 +265,7 @@ abstract class GigaViewer(
|
|||
|
||||
val response = chain.proceed(request)
|
||||
val image = decodeImage(response.body!!.byteStream(), width, height)
|
||||
val body = image.toResponseBody("image/png".toMediaTypeOrNull())
|
||||
val body = image.toResponseBody(jpegMediaType)
|
||||
|
||||
response.close()
|
||||
|
||||
|
@ -283,7 +297,7 @@ abstract class GigaViewer(
|
|||
}
|
||||
|
||||
val output = ByteArrayOutputStream()
|
||||
result.compress(Bitmap.CompressFormat.PNG, 100, output)
|
||||
result.compress(Bitmap.CompressFormat.JPEG, 90, output)
|
||||
return output.toByteArray()
|
||||
}
|
||||
|
||||
|
@ -306,5 +320,12 @@ abstract class GigaViewer(
|
|||
|
||||
private const val DIVIDE_NUM = 4
|
||||
private const val MULTIPLE = 8
|
||||
private val jpegMediaType = "image/jpeg".toMediaType()
|
||||
|
||||
const val CHAPTER_LIST_PAID = 0
|
||||
const val CHAPTER_LIST_LOCKED = 1
|
||||
|
||||
private const val YEN_BANKNOTE = "💴 "
|
||||
private const val LOCK = "🔒 "
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ class GigaViewerGenerator : ThemeSourceGenerator {
|
|||
|
||||
override val themeClass = "GigaViewer"
|
||||
|
||||
override val baseVersionCode: Int = 4
|
||||
override val baseVersionCode: Int = 5
|
||||
|
||||
override val sources = listOf(
|
||||
SingleLang("Comic Days", "https://comic-days.com", "ja"),
|
||||
|
|