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",
|
||||
)
|
||||