diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/es/DragonTranslationParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/es/DragonTranslationParser.kt new file mode 100644 index 00000000..d8528ca4 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/es/DragonTranslationParser.kt @@ -0,0 +1,172 @@ +package org.koitharu.kotatsu.parsers.site.es + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.config.ConfigKey +import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser +import org.koitharu.kotatsu.parsers.model.* +import org.koitharu.kotatsu.parsers.util.* +import java.util.* + +@MangaSourceParser("DRAGONTRANSLATION", "Dragon Translation", "es") +internal class DragonTranslationParser(context: MangaLoaderContext) : LegacyPagedMangaParser(context, MangaParserSource.DRAGONTRANSLATION, 30) { + + override val configKeyDomain = ConfigKey.Domain("dragontranslation.net") + + override fun onCreateConfig(keys: MutableCollection>) { + super.onCreateConfig(keys) + keys.add(userAgentKey) + } + + override fun getRequestHeaders() = super.getRequestHeaders().newBuilder() + .add("referer", "no-referrer") + .build() + + override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED) + + override val filterCapabilities: MangaListFilterCapabilities + get() = MangaListFilterCapabilities( + isSearchSupported = true, + ) + + override suspend fun getFilterOptions() = MangaListFilterOptions( + availableTags = emptySet(), // cant find any URLs for fetch tags + availableContentTypes = EnumSet.of(ContentType.MANGA, ContentType.MANHWA, ContentType.MANHUA), + ) + + override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List { + val url = buildString { + append("https://") + append(domain) + when { + !filter.query.isNullOrEmpty() -> { + append("/mangas?buscar=") + append(filter.query.urlEncoded()) + append("&page=") + append(page.toString()) + } + + else -> { + append("/mangas?page=") + append(page.toString()) + + val tag = filter.tags.oneOrThrowIfMany() + if (filter.tags.isNotEmpty()) { + append("&tag=") + append(tag?.key.orEmpty()) + } + + if (filter.types.isNotEmpty()) { + append("&type=") + when (filter.types.oneOrThrowIfMany()) { + ContentType.MANGA -> "manga" + ContentType.MANHWA -> "manhwa" + ContentType.MANHUA -> "manhua" + else -> "" + } + } + } + } + } + + val doc = webClient.httpGet(url).parseHtml() + val row = doc.select("div.row.gy-3").firstOrNull() ?: return emptyList() + return row.select("article.position-relative.card").mapNotNull { div -> + val href = div.selectFirst("a.lanzador")?.attrAsRelativeUrlOrNull("href") ?: return@mapNotNull null + val coverUrl = div.selectFirst("img.card-img-top.wp-post-image.lazy.loaded")?.src().orEmpty() + Manga( + id = generateUid(href), + url = href, + publicUrl = href, + coverUrl = coverUrl, + title = div.selectFirst("h2.card-title.fs-6.entry-title").text(), + altTitles = emptySet(), + rating = RATING_UNKNOWN, + tags = emptySet(), + authors = emptySet(), + state = null, + source = source, + contentRating = if (isNsfwSource) ContentRating.ADULT else null, + ) + } + } + + override suspend fun getDetails(manga: Manga): Manga { + val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml() + val statusText = doc.selectFirst("p:contains(Status:)")?.text() + val status = when { + statusText?.contains("publishing", ignoreCase = true) == true -> MangaState.ONGOING + else -> null + } + + val chapterElements = doc.select("ul.list-group a") + val totalChapters = chapterElements.size + + val chapters = chapterElements.mapIndexed { index, a -> + val href = a.attrAsRelativeUrl("href") + val title = a.text() + MangaChapter( + id = generateUid(href), + title = title, + number = totalChapters - index.toFloat(), + volume = 0, + url = href, + scanlator = null, + uploadDate = parseDate(a.selectFirst("span")?.text()), + branch = null, + source = source, + ) + } + + return manga.copy( + state = status, + chapters = chapters.reversed(), + ) + } + + override suspend fun getPages(chapter: MangaChapter): List { + val fullUrl = chapter.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + return doc.select("div#chapter_imgs img").map { img -> + val url = img.attr("src") + MangaPage( + id = generateUid(url), + url = url, + preview = null, + source = source, + ) + } + } + + private fun parseDate(dateText: String?): Long { + if (dateText == null) return 0 + + val number = dateText.filter { it.isDigit() }.toIntOrNull() ?: return 0 + val now = System.currentTimeMillis() + + return when { + dateText.contains("minutos") -> { + now - (number * 60 * 1000L) + } + dateText.contains("horas") -> { + now - (number * 60 * 60 * 1000L) + } + dateText.contains("días") -> { + now - (number * 24 * 60 * 60 * 1000L) + } + dateText.contains("día") -> { + now - (number * 24 * 60 * 60 * 1000L) + } + dateText.contains("semanas") -> { + now - (number * 7 * 24 * 60 * 60 * 1000L) + } + dateText.contains("meses") -> { + now - (number * 30 * 24 * 60 * 60 * 1000L) + } + dateText.contains("años") -> { + now - (number * 365 * 24 * 60 * 60 * 1000L) + } + else -> 0L + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/DragonTranslationParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/DragonTranslationParser.kt deleted file mode 100644 index d197fbec..00000000 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/DragonTranslationParser.kt +++ /dev/null @@ -1,76 +0,0 @@ -package org.koitharu.kotatsu.parsers.site.madara.es - -import org.koitharu.kotatsu.parsers.Broken -import org.koitharu.kotatsu.parsers.MangaLoaderContext -import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* -import org.koitharu.kotatsu.parsers.site.madara.MadaraParser -import org.koitharu.kotatsu.parsers.util.* -import java.util.* - -@Broken // no longer works with MadaraParser, need fix -@MangaSourceParser("DRAGONTRANSLATION", "Dragon Translation", "es") -internal class DragonTranslationParser(context: MangaLoaderContext) : - MadaraParser(context, MangaParserSource.DRAGONTRANSLATION, "dragontranslation.net", 30) { - - override val selectPage = "div#chapter_imgs img" - override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED) - - init { - paginator.firstPage = 1 - searchPaginator.firstPage = 1 - } - - override suspend fun getFilterOptions() = super.getFilterOptions().copy( - availableStates = emptySet(), - availableContentRating = emptySet(), - ) - - override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List { - val url = buildString { - append("https://") - append(domain) - when { - !filter.query.isNullOrEmpty() -> { - append("/mangas?buscar=") - append(filter.query.urlEncoded()) - append("&page=") - append(page.toString()) - } - - else -> { - - append("/mangas?page=") - append(page.toString()) - - val tag = filter.tags.oneOrThrowIfMany() - if (filter.tags.isNotEmpty()) { - append("&tag=") - append(tag?.key.orEmpty()) - } - } - } - } - - val doc = webClient.httpGet(url).parseHtml() - val row = doc.select("div.row.gy-3").firstOrNull() ?: return emptyList() - return row.select("article.position-relative.card").mapNotNull { div -> - val href = div.selectFirst("a.lanzador")?.attrAsRelativeUrlOrNull("href") ?: return@mapNotNull null - val coverUrl = div.selectFirst("img.card-img-top.wp-post-image.lazy.loaded")?.src().orEmpty() - Manga( - id = generateUid(href), - url = href, - publicUrl = href, - coverUrl = coverUrl, - title = div.selectFirst("h2.card-title.fs-6.entry-title").text(), - altTitles = emptySet(), - rating = RATING_UNKNOWN, - tags = emptySet(), - authors = emptySet(), - state = null, - source = source, - contentRating = if (isNsfwSource) ContentRating.ADULT else null, - ) - } - } - }