Update domain + Add sources (#1221)

* Update HariManga.kt

* Update Mgkomik.kt

* Update XoxoComics.kt

* Create DuaLeoTruyen.kt

* Create MyComicList.kt

* Update DuaLeoTruyen.kt

* Update summary.yaml

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Add suggestions

Co-authored-by: Koitharu <nvasya95@gmail.com>

* Fixes

---------

Co-authored-by: Koitharu <nvasya95@gmail.com>
master
Draken 1 year ago committed by GitHub
parent 5a4f9d8914
commit de95fa2e3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1 +1 @@
total: 1152
total: 1154

@ -0,0 +1,153 @@
package org.koitharu.kotatsu.parsers.site.en
import androidx.collection.arraySetOf
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.network.UserAgents
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
import java.util.*
@MangaSourceParser("MYCOMICLIST", "MyComicList", "en", ContentType.COMICS)
internal class MyComicList(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.MYCOMICLIST, 24) {
override val configKeyDomain = ConfigKey.Domain("mycomiclist.org")
override fun onCreateConfig(keys: MutableCollection<ConfigKey<*>>) {
super.onCreateConfig(keys)
keys.add(userAgentKey)
}
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.NEWEST,
SortOrder.ALPHABETICAL
)
override val filterCapabilities: MangaListFilterCapabilities
get() = MangaListFilterCapabilities(
isSearchSupported = true,
)
override suspend fun getFilterOptions() = MangaListFilterOptions(
availableTags = fetchAvailableTags(),
availableStates = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED)
)
override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List<Manga> {
val url = buildString {
append("https://")
append(domain)
when {
!filter.query.isNullOrEmpty() -> {
append("/comic-search?key=")
append(filter.query.urlEncoded())
}
filter.tags.isNotEmpty() -> {
append("/")
append(filter.tags.first().key)
append("-comic")
}
else -> when (order) {
SortOrder.UPDATED -> append("/hot-comic")
SortOrder.POPULARITY -> append("/popular-comic")
SortOrder.NEWEST -> append("/new-comic")
else -> append("/ongoing-comic")
}
}
if (page > 1) {
append("?page=")
append(page)
}
}
val doc = webClient.httpGet(url).parseHtml()
return doc.select("div.manga-box").map { div ->
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
val img = div.selectFirst("img.lazyload")
Manga(
id = generateUid(href),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
title = div.selectFirst("h3 a")?.text().orEmpty(),
altTitle = null,
author = null,
tags = emptySet(),
rating = RATING_UNKNOWN,
isNsfw = isNsfwSource,
coverUrl = img?.attr("data-src").orEmpty(),
state = null,
source = source,
)
}
}
override suspend fun getDetails(manga: Manga): Manga {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
return manga.copy(
tags = doc.select("td:contains(Genres:) + td a").mapToSet { a ->
MangaTag(
key = a.attr("href").substringAfterLast('/').substringBefore("-comic"),
title = a.text().toTitleCase(sourceLocale),
source = source
)
},
author = doc.selectFirst("td:contains(Author:) + td")?.textOrNull(),
state = when(doc.selectFirst("td:contains(Status:) + td a")?.text()?.lowercase()) {
"ongoing" -> MangaState.ONGOING
"completed" -> MangaState.FINISHED
else -> null
},
description = doc.selectFirst("div.manga-desc p.pdesc")?.html(),
chapters = doc.select("ul.basic-list li").mapChapters(reversed = true) { i, li ->
val a = li.selectFirst("a.ch-name") ?: return@mapChapters null
val href = a.attrAsRelativeUrl("href")
val name = a.text()
MangaChapter(
id = generateUid(href),
name = name,
number = name.substringAfter('#').toFloatOrNull() ?: (i + 1f),
url = href,
scanlator = null,
uploadDate = 0L,
branch = null,
source = source,
volume = 0,
)
}
)
}
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
val fullUrl = chapter.url.toAbsoluteUrl(domain) + "/all"
val doc = webClient.httpGet(fullUrl).parseHtml()
return doc.select("img.chapter_img.lazyload").mapNotNull { img ->
val imageUrl = img.attrOrNull("data-src") ?: return@mapNotNull null
MangaPage(
id = generateUid(imageUrl),
url = imageUrl,
preview = null,
source = source
)
}
}
private suspend fun fetchAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain").parseHtml()
return doc.select("div.cr-anime-box.genre-box a.genre-name").mapToSet { a ->
val href = a.attr("href")
val key = href.substringAfterLast('/').substringBefore("-comic")
MangaTag(
key = key,
title = a.text().toTitleCase(sourceLocale),
source = source
)
}
}
}

@ -7,4 +7,4 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
@MangaSourceParser("HARIMANGA", "HariManga", "en")
internal class HariManga(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.HARIMANGA, "harimanga.com", pageSize = 10)
MadaraParser(context, MangaParserSource.HARIMANGA, "harimanga.me", pageSize = 10)

@ -5,12 +5,19 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import java.util.*
import kotlin.random.Random
@MangaSourceParser("MGKOMIK", "MgKomik", "id")
internal class Mgkomik(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MGKOMIK, "mgkomik.id", 20) {
override fun onCreateConfig(keys: MutableCollection<ConfigKey<*>>) {
super.onCreateConfig(keys)
keys.add(userAgentKey)
}
override val tagPrefix = "genres/"
override val listUrl = "komik/"
override val datePattern = "dd MMM yy"

@ -0,0 +1,171 @@
package org.koitharu.kotatsu.parsers.site.vi
import org.json.JSONArray
import org.jsoup.nodes.Document
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.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
import java.util.*
@MangaSourceParser("DUALEOTRUYEN", "DuaLeoTruyen", "vi", type = ContentType.HENTAI)
internal class DuaLeoTruyen(context: MangaLoaderContext) :
PagedMangaParser(context, MangaParserSource.DUALEOTRUYEN, 60) {
override val configKeyDomain: ConfigKey.Domain
get() = ConfigKey.Domain("dualeotruyenomega.com")
override val userAgentKey = ConfigKey.UserAgent(UserAgents.CHROME_DESKTOP)
override fun onCreateConfig(keys: MutableCollection<ConfigKey<*>>) {
super.onCreateConfig(keys)
keys.add(userAgentKey)
}
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY
)
override val filterCapabilities: MangaListFilterCapabilities
get() = MangaListFilterCapabilities(
isSearchSupported = true,
)
override suspend fun getFilterOptions() = MangaListFilterOptions(
availableTags = fetchAvailableTags(),
)
override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List<Manga> {
val url = buildString {
append("https://")
append(domain)
when {
!filter.query.isNullOrEmpty() -> {
append("/tim-kiem.html")
append("?key=")
append(filter.query.urlEncoded())
}
filter.tags.isNotEmpty() -> {
append("/the-loai/")
append(filter.tags.first().key)
append(".html")
}
else -> when (order) {
SortOrder.POPULARITY -> append("/top-ngay.html")
else -> append("/truyen-moi-cap-nhat.html")
}
}
if (page > 1) {
append("?page=")
append(page)
}
}
val doc = webClient.httpGet(url).parseHtml()
return doc.select(".box_list > .li_truyen").map { li ->
val href = li.selectFirstOrThrow("a").attrAsRelativeUrl("href")
Manga(
id = generateUid(href),
title = li.selectFirst(".name")?.text().orEmpty(),
altTitle = null,
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
isNsfw = isNsfwSource,
coverUrl = li.selectFirst("img")?.absUrl("data-src").orEmpty(),
tags = emptySet(),
state = null,
author = null,
source = source
)
}
}
override suspend fun getDetails(manga: Manga): Manga {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH)
return manga.copy(
altTitle = doc.selectFirst(".box_info_right h2")?.textOrNull(),
tags = doc.select("ul.list-tag-story li a").mapToSet {
MangaTag(
key = it.attr("href").substringAfterLast('/').substringBefore('.'),
title = it.text().toTitleCase(sourceLocale),
source = source
)
},
state = when (doc.selectFirst(".info-item:has(.fa-rss)")?.text()?.removePrefix("Tình trang: ")) {
"Đang cập nhật" -> MangaState.ONGOING
"Full" -> MangaState.FINISHED
else -> null
},
author = doc.selectFirst(".info-item:has(.fa-user)")?.textOrNull()?.removePrefix("Tác giả: "),
description = doc.selectFirst(".story-detail-info")?.html(),
chapters = doc.select(".list-chapters .chapter-item").mapChapters(reversed = true) { i, div ->
val a = div.selectFirstOrThrow(".chap_name a")
val href = a.attrAsRelativeUrl("href")
val dateText = div.selectFirst(".chap_update")?.text()
MangaChapter(
id = generateUid(href),
name = a.text(),
number = i + 1f,
url = href,
scanlator = null,
uploadDate = dateFormat.tryParse(dateText),
branch = null,
source = source,
volume = 0,
)
}
)
}
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
val fullUrl = chapter.url.toAbsoluteUrl(domain)
val doc = webClient.httpGet(fullUrl).parseHtml()
val chapterId = doc.selectFirst("input[name=chap]")?.`val`()
val comicsId = doc.selectFirst("input[name=truyen]")?.`val`()
if (chapterId != null && comicsId != null) {
webClient.httpPost(
url = "https://$domain/process.php",
form = mapOf(
"action" to "update_view_chap",
"truyen" to comicsId,
"chap" to chapterId
)
)
}
return doc.select(".content_view_chap img").mapIndexed { i, img ->
val url = img.absUrl("data-original")
MangaPage(
id = generateUid(url),
url = url,
preview = null,
source = source
)
}
}
private suspend fun fetchAvailableTags(): Set<MangaTag> {
return listOf(
"18+", "Đam Mỹ", "Harem", "Truyện Màu", "BoyLove", "GirlLove",
"Phiêu lưu", "Yaoi", "Hài Hước", "Bách Hợp", "Chuyển Sinh", "Drama",
"Hành Động", "Kịch Tính", "Cổ Đại", "Ecchi", "Hentai", "Lãng Mạn",
"Người Thú", "Tình Cảm", "Yuri", "Oneshot", "Doujinshi", "ABO"
).mapToSet { name ->
MangaTag(
key = name.lowercase().replace(' ', '-'),
title = name,
source = source
)
}
}
}

@ -183,9 +183,10 @@ internal class XoxoComics(context: MangaLoaderContext) :
val doc = webClient.httpGet(fullUrl).parseHtml()
return doc.select(selectPage).mapNotNull { url ->
val img = url.src()?.toRelativeUrl(domain) ?: return@mapNotNull null
val originalImage = img.replace("[", "").replace("]", "")
MangaPage(
id = generateUid(img),
url = img,
url = originalImage,
preview = null,
source = source,
)

Loading…
Cancel
Save