Rewrote mangaworld extension and new icon (#5198)

This commit is contained in:
antonycaporossi 2020-12-19 15:13:09 +01:00 committed by GitHub
parent c580c9ceed
commit 3de032378b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 109 additions and 86 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'Mangaworld' extName = 'Mangaworld'
pkgNameSuffix = 'it.mangaworld' pkgNameSuffix = 'it.mangaworld'
extClass = '.Mangaworld' extClass = '.Mangaworld'
extVersionCode = 2 extVersionCode = 3
libVersion = '1.2' libVersion = '1.2'
containsNsfw = true containsNsfw = true
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -4,14 +4,17 @@ import eu.kanade.tachiyomi.annotations.Nsfw
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList 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.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.text.ParseException import java.text.ParseException
@ -22,19 +25,19 @@ import java.util.Locale
class Mangaworld : ParsedHttpSource() { class Mangaworld : ParsedHttpSource() {
override val name = "Mangaworld" override val name = "Mangaworld"
override val baseUrl = "https://mangaworld.cc" override val baseUrl = "https://www.mangaworld.cc"
override val lang = "it" override val lang = "it"
override val supportsLatest = true override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient override val client: OkHttpClient = network.cloudflareClient
override fun popularMangaRequest(page: Int): Request { override fun popularMangaRequest(page: Int): Request {
return GET("$baseUrl/page/$page?s&post_type=wp-manga&m_orderby=views", headers) return GET("$baseUrl/archive?sort=most_read&page=$page", headers)
} }
override fun latestUpdatesRequest(page: Int): Request { override fun latestUpdatesRequest(page: Int): Request {
return GET("$baseUrl/page/$page?s&post_type=wp-manga&m_orderby=latest", headers) return GET("$baseUrl/archive?sort=newest&page=$page", headers)
} }
// LIST SELECTOR // LIST SELECTOR
override fun popularMangaSelector() = "div.c-tabs-item__content" override fun popularMangaSelector() = "div.comics-grid .entry"
override fun latestUpdatesSelector() = popularMangaSelector() override fun latestUpdatesSelector() = popularMangaSelector()
override fun searchMangaSelector() = popularMangaSelector() override fun searchMangaSelector() = popularMangaSelector()
@ -43,36 +46,55 @@ class Mangaworld : ParsedHttpSource() {
override fun latestUpdatesFromElement(element: Element): SManga = searchMangaFromElement(element) override fun latestUpdatesFromElement(element: Element): SManga = searchMangaFromElement(element)
// NEXT SELECTOR // NEXT SELECTOR
override fun popularMangaNextPageSelector() = "div.nav-previous.float-left > a" // Not needed
override fun popularMangaNextPageSelector(): String? = null
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
// ////////////////
override fun latestUpdatesParse(response: Response): MangasPage {
val document = response.asJsoup()
val mangas = document.select(popularMangaSelector()).map { element ->
popularMangaFromElement(element)
}
// nextPage is not possible because pagination is loaded after via Javascript
// 16 is the default manga-per-page. If it is less than 16 then there's no next page
val hasNextPage = mangas.size == 16
return MangasPage(mangas, hasNextPage)
}
override fun popularMangaParse(response: Response): MangasPage {
return latestUpdatesParse(response)
}
override fun searchMangaFromElement(element: Element): SManga { override fun searchMangaFromElement(element: Element): SManga {
val manga = SManga.create() val manga = SManga.create()
manga.thumbnail_url = element.select("div.tab-thumb > a > img").attr("src") manga.thumbnail_url = element.select("a.thumb img").attr("src")
element.select("div.tab-thumb > a").first().let { element.select("a").first().let {
manga.setUrlWithoutDomain(it.attr("href")) manga.setUrlWithoutDomain(it.attr("href"))
manga.title = it.attr("title") manga.title = it.attr("title")
} }
return manga return manga
} }
override fun searchMangaParse(response: Response): MangasPage {
return latestUpdatesParse(response)
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = HttpUrl.parse("$baseUrl/page/$page")!!.newBuilder() val url = HttpUrl.parse("$baseUrl/archive?page=$page")!!.newBuilder()
url.addQueryParameter("post_type", "wp-manga")
val pattern = "\\s+".toRegex() val pattern = "\\s+".toRegex()
val q = query.replace(pattern, "+") val q = query
if (query.length > 0) { if (query.length > 0) {
url.addQueryParameter("s", q) url.addQueryParameter("keyword", q)
} else { } else {
url.addQueryParameter("s", "") url.addQueryParameter("keyword", "")
} }
var orderBy = "" var orderBy = ""
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> (if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
when (filter) { when (filter) {
// is Status -> url.addQueryParameter("manga_status", arrayOf("", "completed", "ongoing")[filter.state])
is GenreList -> { is GenreList -> {
val genreInclude = mutableListOf<String>() val genreInclude = mutableListOf<String>()
filter.state.forEach { filter.state.forEach {
@ -82,7 +104,7 @@ class Mangaworld : ParsedHttpSource() {
} }
if (genreInclude.isNotEmpty()) { if (genreInclude.isNotEmpty()) {
genreInclude.forEach { genre -> genreInclude.forEach { genre ->
url.addQueryParameter("genre[]", genre) url.addQueryParameter("genre", genre)
} }
} }
} }
@ -95,41 +117,53 @@ class Mangaworld : ParsedHttpSource() {
} }
if (statuses.isNotEmpty()) { if (statuses.isNotEmpty()) {
statuses.forEach { status -> statuses.forEach { status ->
url.addQueryParameter("status[]", status) url.addQueryParameter("status", status)
}
}
}
is MTypeList -> {
val typeslist = mutableListOf<String>()
filter.state.forEach {
if (it.state == 1) {
typeslist.add(it.id)
}
}
if (typeslist.isNotEmpty()) {
typeslist.forEach { mtype ->
url.addQueryParameter("type", mtype)
} }
} }
} }
is SortBy -> { is SortBy -> {
orderBy = filter.toUriPart() orderBy = filter.toUriPart()
url.addQueryParameter("m_orderby", orderBy) url.addQueryParameter("sort", orderBy)
} }
is TextField -> url.addQueryParameter(filter.key, filter.state) is TextField -> url.addQueryParameter(filter.key, filter.state)
} }
} }
return GET(url.toString(), headers) return GET(url.toString(), headers)
} }
// max 200 results
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val infoElement = document.select("div.site-content").first() val infoElement = document.select("div.comic-info")
val metaData = document.select("div.comic-info").first()
val manga = SManga.create() val manga = SManga.create()
manga.author = infoElement.select("div.author-content")?.text() manga.author = infoElement.select("a[href^=https://www.mangaworld.cc/archive?author=]").first()?.text()
manga.artist = infoElement.select("div.artist-content")?.text() manga.artist = infoElement.select("a[href^=https://www.mangaworld.cc/archive?artist=]")?.text()
val genres = mutableListOf<String>() val genres = mutableListOf<String>()
infoElement.select("div.genres-content a").forEach { element -> metaData.select("div.meta-data a.badge").forEach { element ->
val genre = element.text() val genre = element.text()
genres.add(genre) genres.add(genre)
} }
manga.genre = genres.joinToString(", ") manga.genre = genres.joinToString(", ")
manga.status = parseStatus(infoElement.select("div.post-status > div:nth-child(2) div").text()) manga.status = parseStatus(infoElement.select("a[href^=https://www.mangaworld.cc/archive?status=]").first().attr("href"))
manga.description = document.select("div.summary__content > p")?.text() manga.description = document.select("div#noidungm")?.text()
manga.thumbnail_url = document.select("div.summary_image > a > img").attr("src") manga.thumbnail_url = document.select(".comic-info .thumb > img").attr("src")
return manga return manga
} }
@ -141,14 +175,14 @@ class Mangaworld : ParsedHttpSource() {
else -> SManga.UNKNOWN else -> SManga.UNKNOWN
} }
override fun chapterListSelector() = "li.wp-manga-chapter" override fun chapterListSelector() = ".chapters-wrapper .chapter"
override fun chapterFromElement(element: Element): SChapter { override fun chapterFromElement(element: Element): SChapter {
val urlElement = element.select("a").first() val urlElement = element.select("a.chap").first()
val chapter = SChapter.create() val chapter = SChapter.create()
chapter.setUrlWithoutDomain(getUrl(urlElement)) chapter.setUrlWithoutDomain(getUrl(urlElement))
chapter.name = urlElement.text() chapter.name = urlElement.select("span.d-inline-block").first().text()
chapter.date_upload = element.select("span.chapter-release-date i").last()?.text()?.let { chapter.date_upload = element.select(".chap-date").last()?.text()?.let {
try { try {
SimpleDateFormat("dd MMMM yyyy", Locale.ITALY).parse(it).time SimpleDateFormat("dd MMMM yyyy", Locale.ITALY).parse(it).time
} catch (e: ParseException) { } catch (e: ParseException) {
@ -180,7 +214,7 @@ class Mangaworld : ParsedHttpSource() {
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>() val pages = mutableListOf<Page>()
var i = 0 var i = 0
document.select("div.reading-content * img").forEach { element -> document.select("div#page img.page-image").forEach { element ->
val url = element.attr("src") val url = element.attr("src")
i++ i++
if (url.length != 0) { if (url.length != 0) {
@ -205,91 +239,80 @@ class Mangaworld : ParsedHttpSource() {
"Ordina per", "Ordina per",
arrayOf( arrayOf(
Pair("Rilevanza", ""), Pair("Rilevanza", ""),
Pair("Ultime Aggiunte", "latest"), Pair("Più recenti", "newest"),
Pair("A-Z", "alphabet"), Pair("Meno recenti", "oldest"),
Pair("Voto", "rating"), Pair("A-Z", "a-z"),
Pair("Tendenza", "trending"), Pair("Z-A", "z-a"),
Pair("Più Visualizzati", "views"), Pair("Più letti", "most_read"),
Pair("Nuove Aggiunte", "new-manga") Pair("Meno letti", "less_read")
) )
) )
private class Genre(name: String, val id: String = name) : Filter.TriState(name) private class Genre(name: String, val id: String = name) : Filter.TriState(name)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Generi", genres) private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Generi", genres)
private class MType(name: String, val id: String = name) : Filter.TriState(name)
private class MTypeList(types: List<MType>) : Filter.Group<MType>("Tipologia", types)
private class Status(name: String, val id: String = name) : Filter.TriState(name) private class Status(name: String, val id: String = name) : Filter.TriState(name)
private class StatusList(statuses: List<Status>) : Filter.Group<Status>("Stato", statuses) private class StatusList(statuses: List<Status>) : Filter.Group<Status>("Stato", statuses)
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
// TextField("Judul", "title"), TextField("Anno di rilascio", "year"),
TextField("Autore", "author"),
TextField("Anno di rilascio", "release"),
SortBy(), SortBy(),
StatusList(getStatusList()), StatusList(getStatusList()),
GenreList(getGenreList()) GenreList(getGenreList()),
MTypeList(getTypesList())
) )
private fun getStatusList() = listOf( private fun getStatusList() = listOf(
Status("Completato", "end"), Status("In corso", "ongoing"),
Status("In Corso", "on-going"), Status("Finito", "completed"),
Status("Droppato", "canceled"), Status("Droppato", "dropped"),
Status("In Pausa", "on-hold") Status("In pausa", "paused"),
Status("Cancellato", "canceled")
) )
private fun getTypesList() = listOf(
MType("Manga", "manga"),
MType("Manhua", "manhua"),
MType("Manhwa", "manhwa"),
MType("Oneshot", "oneshot"),
MType("Thai", "thai"),
MType("Vietnamita", "vietnamese")
)
private fun getGenreList() = listOf( private fun getGenreList() = listOf(
Genre("Adulti", "adult"), Genre("Adulti", "adulti"),
Genre("Anime", "anime"), Genre("Arti Marziali", "arti-marziali"),
Genre("Arti Marziali", "martial-arts"), Genre("Avventura", "avventura"),
Genre("Avventura", "adventure"), Genre("Azione", "azione"),
Genre("Azione", "action"), Genre("Commedia", "commedia"),
Genre("Cartoon", "cartoon"),
Genre("Comic", "comic"),
Genre("Commedia", "comedy"),
Genre("Cucina", "cooking"),
Genre("Demoni", "demoni"),
Genre("Detective", "detective"),
Genre("Doujinshi", "doujinshi"), Genre("Doujinshi", "doujinshi"),
Genre("Drama", "drama-"), Genre("Drammatico", "drammatico"),
Genre("Drammatico", "drama"),
Genre("Ecchi", "ecchi"), Genre("Ecchi", "ecchi"),
Genre("Fantasy", "fantasy"), Genre("Fantasy", "fantasy"),
Genre("Game", "game"),
Genre("Gender Bender", "gender-bender"), Genre("Gender Bender", "gender-bender"),
Genre("Harem", "harem"), Genre("Harem", "harem"),
Genre("Hentai", "hentai"), Genre("Hentai", "hentai"),
Genre("Horror", "horror"), Genre("Horror", "horror"),
Genre("Josei", "josei"), Genre("Josei", "josei"),
Genre("Live action", "live-action"), Genre("Lolicon", "lolicon"),
Genre("Magia", "magia"), Genre("Maturo", "maturo"),
Genre("Manga", "manga"),
Genre("Manhua", "manhua"),
Genre("Manhwa", "manhwa"),
Genre("Mature", "mature"),
Genre("Mecha", "mecha"), Genre("Mecha", "mecha"),
Genre("Militari", "militari"), Genre("Mistero", "mistero"),
Genre("Mistero", "mystery"), Genre("Psicologico", "psicologico"),
Genre("Musica", "musica"), Genre("Romantico", "romantico"),
Genre("One shot", "one-shot"),
Genre("Parodia", "parodia"),
Genre("Psicologico", "psychological"),
Genre("Romantico", "romance"),
Genre("RPG", "rpg"),
Genre("Sci-fi", "sci-fi"), Genre("Sci-fi", "sci-fi"),
Genre("Scolastico", "school-life"), Genre("Scolastico", "scolastico"),
Genre("Seinen", "seinen"), Genre("Seinen", "seinen"),
Genre("Shotacon", "shotacon"),
Genre("Shoujo", "shoujo"), Genre("Shoujo", "shoujo"),
Genre("Shoujo Ai", "shoujo-ai"), Genre("Shoujo Ai", "shoujo-ai"),
Genre("Shounen", "shounen"), Genre("Shounen", "shounen"),
Genre("Shounen Ai", "shounen-ai"), Genre("Shounen Ai", "shounen-ai"),
Genre("Slice of Life", "slice-of-life"), Genre("Slice of Life", "slice-of-life"),
Genre("Smut", "smut"), Genre("Smut", "smut"),
Genre("Soft Yaoi", "soft-yaoi"), Genre("Soprannaturale", "soprannaturale"),
Genre("Soft Yuri", "soft-yuri"), Genre("Sport", "sport"),
Genre("Soprannaturale", "supernatural"), Genre("Storico", "storico"),
Genre("Spazio", "spazio"), Genre("Tragico", "tragico"),
Genre("Sport", "sports"),
Genre("Storico", "historical"),
Genre("Super Poteri", "superpower"),
Genre("Thriller", "thriller"),
Genre("Tragico", "tragedy"),
Genre("Vampiri", "vampiri"),
Genre("Webtoon", "webtoon"),
Genre("Yaoi", "yaoi"), Genre("Yaoi", "yaoi"),
Genre("Yuri", "yuri") Genre("Yuri", "yuri")
) )