Skip to content

Commit

Permalink
CrystalComics: Theme changed (#5906)
Browse files Browse the repository at this point in the history
* Theme changed

* Fix lint and update icon

* Use imageFromElement
  • Loading branch information
choppeh authored Nov 7, 2024
1 parent 2670931 commit 936754a
Show file tree
Hide file tree
Showing 13 changed files with 274 additions and 208 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name=".pt.mangalivre.MangaLivreUrlActivity"
android:name="eu.kanade.tachiyomi.multisrc.etoshore.EtoshoreUrlActivity"
android:excludeFromRecents="true"
android:exported="true"
android:theme="@android:style/Theme.NoDisplay">
Expand All @@ -13,9 +13,9 @@
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="mangalivre.one"
android:pathPattern="/manga/..*"
android:scheme="https" />
android:host="${SOURCEHOST}"
android:pathPattern="/.*/..*"
android:scheme="${SOURCESCHEME}" />
</intent-filter>
</activity>
</application>
Expand Down
5 changes: 5 additions & 0 deletions lib-multisrc/etoshore/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
plugins {
id("lib-multisrc")
}

baseVersionCode = 1
242 changes: 242 additions & 0 deletions lib-multisrc/etoshore/src/eu/kanade/tachiyomi/multisrc/Etoshore.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
package eu.kanade.tachiyomi.multisrc.etoshore

import eu.kanade.tachiyomi.network.GET
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.ParsedHttpSource
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import okhttp3.Response
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable

abstract class Etoshore(
override val name: String,
override val baseUrl: String,
final override val lang: String,
) : ParsedHttpSource() {

override val supportsLatest = true

override val client = network.cloudflareClient

// ============================== Popular ==============================

open val popularFilter = FilterList(
SelectionList("", listOf(Tag(value = "views", query = "sort"))),
)

override fun popularMangaRequest(page: Int) = searchMangaRequest(page, "", popularFilter)
override fun popularMangaParse(response: Response) = searchMangaParse(response)

override fun popularMangaSelector() = throw UnsupportedOperationException()
override fun popularMangaNextPageSelector() = throw UnsupportedOperationException()
override fun popularMangaFromElement(element: Element) = throw UnsupportedOperationException()

// ============================== Latest ===============================

open val latestFilter = FilterList(
SelectionList("", listOf(Tag(value = "date", query = "sort"))),
)

override fun latestUpdatesRequest(page: Int) = searchMangaRequest(page, "", latestFilter)
override fun latestUpdatesParse(response: Response) = searchMangaParse(response)

override fun latestUpdatesSelector() = throw UnsupportedOperationException()
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException()

// ============================== Search ===============================

override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/page/$page".toHttpUrl().newBuilder()
.addQueryParameter("s", query)

filters.forEach { filter ->
when (filter) {
is SelectionList -> {
val selected = filter.selected()
url.addQueryParameter(selected.query, selected.value)
}
else -> {}
}
}

return GET(url.build(), headers)
}

override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
if (query.startsWith(PREFIX_SEARCH)) {
val slug = query.substringAfter(PREFIX_SEARCH)
return fetchMangaDetails(SManga.create().apply { url = "/manga/$slug/" })
.map { manga -> MangasPage(listOf(manga), false) }
}
return super.fetchSearchManga(page, query, filters)
}

override fun searchMangaSelector() = ".search-posts .chapter-box .poster a"

override fun searchMangaNextPageSelector() = ".navigation .naviright:has(a)"

override fun searchMangaFromElement(element: Element) = SManga.create().apply {
title = element.attr("title")
thumbnail_url = element.selectFirst("img")?.let(::imageFromElement)
setUrlWithoutDomain(element.absUrl("href"))
}

override fun searchMangaParse(response: Response): MangasPage {
if (filterList.isEmpty()) {
filterParse(response)
}
return super.searchMangaParse(response)
}

// ============================== Details ===============================

override fun mangaDetailsParse(document: Document) = SManga.create().apply {
title = document.selectFirst("h1")!!.text()
description = document.selectFirst(".excerpt p")?.text()
document.selectFirst(".details-right-con img")?.let { thumbnail_url = imageFromElement(it) }
genre = document.select("div.meta-item span.meta-title:contains(Genres) + span a")
.joinToString { it.text() }
author = document.selectFirst("div.meta-item span.meta-title:contains(Author) + span a")
?.text()
document.selectFirst(".status")?.text()?.let {
status = it.toMangaStatus()
}

setUrlWithoutDomain(document.location())
}

protected open fun imageFromElement(element: Element): String? {
return when {
element.hasAttr("data-src") -> element.attr("abs:data-src")
element.hasAttr("data-lazy-src") -> element.attr("abs:data-lazy-src")
element.hasAttr("srcset") -> element.attr("abs:srcset").getSrcSetImage()
element.hasAttr("data-cfsrc") -> element.attr("abs:data-cfsrc")
else -> element.attr("abs:src")
}
}

protected open fun String.getSrcSetImage(): String? {
return this.split(" ")
.filter(URL_REGEX::matches)
.maxOfOrNull(String::toString)
}

protected val completedStatusList: Array<String> = arrayOf(
"Finished",
"Completo",
)

protected open val ongoingStatusList: Array<String> = arrayOf(
"Publishing",
"Ativo",
)

protected val hiatusStatusList: Array<String> = arrayOf(
"on hiatus",
)

protected val canceledStatusList: Array<String> = arrayOf(
"Canceled",
"Discontinued",
)

open fun String.toMangaStatus(): Int {
return when {
containsIn(completedStatusList) -> SManga.COMPLETED
containsIn(ongoingStatusList) -> SManga.ONGOING
containsIn(hiatusStatusList) -> SManga.ON_HIATUS
containsIn(canceledStatusList) -> SManga.CANCELLED
else -> SManga.UNKNOWN
}
}

// ============================== Chapters ============================

override fun chapterListSelector() = ".chapter-list li a"

override fun chapterFromElement(element: Element) = SChapter.create().apply {
name = element.selectFirst(".title")!!.text()
setUrlWithoutDomain(element.absUrl("href"))
}

// ============================== Pages ===============================

override fun pageListParse(document: Document): List<Page> {
return document.select(".chapter-images .chapter-item > img").mapIndexed { index, element ->
Page(index, imageUrl = imageFromElement(element))
}
}

override fun imageUrlParse(document: Document) = ""

// ============================= Filters ==============================

private var filterList = emptyList<Pair<String, List<Tag>>>()

override fun getFilterList(): FilterList {
val filters = mutableListOf<Filter<*>>()

filters += if (filterList.isNotEmpty()) {
filterList.map { SelectionList(it.first, it.second) }
} else {
listOf(Filter.Header("Aperte 'Redefinir' para tentar mostrar os filtros"))
}

return FilterList(filters)
}

protected open fun parseSelection(document: Document, selector: String): Pair<String, List<Tag>>? {
val selectorFilter = "#filter-form $selector .select-item-head .text"
return document.selectFirst(selectorFilter)?.text()?.let { displayName ->
displayName to document.select("#filter-form $selector li").map { element ->
element.selectFirst("input")!!.let { input ->
Tag(
name = element.selectFirst(".text")!!.text(),
value = input.attr("value"),
query = input.attr("name"),
)
}
}
}
}

open val filterListSelector: List<String> = listOf(
".filter-genre",
".filter-status",
".filter-type",
".filter-year",
".filter-sort",
)

open fun filterParse(response: Response) {
val document = Jsoup.parseBodyFragment(response.peekBody(Long.MAX_VALUE).string())
filterList = filterListSelector.mapNotNull { selector -> parseSelection(document, selector) }
}

protected data class Tag(val name: String = "", val value: String = "", val query: String = "")

private open class SelectionList(displayName: String, private val vals: List<Tag>, state: Int = 0) :
Filter.Select<String>(displayName, vals.map { it.name }.toTypedArray(), state) {
fun selected() = vals[state]
}

// ============================= Utils ==============================

private fun String.containsIn(array: Array<String>): Boolean {
return this.lowercase() in array.map { it.lowercase() }
}

companion object {
const val PREFIX_SEARCH = "id:"
val URL_REGEX = """^(https?://[^\s/$.?#].[^\s]*)${'$'}""".toRegex()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.extension.pt.mangalivre
package eu.kanade.tachiyomi.multisrc.etoshore

import android.app.Activity
import android.content.ActivityNotFoundException
Expand All @@ -7,7 +7,7 @@ import android.os.Bundle
import android.util.Log
import kotlin.system.exitProcess

class MangaLivreUrlActivity : Activity() {
class EtoshoreUrlActivity : Activity() {

private val tag = javaClass.simpleName

Expand All @@ -18,7 +18,7 @@ class MangaLivreUrlActivity : Activity() {
val item = pathSegments[1]
val mainIntent = Intent().apply {
action = "eu.kanade.tachiyomi.SEARCH"
putExtra("query", "${MangaLivre.PREFIX_SEARCH}$item")
putExtra("query", "${Etoshore.PREFIX_SEARCH}$item")
putExtra("filter", packageName)
}

Expand Down
4 changes: 2 additions & 2 deletions src/pt/crystalcomics/build.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
ext {
extName = 'CrystalComics'
extClass = '.CrystalComics'
themePkg = 'madara'
themePkg = 'etoshore'
baseUrl = 'https://crystalcomics.com'
overrideVersionCode = 0
overrideVersionCode = 37
}

apply from: "$rootDir/common.gradle"
Binary file modified src/pt/crystalcomics/res/mipmap-hdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/pt/crystalcomics/res/mipmap-mdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/pt/crystalcomics/res/mipmap-xhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/pt/crystalcomics/res/mipmap-xxhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/pt/crystalcomics/res/mipmap-xxxhdpi/ic_launcher.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package eu.kanade.tachiyomi.extension.pt.crystalcomics

import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
import eu.kanade.tachiyomi.multisrc.etoshore.Etoshore
import eu.kanade.tachiyomi.network.interceptor.rateLimit

class CrystalComics : Madara(
class CrystalComics : Etoshore(
"Crystal Comics",
"https://crystalcomics.com",
"pt-BR",
SimpleDateFormat("MMMM dd, yyyy", Locale("pt", "BR")),
) {
override val useNewChapterEndpoint = true
override val client = super.client.newBuilder()
.rateLimit(2)
.build()
}
4 changes: 3 additions & 1 deletion src/pt/mangalivre/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
ext {
extName = 'Manga Livre'
extClass = '.MangaLivre'
extVersionCode = 2
themePkg = 'etoshore'
baseUrl = 'https://mangalivre.one'
overrideVersionCode = 1
isNsfw = true
}

Expand Down
Loading

0 comments on commit 936754a

Please sign in to comment.