Skip to content

Commit

Permalink
Update domain + Add sources (#1221)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
dragonx943 and Koitharu authored Nov 16, 2024
1 parent 5a4f9d8 commit de95fa2
Show file tree
Hide file tree
Showing 6 changed files with 335 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/summary.yaml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
total: 1152
total: 1154
153 changes: 153 additions & 0 deletions src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/MyComicList.kt
Original file line number Diff line number Diff line change
@@ -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
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
171 changes: 171 additions & 0 deletions src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/DuaLeoTruyen.kt
Original file line number Diff line number Diff line change
@@ -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
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
Expand Down

0 comments on commit de95fa2

Please sign in to comment.