Add GigaViewer to multisrc (#7125)

* Add GigaViewer to multisrc.

* Add MagComi.
This commit is contained in:
Alessandro Jean 2021-05-21 09:40:06 -03:00 committed by GitHub
parent 35a77d7f0c
commit efc037301b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 283 additions and 55 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -0,0 +1,34 @@
package eu.kanade.tachiyomi.extension.ja.comicgardo
import eu.kanade.tachiyomi.multisrc.gigaviewer.GigaViewer
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.OkHttpClient
import org.jsoup.nodes.Element
class ComicGardo : GigaViewer(
"Comic Gardo",
"https://comic-gardo.com",
"ja",
"https://cdn-img.comic-gardo.com/public/page"
) {
override val supportsLatest: Boolean = false
override val client: OkHttpClient = super.client.newBuilder()
.addInterceptor(::imageIntercept)
.build()
override val publisher: String = "オーバーラップ"
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")
setUrlWithoutDomain(element.attr("href"))
}
override fun getCollections(): List<Collection> = listOf(
Collection("連載一覧", "")
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1,44 @@
package eu.kanade.tachiyomi.extension.ja.kuragebunch
import eu.kanade.tachiyomi.multisrc.gigaviewer.GigaViewer
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.OkHttpClient
import okhttp3.Request
import org.jsoup.nodes.Element
class KurageBunch : GigaViewer(
"Kurage Bunch",
"https://kuragebunch.com",
"ja",
"https://cdn-img.kuragebunch.com"
) {
override val supportsLatest: Boolean = false
override val client: OkHttpClient = super.client.newBuilder()
.addInterceptor(::imageIntercept)
.build()
override val publisher: String = "株式会社"
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/series/kuragebunch", headers)
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"))
}
override fun chapterListSelector(): String = "li.episode"
override fun getCollections(): List<Collection> = listOf(
Collection("くらげバンチ", "kuragebunch"),
Collection("読切", "oneshot"),
Collection("月刊コミックバンチ", "comicbunch"),
Collection("Bバンチ", "bbunch"),
Collection("ututu", "ututu")
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

View File

@ -0,0 +1,36 @@
package eu.kanade.tachiyomi.extension.ja.magazinepocket
import eu.kanade.tachiyomi.multisrc.gigaviewer.GigaViewer
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.OkHttpClient
import org.jsoup.nodes.Element
class MagazinePocket : GigaViewer(
"Magazine Pocket",
"https://pocket.shonenmagazine.com",
"ja",
"https://cdn-img.pocket.shonenmagazine.com/public/page"
) {
override val client: OkHttpClient = super.client.newBuilder()
.addInterceptor(::imageIntercept)
.build()
override val publisher: String = "講談社"
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")
setUrlWithoutDomain(element.attr("href"))
}
override fun latestUpdatesSelector(): String = "section.daily.$dayOfWeek " + popularMangaSelector()
override fun getCollections(): List<Collection> = listOf(
Collection("マガポケ連載一覧", ""),
Collection("週刊少年マガジン連載一覧", "smaga"),
Collection("別冊少年マガジン連載一覧", "bmaga")
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -0,0 +1,34 @@
package eu.kanade.tachiyomi.extension.ja.magcomi
import eu.kanade.tachiyomi.multisrc.gigaviewer.GigaViewer
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.OkHttpClient
import org.jsoup.nodes.Element
class MagComi : GigaViewer(
"MAGCOMI",
"https://magcomi.com",
"ja",
"https://cdn-img.magcomi.com/public/page"
) {
override val supportsLatest: Boolean = false
override val client: OkHttpClient = super.client.newBuilder()
.addInterceptor(::imageIntercept)
.build()
override val publisher: String = "マッグガーデン"
override fun popularMangaSelector(): String = "ul.magcomi-series-list li.series-item > a"
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
title = element.select("h3.series-title").text()
thumbnail_url = element.select("div.series-thumb img").attr("src")
setUrlWithoutDomain(element.attr("href"))
}
override fun getCollections(): List<Collection> = listOf(
Collection("連載・読切", "")
)
}

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

@ -0,0 +1,24 @@
package eu.kanade.tachiyomi.extension.ja.shonenjumpplus
import eu.kanade.tachiyomi.multisrc.gigaviewer.GigaViewer
import okhttp3.OkHttpClient
class ShonenJumpPlus : GigaViewer(
"Shonen Jump+",
"https://shonenjumpplus.com",
"ja",
"https://cdn-ak-img.shonenjumpplus.com"
) {
override val client: OkHttpClient = super.client.newBuilder()
.addInterceptor(::imageIntercept)
.build()
override val publisher: String = "集英社"
override fun getCollections(): List<Collection> = listOf(
Collection("ジャンプ+連載一覧", ""),
Collection("ジャンプ+読切シリーズ", "oneshot"),
Collection("連載終了作品", "finished")
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -0,0 +1,38 @@
package eu.kanade.tachiyomi.extension.ja.tonarinoyoungjump
import eu.kanade.tachiyomi.multisrc.gigaviewer.GigaViewer
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.OkHttpClient
import org.jsoup.nodes.Element
class TonariNoYoungJump : GigaViewer(
"Tonari no Young Jump",
"https://tonarinoyj.jp",
"ja",
"https://cdn-img.tonarinoyj.jp/public/page"
) {
override val supportsLatest: Boolean = false
override val client: OkHttpClient = super.client.newBuilder()
.addInterceptor(::imageIntercept)
.build()
override val publisher: String = "集英社"
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")
setUrlWithoutDomain(element.attr("href"))
}
override fun chapterListSelector(): String = "li.episode"
override fun getCollections(): List<Collection> = listOf(
Collection("連載一覧", ""),
Collection("読切作品", "oneshot"),
Collection("連載終了作品", "finished")
)
}

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.extension.ja.shonenjumpplus package eu.kanade.tachiyomi.multisrc.gigaviewer
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
@ -22,7 +22,6 @@ import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody import okhttp3.ResponseBody.Companion.toResponseBody
@ -37,28 +36,24 @@ import java.util.Calendar
import java.util.Locale import java.util.Locale
import kotlin.math.floor import kotlin.math.floor
class ShonenJumpPlus : ParsedHttpSource() { abstract class GigaViewer(
override val name: String,
override val name = "Shonen Jump+" override val baseUrl: String,
override val lang: String,
override val baseUrl = "https://shonenjumpplus.com" private val cdnUrl: String = ""
) : ParsedHttpSource() {
override val lang = "ja"
override val supportsLatest = true override val supportsLatest = true
override val client: OkHttpClient = network.client.newBuilder() protected val dayOfWeek: String by lazy {
.addInterceptor { imageIntercept(it) }
.build()
private val dayOfWeek: String by lazy {
Calendar.getInstance() Calendar.getInstance()
.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.US)!! .getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.US)!!
.toLowerCase(Locale.US) .toLowerCase(Locale.US)
} }
protected open val publisher: String = ""
override fun headersBuilder(): Headers.Builder = Headers.Builder() override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", USER_AGENT)
.add("Origin", baseUrl) .add("Origin", baseUrl)
.add("Referer", baseUrl) .add("Referer", baseUrl)
@ -91,8 +86,8 @@ class ShonenJumpPlus : ParsedHttpSource() {
return GET(url.toString(), headers) return GET(url.toString(), headers)
} }
val listMode = (filters[0] as SeriesListModeFilter).state val collectionSelected = (filters[0] as CollectionFilter).selected
return GET("$baseUrl/series/${LIST_MODES[listMode].second}", headers) return GET("$baseUrl/series/${collectionSelected.path}", headers)
} }
override fun searchMangaParse(response: Response): MangasPage { override fun searchMangaParse(response: Response): MangasPage {
@ -102,7 +97,7 @@ class ShonenJumpPlus : ParsedHttpSource() {
return popularMangaParse(response) return popularMangaParse(response)
} }
override fun searchMangaSelector() = "ul.search-series-list li" override fun searchMangaSelector() = "ul.search-series-list li, ul.series-list li"
override fun searchMangaFromElement(element: Element): SManga = SManga.create().apply { override fun searchMangaFromElement(element: Element): SManga = SManga.create().apply {
title = element.select("div.title-box p.series-title").text() title = element.select("div.title-box p.series-title").text()
@ -112,8 +107,10 @@ class ShonenJumpPlus : ParsedHttpSource() {
override fun searchMangaNextPageSelector(): String? = null override fun searchMangaNextPageSelector(): String? = null
protected open fun mangaDetailsInfoSelector(): String = "section.series-information div.series-header"
override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply {
val infoElement = document.select("section.series-information div.series-header") val infoElement = document.select(mangaDetailsInfoSelector()).first()!!
title = infoElement.select("h1.series-header-title").text() title = infoElement.select("h1.series-header-title").text()
author = infoElement.select("h2.series-header-author").text() author = infoElement.select("h2.series-header-author").text()
@ -130,8 +127,8 @@ class ShonenJumpPlus : ParsedHttpSource() {
.toHttpUrlOrNull()!! .toHttpUrlOrNull()!!
val firstListEndpoint = readableProductList.attr("data-first-list-endpoint") val firstListEndpoint = readableProductList.attr("data-first-list-endpoint")
.toHttpUrlOrNull()!! .toHttpUrlOrNull()!!
val numberSince = latestListEndpoint.queryParameter("number_since")!!.toInt() val numberSince = latestListEndpoint.queryParameter("number_since")!!.toFloat()
.coerceAtLeast(firstListEndpoint.queryParameter("number_since")!!.toInt()) .coerceAtLeast(firstListEndpoint.queryParameter("number_since")!!.toFloat())
val newHeaders = headers.newBuilder() val newHeaders = headers.newBuilder()
.set("Referer", response.request.url.toString()) .set("Referer", response.request.url.toString())
@ -158,6 +155,8 @@ class ShonenJumpPlus : ParsedHttpSource() {
result = client.newCall(request).execute() result = client.newCall(request).execute()
} }
result.close()
return chapters return chapters
} }
@ -171,8 +170,8 @@ class ShonenJumpPlus : ParsedHttpSource() {
name = info.select("h4.series-episode-list-title").text() name = info.select("h4.series-episode-list-title").text()
date_upload = info.select("span.series-episode-list-date").first() date_upload = info.select("span.series-episode-list-date").first()
?.text().orEmpty() ?.text().orEmpty()
.tryParseDate() .toDate()
scanlator = "集英社" scanlator = publisher
setUrlWithoutDomain(if (info.tagName() == "a") info.attr("href") else mangaUrl) setUrlWithoutDomain(if (info.tagName() == "a") info.attr("href") else mangaUrl)
} }
} }
@ -203,17 +202,26 @@ class ShonenJumpPlus : ParsedHttpSource() {
return GET(page.imageUrl!!, newHeaders) return GET(page.imageUrl!!, newHeaders)
} }
private class SeriesListModeFilter : Filter.Select<String>( protected data class Collection(val name: String, val path: String) {
"一覧", override fun toString(): String = name
LIST_MODES.map { it.first }.toTypedArray() }
)
override fun getFilterList(): FilterList = FilterList(SeriesListModeFilter()) private class CollectionFilter(val collections: List<Collection>) : Filter.Select<Collection>(
"コレクション",
collections.toTypedArray()
) {
val selected: Collection
get() = collections[state]
}
private fun imageIntercept(chain: Interceptor.Chain): Response { override fun getFilterList(): FilterList = FilterList(CollectionFilter(getCollections()))
protected open fun getCollections(): List<Collection> = emptyList()
protected open fun imageIntercept(chain: Interceptor.Chain): Response {
var request = chain.request() var request = chain.request()
if (!request.url.toString().startsWith(CDN_URL)) { if (!request.url.toString().startsWith(cdnUrl)) {
return chain.proceed(request) return chain.proceed(request)
} }
@ -229,10 +237,13 @@ class ShonenJumpPlus : ParsedHttpSource() {
val response = chain.proceed(request) val response = chain.proceed(request)
val image = decodeImage(response.body!!.byteStream(), width, height) val image = decodeImage(response.body!!.byteStream(), width, height)
val body = image.toResponseBody("image/png".toMediaTypeOrNull()) val body = image.toResponseBody("image/png".toMediaTypeOrNull())
response.close()
return response.newBuilder().body(body).build() return response.newBuilder().body(body).build()
} }
private fun decodeImage(image: InputStream, width: Int, height: Int): ByteArray { protected open fun decodeImage(image: InputStream, width: Int, height: Int): ByteArray {
val input = BitmapFactory.decodeStream(image) val input = BitmapFactory.decodeStream(image)
val cWidth = (floor(width.toDouble() / (DIVIDE_NUM * MULTIPLE)) * MULTIPLE).toInt() val cWidth = (floor(width.toDouble() / (DIVIDE_NUM * MULTIPLE)) * MULTIPLE).toInt()
val cHeight = (floor(height.toDouble() / (DIVIDE_NUM * MULTIPLE)) * MULTIPLE).toInt() val cHeight = (floor(height.toDouble() / (DIVIDE_NUM * MULTIPLE)) * MULTIPLE).toInt()
@ -261,9 +272,9 @@ class ShonenJumpPlus : ParsedHttpSource() {
return output.toByteArray() return output.toByteArray()
} }
private fun String.tryParseDate(): Long { private fun String.toDate(): Long {
return try { return try {
DATE_PARSER.parse(this)!!.time DATE_PARSER.parse(this)?.time ?: 0L
} catch (e: ParseException) { } catch (e: ParseException) {
0L 0L
} }
@ -272,16 +283,8 @@ class ShonenJumpPlus : ParsedHttpSource() {
private fun Response.asJsonObject(): JsonObject = JsonParser.parseString(body!!.string()).obj private fun Response.asJsonObject(): JsonObject = JsonParser.parseString(body!!.string()).obj
companion object { companion object {
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36"
private val DATE_PARSER by lazy { SimpleDateFormat("yyyy/MM/dd", Locale.ENGLISH) } private val DATE_PARSER by lazy { SimpleDateFormat("yyyy/MM/dd", Locale.ENGLISH) }
private val LIST_MODES = listOf(
Pair("ジャンプ+連載一覧", ""),
Pair("ジャンプ+読切シリーズ", "oneshot"),
Pair("連載終了作品", "finished")
)
private const val CDN_URL = "https://cdn-ak-img.shonenjumpplus.com"
private const val DIVIDE_NUM = 4 private const val DIVIDE_NUM = 4
private const val MULTIPLE = 8 private const val MULTIPLE = 8
} }

View File

@ -0,0 +1,29 @@
package eu.kanade.tachiyomi.multisrc.gigaviewer
import generator.ThemeSourceData.SingleLang
import generator.ThemeSourceGenerator
class GigaViewerGenerator : ThemeSourceGenerator {
override val themePkg = "gigaviewer"
override val themeClass = "GigaViewer"
override val baseVersionCode: Int = 1
override val sources = listOf(
SingleLang("Comic Gardo", "https://comic-gardo.com", "ja"),
SingleLang("Kurage Bunch", "https://kuragebunch.com", "ja"),
SingleLang("MAGCOMI", "https://magcomi.com", "ja", className = "MagComi"),
SingleLang("Magazine Pocket", "https://pocket.shonenmagazine.com", "ja"),
SingleLang("Shonen Jump+", "https://shonenjumpplus.com", "ja", pkgName = "shonenjumpplus", className = "ShonenJumpPlus", overrideVersionCode = 2),
SingleLang("Tonari no Young Jump", "https://tonarinoyj.jp", "ja", className = "TonariNoYoungJump")
)
companion object {
@JvmStatic
fun main(args: Array<String>) {
GigaViewerGenerator().createAll()
}
}
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="eu.kanade.tachiyomi.extension" />

View File

@ -1,12 +0,0 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
ext {
extName = 'Shonen Jump+'
pkgNameSuffix = 'ja.shonenjumpplus'
extClass = '.ShonenJumpPlus'
extVersionCode = 2
libVersion = '1.2'
}
apply from: "$rootDir/common.gradle"