move MangaYu to standalone (#4876)

* add MangaYu source standalone

they change to other theme from mmrcms

* remove MangaYu from mmrcms
This commit is contained in:
Riztard Lanthorn 2020-11-16 19:44:00 +07:00 committed by GitHub
parent 484cfdd39f
commit 840dffeedd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 227 additions and 3 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'My Manga Reader CMS (Many sources)'
pkgNameSuffix = 'all.mmrcms'
extClass = '.MyMangaReaderCMSSources'
extVersionCode = 51
extVersionCode = 52
libVersion = '1.2'
containsNsfw = true
}

View File

@ -267,7 +267,6 @@ class Generator {
SourceData("pt-BR", "Remangas", "https://remangas.top"),
SourceData("pt-BR", "AnimaRegia", "https://animaregia.net"),
SourceData("tr", "NoxSubs", "https://noxsubs.com"),
SourceData("id", "MangaYu", "https://mangayu.com"),
SourceData("tr", "MangaVadisi", "http://manga-v2.mangavadisi.org"),
SourceData("id", "MangaID", "https://mangaid.click"),
SourceData("fr", "Jpmangas", "https://www.jpmangas.com"),
@ -277,6 +276,7 @@ class Generator {
SourceData("other", "HentaiShark", "https://www.hentaishark.com", true)
)
// Changed CMS
// SourceData("id", "MangaYu", "https://mangayu.com"),
// SourceData("en", "MangaTreat Scans", "http://www.mangatreat.com"),
// SourceData("en", "Chibi Manga Reader", "https://www.cmreader.info"),
// SourceData("tr", "Epikmanga", "https://www.epikmanga.com"),

View File

@ -147,7 +147,7 @@ open class MyMangaReaderCMSSource(
elements.select("a.fa-info-circle + a").firstOrNull()?.hasText() == true -> elements.map { latestUpdatesFromElement(it, "a.fa-info-circle + a") }
// List layout (most sources)
elements.select("a").firstOrNull()?.hasText() == true -> elements.map { latestUpdatesFromElement(it, "a") }
// Grid layout (e.g. MangaYu and MangaID)
// Grid layout (e.g. MangaID)
else -> document.select(gridLatestUpdatesSelector()).map { gridLatestUpdatesFromElement(it) }
}
}

View File

@ -0,0 +1,12 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
ext {
extName = 'MangaYu'
pkgNameSuffix = 'id.mangayu'
extClass = '.MangaYu'
extVersionCode = 1
libVersion = '1.2'
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,212 @@
package eu.kanade.tachiyomi.extension.id.mangayu
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.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
import okhttp3.Request
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class MangaYu : ParsedHttpSource() {
override val name = "MangaYu"
override val baseUrl = "https://mangayu.com"
override val lang = "id"
override val supportsLatest = true
private val dateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.US)
protected fun Element.imgAttr(): String = if (this.hasAttr("data-src")) this.attr("abs:data-src") else this.attr("abs:src")
override fun popularMangaRequest(page: Int): Request {
return GET("$baseUrl/manga?order_by=views&page=$page", headers)
}
override fun latestUpdatesRequest(page: Int): Request {
return GET("$baseUrl/manga?order_by=latest&page=$page", headers)
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = HttpUrl.parse("$baseUrl/search")!!.newBuilder()
.addQueryParameter("query", query)
.addQueryParameter("page", page.toString())
val newUrl = null
filters.forEach { filter ->
when (filter) {
is SortByFilter -> {
url.addQueryParameter("order_by", filter.toUriPart())
}
// TODO GENRE with $baseUrl/genre
}
}
return GET(url.toString(), headers)
}
override fun popularMangaSelector() = ".box-grid .card > div.card-body"
override fun latestUpdatesSelector() = popularMangaSelector()
override fun searchMangaSelector() = popularMangaSelector()
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
manga.thumbnail_url = element.select("div.img-box a img").attr("src")
manga.title = element.select("a.link-manga").text()
val item = element.select(".img-box a")
manga.setUrlWithoutDomain(item.attr("href"))
return manga
}
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
override fun popularMangaNextPageSelector() = "a.page-link[rel=next]"
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
author = document.select("tr:contains(Author) td:nth-child(2)").text()
artist = document.select("tr:contains(Artist) td:nth-child(2)").text()
status = parseStatus(document.select("tr:contains(Status) td").firstOrNull()?.ownText())
description = document.select("div.card-body h5 ~ p").text()
genre = document.select("tr:contains(Genre) a").joinToString { it.text() }
}
protected fun parseStatus(element: String?): Int = when {
element == null -> SManga.UNKNOWN
listOf("ongoing", "publishing").any { it.contains(element, ignoreCase = true) } -> SManga.ONGOING
listOf("completed").any { it.contains(element, ignoreCase = true) } -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
override fun chapterListSelector() = "div.chapter-list a"
override fun chapterFromElement(element: Element) = SChapter.create().apply {
setUrlWithoutDomain(element.attr("href"))
// timeStamp to remove child timestamp inside chapter name
val timeStamp = element.select("a.list-chapter i").text()
name = element.select("a.list-chapter").text().substringBefore(timeStamp)
date_upload = timeStamp.let { parseChapterDate(it) } ?: 0
}
fun parseChapterDate(date: String): Long {
return if (date.contains("yang lalu")) {
val value = date.split(' ')[0].toInt()
when {
"menit" in date -> Calendar.getInstance().apply {
add(Calendar.MINUTE, value * -1)
}.timeInMillis
"jam" in date -> Calendar.getInstance().apply {
add(Calendar.HOUR_OF_DAY, value * -1)
}.timeInMillis
"hari" in date -> Calendar.getInstance().apply {
add(Calendar.DATE, value * -1)
}.timeInMillis
"minggu" in date -> Calendar.getInstance().apply {
add(Calendar.DATE, value * 7 * -1)
}.timeInMillis
"bulan" in date -> Calendar.getInstance().apply {
add(Calendar.MONTH, value * -1)
}.timeInMillis
"tahun" in date -> Calendar.getInstance().apply {
add(Calendar.YEAR, value * -1)
}.timeInMillis
else -> {
0L
}
}
} else {
try {
dateFormat.parse(date)?.time ?: 0
} catch (_: Exception) {
0L
}
}
}
override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
var i = 0
document.select("div.row img.ch-img").forEach { element ->
val url = element.attr("src")
i++
if (url.isNotEmpty()) {
pages.add(Page(i, "", url))
}
}
return pages
}
override fun imageUrlParse(document: Document) = ""
private class SortByFilter : UriPartFilter(
"Sort By",
arrayOf(
Pair("Default", ""),
Pair("A-Z", "name"),
Pair("Latest Update", "latest"),
Pair("Latest Added", "new"),
Pair("Popular", "views")
)
)
private class Genre(name: String, val id: String = name) : Filter.TriState(name)
private class GenreListFilter(genres: List<Genre>) : Filter.Group<Genre>("Genre", genres)
override fun getFilterList() = FilterList(
SortByFilter()
)
// need to add thing to search filter for genre
private fun getGenreList() = listOf(
Genre("Action", "action"),
Genre("Adventure", "adventure"),
Genre("Comedy", "comedy"),
Genre("Doujinshi", "doujinshi"),
Genre("Drama", "drama"),
Genre("Ecchi", "ecchi"),
Genre("Fantasy", "fantasy"),
Genre("Gender Bender", "gender-bender"),
Genre("Harem", "harem"),
Genre("Historical", "historical"),
Genre("Horror", "horror"),
Genre("Isekai", "isekai"),
Genre("Josei", "josei"),
Genre("Martial Arts", "martial-arts"),
Genre("Mature", "mature"),
Genre("Mecha", "mecha"),
Genre("Mystery", "mystery"),
Genre("One-shot", "one-shot"),
Genre("Psychological", "psychological"),
Genre("Reincarnation", "reincarnation"),
Genre("Romance", "romance"),
Genre("School Life", "school-life"),
Genre("Sci-fi", "sci-fi"),
Genre("Seinen", "seinen"),
Genre("Shoujo", "shoujo"),
Genre("Shoujo Ai", "shoujo-ai"),
Genre("Shounen", "shounen"),
Genre("Shounen Ai", "shounen-ai"),
Genre("Slice of Life", "slice-of-life"),
Genre("Sports", "sports"),
Genre("Supernatural", "supernatural"),
Genre("Tragedy", "tragedy"),
Genre("Yaoi", "yaoi"),
Genre("Yuri", "yuri"),
Genre("Loli", "loli"),
Genre("Game", "game"),
Genre("Medical", "medical"),
)
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
fun toUriPart() = vals[state].second
}
}