Web Comic Gamma: update Plus for new theme (#14301)
@ -1,83 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.extension.ja.webcomicgamma
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.multisrc.comicgamma.ComicGamma
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
|
||||||
import org.jsoup.nodes.Document
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
import org.jsoup.select.Evaluator
|
|
||||||
|
|
||||||
class WebComicGamma : ComicGamma("Web Comic Gamma", "https://webcomicgamma.takeshobo.co.jp") {
|
|
||||||
override val supportsLatest = false
|
|
||||||
|
|
||||||
override fun popularMangaSelector() = ".tab_panel.active .manga_item"
|
|
||||||
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
|
|
||||||
url = element.selectFirst(Evaluator.Tag("a")).attr("href")
|
|
||||||
title = element.selectFirst(Evaluator.Class("manga_title")).text()
|
|
||||||
author = element.selectFirst(Evaluator.Class("manga_author")).text()
|
|
||||||
val genreList = element.select(Evaluator.Tag("li")).map { it.text() }
|
|
||||||
genre = genreList.joinToString()
|
|
||||||
status = when {
|
|
||||||
genreList.contains("完結") && !genreList.contains("リピート配信") -> SManga.COMPLETED
|
|
||||||
else -> SManga.ONGOING
|
|
||||||
}
|
|
||||||
thumbnail_url = element.selectFirst(Evaluator.Tag("img")).absUrl("src")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used.")
|
|
||||||
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException("Not used.")
|
|
||||||
override fun latestUpdatesSelector() = throw UnsupportedOperationException("Not used.")
|
|
||||||
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException("Not used.")
|
|
||||||
|
|
||||||
override fun mangaDetailsParse(document: Document): SManga {
|
|
||||||
val titleElement = document.selectFirst(Evaluator.Class("manga__title"))
|
|
||||||
val titleName = titleElement.child(0).text()
|
|
||||||
val desc = document.selectFirst(".detail__item > p")?.run {
|
|
||||||
select(Evaluator.Tag("br")).prepend("\\n")
|
|
||||||
this.text().replace("\\n", "\n").replace("\n ", "\n")
|
|
||||||
}
|
|
||||||
val listResponse = client.newCall(popularMangaRequest(0)).execute()
|
|
||||||
val manga = popularMangaParse(listResponse).mangas.find { it.title == titleName }
|
|
||||||
return manga?.apply { description = desc } ?: SManga.create().apply {
|
|
||||||
author = titleElement.child(1).text()
|
|
||||||
description = desc
|
|
||||||
status = SManga.UNKNOWN
|
|
||||||
val slug = document.location().removeSuffix("/").substringAfterLast("/")
|
|
||||||
thumbnail_url = "$baseUrl/img/manga_thumb/${slug}_list.jpg"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun chapterListSelector() = ".read__area > .read__outer > a"
|
|
||||||
override fun chapterFromElement(element: Element) = SChapter.create().apply {
|
|
||||||
url = element.attr("href").toOldChapterUrl()
|
|
||||||
val number = url.removeSuffix("/").substringAfterLast('/').replace('_', '.')
|
|
||||||
val list = element.selectFirst(Evaluator.Class("read__contents")).children()
|
|
||||||
name = "[$number] ${list[0].text()}"
|
|
||||||
if (list.size >= 3) {
|
|
||||||
date_upload = dateFormat.parseJST(list[2].text())?.time ?: 0L
|
|
||||||
}
|
|
||||||
if (date_upload <= 0L) date_upload = -1L // hide unknown ones
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter) =
|
|
||||||
GET(baseUrl + chapter.url.toNewChapterUrl(), headers)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val dateFormat by lazy { getJSTFormat("yyyy年M月dd日") }
|
|
||||||
|
|
||||||
private fun String.toOldChapterUrl(): String {
|
|
||||||
// ../../../_files/madeinabyss/063_2/
|
|
||||||
val segments = split('/')
|
|
||||||
val size = segments.size
|
|
||||||
val slug = segments[size - 3]
|
|
||||||
val number = segments[size - 2]
|
|
||||||
return "/manga/$slug/_files/$number/"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.toNewChapterUrl(): String {
|
|
||||||
val segments = split('/')
|
|
||||||
return "/_files/${segments[2]}/${segments[4]}/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 29 KiB |
@ -1,77 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.extension.ja.webcomicgammaplus
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.multisrc.comicgamma.ComicGamma
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
|
||||||
import org.jsoup.nodes.Document
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
import java.text.DateFormat
|
|
||||||
|
|
||||||
class WebComicGammaPlus : ComicGamma("Web Comic Gamma Plus", "https://gammaplus.takeshobo.co.jp") {
|
|
||||||
override val supportsLatest = true
|
|
||||||
|
|
||||||
override fun popularMangaSelector() = ".work_list li"
|
|
||||||
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
|
|
||||||
setUrlWithoutDomain(element.select("a").attr("abs:href"))
|
|
||||||
val image = element.select("img")
|
|
||||||
title = image.attr("alt").removePrefix("『").removeSuffix("』作品ページへ")
|
|
||||||
thumbnail_url = image.attr("abs:src")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/", headers)
|
|
||||||
override fun latestUpdatesNextPageSelector(): String? = null
|
|
||||||
override fun latestUpdatesSelector() = ".whatsnew li:contains(読む)"
|
|
||||||
override fun latestUpdatesFromElement(element: Element) = SManga.create().apply {
|
|
||||||
val url = element.select(".show_detail").attr("abs:href")
|
|
||||||
setUrlWithoutDomain(url)
|
|
||||||
title = element.select("h3").textNodes()[0].text()
|
|
||||||
thumbnail_url = url + "main.jpg"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
|
||||||
title = document.select("h1").text()
|
|
||||||
author = document.select(".author").text()
|
|
||||||
description = document.select(".work_sammary").text()
|
|
||||||
val nextDate = document.select(".episode_caption:contains(【次回更新】)")
|
|
||||||
if (nextDate.isNotEmpty()) {
|
|
||||||
val dateStr = nextDate.textNodes()
|
|
||||||
.filter { it.text().contains("【次回更新】") }[0]
|
|
||||||
.text().trim().removePrefix("【次回更新】")
|
|
||||||
val localDate = JST_FORMAT_DESC.parseJST(dateStr)?.let { LOCAL_FORMAT_DESC.format(it) }
|
|
||||||
if (localDate != null) description = "【Next/Repeat: $localDate】\n$description"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun chapterListSelector() =
|
|
||||||
".box_episode > .box_episode_L:contains(読む), .box_episode > .box_episode_M:contains(読む)" // filter out purchase links
|
|
||||||
|
|
||||||
override fun chapterFromElement(element: Element) = SChapter.create().apply {
|
|
||||||
val url = element.select("a[id^=read]").attr("abs:href")
|
|
||||||
setUrlWithoutDomain(url)
|
|
||||||
val chapterNumber = url.removeSuffix("/").substringAfterLast('/').replace('_', '.')
|
|
||||||
val title = element.select(".episode_title").textNodes().filterNot {
|
|
||||||
it.text().contains("集中連載") || it.text().contains("配信中!!")
|
|
||||||
}.joinToString("/") { it.text() }
|
|
||||||
name = "$chapterNumber $title"
|
|
||||||
element.select(".episode_caption").textNodes().forEach {
|
|
||||||
if (it.text().contains("【公開日】")) {
|
|
||||||
val date = it.text().trim().removePrefix("【公開日】")
|
|
||||||
date_upload = JST_FORMAT_LIST.parseJST(date)!!.time
|
|
||||||
} else if (it.text().contains("【次回更新】")) {
|
|
||||||
val date = it.text().trim().removePrefix("【次回更新】")
|
|
||||||
val localDate = JST_FORMAT_LIST.parseJST(date)?.let { LOCAL_FORMAT_LIST.format(it) }
|
|
||||||
if (localDate != null) scanlator = "~$localDate"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (date_upload <= 0L) date_upload = -1L // hide unknown ones
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val datePattern = "yyyy年M月dd日(E)"
|
|
||||||
private val JST_FORMAT_DESC by lazy { getJSTFormat(datePattern) }
|
|
||||||
private val JST_FORMAT_LIST by lazy { getJSTFormat(datePattern) }
|
|
||||||
private val LOCAL_FORMAT_DESC by lazy { DateFormat.getDateTimeInstance() }
|
|
||||||
private val LOCAL_FORMAT_LIST by lazy { DateFormat.getDateTimeInstance() }
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,24 +4,46 @@ import eu.kanade.tachiyomi.network.GET
|
|||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
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.Page
|
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.source.online.ParsedHttpSource
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
|
import org.jsoup.select.Evaluator
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.TimeZone
|
import java.util.TimeZone
|
||||||
|
|
||||||
abstract class ComicGamma(
|
open class ComicGamma(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val baseUrl: String,
|
override val baseUrl: String,
|
||||||
override val lang: String = "ja",
|
override val lang: String = "ja",
|
||||||
) : ParsedHttpSource() {
|
) : ParsedHttpSource() {
|
||||||
|
override val supportsLatest = false
|
||||||
|
|
||||||
override val client = network.client.newBuilder().addInterceptor(PtImgInterceptor).build()
|
override val client = network.client.newBuilder().addInterceptor(PtImgInterceptor).build()
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/manga/", headers)
|
override fun popularMangaRequest(page: Int) = GET("$baseUrl/manga/", headers)
|
||||||
override fun popularMangaNextPageSelector(): String? = null
|
override fun popularMangaNextPageSelector(): String? = null
|
||||||
|
override fun popularMangaSelector() = ".tab_panel.active .manga_item"
|
||||||
|
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
|
||||||
|
url = element.selectFirst(Evaluator.Tag("a")).attr("href")
|
||||||
|
title = element.selectFirst(Evaluator.Class("manga_title")).text()
|
||||||
|
author = element.selectFirst(Evaluator.Class("manga_author")).text()
|
||||||
|
val genreList = element.select(Evaluator.Tag("li")).map { it.text() }
|
||||||
|
genre = genreList.joinToString()
|
||||||
|
status = when {
|
||||||
|
genreList.contains("完結") && !genreList.contains("リピート配信") -> SManga.COMPLETED
|
||||||
|
else -> SManga.ONGOING
|
||||||
|
}
|
||||||
|
thumbnail_url = element.selectFirst(Evaluator.Tag("img")).absUrl("src")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used.")
|
||||||
|
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException("Not used.")
|
||||||
|
override fun latestUpdatesSelector() = throw UnsupportedOperationException("Not used.")
|
||||||
|
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException("Not used.")
|
||||||
|
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
|
||||||
fetchPopularManga(page).map { p -> MangasPage(p.mangas.filter { it.title.contains(query) }, false) }
|
fetchPopularManga(page).map { p -> MangasPage(p.mangas.filter { it.title.contains(query) }, false) }
|
||||||
@ -37,6 +59,38 @@ abstract class ComicGamma(
|
|||||||
Page(i, imageUrl = e.attr("abs:data-ptimg"))
|
Page(i, imageUrl = e.attr("abs:data-ptimg"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun mangaDetailsParse(document: Document): SManga {
|
||||||
|
val titleElement = document.selectFirst(Evaluator.Class("manga__title"))
|
||||||
|
val titleName = titleElement.child(0).text()
|
||||||
|
val desc = document.selectFirst(".detail__item > p:not(:empty)")?.run {
|
||||||
|
select(Evaluator.Tag("br")).prepend("\\n")
|
||||||
|
this.text().replace("\\n", "\n").replace("\n ", "\n")
|
||||||
|
}
|
||||||
|
val listResponse = client.newCall(popularMangaRequest(0)).execute()
|
||||||
|
val manga = popularMangaParse(listResponse).mangas.find { it.title == titleName }
|
||||||
|
return manga?.apply { description = desc } ?: SManga.create().apply {
|
||||||
|
author = titleElement.child(1).text()
|
||||||
|
description = desc
|
||||||
|
status = SManga.UNKNOWN
|
||||||
|
val slug = document.location().removeSuffix("/").substringAfterLast("/")
|
||||||
|
thumbnail_url = "$baseUrl/img/manga_thumb/${slug}_list.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun chapterListSelector() = ".read__area > .read__outer > a:not([href=#comics])"
|
||||||
|
override fun chapterFromElement(element: Element) = SChapter.create().apply {
|
||||||
|
url = element.attr("href").toOldChapterUrl()
|
||||||
|
val number = url.removeSuffix("/").substringAfterLast('/').replace('_', '.')
|
||||||
|
val list = element.selectFirst(Evaluator.Class("read__contents")).children()
|
||||||
|
name = "[$number] ${list[0].text()}"
|
||||||
|
if (list.size >= 3) {
|
||||||
|
date_upload = dateFormat.parseJST(list[2].text())?.time ?: 0L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pageListRequest(chapter: SChapter) =
|
||||||
|
GET(baseUrl + chapter.url.toNewChapterUrl(), headers)
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
|
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -48,5 +102,21 @@ abstract class ComicGamma(
|
|||||||
SimpleDateFormat(datePattern, Locale.JAPANESE).apply {
|
SimpleDateFormat(datePattern, Locale.JAPANESE).apply {
|
||||||
timeZone = TimeZone.getTimeZone("GMT+09:00")
|
timeZone = TimeZone.getTimeZone("GMT+09:00")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val dateFormat by lazy { getJSTFormat("yyyy年M月dd日") }
|
||||||
|
|
||||||
|
private fun String.toOldChapterUrl(): String {
|
||||||
|
// ../../../_files/madeinabyss/063_2/
|
||||||
|
val segments = split('/')
|
||||||
|
val size = segments.size
|
||||||
|
val slug = segments[size - 3]
|
||||||
|
val number = segments[size - 2]
|
||||||
|
return "/manga/$slug/_files/$number/"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.toNewChapterUrl(): String {
|
||||||
|
val segments = split('/')
|
||||||
|
return "/_files/${segments[2]}/${segments[4]}/"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import generator.ThemeSourceGenerator
|
|||||||
class ComicGammaGenerator : ThemeSourceGenerator {
|
class ComicGammaGenerator : ThemeSourceGenerator {
|
||||||
override val themeClass = "ComicGamma"
|
override val themeClass = "ComicGamma"
|
||||||
override val themePkg = "comicgamma"
|
override val themePkg = "comicgamma"
|
||||||
override val baseVersionCode = 3
|
override val baseVersionCode = 6
|
||||||
override val sources = listOf(
|
override val sources = listOf(
|
||||||
SingleLang(
|
SingleLang(
|
||||||
name = "Web Comic Gamma",
|
name = "Web Comic Gamma",
|
||||||
@ -16,7 +16,7 @@ class ComicGammaGenerator : ThemeSourceGenerator {
|
|||||||
className = "WebComicGamma",
|
className = "WebComicGamma",
|
||||||
pkgName = "webcomicgamma",
|
pkgName = "webcomicgamma",
|
||||||
sourceName = "Web Comic Gamma",
|
sourceName = "Web Comic Gamma",
|
||||||
overrideVersionCode = 2,
|
overrideVersionCode = 0,
|
||||||
),
|
),
|
||||||
SingleLang(
|
SingleLang(
|
||||||
name = "Web Comic Gamma Plus",
|
name = "Web Comic Gamma Plus",
|
||||||
|