Add TakeComic / Remove Web Comic Ganma Plus & Web Comic Ganma & multisrc (#11183)
* add storiadash * remove and add takecomic * api and refactor * apiUrl
@ -1,9 +0,0 @@
|
||||
plugins {
|
||||
id("lib-multisrc")
|
||||
}
|
||||
|
||||
baseVersionCode = 9
|
||||
|
||||
dependencies {
|
||||
api(project(":lib:speedbinb"))
|
||||
}
|
||||
@ -1,129 +0,0 @@
|
||||
package eu.kanade.tachiyomi.multisrc.comicgamma
|
||||
|
||||
import eu.kanade.tachiyomi.lib.speedbinb.SpeedBinbInterceptor
|
||||
import eu.kanade.tachiyomi.lib.speedbinb.SpeedBinbReader
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import org.jsoup.select.Evaluator
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
|
||||
open class ComicGamma(
|
||||
override val name: String,
|
||||
override val baseUrl: String,
|
||||
override val lang: String = "ja",
|
||||
) : ParsedHttpSource() {
|
||||
override val supportsLatest = false
|
||||
|
||||
private val json = Injekt.get<Json>()
|
||||
|
||||
override val client = network.cloudflareClient.newBuilder()
|
||||
.addInterceptor(SpeedBinbInterceptor(json))
|
||||
.build()
|
||||
|
||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/manga/", headers)
|
||||
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()
|
||||
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException()
|
||||
override fun latestUpdatesSelector() = throw UnsupportedOperationException()
|
||||
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException()
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
|
||||
fetchPopularManga(page).map { p -> MangasPage(p.mangas.filter { it.title.contains(query) }, false) }
|
||||
|
||||
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException()
|
||||
override fun searchMangaSelector() = throw UnsupportedOperationException()
|
||||
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException()
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
|
||||
throw UnsupportedOperationException()
|
||||
|
||||
private val reader by lazy { SpeedBinbReader(client, headers, json) }
|
||||
|
||||
override fun pageListParse(document: Document) = reader.pageListParse(document)
|
||||
|
||||
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()
|
||||
|
||||
companion object {
|
||||
internal fun SimpleDateFormat.parseJST(date: String) = parse(date)?.apply {
|
||||
time += 12 * 3600 * 1000 // updates at 12 noon
|
||||
}
|
||||
|
||||
private fun getJSTFormat(datePattern: String) =
|
||||
SimpleDateFormat(datePattern, Locale.JAPANESE).apply {
|
||||
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]}/"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/ja/takecomic/build.gradle
Normal file
@ -0,0 +1,10 @@
|
||||
ext {
|
||||
extName = 'TakeComic'
|
||||
extClass = '.TakeComic'
|
||||
themePkg = 'comiciviewer'
|
||||
baseUrl = 'https://takecomic.jp'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
BIN
src/ja/takecomic/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/ja/takecomic/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
src/ja/takecomic/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
src/ja/takecomic/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
src/ja/takecomic/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
@ -0,0 +1,180 @@
|
||||
package eu.kanade.tachiyomi.extension.ja.takecomic
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import keiyoushi.utils.parseAs
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
class ApiResponse(
|
||||
val series: SeriesData,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class SeriesData(
|
||||
val summary: SeriesSummary,
|
||||
private val episodes: List<Episode> = emptyList(),
|
||||
) {
|
||||
fun toSChapter(accessMap: Map<String, EpisodeAccess>, showLocked: Boolean, showCampaignLocked: Boolean): List<SChapter> {
|
||||
return this.episodes.mapNotNull { episode ->
|
||||
val accessInfo = accessMap[episode.id]
|
||||
val hasAccess = accessInfo?.hasAccess
|
||||
val isCampaign = accessInfo?.isCampaign
|
||||
val isLocked = !hasAccess!!
|
||||
val isCampaignLocked = isLocked && isCampaign!!
|
||||
|
||||
if (isCampaignLocked && !showCampaignLocked) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
if (isLocked && !isCampaignLocked && !showLocked) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
|
||||
SChapter.create().apply {
|
||||
name = episode.title
|
||||
date_upload = episode.datePublished * 1000L
|
||||
when {
|
||||
isCampaignLocked -> {
|
||||
name = "➡\uFE0F $name"
|
||||
url = "/episodes/${episode.id}#${TakeComic.LOGIN_SUFFIX}"
|
||||
}
|
||||
isLocked -> {
|
||||
name = "🔒 $name"
|
||||
url = "/episodes/${episode.id}"
|
||||
}
|
||||
else -> {
|
||||
url = "/episodes/${episode.id}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class SeriesSummary(
|
||||
private val name: String,
|
||||
private val description: String,
|
||||
private val author: List<Author>,
|
||||
private val images: List<SeriesImage>,
|
||||
private val tag: List<Tag>,
|
||||
) {
|
||||
fun toSManga(seriesHash: String): SManga = SManga.create().apply {
|
||||
url = "/series/$seriesHash"
|
||||
title = this@SeriesSummary.name
|
||||
author = this@SeriesSummary.author.joinToString { it.name }
|
||||
artist = author
|
||||
description = try {
|
||||
this@SeriesSummary.description.parseAs<List<DescriptionNode>>()
|
||||
.joinToString("\n") { node -> node.children.joinToString { it.text } }
|
||||
} catch (e: Exception) {
|
||||
this@SeriesSummary.description
|
||||
}
|
||||
genre = this@SeriesSummary.tag.joinToString { it.name }
|
||||
thumbnail_url = this@SeriesSummary.images.joinToString { it.url }
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class Author(
|
||||
val name: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class SeriesImage(
|
||||
val url: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class Tag(
|
||||
val name: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class Episode(
|
||||
val id: String,
|
||||
val title: String,
|
||||
val datePublished: Long,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class DescriptionNode(
|
||||
val children: List<DescriptionChild>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class DescriptionChild(
|
||||
val text: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class AccessApiResponse(
|
||||
val seriesAccess: SeriesAccess,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class SeriesAccess(
|
||||
val episodeAccesses: List<EpisodeAccess>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class EpisodeAccess(
|
||||
val episodeId: String,
|
||||
val hasAccess: Boolean,
|
||||
val isCampaign: Boolean,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class SearchApiResponse(
|
||||
val searchResult: SearchResult,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class SearchResult(
|
||||
val series: SeriesResult,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class SeriesResult(
|
||||
val total: Int,
|
||||
val series: List<SearchSeries>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class SearchSeries(
|
||||
private val id: String,
|
||||
private val name: String,
|
||||
private val images: List<SeriesImage>,
|
||||
) {
|
||||
fun toSManga(): SManga = SManga.create().apply {
|
||||
url = "/series/$id"
|
||||
title = name
|
||||
thumbnail_url = images.joinToString { it.url }
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class UserInfoApiResponse(
|
||||
val user: UserData?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class UserData(
|
||||
val id: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class EpisodeDetailsApiResponse(
|
||||
val episode: EpisodeDetails,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class EpisodeDetails(
|
||||
val content: List<EpisodeContent> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
class EpisodeContent(
|
||||
val type: String,
|
||||
val viewerId: String? = null,
|
||||
)
|
||||
@ -0,0 +1,227 @@
|
||||
package eu.kanade.tachiyomi.extension.ja.takecomic
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.PreferenceScreen
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import eu.kanade.tachiyomi.multisrc.comiciviewer.ComiciViewer
|
||||
import eu.kanade.tachiyomi.multisrc.comiciviewer.ViewerResponse
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
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.util.asJsoup
|
||||
import keiyoushi.utils.firstInstance
|
||||
import keiyoushi.utils.getPreferencesLazy
|
||||
import keiyoushi.utils.parseAs
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import kotlin.getValue
|
||||
|
||||
class TakeComic : ComiciViewer(
|
||||
"TakeComic",
|
||||
"https://takecomic.jp",
|
||||
"ja",
|
||||
) {
|
||||
private val apiUrl = "$baseUrl/api"
|
||||
private val preferences: SharedPreferences by getPreferencesLazy()
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
return latestUpdatesParse(response)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/series/list/up/$page", headers)
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup()
|
||||
val mangas = document.select("div.series-list-item").map { element ->
|
||||
SManga.create().apply {
|
||||
setUrlWithoutDomain(element.selectFirst("a.series-list-item-link")!!.attr("href"))
|
||||
title = element.selectFirst("div.series-list-item-h span")!!.text()
|
||||
thumbnail_url = element.selectFirst("img.series-list-item-img")?.attr("src")?.let { baseUrl.toHttpUrlOrNull()?.newBuilder(it)?.build()?.queryParameter("url") }
|
||||
}
|
||||
}
|
||||
val hasNextPage = document.selectFirst("a.g-pager-link.mode-active + a.g-pager-link") != null
|
||||
return MangasPage(mangas, hasNextPage)
|
||||
}
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
if (query.isNotBlank()) {
|
||||
val url = "$apiUrl/search".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("q", query)
|
||||
.addQueryParameter("page", page.toString())
|
||||
.addQueryParameter("size", SEARCH_PAGE_SIZE.toString())
|
||||
.build()
|
||||
return GET(url, headers)
|
||||
}
|
||||
|
||||
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
||||
val browseFilter = filterList.firstInstance<BrowseFilter>()
|
||||
val path = getFilterOptions()[browseFilter.state].second
|
||||
|
||||
val url = if (path == "/ranking/manga") {
|
||||
"$baseUrl$path"
|
||||
} else {
|
||||
"$baseUrl$path/$page"
|
||||
}
|
||||
return GET(url, headers)
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
val url = response.request.url.toString()
|
||||
if (url.contains("/api/search")) {
|
||||
val result = response.parseAs<SearchApiResponse>().searchResult.series
|
||||
val mangas = result.series.map { it.toSManga() }
|
||||
val page = response.request.url.queryParameter("page")!!.toInt()
|
||||
val hasNextPage = result.total > page * SEARCH_PAGE_SIZE
|
||||
return MangasPage(mangas, hasNextPage)
|
||||
}
|
||||
return latestUpdatesParse(response)
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val seriesHash = response.request.url.pathSegments.last()
|
||||
val apiUrl = "$apiUrl/episodes".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("seriesHash", seriesHash)
|
||||
.build()
|
||||
val apiRequest = GET(apiUrl, headers)
|
||||
val apiResponse = client.newCall(apiRequest).execute()
|
||||
return apiResponse.parseAs<ApiResponse>().series.summary.toSManga(seriesHash)
|
||||
}
|
||||
|
||||
override fun chapterListRequest(manga: SManga): Request {
|
||||
val seriesHash = manga.url.substringAfterLast("/")
|
||||
val apiUrl = "$apiUrl/episodes".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("seriesHash", seriesHash)
|
||||
.addQueryParameter("episodeFrom", "1")
|
||||
.addQueryParameter("episodeTo", "9999")
|
||||
.build()
|
||||
return GET(apiUrl, headers)
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val apiResponse = response.parseAs<ApiResponse>()
|
||||
val seriesHash = response.request.url.queryParameter("seriesHash")!!
|
||||
|
||||
val accessUrl = "$apiUrl/series/access".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("seriesHash", seriesHash)
|
||||
.addQueryParameter("episodeFrom", "1")
|
||||
.addQueryParameter("episodeTo", "9999")
|
||||
.build()
|
||||
val accessRequest = GET(accessUrl, headers, CacheControl.FORCE_NETWORK)
|
||||
val accessResponse = client.newCall(accessRequest).execute()
|
||||
val accessMap = accessResponse.parseAs<AccessApiResponse>().seriesAccess.episodeAccesses
|
||||
.associateBy { it.episodeId }
|
||||
|
||||
val showLocked = preferences.getBoolean(SHOW_LOCKED_PREF_KEY, true)
|
||||
val showCampaignLocked = preferences.getBoolean(SHOW_CAMPAIGN_LOCKED_PREF_KEY, true)
|
||||
|
||||
return apiResponse.series.toSChapter(accessMap, showLocked, showCampaignLocked).reversed()
|
||||
}
|
||||
|
||||
override fun pageListRequest(chapter: SChapter): Request {
|
||||
if (chapter.url.endsWith(LOGIN_SUFFIX)) {
|
||||
throw Exception("This chapter is free but you need to log in via WebView and refresh the entry")
|
||||
}
|
||||
return super.pageListRequest(chapter)
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val episodeId = response.request.url.pathSegments.last()
|
||||
|
||||
var comiciViewerId: String? = null
|
||||
var memberJwt: String? = null
|
||||
|
||||
try {
|
||||
val apiUrl = "$apiUrl/episodes/$episodeId"
|
||||
val accessRequest = GET(apiUrl, headers, CacheControl.FORCE_NETWORK)
|
||||
val apiResponse = client.newCall(accessRequest).execute()
|
||||
if (apiResponse.isSuccessful) {
|
||||
comiciViewerId = apiResponse.parseAs<EpisodeDetailsApiResponse>()
|
||||
.episode.content
|
||||
.firstOrNull { it.type == "viewer" }?.viewerId
|
||||
}
|
||||
} catch (e: Exception) { comiciViewerId = null }
|
||||
|
||||
if (comiciViewerId == null) {
|
||||
val document = response.asJsoup()
|
||||
val viewer = document.selectFirst("#comici-viewer") ?: throw Exception("Log in via WebView and purchase this chapter to read")
|
||||
comiciViewerId = viewer.attr("data-comici-viewer-id")
|
||||
memberJwt = viewer.attr("data-member-jwt")
|
||||
}
|
||||
|
||||
val userId = try {
|
||||
val userInfoResponse = client.newCall(GET("$apiUrl/user/info", headers)).execute()
|
||||
userInfoResponse.parseAs<UserInfoApiResponse>().user?.id
|
||||
} catch (e: Exception) {
|
||||
memberJwt
|
||||
}
|
||||
|
||||
val requestUrl = "$apiUrl/book/contentsInfo".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("comici-viewer-id", comiciViewerId)
|
||||
.addQueryParameter("user-id", userId)
|
||||
.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. HTTP ${initialResponse.code}")
|
||||
}
|
||||
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) {
|
||||
super.setupPreferenceScreen(screen)
|
||||
SwitchPreferenceCompat(screen.context).apply {
|
||||
key = SHOW_CAMPAIGN_LOCKED_PREF_KEY
|
||||
title = "Show 'Require Login' chapters"
|
||||
summary = "Shows chapters that are free but require login"
|
||||
setDefaultValue(true)
|
||||
}.also(screen::addPreference)
|
||||
}
|
||||
|
||||
override fun getFilterOptions(): List<Pair<String, String>> = listOf(
|
||||
Pair("ランキング", "/ranking/manga"),
|
||||
Pair("更新順", "/series/list/up"),
|
||||
Pair("新作順", "/series/list/new"),
|
||||
Pair("完結", "/category/manga/complete"),
|
||||
Pair("月曜日", "/category/manga/day/1"),
|
||||
Pair("火曜日", "/category/manga/day/2"),
|
||||
Pair("水曜日", "/category/manga/day/3"),
|
||||
Pair("木曜日", "/category/manga/day/4"),
|
||||
Pair("金曜日", "/category/manga/day/5"),
|
||||
Pair("土曜日", "/category/manga/day/6"),
|
||||
Pair("日曜日", "/category/manga/day/7"),
|
||||
Pair("その他", "/category/manga/day/8"),
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val SEARCH_PAGE_SIZE = 24
|
||||
private const val SHOW_LOCKED_PREF_KEY = "pref_show_locked_chapters"
|
||||
private const val SHOW_CAMPAIGN_LOCKED_PREF_KEY = "pref_show_campaign_locked_chapters"
|
||||
const val LOGIN_SUFFIX = "#LOGIN"
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Web Comic Gamma'
|
||||
extClass = '.WebComicGamma'
|
||||
themePkg = 'comicgamma'
|
||||
baseUrl = 'https://webcomicgamma.takeshobo.co.jp'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 13 KiB |
@ -1,5 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.ja.webcomicgamma
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.comicgamma.ComicGamma
|
||||
|
||||
class WebComicGamma : ComicGamma("Web Comic Gamma", "https://webcomicgamma.takeshobo.co.jp", "ja")
|
||||
@ -1,10 +0,0 @@
|
||||
ext {
|
||||
extName = 'Web Comic Gamma Plus'
|
||||
extClass = '.WebComicGammaPlus'
|
||||
themePkg = 'comicgamma'
|
||||
baseUrl = 'https://gammaplus.takeshobo.co.jp'
|
||||
overrideVersionCode = 0
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 8.4 KiB |
@ -1,5 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.ja.webcomicgammaplus
|
||||
|
||||
import eu.kanade.tachiyomi.multisrc.comicgamma.ComicGamma
|
||||
|
||||
class WebComicGammaPlus : ComicGamma("Web Comic Gamma Plus", "https://gammaplus.takeshobo.co.jp", "ja")
|
||||