@@ -85,7 +85,7 @@ internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(contex
|
||||
coverUrl = jo.getString("cover_url"),
|
||||
largeCoverUrl = null,
|
||||
description = jo.getStringOrNull("desc"),
|
||||
tags = jo.selectGenres("genres", tagsMap),
|
||||
tags = jo.selectGenres(tagsMap),
|
||||
state = runCatching {
|
||||
if (jo.getBoolean("translation_completed")) {
|
||||
MangaState.FINISHED
|
||||
@@ -203,8 +203,8 @@ internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(contex
|
||||
return chaptersBuilder.toList()
|
||||
}
|
||||
|
||||
private fun JSONObject.selectGenres(name: String, tags: SparseArrayCompat<MangaTag>): Set<MangaTag> {
|
||||
val array = optJSONArray(name) ?: return emptySet()
|
||||
private fun JSONObject.selectGenres(tags: SparseArrayCompat<MangaTag>): Set<MangaTag> {
|
||||
val array = optJSONArray("genres") ?: return emptySet()
|
||||
val res = ArraySet<MangaTag>(array.length())
|
||||
for (i in 0 until array.length()) {
|
||||
val id = array.getInt(i)
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
package org.koitharu.kotatsu.parsers.site.all
|
||||
|
||||
import androidx.collection.ArraySet
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("HENTAIFOX", "Hentai Fox", type = ContentType.HENTAI)
|
||||
internal class HentaiFox(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.HENTAIFOX, 20) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
|
||||
override val configKeyDomain = ConfigKey.Domain("hentaifox.com")
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("/tag/")
|
||||
append(tag?.key.orEmpty())
|
||||
if (page > 1) {
|
||||
append("/pag/")
|
||||
append(page)
|
||||
append("/")
|
||||
}
|
||||
} else if (!query.isNullOrEmpty()) {
|
||||
append("/search/?q=")
|
||||
append(query.urlEncoded())
|
||||
if (page > 1) {
|
||||
append("&page=")
|
||||
append(page)
|
||||
}
|
||||
} else {
|
||||
if (page > 2) {
|
||||
append("/pag/")
|
||||
append(page)
|
||||
append("/")
|
||||
} else if (page > 1) {
|
||||
append("/page/")
|
||||
append(page)
|
||||
append("/")
|
||||
}
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select(".lc_galleries .thumb").map { div ->
|
||||
val href = div.selectFirstOrThrow(".inner_thumb a").attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = div.select("h2.g_title").text(),
|
||||
altTitle = null,
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = isNsfwSource,
|
||||
coverUrl = div.selectFirstOrThrow("img").src().orEmpty(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//Tags are deliberately reduced because there are too many and this slows down the application.
|
||||
//only the most popular ones are taken.
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
return coroutineScope {
|
||||
(1..3).map { page ->
|
||||
async { getTags(page) }
|
||||
}
|
||||
}.awaitAll().flattenTo(ArraySet(360))
|
||||
}
|
||||
|
||||
private suspend fun getTags(page: Int): Set<MangaTag> {
|
||||
val url = "https://$domain/tags/popular/pag/$page/"
|
||||
val root = webClient.httpGet(url).parseHtml()
|
||||
return root.parseTags()
|
||||
}
|
||||
|
||||
private fun Element.parseTags() = select(".list_tags a.tag_btn").mapToSet {
|
||||
val key = it.attr("href").removeSuffix('/').substringAfterLast('/')
|
||||
MangaTag(
|
||||
key = key,
|
||||
title = it.selectFirstOrThrow("h3").text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val urlChapters = manga.url.replace("/gallery/", "/g/") + "1/"
|
||||
return manga.copy(
|
||||
altTitle = null,
|
||||
tags = doc.select("ul.tags a.tag_btn ").mapNotNullToSet {
|
||||
val key = it.attr("href").removeSuffix('/').substringAfterLast('/')
|
||||
MangaTag(
|
||||
key = key,
|
||||
title = it.html().substringBefore("<span"),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst("ul.artists a.tag_btn")?.html()?.substringBefore("<span"),
|
||||
description = null,
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = manga.id,
|
||||
name = manga.title,
|
||||
number = 1,
|
||||
url = urlChapters,
|
||||
scanlator = null,
|
||||
uploadDate = 0,
|
||||
branch = doc.selectFirstOrThrow("ul.languages a.tag_btn").html().substringBefore("<span"),
|
||||
source = source,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getRelatedManga(seed: Manga): List<Manga> {
|
||||
val doc = webClient.httpGet(seed.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow(".related_galleries")
|
||||
return root.select("div.thumb").mapNotNull { div ->
|
||||
val a = div.selectFirst(".inner_thumb a") ?: return@mapNotNull null
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(a.host ?: domain),
|
||||
altTitle = null,
|
||||
title = div.selectFirstOrThrow("h2.g_title").text(),
|
||||
author = null,
|
||||
coverUrl = div.selectFirst("img")?.src().orEmpty(),
|
||||
tags = emptySet(),
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
isNsfw = isNsfwSource,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val totalPages = doc.selectFirstOrThrow(".total_pages").text().toInt()
|
||||
val rawUrl = chapter.url.replace("/1/", "/")
|
||||
return (1..totalPages).map {
|
||||
val url = "$rawUrl$it/"
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val root = doc.body()
|
||||
return root.requireElementById("gimg").attrAsAbsoluteUrl("data-src")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package org.koitharu.kotatsu.parsers.site.all
|
||||
|
||||
import androidx.collection.ArraySet
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("IMHENTAI", "ImHentai", type = ContentType.HENTAI)
|
||||
internal class ImHentai(context: MangaLoaderContext) :
|
||||
PagedMangaParser(context, MangaSource.IMHENTAI, pageSize = 20) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> =
|
||||
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.RATING)
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain("imhentai.xxx")
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
|
||||
if (!query.isNullOrEmpty()) {
|
||||
append("/search/?key=")
|
||||
append(query.urlEncoded())
|
||||
append("&page=")
|
||||
append(page)
|
||||
} else if (!tags.isNullOrEmpty()) {
|
||||
append("/tag/")
|
||||
append(tag?.key.orEmpty())
|
||||
append("/")
|
||||
when (sortOrder) {
|
||||
SortOrder.UPDATED -> append("")
|
||||
SortOrder.POPULARITY -> append("popular/")
|
||||
else -> append("")
|
||||
}
|
||||
append("?page=")
|
||||
append(page)
|
||||
} else {
|
||||
append("/search/?page=")
|
||||
append(page)
|
||||
when (sortOrder) {
|
||||
SortOrder.UPDATED -> append("<=1&pp=0")
|
||||
SortOrder.POPULARITY -> append("<=0&pp=1")
|
||||
SortOrder.RATING -> append("<=0&pp=0")
|
||||
else -> append("<=1&pp=0")
|
||||
}
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select("div.galleries div.thumb").map { div ->
|
||||
val a = div.selectFirstOrThrow(".inner_thumb a")
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
coverUrl = a.selectFirst("img")?.src().orEmpty(),
|
||||
title = div.selectFirst(".caption")?.text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//Tags are deliberately reduced because there are too many and this slows down the application.
|
||||
//only the most popular ones are taken.
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
return coroutineScope {
|
||||
(1..3).map { page ->
|
||||
async { getTags(page) }
|
||||
}
|
||||
}.awaitAll().flattenTo(ArraySet(360))
|
||||
}
|
||||
|
||||
private suspend fun getTags(page: Int): Set<MangaTag> {
|
||||
val url = "https://$domain/tags/popular/?page=$page"
|
||||
val root = webClient.httpGet(url).parseHtml()
|
||||
return root.parseTags()
|
||||
}
|
||||
|
||||
private fun Element.parseTags() = select("div.stags a.tag_btn").mapToSet {
|
||||
val href = it.attr("href").substringAfterLast("tag/").substringBeforeLast('/')
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = it.selectFirstOrThrow("h3.list_tag").text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
manga.copy(
|
||||
tags = doc.body().select("li:contains(Tags) a.tag").mapNotNullToSet {
|
||||
val href = it.attr("href").substringAfterLast("tag/").substringBeforeLast('/')
|
||||
val name = it.html().substringBeforeLast("<span")
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = name,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst("li:contains(Artists) a.tag")?.html()?.substringBefore("<span"),
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = manga.id,
|
||||
name = manga.title,
|
||||
number = 1,
|
||||
url = manga.url,
|
||||
scanlator = null,
|
||||
uploadDate = 0,
|
||||
branch = doc.selectFirst("li:contains(Language) a.tag")?.html()?.substringBeforeLast("<span"),
|
||||
source = source,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getRelatedManga(seed: Manga): List<Manga> {
|
||||
val doc = webClient.httpGet(seed.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow("div.related")
|
||||
return root.select("div.thumb").mapNotNull { div ->
|
||||
val a = div.selectFirstOrThrow(".inner_thumb a")
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
coverUrl = a.selectFirst("img")?.src().orEmpty(),
|
||||
title = div.selectFirst(".caption")?.text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val totalPages = doc.selectFirstOrThrow(".pages").text().replace("Pages: ", "").toInt() + 1
|
||||
val domainImg = doc.requireElementById("append_thumbs").selectFirstOrThrow("img").src()?.replace("1t.jpg", "")
|
||||
val pages = ArrayList<MangaPage>(totalPages)
|
||||
for (i in 1 until totalPages) {
|
||||
val url = "$domainImg$i.jpg"
|
||||
pages.add(
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
),
|
||||
)
|
||||
}
|
||||
return pages
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.parsers.site.en
|
||||
package org.koitharu.kotatsu.parsers.site.all
|
||||
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
@@ -114,7 +114,7 @@ internal abstract class AnimeBootstrapParser(
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
|
||||
val chaptersDeferred = async { getChapters(manga, doc) }
|
||||
val chaptersDeferred = async { getChapters(doc) }
|
||||
|
||||
val desc = doc.selectFirstOrThrow(selectDesc).html()
|
||||
|
||||
@@ -141,7 +141,7 @@ internal abstract class AnimeBootstrapParser(
|
||||
|
||||
protected open val selectChapter = "div.anime__details__episodes a"
|
||||
|
||||
protected open suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
protected open suspend fun getChapters(doc: Document): List<MangaChapter> {
|
||||
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, a ->
|
||||
val href = a.attr("href")
|
||||
MangaChapter(
|
||||
|
||||
@@ -102,7 +102,7 @@ internal class PapScan(context: MangaLoaderContext) :
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
|
||||
val chaptersDeferred = async { getChapters(manga, doc) }
|
||||
val chaptersDeferred = async { getChapters(doc) }
|
||||
|
||||
val desc = doc.selectFirstOrThrow(selectDesc).html()
|
||||
|
||||
@@ -126,7 +126,7 @@ internal class PapScan(context: MangaLoaderContext) :
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
override suspend fun getChapters(doc: Document): List<MangaChapter> {
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val href = li.selectFirstOrThrow("a").attr("href")
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
package org.koitharu.kotatsu.parsers.site.ar
|
||||
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONIndexed
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("FLIXSCANS", "Flix Scans", "ar")
|
||||
internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.FLIXSCANS, 18) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
|
||||
override val configKeyDomain = ConfigKey.Domain("flixscans.com")
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val json = if (!query.isNullOrEmpty()) {
|
||||
if (page > 1) {
|
||||
return emptyList()
|
||||
}
|
||||
val url = "https://api.$domain/api/v1/search/serie"
|
||||
val body = JSONObject()
|
||||
body.put("title", query.urlEncoded())
|
||||
webClient.httpPost(url, body).parseJson().getJSONArray("data")
|
||||
} else if (!tags.isNullOrEmpty()) {
|
||||
if (page > 1) {
|
||||
return emptyList()
|
||||
}
|
||||
val tagQuery = tags.joinToString(separator = ",") { it.key }
|
||||
val url = "https://api.$domain/api/v1/search/advance?=&genres=$tagQuery&serie_type=webtoon"
|
||||
webClient.httpGet(url).parseJson().getJSONArray("data")
|
||||
} else {
|
||||
val url = "https://api.$domain/api/v1/webtoon/homepage/latest/home?page=$page"
|
||||
webClient.httpGet(url).parseJson().getJSONArray("data")
|
||||
}
|
||||
return json.mapJSON { j ->
|
||||
val href = "https://$domain/series/${j.getString("prefix")}-${j.getString("id")}-${j.getString("slug")}"
|
||||
val cover = "https://api.$domain/storage/" + j.getString("thumbnail")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = j.getString("title"),
|
||||
altTitle = null,
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
coverUrl = cover,
|
||||
tags = emptySet(),
|
||||
state = when (j.getString("status")) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
"completed" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
author = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/search/advance").parseHtml()
|
||||
val json = JSONArray(doc.requireElementById("__NUXT_DATA__").data())
|
||||
val tagsList = json.getJSONArray(3).toString().replace("[", "").replace("]", "").split(",")
|
||||
return tagsList.mapNotNullToSet { idTag ->
|
||||
val id = idTag.toInt()
|
||||
val idKey = json.getJSONObject(id).getInt("id")
|
||||
val key = json.get(idKey).toString()
|
||||
val idName = json.getJSONObject(id).getInt("name")
|
||||
val name = json.get(idName).toString()
|
||||
MangaTag(
|
||||
key = key,
|
||||
title = name,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val chaptersDeferred = async { loadChapters(manga.url) }
|
||||
val json = JSONArray(doc.requireElementById("__NUXT_DATA__").data())
|
||||
val descId = json.getJSONObject(6).getInt("story")
|
||||
val desc = json.getString(descId)
|
||||
val tagsId = json.getJSONObject(6).getInt("genres")
|
||||
val tagsList = json.getJSONArray(tagsId).toString().replace("[", "").replace("]", "").split(",")
|
||||
val ratingId = json.getJSONObject(6).getInt("rating")
|
||||
val rating = json.getString(ratingId)
|
||||
val nsfwId = json.getJSONObject(6).getInt("nsfw")
|
||||
val nsfw = json.getBoolean(nsfwId)
|
||||
manga.copy(
|
||||
description = desc,
|
||||
tags = tagsList.mapToSet { idTag ->
|
||||
val id = idTag.toInt()
|
||||
val idKey = json.getJSONObject(id).getInt("id")
|
||||
val key = json.get(idKey).toString()
|
||||
val idName = json.getJSONObject(id).getInt("name")
|
||||
val name = json.get(idName).toString()
|
||||
MangaTag(
|
||||
key = key,
|
||||
title = name,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
rating = rating?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
isNsfw = nsfw,
|
||||
chapters = chaptersDeferred.await(),
|
||||
)
|
||||
}
|
||||
|
||||
private val dateFormat = SimpleDateFormat("yyyy-MM-dd", sourceLocale)
|
||||
|
||||
private suspend fun loadChapters(baseUrl: String): List<MangaChapter> {
|
||||
val key = baseUrl.substringAfter("-").substringBefore("-")
|
||||
val seriesKey = baseUrl.substringAfterLast("/").substringBefore("-")
|
||||
val json = JSONArray(webClient.httpGet("https://api.$domain/api/v1/webtoon/chapters/$key-desc").parseRaw())
|
||||
return json.mapJSONIndexed { i, j ->
|
||||
val url = "https://$domain/read/webtoon/$seriesKey-${j.getString("id")}-${j.getString("slug")}"
|
||||
val date = j.getString("createdAt").substringBeforeLast("T")
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
name = j.getString("slug").replace('-', ' '),
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = dateFormat.tryParse(date),
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val json = JSONArray(doc.requireElementById("__NUXT_DATA__").data())
|
||||
val chapterData = json.getJSONObject(6).getInt("chapterData")
|
||||
val pageLocate = json.getJSONObject(chapterData).getInt("webtoon")
|
||||
val jsonPages = json.getJSONArray(pageLocate)
|
||||
val pages = ArrayList<MangaPage>(jsonPages.length())
|
||||
for (i in 0 until jsonPages.length()) {
|
||||
val id = jsonPages.getInt(i)
|
||||
val url = "https://api.$domain/storage/" + json.getString(id)
|
||||
pages.add(
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
)
|
||||
}
|
||||
return pages
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package org.koitharu.kotatsu.parsers.site.ar
|
||||
|
||||
import okhttp3.Headers
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.network.UserAgents
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("MANGASTORM", "Manga Storm", "ar")
|
||||
internal class MangaStorm(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGASTORM, 30) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY)
|
||||
override val configKeyDomain = ConfigKey.Domain("mangastorm.org")
|
||||
|
||||
override val headers: Headers = Headers.Builder()
|
||||
.add("User-Agent", UserAgents.CHROME_DESKTOP)
|
||||
.build()
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url =
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/categories/")
|
||||
append(tag?.key.orEmpty())
|
||||
append("?page=")
|
||||
append(page)
|
||||
}
|
||||
} else {
|
||||
buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/mangas?page=")
|
||||
append(page)
|
||||
if (!query.isNullOrEmpty()) {
|
||||
append("&query=")
|
||||
append(query.urlEncoded())
|
||||
}
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select("div.row div.col").map { div ->
|
||||
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = div.select(".manga-ct-title").text(),
|
||||
altTitle = null,
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
coverUrl = div.selectFirstOrThrow("img").src().orEmpty(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> = emptySet()
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
|
||||
val root = doc.selectFirstOrThrow(".card-body .col-lg-9")
|
||||
|
||||
return manga.copy(
|
||||
altTitle = null,
|
||||
state = null,
|
||||
tags = root.select(".flex-wrap a").mapNotNullToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = null,
|
||||
description = root.selectFirstOrThrow(".card-text").text(),
|
||||
chapters = doc.select(".card-body a.btn-fixed-width").mapChapters(reversed = true) { i, a ->
|
||||
val url = a.attrAsRelativeUrl("href")
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
name = a.text(),
|
||||
number = i + 1,
|
||||
url = url,
|
||||
scanlator = null,
|
||||
uploadDate = 0,
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml().requireElementById("content")
|
||||
return doc.select("div.text-center .img-fluid").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import java.util.*
|
||||
internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.TEAMXNOVEL, 10) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
|
||||
override val configKeyDomain = ConfigKey.Domain("team1x12.com")
|
||||
override val configKeyDomain = ConfigKey.Domain("team11x11.com")
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
@@ -26,9 +26,9 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
|
||||
val url = buildString {
|
||||
append("https://$domain")
|
||||
append("https://")
|
||||
append(domain)
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("/series?genre=")
|
||||
append(tag?.key.orEmpty())
|
||||
@@ -57,7 +57,6 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
}
|
||||
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
return doc.select("div.listupd .bs .bsx").ifEmpty {
|
||||
doc.select("div.post-body .box")
|
||||
}.map { div ->
|
||||
@@ -97,7 +96,6 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val mangaUrl = manga.url.toAbsoluteUrl(domain)
|
||||
|
||||
val maxPageChapterSelect = doc.select(".pagination .page-item a")
|
||||
var maxPageChapter = 1
|
||||
if (!maxPageChapterSelect.isNullOrEmpty()) {
|
||||
@@ -108,7 +106,6 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return manga.copy(
|
||||
altTitle = null,
|
||||
state = when (doc.selectFirstOrThrow(".full-list-info:contains(الحالة:) a").text()) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("CLONEMANGA", "CloneManga", "en")
|
||||
@MangaSourceParser("CLONEMANGA", "Clone Manga", "en")
|
||||
internal class CloneMangaParser(context: MangaLoaderContext) : MangaParser(context, MangaSource.CLONEMANGA) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> = Collections.singleton(
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("COMICEXTRA", "ComicExtra", "en")
|
||||
@MangaSourceParser("COMICEXTRA", "Comic Extra", "en")
|
||||
internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.COMICEXTRA, 25) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST)
|
||||
|
||||
146
src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/Fakku.kt
Normal file
146
src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/Fakku.kt
Normal file
@@ -0,0 +1,146 @@
|
||||
package org.koitharu.kotatsu.parsers.site.en
|
||||
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("FAKKU", "Fakku", "en", ContentType.HENTAI)
|
||||
internal class Fakku(context: MangaLoaderContext) :
|
||||
PagedMangaParser(context, MangaSource.FAKKU, pageSize = 25) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> =
|
||||
EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.NEWEST, SortOrder.UPDATED)
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain("fakku.cc")
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
when {
|
||||
!query.isNullOrEmpty() -> {
|
||||
append("/search?q=")
|
||||
append(query.urlEncoded())
|
||||
append("&")
|
||||
}
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/tags/")
|
||||
append(tag?.key.orEmpty())
|
||||
append("?")
|
||||
}
|
||||
|
||||
else -> {
|
||||
append("?")
|
||||
}
|
||||
}
|
||||
append("page=")
|
||||
append(page)
|
||||
append("&sort=")
|
||||
when (sortOrder) {
|
||||
SortOrder.ALPHABETICAL -> append("title")
|
||||
SortOrder.NEWEST -> append("created_at")
|
||||
SortOrder.UPDATED -> append("published_at")
|
||||
else -> append("published_at")
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select("div.entries .entry a").map { a ->
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
coverUrl = a.selectFirst("img")?.src().orEmpty(),
|
||||
title = a.selectFirst(".title")?.text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val root = webClient.httpGet("https://$domain/tags").parseHtml()
|
||||
return root.select("div.entries .entry a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringAfterLast("/"),
|
||||
title = it.selectFirstOrThrow(".name").text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val genreDeferred = async {
|
||||
webClient.httpGet(manga.url.toAbsoluteUrl(domain) + ".json").parseJson()
|
||||
}
|
||||
val genre = genreDeferred.await()
|
||||
manga.copy(
|
||||
author = doc.selectFirst("tr.artists a")?.text(),
|
||||
tags = if (genre.toString().contains("tags")) {
|
||||
genre.getJSONArray("tags").mapJSONToSet {
|
||||
MangaTag(
|
||||
key = it.getString("slug"),
|
||||
title = it.getString("name"),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
emptySet()
|
||||
},
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = manga.id,
|
||||
name = manga.title,
|
||||
number = 1,
|
||||
url = manga.url + "/1",
|
||||
scanlator = null,
|
||||
uploadDate = 0,
|
||||
branch = null,
|
||||
source = source,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val totalPages = doc.selectFirstOrThrow(".total").text().toInt()
|
||||
val rawUrl = chapter.url.substringBeforeLast("/")
|
||||
return (1..totalPages).map {
|
||||
val url = "$rawUrl/$it"
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val root = doc.body()
|
||||
return root.selectFirstOrThrow(".page img").attrAsAbsoluteUrl("src")
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("LIKEMANGA", "LikeManga", "en")
|
||||
@MangaSourceParser("LIKEMANGA", "Like Manga", "en")
|
||||
internal class LikeManga(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.LIKEMANGA, 36) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST)
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("MANGAOWL", "Mangaowl", "en")
|
||||
@MangaSourceParser("MANGAOWL", "Manga Owl .To", "en")
|
||||
internal class Mangaowl(context: MangaLoaderContext) :
|
||||
PagedMangaParser(context, MangaSource.MANGAOWL, pageSize = 24) {
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("MANHWA18", "Manhwa18", "en", type = ContentType.HENTAI)
|
||||
@MangaSourceParser("MANHWA18", "Manhwa 18", "en", type = ContentType.HENTAI)
|
||||
class Manhwa18Parser(context: MangaLoaderContext) :
|
||||
PagedMangaParser(context, MangaSource.MANHWA18, pageSize = 18, searchPageSize = 18) {
|
||||
|
||||
|
||||
168
src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/Pururin.kt
Normal file
168
src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/Pururin.kt
Normal file
@@ -0,0 +1,168 @@
|
||||
package org.koitharu.kotatsu.parsers.site.en
|
||||
|
||||
import androidx.collection.ArraySet
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("PURURIN", "Pururin", "en", ContentType.HENTAI)
|
||||
internal class Pururin(context: MangaLoaderContext) :
|
||||
PagedMangaParser(context, MangaSource.PURURIN, pageSize = 20) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> =
|
||||
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.RATING, SortOrder.ALPHABETICAL)
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain("pururin.to")
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
if (!query.isNullOrEmpty()) {
|
||||
append("/search?q=")
|
||||
append(query.urlEncoded())
|
||||
append("&page=")
|
||||
append(page)
|
||||
} else {
|
||||
append("/browse")
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("/tags/content/")
|
||||
append(tag?.key.orEmpty())
|
||||
append("/")
|
||||
}
|
||||
append("?page=")
|
||||
append(page)
|
||||
append("&sort=")
|
||||
when (sortOrder) {
|
||||
SortOrder.UPDATED -> append("")
|
||||
SortOrder.POPULARITY -> append("most-viewed")
|
||||
SortOrder.RATING -> append("highest-rated")
|
||||
SortOrder.ALPHABETICAL -> append("title")
|
||||
else -> append("")
|
||||
}
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select(".row-gallery a.card-gallery").map { a ->
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
coverUrl = a.selectFirst("img.card-img-top")?.src().orEmpty(),
|
||||
title = a.selectFirst(".title")?.text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
return coroutineScope {
|
||||
(1..4).map { page ->
|
||||
async { getTags(page) }
|
||||
}
|
||||
}.awaitAll().flattenTo(ArraySet(360))
|
||||
}
|
||||
|
||||
private suspend fun getTags(page: Int): Set<MangaTag> {
|
||||
val url = "https://$domain/tags/content?order=uses&page=$page"
|
||||
val root = webClient.httpGet(url).parseHtml()
|
||||
return root.parseTags()
|
||||
}
|
||||
|
||||
private fun Element.parseTags() = select("table tr td a").mapToSet {
|
||||
val href = it.attr("href").substringAfterLast("content/").substringBeforeLast('/')
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
manga.copy(
|
||||
description = doc.selectFirst("p.mb-2")?.text().orEmpty(),
|
||||
rating = doc.selectFirst("td span.rating")?.attr("content")?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
tags = doc.body().select("tr:contains(Contents) ul.list-inline a").mapNotNullToSet {
|
||||
val href = it.attr("href").substringAfterLast("content/").substringBeforeLast('/')
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst("a[itemprop=author]")?.text(),
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = manga.id,
|
||||
name = manga.title,
|
||||
number = 1,
|
||||
url = manga.url,
|
||||
scanlator = null,
|
||||
uploadDate = 0,
|
||||
branch = null,
|
||||
source = source,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getRelatedManga(seed: Manga): List<Manga> {
|
||||
val doc = webClient.httpGet(seed.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow(".row-gallery-small")
|
||||
return root.select("a.card-gallery").mapNotNull { a ->
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
coverUrl = a.selectFirst("img.card-img-top")?.src().orEmpty(),
|
||||
title = a.selectFirst(".title")?.text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".gallery-preview img").map { url ->
|
||||
val img = url.src()?.toRelativeUrl(domain) ?: url.parseFailed("Image src not found")
|
||||
val urlImage = img.replace("t.", ".")
|
||||
MangaPage(
|
||||
id = generateUid(urlImage),
|
||||
url = urlImage,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,12 +99,12 @@ class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaParser(
|
||||
state = parseStatus(contents.select("span.book-status").text().orEmpty()),
|
||||
author = contents.selectFirst("h5.card-title")?.attr("title")?.substringAfter(", "),
|
||||
chapters = if (doc.select("div.chapters").isEmpty()) {
|
||||
doc.select(oneShotChapterListSelector()).mapChapters(reversed = true) { _, item ->
|
||||
doc.select(oneShotChapterListSelector).mapChapters(reversed = true) { _, item ->
|
||||
oneShotChapterFromElement(item)
|
||||
}
|
||||
} else {
|
||||
val chapters = ChaptersListBuilder(10)
|
||||
doc.select(regularChapterListSelector()).reversed().forEachIndexed { i, item ->
|
||||
doc.select(regularChapterListSelector).reversed().forEachIndexed { i, item ->
|
||||
val chaptername = item.select("div.col-10.text-truncate").text().replace(" ", " ").trim()
|
||||
val scanelement = item.select("ul.chapter-list > li")
|
||||
scanelement.forEach { chapters.add(regularChapterFromElement(it, chaptername, i)) }
|
||||
@@ -114,7 +114,7 @@ class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaParser(
|
||||
)
|
||||
}
|
||||
|
||||
private fun oneShotChapterListSelector() = "div.chapter-list-element > ul.list-group li.list-group-item"
|
||||
private val oneShotChapterListSelector = "div.chapter-list-element > ul.list-group li.list-group-item"
|
||||
|
||||
private fun oneShotChapterFromElement(element: Element): MangaChapter {
|
||||
val href = element.selectFirstOrThrow("div.row > .text-right > a").attrAsRelativeUrl("href")
|
||||
@@ -130,7 +130,7 @@ class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaParser(
|
||||
)
|
||||
}
|
||||
|
||||
private fun regularChapterListSelector() = "div.chapters > ul.list-group li.p-0.list-group-item"
|
||||
private val regularChapterListSelector = "div.chapters > ul.list-group li.p-0.list-group-item"
|
||||
|
||||
private fun regularChapterFromElement(element: Element, chName: String, number: Int): MangaChapter {
|
||||
val href = element.selectFirstOrThrow("div.row > .text-right > a").attrAsRelativeUrl("href")
|
||||
|
||||
@@ -27,7 +27,7 @@ internal abstract class FmreaderParser(
|
||||
SortOrder.ALPHABETICAL,
|
||||
)
|
||||
|
||||
protected open val listeurl = "/manga-list.html"
|
||||
protected open val listUrl = "/manga-list.html"
|
||||
protected open val datePattern = "MMMM d, yyyy"
|
||||
protected open val tagPrefix = "manga-list-genre-"
|
||||
|
||||
@@ -66,7 +66,7 @@ internal abstract class FmreaderParser(
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append(listeurl)
|
||||
append(listUrl)
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
when {
|
||||
@@ -114,7 +114,7 @@ internal abstract class FmreaderParser(
|
||||
protected open val selectBodyTag = "ul.filter-type li a"
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listeurl").parseHtml()
|
||||
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
|
||||
return doc.select(selectBodyTag).mapNotNullToSet { a ->
|
||||
val href = a.attr("href").substringAfter(tagPrefix).substringBeforeLast(".html")
|
||||
MangaTag(
|
||||
@@ -134,7 +134,7 @@ internal abstract class FmreaderParser(
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val chaptersDeferred = async { getChapters(manga, doc) }
|
||||
val chaptersDeferred = async { getChapters(doc) }
|
||||
val desc = doc.selectFirstOrThrow(selectDesc).html()
|
||||
val stateDiv = doc.selectFirst(selectState)
|
||||
val state = stateDiv?.let {
|
||||
@@ -145,7 +145,6 @@ internal abstract class FmreaderParser(
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
val alt = doc.body().selectFirst(selectAlt)?.text()?.replace("Other names", "")
|
||||
val auth = doc.body().selectFirst(selectAut)?.text()
|
||||
manga.copy(
|
||||
@@ -168,7 +167,7 @@ internal abstract class FmreaderParser(
|
||||
protected open val selectDate = "div.chapter-time"
|
||||
protected open val selectChapter = "ul.list-chapters a"
|
||||
|
||||
protected open suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
protected open suspend fun getChapters(doc: Document): List<MangaChapter> {
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, a ->
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
@@ -194,10 +193,8 @@ internal abstract class FmreaderParser(
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
|
||||
return doc.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -10,11 +10,11 @@ import org.koitharu.kotatsu.parsers.site.fmreader.FmreaderParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
@MangaSourceParser("MANHWA18COM", "Manhwa18 .Com", "en", ContentType.HENTAI)
|
||||
@MangaSourceParser("MANHWA18COM", "Manhwa 18 .Com", "en", ContentType.HENTAI)
|
||||
internal class Manhwa18Com(context: MangaLoaderContext) :
|
||||
FmreaderParser(context, MangaSource.MANHWA18COM, "manhwa18.com") {
|
||||
|
||||
override val listeurl = "/tim-kiem"
|
||||
override val listUrl = "/tim-kiem"
|
||||
override val selectState = "div.info-item:contains(Status) span.info-value "
|
||||
override val selectAlt = "div.info-item:contains(Other name) span.info-value "
|
||||
override val selectTag = "div.info-item:contains(Genre) span.info-value a"
|
||||
@@ -45,7 +45,7 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
|
||||
else -> append("last_update")
|
||||
}
|
||||
} else {
|
||||
append(listeurl)
|
||||
append(listUrl)
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
when {
|
||||
@@ -87,7 +87,7 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listeurl").parseHtml()
|
||||
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
|
||||
return doc.select(selectBodyTag).mapNotNullToSet { a ->
|
||||
val href = a.attr("href").substringAfterLast("/")
|
||||
MangaTag(
|
||||
@@ -101,7 +101,7 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val chaptersDeferred = async { getChapters(manga, doc) }
|
||||
val chaptersDeferred = async { getChapters(doc) }
|
||||
val desc = doc.selectFirstOrThrow(selectDesc).html()
|
||||
val stateDiv = doc.selectFirst(selectState)
|
||||
val state = stateDiv?.let {
|
||||
@@ -129,7 +129,7 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
override suspend fun getChapters(doc: Document): List<MangaChapter> {
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, a ->
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
|
||||
@@ -25,7 +25,7 @@ internal class OlimpoScans(context: MangaLoaderContext) :
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append(listeurl)
|
||||
append(listUrl)
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
when {
|
||||
|
||||
@@ -37,7 +37,7 @@ internal class Klz9(context: MangaLoaderContext) :
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/$listeurl")
|
||||
append("/$listUrl")
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
when {
|
||||
@@ -81,12 +81,12 @@ internal class Klz9(context: MangaLoaderContext) :
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
override suspend fun getChapters(doc: Document): List<MangaChapter> {
|
||||
val slug = doc.selectFirstOrThrow("div.h0rating").attr("slug")
|
||||
val docload =
|
||||
val docLoad =
|
||||
webClient.httpGet("https://$domain/app/manga/controllers/cont.listChapter.php?slug=$slug").parseHtml()
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return docload.body().select(selectChapter).mapChapters(reversed = true) { i, a ->
|
||||
return docLoad.body().select(selectChapter).mapChapters(reversed = true) { i, a ->
|
||||
val href = "/" + a.selectFirstOrThrow("a.chapter").attrAsRelativeUrl("href")
|
||||
val dateText = a.selectFirst(selectDate)?.text()
|
||||
MangaChapter(
|
||||
@@ -109,8 +109,8 @@ internal class Klz9(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val cid = doc.selectFirstOrThrow("#chapter").attr("value")
|
||||
val docload = webClient.httpGet("https://$domain/app/manga/controllers/cont.listImg.php?cid=$cid").parseHtml()
|
||||
return docload.select(selectPage).map { img ->
|
||||
val docLoad = webClient.httpGet("https://$domain/app/manga/controllers/cont.listImg.php?cid=$cid").parseHtml()
|
||||
return docLoad.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
|
||||
MangaPage(
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.koitharu.kotatsu.parsers.site.fmreader.ja
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
@@ -11,16 +10,16 @@ import org.koitharu.kotatsu.parsers.site.fmreader.FmreaderParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
@MangaSourceParser("WELOVEMANGA", "WeLoveManga", "ja")
|
||||
@MangaSourceParser("WELOVEMANGA", "We Love Manga", "ja")
|
||||
internal class WeLoveManga(context: MangaLoaderContext) :
|
||||
FmreaderParser(context, MangaSource.WELOVEMANGA, "welovemanga.one") {
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
override suspend fun getChapters(doc: Document): List<MangaChapter> {
|
||||
val mid = doc.selectFirstOrThrow("div.cmt input").attr("value")
|
||||
val docload =
|
||||
val docLoad =
|
||||
webClient.httpGet("https://$domain/app/manga/controllers/cont.Listchapter.php?mid=$mid").parseHtml()
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return docload.body().select(selectChapter).mapChapters(reversed = true) { i, a ->
|
||||
return docLoad.body().select(selectChapter).mapChapters(reversed = true) { i, a ->
|
||||
val href = a.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
val dateText = a.selectFirst(selectDate)?.text()
|
||||
MangaChapter(
|
||||
@@ -43,8 +42,8 @@ internal class WeLoveManga(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val cid = doc.selectFirstOrThrow("#chapter").attr("value")
|
||||
val docload = webClient.httpGet("https://$domain/app/manga/controllers/cont.listImg.php?cid=$cid").parseHtml()
|
||||
return docload.select("img").map { img ->
|
||||
val docLoad = webClient.httpGet("https://$domain/app/manga/controllers/cont.listImg.php?cid=$cid").parseHtml()
|
||||
return docLoad.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
|
||||
MangaPage(
|
||||
|
||||
@@ -38,7 +38,6 @@ internal abstract class FoolSlideParser(
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val doc = if (!query.isNullOrEmpty()) {
|
||||
val url = buildString {
|
||||
append("https://$domain/$searchUrl")
|
||||
@@ -62,7 +61,6 @@ internal abstract class FoolSlideParser(
|
||||
}
|
||||
webClient.httpGet(url).parseHtml()
|
||||
}
|
||||
|
||||
return doc.select("div.list div.group").map { div ->
|
||||
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
@@ -90,26 +88,22 @@ internal abstract class FoolSlideParser(
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val testAdultPage = webClient.httpGet(fullUrl).parseHtml()
|
||||
|
||||
val doc = if (testAdultPage.selectFirst("div.info form") != null) {
|
||||
webClient.httpPost(fullUrl, "adult=true").parseHtml()
|
||||
} else {
|
||||
testAdultPage
|
||||
}
|
||||
val chapters = getChapters(manga, doc)
|
||||
|
||||
val chapters = getChapters(doc)
|
||||
val desc = if (doc.selectFirstOrThrow(selectInfo).html().contains("</b>")) {
|
||||
doc.selectFirstOrThrow(selectInfo).text().substringAfterLast(": ")
|
||||
} else {
|
||||
doc.selectFirstOrThrow(selectInfo).text()
|
||||
}
|
||||
|
||||
val author = if (doc.selectFirstOrThrow(selectInfo).html().contains("</b>")) {
|
||||
doc.selectFirstOrThrow(selectInfo).text().substringAfter(": ").substringBefore("Art")
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
manga.copy(
|
||||
coverUrl = doc.selectFirst(".thumbnail img")?.src() ?: manga.coverUrl,
|
||||
description = desc,
|
||||
@@ -124,7 +118,7 @@ internal abstract class FoolSlideParser(
|
||||
protected open val selectDate = ".meta_r"
|
||||
protected open val selectChapter = "div.list div.element"
|
||||
|
||||
protected open suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
protected open suspend fun getChapters(doc: Document): List<MangaChapter> {
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, div ->
|
||||
val a = div.selectFirstOrThrow(".title a")
|
||||
|
||||
@@ -77,7 +77,7 @@ internal class AssortedScans(context: MangaLoaderContext) :
|
||||
} else {
|
||||
testAdultPage
|
||||
}
|
||||
val chapters = getChapters(manga, doc)
|
||||
val chapters = getChapters(doc)
|
||||
val desc = doc.getElementById("series-desc")?.selectFirst("div")?.html()
|
||||
val alt = doc.getElementById("series-aliases")?.selectFirst("div.alias")?.text()
|
||||
val author = doc.getElementById("series-authors")?.selectFirst("div.author")?.text()
|
||||
@@ -97,7 +97,7 @@ internal class AssortedScans(context: MangaLoaderContext) :
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
override suspend fun getChapters(doc: Document): List<MangaChapter> {
|
||||
return doc.body().select("div.chapter").mapChapters(reversed = true) { i, div ->
|
||||
val a = div.selectFirstOrThrow("a")
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
|
||||
|
||||
@MangaSourceParser("DEATHTOLLSCANS", "DeathToll Scans", "en")
|
||||
@MangaSourceParser("DEATHTOLLSCANS", "Death Toll Scans", "en")
|
||||
internal class Deathtollscans(context: MangaLoaderContext) :
|
||||
FoolSlideParser(context, MangaSource.DEATHTOLLSCANS, "reader.deathtollscans.net", 26)
|
||||
|
||||
@@ -21,7 +21,7 @@ internal class Seinagi(context: MangaLoaderContext) :
|
||||
} else {
|
||||
testAdultPage
|
||||
}
|
||||
val chapters = getChapters(manga, doc)
|
||||
val chapters = getChapters(doc)
|
||||
val desc = if (doc.selectFirstOrThrow(selectInfo).html().contains("Description")) {
|
||||
doc.selectFirstOrThrow(selectInfo).text().substringAfter("Description: ").substringBefore("Readings")
|
||||
} else {
|
||||
|
||||
@@ -19,7 +19,7 @@ internal class Pzykosis666hFansub(context: MangaLoaderContext) :
|
||||
} else {
|
||||
testAdultPage
|
||||
}
|
||||
val chapters = getChapters(manga, doc)
|
||||
val chapters = getChapters(doc)
|
||||
val desc = if (doc.selectFirstOrThrow(selectInfo).html().contains("Descripción")) {
|
||||
doc.selectFirstOrThrow(selectInfo).text().substringAfter("Descripción: ").substringBefore("Lecturas")
|
||||
} else {
|
||||
|
||||
@@ -25,7 +25,7 @@ internal class SeinagiAdulto(context: MangaLoaderContext) :
|
||||
} else {
|
||||
testAdultPage
|
||||
}
|
||||
val chapters = getChapters(manga, doc)
|
||||
val chapters = getChapters(doc)
|
||||
val desc = if (doc.selectFirstOrThrow(selectInfo).html().contains("Descripción")) {
|
||||
doc.selectFirstOrThrow(selectInfo).text().substringAfter("Descripción: ").substringBefore("Lecturas")
|
||||
} else {
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.getIntOrDefault
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("BENTOMANGA", "BentoManga", "fr")
|
||||
@MangaSourceParser("BENTOMANGA", "Bento Manga", "fr")
|
||||
internal class BentomangaParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.BENTOMANGA, 10) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.network.UserAgents
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import java.lang.IllegalArgumentException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -48,20 +49,19 @@ internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(cont
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
if (!query.isNullOrEmpty()) {
|
||||
throw IllegalArgumentException("Search is not supported by this source")
|
||||
}
|
||||
if (sortOrder == SortOrder.ALPHABETICAL) {
|
||||
|
||||
if (page > 1) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/api/get/catalog?page=0&filter=all")
|
||||
}
|
||||
val json = webClient.httpGet(url).parseJsonArray()
|
||||
|
||||
return json.mapJSON { j ->
|
||||
val urlManga = "https://$domain/api/get/card/${j.getString("slug")}"
|
||||
val img = "https://$domain/upload/min_cover/${j.getString("image")}"
|
||||
@@ -93,7 +93,6 @@ internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(cont
|
||||
append(page)
|
||||
}
|
||||
val json = webClient.httpGet(url).parseJsonArray()
|
||||
|
||||
return json.mapJSON { j ->
|
||||
val urlManga = "https://$domain/api/get/card/${j.getString("manga_slug")}"
|
||||
val img = "https://$domain/upload/min_cover/${j.getString("manga_image")}"
|
||||
@@ -119,10 +118,8 @@ internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(cont
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val json = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseJson()
|
||||
|
||||
val jsonManga = json.getJSONObject("manga")
|
||||
val chapters = json.getJSONObject("chapters").toString().split("{\"id\":").drop(1) // Possible improvement here
|
||||
|
||||
val chapters = json.getJSONObject("chapters").toString().split("{\"id\":").drop(1)
|
||||
val slug = manga.url.substringAfterLast("/")
|
||||
val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.FRANCE)
|
||||
return manga.copy(
|
||||
@@ -140,8 +137,7 @@ internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(cont
|
||||
val url = "https://$domain/api/get/chapter/$slug/$id"
|
||||
val date = getDateString(
|
||||
it.substringAfter("\"date\":\"").substringBefore("\",").toLong(),
|
||||
) // Possible improvement here
|
||||
|
||||
)
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
name = "Chapitre : $id",
|
||||
@@ -159,27 +155,25 @@ internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(cont
|
||||
private val simpleDateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.FRANCE)
|
||||
private fun getDateString(time: Long): String = simpleDateFormat.format(time * 1000L)
|
||||
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val jsonPage = webClient.httpGet(fullUrl).parseJson()
|
||||
|
||||
val idManga = jsonPage.getJSONObject("manga").getString("id")
|
||||
val slugChapter = chapter.url.substringAfterLast("/")
|
||||
|
||||
val pages = jsonPage.getJSONObject("chapter").getJSONArray("files").toString()
|
||||
.replace("[", "").replace("]", "").replace("\"", "")
|
||||
.split(",") // Possible improvement here
|
||||
|
||||
return pages.map { img ->
|
||||
val url = "https://$domain/upload/chapitre/$idManga/$slugChapter/$img"
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
val idManga = jsonPage.getJSONObject("manga").getInt("id")
|
||||
val slug = jsonPage.getJSONObject("chapter").getInt("chapter")
|
||||
val jsonPages = jsonPage.getJSONObject("chapter").getJSONArray("files")
|
||||
val pages = ArrayList<MangaPage>(jsonPages.length())
|
||||
for (i in 0 until jsonPages.length()) {
|
||||
val url = "https://$domain/upload/chapters/$idManga/$slug/${jsonPages.getString(i)}"
|
||||
pages.add(
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
),
|
||||
)
|
||||
}
|
||||
return pages
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> = emptySet()
|
||||
|
||||
@@ -167,7 +167,6 @@ internal class ScansMangasMe(context: MangaLoaderContext) :
|
||||
|
||||
val pages = ArrayList<MangaPage>(images.length())
|
||||
for (i in 0 until images.length()) {
|
||||
|
||||
val pageTake = images.getJSONObject(i)
|
||||
pages.add(
|
||||
MangaPage(
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.heancmsalt.HeanCmsAlt
|
||||
|
||||
@MangaSourceParser("LEGIONSCANS", "CerberuSeries", "es")
|
||||
@MangaSourceParser("LEGIONSCANS", "Cerberus Series", "es")
|
||||
internal class CerberuSeries(context: MangaLoaderContext) :
|
||||
HeanCmsAlt(context, MangaSource.LEGIONSCANS, "cerberuseries.xyz")
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("DOUJINDESU", "DoujinDesu", "id")
|
||||
@MangaSourceParser("DOUJINDESU", "Doujin Desu", "id")
|
||||
class DoujinDesuParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.DOUJINDESU, pageSize = 18) {
|
||||
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.*
|
||||
private const val STATUS_ONGOING = "連載"
|
||||
private const val STATUS_FINISHED = "完結"
|
||||
|
||||
@MangaSourceParser("NICOVIDEO_SEIGA", "NicoVideo Seiga", "ja")
|
||||
@MangaSourceParser("NICOVIDEO_SEIGA", "Nico Video Seiga", "ja")
|
||||
class NicovideoSeigaParser(context: MangaLoaderContext) :
|
||||
MangaParser(context, MangaSource.NICOVIDEO_SEIGA),
|
||||
MangaParserAuthProvider {
|
||||
|
||||
@@ -33,9 +33,8 @@ internal abstract class MadaraParser(
|
||||
|
||||
protected open val tagPrefix = "manga-genre/"
|
||||
protected open val datePattern = "MMMM d, yyyy"
|
||||
protected open val stylepage = "?style=list"
|
||||
|
||||
protected open val postreq = false
|
||||
protected open val stylePage = "?style=list"
|
||||
protected open val postReq = false
|
||||
|
||||
init {
|
||||
paginator.firstPage = 0
|
||||
@@ -52,7 +51,6 @@ internal abstract class MadaraParser(
|
||||
parseFailed("Cannot find tableValue for node ${text()}")
|
||||
}
|
||||
|
||||
|
||||
@JvmField
|
||||
protected val ongoing: Set<String> = hashSetOf(
|
||||
"مستمرة",
|
||||
@@ -358,7 +356,7 @@ internal abstract class MadaraParser(
|
||||
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text()
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
@@ -378,8 +376,7 @@ internal abstract class MadaraParser(
|
||||
}
|
||||
|
||||
protected open suspend fun loadChapters(mangaUrl: String, document: Document): List<MangaChapter> {
|
||||
|
||||
val doc = if (postreq) {
|
||||
val doc = if (postReq) {
|
||||
val mangaId = document.select("div#manga-chapters-holder").attr("data-id")
|
||||
val url = "https://$domain/wp-admin/admin-ajax.php"
|
||||
val postdata = "action=manga_get_chapters&manga=$mangaId"
|
||||
@@ -388,13 +385,11 @@ internal abstract class MadaraParser(
|
||||
val url = mangaUrl.toAbsoluteUrl(domain).removeSuffix('/') + "/ajax/chapters/"
|
||||
webClient.httpPost(url, emptyMap()).parseHtml()
|
||||
}
|
||||
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
|
||||
return doc.select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text()
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
@@ -413,13 +408,35 @@ internal abstract class MadaraParser(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getRelatedManga(seed: Manga): List<Manga> {
|
||||
val doc = webClient.httpGet(seed.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow(".related-manga")
|
||||
return root.select("div.related-reading-wrap").mapNotNull { div ->
|
||||
val a = div.selectFirst("a") ?: return@mapNotNull null
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(a.host ?: domain),
|
||||
altTitle = null,
|
||||
title = div.selectFirstOrThrow(".widget-title").text(),
|
||||
author = null,
|
||||
coverUrl = div.selectFirst("img")?.src().orEmpty(),
|
||||
tags = emptySet(),
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
isNsfw = isNsfwSource,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
protected open val selectBodyPage = "div.main-col-inner div.reading-content"
|
||||
protected open val selectPage = "div.page-break, div.login-required"
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
|
||||
val chapterProtector = doc.getElementById("chapter-protector-data")
|
||||
if (chapterProtector == null) {
|
||||
val root = doc.body().selectFirstOrThrow(selectBodyPage)
|
||||
|
||||
@@ -21,7 +21,7 @@ internal class Ero18x(context: MangaLoaderContext) :
|
||||
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirstOrThrow("a")
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text()
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
|
||||
@@ -12,5 +12,5 @@ internal class MangaTop(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGATOP, "mangatop.site") {
|
||||
override val datePattern = "d MMMM yyyy"
|
||||
override val sourceLocale: Locale = Locale.ENGLISH
|
||||
override val stylepage = ""
|
||||
override val stylePage = ""
|
||||
}
|
||||
|
||||
@@ -13,13 +13,11 @@ import org.koitharu.kotatsu.parsers.util.generateUid
|
||||
import org.koitharu.kotatsu.parsers.util.mapChapters
|
||||
import org.koitharu.kotatsu.parsers.util.parseFailed
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
@MangaSourceParser("MANHWARAW", "Manhwa Raw", "", ContentType.HENTAI)
|
||||
internal class ManhwaRaw(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHWARAW, "manhwa-raw.com", 10) {
|
||||
override val datePattern = "MMMM d"
|
||||
override val sourceLocale: Locale = Locale.ENGLISH
|
||||
override val datePattern = "MM/dd"
|
||||
override val withoutAjax = true
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
@@ -27,10 +25,9 @@ internal class ManhwaRaw(context: MangaLoaderContext) :
|
||||
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text()
|
||||
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
val name = a.selectFirst("h4")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
name = name,
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.Locale
|
||||
@MangaSourceParser("MANYTOON_CLUB", "Many Toon .Club", "", ContentType.HENTAI)
|
||||
internal class ManyToonClub(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANYTOON_CLUB, "manytoon.club") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val listUrl = "manhwa-raw/"
|
||||
override val tagPrefix = "manhwa-raw-genre/"
|
||||
override val sourceLocale: Locale = Locale.ENGLISH
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("AZORANOV", "Azoranov", "ar")
|
||||
@MangaSourceParser("AZORANOV", "Azora Nov", "ar")
|
||||
internal class Azoranov(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.AZORANOV, "azoranov.com", pageSize = 10) {
|
||||
override val tagPrefix = "series-genre/"
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("GATEMANGA", "Gate Manga", "ar")
|
||||
internal class GateManga(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.GATEMANGA, "gatemanga.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val datePattern = "d MMMM، yyyy"
|
||||
override val listUrl = "ar/"
|
||||
override val withoutAjax = true
|
||||
|
||||
@@ -6,8 +6,8 @@ import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGA_LEK", "Manga-Lek", "ar")
|
||||
internal class Manga_Lek(context: MangaLoaderContext) :
|
||||
internal class MangaLekCom(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGA_LEK, "manga-lek.com") {
|
||||
override val listUrl = "mangalek/"
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
@@ -9,5 +9,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
internal class MangaLeks(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGALEKS, "mangaleks.com") {
|
||||
override val datePattern = "yyyy/MM/dd"
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGALIKE", "Manga Like", "ar")
|
||||
internal class MangaLike(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGALIKE, "mangalike.me", pageSize = 10)
|
||||
MadaraParser(context, MangaSource.MANGALIKE, "manga-like.net", pageSize = 10)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.ar
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGATIME", "Manga Time", "ar")
|
||||
internal class MangaTime(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGATIME, "mangatime.co") {
|
||||
override val datePattern = "d MMMM، yyyy"
|
||||
}
|
||||
@@ -5,9 +5,9 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGARBIC", "Mangarbic", "ar")
|
||||
@MangaSourceParser("MANGARBIC", "Manga Arabic", "ar")
|
||||
internal class Mangarbic(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGARBIC, "mangarabic.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val datePattern = "yyyy/MM/dd"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGASPARK", "Manga Spark", "ar")
|
||||
internal class Mangaspark(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGASPARK, "mangaspark.org", pageSize = 10) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val datePattern = "d MMMM، yyyy"
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("NIJITRANSLATIONS", "Niji Translations", "ar")
|
||||
internal class NijiTranslations(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.NIJITRANSLATIONS, "niji-translations.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("PEWPIECE", "PewPiece", "ar")
|
||||
@MangaSourceParser("PEWPIECE", "Pew Piece", "ar")
|
||||
internal class PewPiece(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.PEWPIECE, "pewpiece.com")
|
||||
|
||||
@@ -10,5 +10,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
internal class AdultWebtoon(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.ADULT_WEBTOON, "adultwebtoon.com") {
|
||||
override val tagPrefix = "adult-webtoon-genre/"
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
internal class Astrallibrary(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.ASTRALLIBRARY, "astrallibrary.net", 18) {
|
||||
override val datePattern = "dd MMM"
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("BLOG_MANGA", "Blog Manga", "en")
|
||||
internal class BlogManga(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.BLOG_MANGA, "blogmanga.net") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -11,5 +11,5 @@ internal class BoysLove(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.BOYS_LOVE, "boyslove.me", 20) {
|
||||
override val tagPrefix = "boyslove-genre/"
|
||||
override val listUrl = "boyslove/"
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ internal class CoffeeMangaTop(context: MangaLoaderContext) :
|
||||
return doc.select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = link,
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("CREEPYSCANS", "Creepy Scans", "en")
|
||||
internal class CreepyScans(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.CREEPYSCANS, "creepyscans.com") {
|
||||
override val stylepage = ""
|
||||
override val stylePage = ""
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("FREECOMICONLINE", "Free Comic Online", "en", ContentType.HENTAI)
|
||||
internal class FreeComicOnline(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.FREECOMICONLINE, "freecomiconline.me") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val listUrl = "comic/"
|
||||
override val tagPrefix = "comic-genre/"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("GDSCANS", "GdScans", "en")
|
||||
@MangaSourceParser("GDSCANS", "Gd Scans", "en")
|
||||
internal class GdScans(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.GDSCANS, "gdscans.com", 10) {
|
||||
override val tagPrefix = "webtoon-genre/"
|
||||
|
||||
@@ -10,5 +10,5 @@ internal class GourmetScans(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.GOURMETSCANS, "gourmetscans.net") {
|
||||
override val listUrl = "project/"
|
||||
override val tagPrefix = "genre/"
|
||||
override val stylepage = ""
|
||||
override val stylePage = ""
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("HMANHWA", "HManhwa", "en", ContentType.HENTAI)
|
||||
@MangaSourceParser("HMANHWA", "H Manhwa", "en", ContentType.HENTAI)
|
||||
internal class HManhwa(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HMANHWA, "hmanhwa.com") {
|
||||
override val tagPrefix = "manhwa-genre/"
|
||||
override val listUrl = "manhwa/"
|
||||
override val datePattern = "dd MMM"
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("HSCANS", "HScans", "en")
|
||||
@MangaSourceParser("HSCANS", "H Scans", "en")
|
||||
internal class HScans(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HSCANS, "hscans.com", 10) {
|
||||
|
||||
|
||||
@@ -9,5 +9,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("HENTAIMANGA", "Hentai Manga", "en", ContentType.HENTAI)
|
||||
internal class HentaiManga(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HENTAIMANGA, "hentaimanga.me", 36) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("HENTAIWEBTOON", "Hentai Webtoon", "en", ContentType.HENTAI)
|
||||
internal class HentaiWebtoon(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HENTAIWEBTOON, "hentaiwebtoon.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("HENTAIXCOMIC", "Hentai x Comic", "en", ContentType.HENTAI)
|
||||
internal class HentaixComic(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HENTAIXCOMIC, "hentaixcomic.com", 16) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("HENTAIXYURI", "Hentai x Yuri", "en", ContentType.HENTAI)
|
||||
internal class HentaixYuri(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HENTAIXYURI, "hentaixyuri.com", 16) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -14,15 +14,15 @@ import java.text.SimpleDateFormat
|
||||
@MangaSourceParser("HENTAIXDICKGIRL", "Hentai x Dickgirl", "en", ContentType.HENTAI)
|
||||
internal class Hentaixdickgirl(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HENTAIXDICKGIRL, "hentaixdickgirl.com", 16) {
|
||||
override val postReq = true
|
||||
|
||||
override val postreq = true
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
val root2 = doc.body().selectFirstOrThrow("div.listing-chapters_wrap")
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return root2.select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text()
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
|
||||
@@ -14,7 +14,7 @@ internal class InstaManhwa(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.INSTAMANHWA, "www.instamanhwa.com", 15) {
|
||||
override val tagPrefix = "genre/"
|
||||
override val listUrl = "latest/"
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val datePattern = "d MMMM, yyyy"
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||
@@ -113,7 +113,7 @@ internal class InstaManhwa(context: MangaLoaderContext) :
|
||||
return doc.select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text()
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
|
||||
@@ -113,7 +113,7 @@ internal class IsekaiScan(context: MangaLoaderContext) :
|
||||
return doc.select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = link,
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("ITSYOURIGHTMANHUA", "Itsyourightmanhua", "en")
|
||||
@MangaSourceParser("ITSYOURIGHTMANHUA", "Its You Right Manhua", "en")
|
||||
internal class Itsyourightmanhua(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.ITSYOURIGHTMANHUA, "itsyourightmanhua.com", 10)
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("JAIMINISBOX", "Jaiminisbox", "en")
|
||||
@MangaSourceParser("JAIMINISBOX", "Jaiminis Box", "en")
|
||||
internal class Jaiminisbox(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.JAIMINISBOX, "jaiminisbox.net")
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("JIMANGA", "JiManga", "en")
|
||||
@MangaSourceParser("JIMANGA", "Ji Manga", "en")
|
||||
internal class JiManga(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.JIMANGA, "jimanga.com")
|
||||
|
||||
@@ -9,6 +9,6 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("LOLICONMOBI", "Lolicon Mobi", "en", ContentType.HENTAI)
|
||||
internal class LoliconMobi(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.LOLICONMOBI, "lolicon.mobi") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val tagPrefix = "lolicon-genre/"
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGABOB", "Manga Bob", "en")
|
||||
internal class MangaBob(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGABOB, "mangabob.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
internal class MangaClashTv(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGACLASH_TV, "mangaclash.tv", pageSize = 10) {
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ internal class MangaDass(context: MangaLoaderContext) :
|
||||
return root2.select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text()
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGADINOTOP", "Manga Dino", "en")
|
||||
internal class MangaDinoTop(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGADINOTOP, "mangadino.top", 10) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ internal class MangaDna(context: MangaLoaderContext) :
|
||||
return root2.select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectDate)?.text()
|
||||
val name = a.selectFirst("p")?.text() ?: a.ownText()
|
||||
MangaChapter(
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGAEFFECT", "MangaEffect", "en")
|
||||
@MangaSourceParser("MANGAEFFECT", "Manga Effect", "en")
|
||||
internal class MangaEffect(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAEFFECT, "mangaeffect.com") {
|
||||
override val datePattern = "dd.MM.yyyy"
|
||||
|
||||
@@ -9,6 +9,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGAFORFREE", "Manga For Free", "en", ContentType.HENTAI)
|
||||
internal class MangaForFree(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAFORFREE, "mangaforfree.com", 10) {
|
||||
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGAFOXFULL", "Manga Fox Full", "en")
|
||||
internal class MangaFoxFull(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAFOXFULL, "mangafoxfull.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGAFREAK", "Manga Freak", "en")
|
||||
internal class MangaFreak(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAFREAK, "mangafreak.online") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val datePattern = "dd MMMM، yyyy"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGALEVELING", "Manga Leveling", "en")
|
||||
internal class MangaLeveling(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGALEVELING, "mangaleveling.com", 30) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val tagPrefix = "comics-genre/"
|
||||
override val listUrl = "comics/"
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
@@ -7,6 +7,4 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGA_MANHUA", "Manga Manhua", "en")
|
||||
internal class MangaManhua(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGA_MANHUA, "mangamanhua.online", pageSize = 10) {
|
||||
override val datePattern = "d MMMM، yyyy"
|
||||
}
|
||||
MadaraParser(context, MangaSource.MANGA_MANHUA, "mangaonlineteam.com", pageSize = 10)
|
||||
|
||||
@@ -6,8 +6,8 @@ import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGAOWLBLOG", "MangaOwl .Blog", "en", ContentType.HENTAI)
|
||||
@MangaSourceParser("MANGAOWLBLOG", "Manga Owl .Blog", "en", ContentType.HENTAI)
|
||||
internal class MangaOwlBlog(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAOWLBLOG, "mangaowl.blog", 20) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGAOWL_IO", "MangaOwl .Io", "en")
|
||||
@MangaSourceParser("MANGAOWL_IO", "Manga Owl .Io", "en")
|
||||
internal class MangaOwlIo(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAOWL_IO, "mangaowl.io") {
|
||||
override val listUrl = "mangaowl-all/"
|
||||
|
||||
@@ -112,7 +112,7 @@ internal class MangaPure(context: MangaLoaderContext) :
|
||||
return doc.select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + stylepage
|
||||
val link = href + stylePage
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = link,
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGARAWINFO", "Manga-Raw .Info", "en")
|
||||
internal class MangaRawInfo(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGARAWINFO, "manga-raw.info", 20) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGAROCKY", "Manga Rocky", "en")
|
||||
internal class MangaRocky(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAROCKY, "mangarocky.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGAUPDATESTOP", "Manga Updates .Top", "en")
|
||||
internal class MangaUpdatesTop(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAUPDATESTOP, "mangaupdates.top", 10) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGANELO", "Manga Nelo", "en")
|
||||
internal class Manganelo(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGANELO, "manganelo.biz", 10) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGAOWL_ONE", "MangaOwl .One", "en", ContentType.HENTAI)
|
||||
@MangaSourceParser("MANGAOWL_ONE", "Manga Owl .One", "en", ContentType.HENTAI)
|
||||
internal class MangaowlOne(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAOWL_ONE, "mangaowl.one") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANGAX1", "MangaX1", "en")
|
||||
internal class Mangax1(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAX1, "mangax1.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANHUASCANINFO", "Manhua Scan .Info", "en")
|
||||
internal class ManhuaScanInfo(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHUASCANINFO, "manhuascan.info", 10) {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANHUAES", "Manhuaes", "en")
|
||||
@MangaSourceParser("MANHUAES", "ManhuaEs", "en")
|
||||
internal class Manhuaes(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHUAES, "manhuaes.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANHUAGA", "Manhuaga", "en")
|
||||
@MangaSourceParser("MANHUAGA", "ManhuaGa", "en")
|
||||
internal class Manhuaga(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHUAGA, "manhuaga.com")
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANHUASY", "Manhuasy", "en")
|
||||
@MangaSourceParser("MANHUASY", "ManhuaSy", "en")
|
||||
internal class Manhuasy(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHUASY, "www.manhuasy.com") {
|
||||
override val listUrl = "manhua/"
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANHUAUS", "Manhuaus", "en")
|
||||
@MangaSourceParser("MANHUAUS", "ManhuaUs", "en")
|
||||
internal class Manhuaus(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHUAUS, "manhuaus.com")
|
||||
|
||||
@@ -6,8 +6,8 @@ import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANHWA18APP", "Manhwa18 .App", "en", ContentType.HENTAI)
|
||||
@MangaSourceParser("MANHWA18APP", "Manhwa 18 .App", "en", ContentType.HENTAI)
|
||||
internal class Manhwa18App(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHWA18APP, "manhwa18.app") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -6,9 +6,8 @@ import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANHWA18ORG", "Manhwa18 .Org", "en", ContentType.HENTAI)
|
||||
@MangaSourceParser("MANHWA18ORG", "Manhwa 18 .Org", "en", ContentType.HENTAI)
|
||||
internal class Manhwa18Org(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHWA18ORG, "manhwa18.org") {
|
||||
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANHWA2READ", "Manhwa2Read", "en")
|
||||
@MangaSourceParser("MANHWA2READ", "Manhwa 2 Read", "en")
|
||||
internal class Manhwa2Read(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHWA2READ, "manhwa2read.com")
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
@MangaSourceParser("MANHWARAW_COM", "Manhwa Raw .Com", "en", ContentType.HENTAI)
|
||||
internal class ManhwaRawCom(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHWARAW_COM, "manhwaraw.com") {
|
||||
override val postreq = true
|
||||
override val postReq = true
|
||||
override val listUrl = "manhwa-raw/"
|
||||
override val tagPrefix = "manhwa-raw-genre/"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user