ComiciViewer: add multisrc Comici Viewer (#10970)
* multisrc comici * fixes and filters * fix parameters * fixes and sources
5
lib-multisrc/comiciviewer/build.gradle.kts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
plugins {
|
||||||
|
id("lib-multisrc")
|
||||||
|
}
|
||||||
|
|
||||||
|
baseVersionCode = 1
|
||||||
BIN
lib-multisrc/comiciviewer/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
lib-multisrc/comiciviewer/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
lib-multisrc/comiciviewer/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
lib-multisrc/comiciviewer/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
lib-multisrc/comiciviewer/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
@ -0,0 +1,244 @@
|
|||||||
|
package eu.kanade.tachiyomi.multisrc.comiciviewer
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import androidx.preference.PreferenceScreen
|
||||||
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
|
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 keiyoushi.utils.firstInstance
|
||||||
|
import keiyoushi.utils.getPreferencesLazy
|
||||||
|
import keiyoushi.utils.parseAs
|
||||||
|
import keiyoushi.utils.tryParse
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
abstract class ComiciViewer(
|
||||||
|
override val name: String,
|
||||||
|
override val baseUrl: String,
|
||||||
|
override val lang: String,
|
||||||
|
) : ConfigurableSource, HttpSource() {
|
||||||
|
private val preferences: SharedPreferences by getPreferencesLazy()
|
||||||
|
private val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.JAPAN)
|
||||||
|
|
||||||
|
override val supportsLatest = true
|
||||||
|
|
||||||
|
override val client = super.client.newBuilder()
|
||||||
|
.addInterceptor(ImageInterceptor())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
override fun headersBuilder() = super.headersBuilder()
|
||||||
|
.set("Referer", "$baseUrl/")
|
||||||
|
|
||||||
|
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/ranking/manga", headers)
|
||||||
|
|
||||||
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
|
val document = response.asJsoup()
|
||||||
|
val mangas = document.select("div.ranking-box-vertical, div.ranking-box-vertical-top3").map { element ->
|
||||||
|
SManga.create().apply {
|
||||||
|
setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||||
|
title = element.selectFirst(".title-text")!!.text()
|
||||||
|
thumbnail_url = element.selectFirst("source")?.attr("data-srcset")?.substringBefore(" ")?.let { "https:$it" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MangasPage(mangas, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/category/manga", headers)
|
||||||
|
|
||||||
|
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||||
|
val document = response.asJsoup()
|
||||||
|
val mangas = document.select("div.category-box-vertical").map { element ->
|
||||||
|
SManga.create().apply {
|
||||||
|
setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
|
||||||
|
title = element.selectFirst(".title-text")!!.text()
|
||||||
|
thumbnail_url = element.selectFirst("source")?.attr("data-srcset")?.substringBefore(" ")?.let { "https:$it" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MangasPage(mangas, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
|
if (query.isNotBlank()) {
|
||||||
|
val url = "$baseUrl/search".toHttpUrl().newBuilder()
|
||||||
|
.addQueryParameter("keyword", query)
|
||||||
|
.addQueryParameter("page", (page - 1).toString())
|
||||||
|
.addQueryParameter("filter", "series")
|
||||||
|
.build()
|
||||||
|
return GET(url, headers)
|
||||||
|
}
|
||||||
|
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
||||||
|
val browseFilter = filterList.firstInstance<BrowseFilter>()
|
||||||
|
val pathAndQuery = getFilterOptions()[browseFilter.state].second
|
||||||
|
val url = (baseUrl + pathAndQuery).toHttpUrl().newBuilder().build()
|
||||||
|
|
||||||
|
return GET(url, headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
|
val url = response.request.url.toString()
|
||||||
|
|
||||||
|
return when {
|
||||||
|
url.contains("/ranking/") -> popularMangaParse(response)
|
||||||
|
url.contains("/category/") -> latestUpdatesParse(response)
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val document = response.asJsoup()
|
||||||
|
val mangas = document.select("div.manga-store-item").map { element ->
|
||||||
|
SManga.create().apply {
|
||||||
|
setUrlWithoutDomain(
|
||||||
|
element.selectFirst("a.c-ms-clk-article")!!.attr("href"),
|
||||||
|
)
|
||||||
|
title = element.selectFirst("h2.manga-title")!!.text()
|
||||||
|
thumbnail_url =
|
||||||
|
element.selectFirst("source")?.attr("data-srcset")?.substringBefore(" ")
|
||||||
|
?.let { "https:$it" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val hasNextPage = document.selectFirst("li.mode-paging-active + li > a") != null
|
||||||
|
return MangasPage(mangas, hasNextPage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mangaDetailsParse(response: Response): SManga {
|
||||||
|
val document = response.asJsoup()
|
||||||
|
return SManga.create().apply {
|
||||||
|
title = document.select("h1.series-h-title span").last()!!.text()
|
||||||
|
author = document.select("div.series-h-credit-user").text()
|
||||||
|
artist = author
|
||||||
|
description = document.selectFirst("div.series-h-credit-info-text-text")?.text()
|
||||||
|
genre = document.select("a.series-h-tag-link").joinToString { it.text().removePrefix("#") }
|
||||||
|
thumbnail_url = document.selectFirst("div.series-h-img source")?.attr("data-srcset")?.substringBefore(" ")?.let { "https:$it" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun chapterListRequest(manga: SManga): Request {
|
||||||
|
return GET(baseUrl + manga.url + "/list?s=1", headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
|
val showLocked = preferences.getBoolean(SHOW_LOCKED_PREF_KEY, true)
|
||||||
|
val document = response.asJsoup()
|
||||||
|
|
||||||
|
return document.select("div.series-ep-list-item").mapNotNull { element ->
|
||||||
|
val link = element.selectFirst("a.g-episode-link-wrapper")!!
|
||||||
|
|
||||||
|
val isFree = element.selectFirst("span.free-icon-new") != null
|
||||||
|
val isTicketLocked = element.selectFirst("img[data-src*='free_charge_ja.svg']") != null
|
||||||
|
val isCoinLocked = element.selectFirst("img[data-src*='coin.svg']") != null
|
||||||
|
val isLocked = !isFree
|
||||||
|
|
||||||
|
if (!showLocked && isLocked) {
|
||||||
|
return@mapNotNull null
|
||||||
|
}
|
||||||
|
|
||||||
|
SChapter.create().apply {
|
||||||
|
val chapterUrl = link.attr("data-href")
|
||||||
|
if (chapterUrl.isNotEmpty()) {
|
||||||
|
setUrlWithoutDomain(chapterUrl)
|
||||||
|
} else {
|
||||||
|
url = response.request.url.toString() + "#" + link.attr("data-article") + DUMMY_URL_SUFFIX
|
||||||
|
}
|
||||||
|
|
||||||
|
name = link.selectFirst("span.series-ep-list-item-h-text")!!.text()
|
||||||
|
when {
|
||||||
|
isTicketLocked -> name = "🔒 $name"
|
||||||
|
isCoinLocked -> name = "\uD83E\uDE99 $name"
|
||||||
|
}
|
||||||
|
|
||||||
|
date_upload = dateFormat.tryParse(element.selectFirst("time")?.attr("datetime"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
|
if (chapter.url.endsWith(DUMMY_URL_SUFFIX)) {
|
||||||
|
throw Exception("Log in via WebView to read purchased chapters and refresh the entry")
|
||||||
|
}
|
||||||
|
return super.pageListRequest(chapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
|
val document = response.asJsoup()
|
||||||
|
val viewer = document.selectFirst("#comici-viewer") ?: throw Exception("You need to log in via WebView to read this chapter or purchase this chapter")
|
||||||
|
val comiciViewerId = viewer.attr("comici-viewer-id")
|
||||||
|
val memberJwt = viewer.attr("data-member-jwt")
|
||||||
|
val requestUrl = "$baseUrl/book/contentsInfo".toHttpUrl().newBuilder()
|
||||||
|
.addQueryParameter("comici-viewer-id", comiciViewerId)
|
||||||
|
.addQueryParameter("user-id", memberJwt)
|
||||||
|
.addQueryParameter("page-from", "0")
|
||||||
|
|
||||||
|
val pageTo = client.newCall(GET(requestUrl.addQueryParameter("page-to", "1").build(), headers))
|
||||||
|
.execute().use { initialResponse ->
|
||||||
|
if (!initialResponse.isSuccessful) {
|
||||||
|
throw Exception("Failed to get page list")
|
||||||
|
}
|
||||||
|
initialResponse.parseAs<ViewerResponse>().totalPages.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
val getAllPagesUrl = requestUrl.setQueryParameter("page-to", pageTo).build()
|
||||||
|
return client.newCall(GET(getAllPagesUrl, headers)).execute().use { allPagesResponse ->
|
||||||
|
if (allPagesResponse.isSuccessful) {
|
||||||
|
allPagesResponse.parseAs<ViewerResponse>().result.map { resultItem ->
|
||||||
|
val urlBuilder = resultItem.imageUrl.toHttpUrl().newBuilder()
|
||||||
|
if (resultItem.scramble.isNotEmpty()) {
|
||||||
|
urlBuilder.addQueryParameter("scramble", resultItem.scramble)
|
||||||
|
}
|
||||||
|
Page(
|
||||||
|
index = resultItem.sort,
|
||||||
|
imageUrl = urlBuilder.build().toString(),
|
||||||
|
)
|
||||||
|
}.sortedBy { it.index }
|
||||||
|
} else {
|
||||||
|
throw Exception("Failed to get full page list")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||||
|
SwitchPreferenceCompat(screen.context).apply {
|
||||||
|
key = SHOW_LOCKED_PREF_KEY
|
||||||
|
title = "Show locked chapters"
|
||||||
|
setDefaultValue(true)
|
||||||
|
}.also(screen::addPreference)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open class BrowseFilter(vals: Array<String>) : Filter.Select<String>("Filter by", vals)
|
||||||
|
|
||||||
|
protected open fun getFilterOptions(): List<Pair<String, String>> = listOf(
|
||||||
|
Pair("ランキング", "/ranking/manga"),
|
||||||
|
Pair("読み切り", "/category/manga?type=読み切り"),
|
||||||
|
Pair("完結", "/category/manga?type=完結"),
|
||||||
|
Pair("月曜日", "/category/manga?type=連載中&day=月"),
|
||||||
|
Pair("火曜日", "/category/manga?type=連載中&day=火"),
|
||||||
|
Pair("水曜日", "/category/manga?type=連載中&day=水"),
|
||||||
|
Pair("木曜日", "/category/manga?type=連載中&day=木"),
|
||||||
|
Pair("金曜日", "/category/manga?type=連載中&day=金"),
|
||||||
|
Pair("土曜日", "/category/manga?type=連載中&day=土"),
|
||||||
|
Pair("日曜日", "/category/manga?type=連載中&day=日"),
|
||||||
|
Pair("その他", "/category/manga?type=連載中&day=その他"),
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun getFilterList() = FilterList(
|
||||||
|
BrowseFilter(getFilterOptions().map { it.first }.toTypedArray()),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Unsupported
|
||||||
|
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val SHOW_LOCKED_PREF_KEY = "pref_show_locked_chapters"
|
||||||
|
private const val DUMMY_URL_SUFFIX = "NeedLogin"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package eu.kanade.tachiyomi.multisrc.comiciviewer
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class ViewerResponse(
|
||||||
|
val result: List<PageDto>,
|
||||||
|
val totalPages: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class PageDto(
|
||||||
|
val imageUrl: String,
|
||||||
|
val scramble: String,
|
||||||
|
val sort: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
class TilePos(
|
||||||
|
val x: Int,
|
||||||
|
val y: Int,
|
||||||
|
)
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
package eu.kanade.tachiyomi.multisrc.comiciviewer
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Rect
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.Response
|
||||||
|
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
|
||||||
|
class ImageInterceptor : Interceptor {
|
||||||
|
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val request = chain.request()
|
||||||
|
val scrambleData = request.url.queryParameter("scramble")
|
||||||
|
|
||||||
|
if (scrambleData.isNullOrEmpty()) {
|
||||||
|
return chain.proceed(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
val newUrl = request.url.newBuilder()
|
||||||
|
.removeAllQueryParameters("scramble")
|
||||||
|
.build()
|
||||||
|
val newRequest = request.newBuilder().url(newUrl).build()
|
||||||
|
|
||||||
|
val response = chain.proceed(newRequest)
|
||||||
|
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
val tiles = buildList {
|
||||||
|
scrambleData.drop(1).dropLast(1).replace(" ", "").split(",").forEach {
|
||||||
|
val scrambleInt = it.toInt()
|
||||||
|
add(TilePos(scrambleInt / 4, scrambleInt % 4))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val scrambledImg = BitmapFactory.decodeStream(response.body.byteStream())
|
||||||
|
val descrambledImg =
|
||||||
|
unscrambleImage(scrambledImg, scrambledImg.width, scrambledImg.height, tiles)
|
||||||
|
|
||||||
|
val output = ByteArrayOutputStream()
|
||||||
|
descrambledImg.compress(Bitmap.CompressFormat.JPEG, 90, output)
|
||||||
|
|
||||||
|
val body = output.toByteArray().toResponseBody("image/jpeg".toMediaType())
|
||||||
|
|
||||||
|
return response.newBuilder().body(body).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun unscrambleImage(
|
||||||
|
rawImage: Bitmap,
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
tiles: List<TilePos>,
|
||||||
|
): Bitmap {
|
||||||
|
val descrambledImg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||||
|
val canvas = Canvas(descrambledImg)
|
||||||
|
|
||||||
|
val tileWidth = width / 4
|
||||||
|
val tileHeight = height / 4
|
||||||
|
|
||||||
|
var count = 0
|
||||||
|
for (x in 0..3) {
|
||||||
|
for (y in 0..3) {
|
||||||
|
val desRect = Rect(
|
||||||
|
x * tileWidth,
|
||||||
|
y * tileHeight,
|
||||||
|
(x + 1) * tileWidth,
|
||||||
|
(y + 1) * tileHeight,
|
||||||
|
)
|
||||||
|
val srcRect = Rect(
|
||||||
|
tiles[count].x * tileWidth,
|
||||||
|
tiles[count].y * tileHeight,
|
||||||
|
(tiles[count].x + 1) * tileWidth,
|
||||||
|
(tiles[count].y + 1) * tileHeight,
|
||||||
|
)
|
||||||
|
canvas.drawBitmap(rawImage, srcRect, desRect, null)
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return descrambledImg
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/ja/bigcomics/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "Big Comics"
|
||||||
|
extClass = ".BigComics"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://bigcomics.jp"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/bigcomics/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
src/ja/bigcomics/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/ja/bigcomics/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
src/ja/bigcomics/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/ja/bigcomics/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.bigcomics
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
|
||||||
|
class BigComics : ComiciViewer(
|
||||||
|
"Big Comics",
|
||||||
|
"https://bigcomics.jp",
|
||||||
|
"ja",
|
||||||
|
)
|
||||||
10
src/ja/comicmedu/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "Comic MeDu"
|
||||||
|
extClass = ".ComicMeDu"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://comic-medu.com"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/comicmedu/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
src/ja/comicmedu/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/ja/comicmedu/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
src/ja/comicmedu/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/ja/comicmedu/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
@ -0,0 +1,16 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.comicmedu
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
|
||||||
|
class ComicMeDu : ComiciViewer(
|
||||||
|
"Comic MeDu",
|
||||||
|
"https://comic-medu.com",
|
||||||
|
"ja",
|
||||||
|
) {
|
||||||
|
override fun getFilterOptions(): List<Pair<String, String>> = listOf(
|
||||||
|
Pair("ランキング", "/ranking/manga"),
|
||||||
|
Pair("読み切り", "/category/manga?type=読み切り"),
|
||||||
|
Pair("完結", "/category/manga?type=完結"),
|
||||||
|
Pair("連載", "/category/manga?type=連載中"),
|
||||||
|
)
|
||||||
|
}
|
||||||
10
src/ja/comicpash/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "Comic Pash"
|
||||||
|
extClass = ".ComicPash"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://comicpash.jp"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/comicpash/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
src/ja/comicpash/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/ja/comicpash/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
src/ja/comicpash/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
src/ja/comicpash/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,22 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.comicpash
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
|
||||||
|
class ComicPash : ComiciViewer(
|
||||||
|
"Comic Pash",
|
||||||
|
"https://comicpash.jp",
|
||||||
|
"ja",
|
||||||
|
) {
|
||||||
|
override fun getFilterOptions(): List<Pair<String, String>> = listOf(
|
||||||
|
Pair("ランキング", "/ranking/manga"),
|
||||||
|
Pair("読み切り", "/category/manga?type=読み切り"),
|
||||||
|
Pair("完結", "/category/manga?type=完結"),
|
||||||
|
Pair("月曜日", "/category/manga?type=連載中&day=月"),
|
||||||
|
Pair("火曜日", "/category/manga?type=連載中&day=火"),
|
||||||
|
Pair("水曜日", "/category/manga?type=連載中&day=水"),
|
||||||
|
Pair("木曜日", "/category/manga?type=連載中&day=木"),
|
||||||
|
Pair("金曜日", "/category/manga?type=連載中&day=金"),
|
||||||
|
Pair("土曜日", "/category/manga?type=連載中&day=土"),
|
||||||
|
Pair("日曜日", "/category/manga?type=連載中&day=日"),
|
||||||
|
)
|
||||||
|
}
|
||||||
10
src/ja/comicride/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "Comic Ride"
|
||||||
|
extClass = ".ComicRide"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://comicride.jp"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/comicride/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
src/ja/comicride/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src/ja/comicride/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
src/ja/comicride/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/ja/comicride/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.comicride
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
|
||||||
|
class ComicRide : ComiciViewer(
|
||||||
|
"Comic Ride",
|
||||||
|
"https://comicride.jp",
|
||||||
|
"ja",
|
||||||
|
)
|
||||||
10
src/ja/jnbooks/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "J-N Books"
|
||||||
|
extClass = ".JNBooks"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://comic.j-nbooks.jp"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/jnbooks/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
src/ja/jnbooks/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src/ja/jnbooks/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
src/ja/jnbooks/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/ja/jnbooks/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,24 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.jnbooks
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
class JNBooks : ComiciViewer(
|
||||||
|
"J-N Books",
|
||||||
|
"https://comic.j-nbooks.jp",
|
||||||
|
"ja",
|
||||||
|
) {
|
||||||
|
override val supportsLatest = false
|
||||||
|
|
||||||
|
override fun popularMangaRequest(page: Int): Request = latestUpdatesRequest(page)
|
||||||
|
|
||||||
|
override fun popularMangaParse(response: Response): MangasPage = latestUpdatesParse(response)
|
||||||
|
|
||||||
|
override fun getFilterOptions(): List<Pair<String, String>> = listOf(
|
||||||
|
Pair("読み切り", "/category/manga?type=読み切り"),
|
||||||
|
Pair("完結", "/category/manga?type=完結"),
|
||||||
|
Pair("連載", "/category/manga?type=連載中"),
|
||||||
|
)
|
||||||
|
}
|
||||||
10
src/ja/kimicomi/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "KimiComi"
|
||||||
|
extClass = ".KimiComi"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://kimicomi.com"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/kimicomi/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
src/ja/kimicomi/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
src/ja/kimicomi/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
src/ja/kimicomi/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/ja/kimicomi/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,22 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.kimicomi
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
|
||||||
|
class KimiComi : ComiciViewer(
|
||||||
|
"KimiComi",
|
||||||
|
"https://kimicomi.com",
|
||||||
|
"ja",
|
||||||
|
) {
|
||||||
|
override fun getFilterOptions(): List<Pair<String, String>> = listOf(
|
||||||
|
Pair("ランキング", "/ranking/manga"),
|
||||||
|
Pair("読み切り", "/category/manga?type=読み切り"),
|
||||||
|
Pair("完結", "/category/manga?type=完結"),
|
||||||
|
Pair("月曜日", "/category/manga?type=連載中&day=月"),
|
||||||
|
Pair("火曜日", "/category/manga?type=連載中&day=火"),
|
||||||
|
Pair("水曜日", "/category/manga?type=連載中&day=水"),
|
||||||
|
Pair("木曜日", "/category/manga?type=連載中&day=木"),
|
||||||
|
Pair("金曜日", "/category/manga?type=連載中&day=金"),
|
||||||
|
Pair("土曜日", "/category/manga?type=連載中&day=土"),
|
||||||
|
Pair("日曜日", "/category/manga?type=連載中&day=日"),
|
||||||
|
)
|
||||||
|
}
|
||||||
10
src/ja/magkan/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "MagKan"
|
||||||
|
extClass = ".MagKan"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://kansai.mag-garden.co.jp"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/magkan/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
src/ja/magkan/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src/ja/magkan/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
src/ja/magkan/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/ja/magkan/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
@ -0,0 +1,23 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.magkan
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
class MagKan : ComiciViewer(
|
||||||
|
"MagKan",
|
||||||
|
"https://kansai.mag-garden.co.jp",
|
||||||
|
"ja",
|
||||||
|
) {
|
||||||
|
override val supportsLatest = false
|
||||||
|
|
||||||
|
override fun popularMangaRequest(page: Int): Request = latestUpdatesRequest(page)
|
||||||
|
|
||||||
|
override fun popularMangaParse(response: Response): MangasPage = latestUpdatesParse(response)
|
||||||
|
|
||||||
|
override fun getFilterOptions(): List<Pair<String, String>> = listOf(
|
||||||
|
Pair("読み切り", "/category/manga?type=読み切り"),
|
||||||
|
Pair("連載", "/category/manga?type=連載中"),
|
||||||
|
)
|
||||||
|
}
|
||||||
10
src/ja/mangabang/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "MangaBang Comics"
|
||||||
|
extClass = ".MangaBang"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://comics.manga-bang.com"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/mangabang/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
src/ja/mangabang/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/ja/mangabang/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
src/ja/mangabang/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
src/ja/mangabang/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,15 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.mangabang
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
|
||||||
|
class MangaBang : ComiciViewer(
|
||||||
|
"MangaBang Comics",
|
||||||
|
"https://comics.manga-bang.com",
|
||||||
|
"ja",
|
||||||
|
) {
|
||||||
|
override fun getFilterOptions(): List<Pair<String, String>> = listOf(
|
||||||
|
Pair("ランキング", "/ranking/manga"),
|
||||||
|
Pair("完結", "/category/manga?type=完結"),
|
||||||
|
Pair("連載", "/category/manga?type=連載中"),
|
||||||
|
)
|
||||||
|
}
|
||||||
10
src/ja/younganimal/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "Young Animal"
|
||||||
|
extClass = ".YoungAnimal"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://younganimal.com"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = false
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/younganimal/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
src/ja/younganimal/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src/ja/younganimal/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
src/ja/younganimal/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/ja/younganimal/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.younganimal
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
|
||||||
|
class YoungAnimal : ComiciViewer(
|
||||||
|
"Young Animal",
|
||||||
|
"https://younganimal.com",
|
||||||
|
"ja",
|
||||||
|
)
|
||||||
10
src/ja/youngchampion/build.gradle
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ext {
|
||||||
|
extName = "Young Champion"
|
||||||
|
extClass = ".YoungChampion"
|
||||||
|
themePkg = 'comiciviewer'
|
||||||
|
baseUrl = "https://youngchampion.jp"
|
||||||
|
overrideVersionCode = 0
|
||||||
|
isNsfw = true
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
BIN
src/ja/youngchampion/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
src/ja/youngchampion/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/ja/youngchampion/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
src/ja/youngchampion/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/ja/youngchampion/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,9 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.ja.youngchampion
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||||
|
|
||||||
|
class YoungChampion : ComiciViewer(
|
||||||
|
"Young Champion",
|
||||||
|
"https://youngchampion.jp",
|
||||||
|
"ja",
|
||||||
|
)
|
||||||