diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/bitmap/Bitmap.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/bitmap/Bitmap.kt index 6162e13c..e9be3b8d 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/bitmap/Bitmap.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/bitmap/Bitmap.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.parsers.bitmap interface Bitmap { + val width: Int val height: Int diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/bitmap/Rect.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/bitmap/Rect.kt index dbb321a7..95d972f1 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/bitmap/Rect.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/bitmap/Rect.kt @@ -6,8 +6,10 @@ data class Rect( val right: Int = 0, val bottom: Int = 0, ) { + val width: Int get() = right - left + val height: Int get() = bottom - top } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/MangaReaderToParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/MangaReaderToParser.kt index 02ca01cd..5411a1a3 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/MangaReaderToParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/MangaReaderToParser.kt @@ -1,11 +1,14 @@ package org.koitharu.kotatsu.parsers.site.all +import androidx.collection.MutableIntObjectMap import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Interceptor import okhttp3.Response import org.jsoup.Jsoup import org.jsoup.nodes.Document -import org.koitharu.kotatsu.parsers.* +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.PagedMangaParser import org.koitharu.kotatsu.parsers.bitmap.Bitmap import org.koitharu.kotatsu.parsers.bitmap.Rect import org.koitharu.kotatsu.parsers.config.ConfigKey @@ -17,7 +20,8 @@ import javax.crypto.spec.SecretKeySpec import kotlin.math.min @MangaSourceParser("MANGAREADERTO", "MangaReader.To") -class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGAREADERTO, 16), Interceptor { +class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGAREADERTO, 16), + Interceptor { override val configKeyDomain = ConfigKey.Domain("mangareader.to") @@ -26,7 +30,7 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex SortOrder.RATING, SortOrder.UPDATED, SortOrder.NEWEST, - SortOrder.ALPHABETICAL + SortOrder.ALPHABETICAL, ) override val availableStates: Set = EnumSet.allOf(MangaState::class.java) @@ -38,7 +42,7 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex MangaTag( title = it.ownText().trim(), key = it.attr("data-id"), - source = source + source = source, ) }.associateBy { it.title } } @@ -57,6 +61,7 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex addQueryParameter("keyword", filter.query) addQueryParameter("page", page.toString()) } + is MangaListFilter.Advanced -> { addPathSegment("filter") addQueryParameter("page", page.toString()) @@ -69,7 +74,7 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex SortOrder.NEWEST -> "release-date" SortOrder.ALPHABETICAL -> "name-az" else -> "default" - } + }, ) addQueryParameter("genres", filter.tags.joinToString(",") { it.key }) addQueryParameter( @@ -81,9 +86,10 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex MangaState.PAUSED -> "3" MangaState.UPCOMING -> "5" null -> "" - } + }, ) } + null -> { addPathSegment("filter") addQueryParameter("page", page.toString()) @@ -108,31 +114,32 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex isNsfw = false, rating = RATING_UNKNOWN, state = null, - tags = emptySet() + tags = emptySet(), ) } } override suspend fun getRelatedManga(seed: Manga): List { val document = webClient.httpGet(seed.url.toAbsoluteUrl(domain)).parseHtml() - return document.select(".block_area_authors-other .manga_list-sbs .manga-poster, .featured-block-ul .manga-poster").map { - val mangaUrl = it.attrAsRelativeUrl("href") - val thumb = it.select("img") - Manga( - id = generateUid(mangaUrl), - url = mangaUrl, - publicUrl = mangaUrl.toAbsoluteUrl(domain), - title = thumb.attr("alt"), - coverUrl = thumb.attr("src"), - source = source, - altTitle = null, - author = null, - isNsfw = false, - rating = RATING_UNKNOWN, - state = null, - tags = emptySet() - ) - } + return document.select(".block_area_authors-other .manga_list-sbs .manga-poster, .featured-block-ul .manga-poster") + .map { + val mangaUrl = it.attrAsRelativeUrl("href") + val thumb = it.select("img") + Manga( + id = generateUid(mangaUrl), + url = mangaUrl, + publicUrl = mangaUrl.toAbsoluteUrl(domain), + title = thumb.attr("alt"), + coverUrl = thumb.attr("src"), + source = source, + altTitle = null, + author = null, + isNsfw = false, + rating = RATING_UNKNOWN, + state = null, + tags = emptySet(), + ) + } } override suspend fun getDetails(manga: Manga): Manga { @@ -165,16 +172,18 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex else -> null } }, - author = document.select("div.anisc-info a[href*=/author/]").joinToString { it.ownText().replace(", ", " ") }, + author = document.select("div.anisc-info a[href*=/author/]") + .joinToString { it.ownText().replace(", ", " ") }, description = document.select("div.description").text(), chapters = parseChapters(document), - source = source + source = source, ) } private fun parseChapters(document: Document): List { - val total = document.select(".chapters-list-ul > ul > li.chapter-item, .volume-list-ul div.lang-volumes > div.item").size - val chapters = ArrayList(total) + val total = + document.select(".chapters-list-ul > ul > li.chapter-item, .volume-list-ul div.lang-volumes > div.item").size + val chapters = ChaptersListBuilder(total) document.select(".chapters-list-ul > ul").forEach { ul -> ul.select("li.chapter-item").reversed().forEach { li -> @@ -190,8 +199,8 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex scanlator = null, uploadDate = 0L, branch = createBranchName(ul.id().substringBefore("-chapters"), "Chapters"), - source = source - ) + source = source, + ), ) } } @@ -204,19 +213,19 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex MangaChapter( id = generateUid(url), name = name, - number = numRegex.find(name)!!.groupValues[1].toFloat(), + number = numRegex.find(name)?.groupValues?.getOrNull(1)?.toFloatOrNull() ?: 0f, volume = 0, url = url, scanlator = null, uploadDate = 0L, branch = createBranchName(div.id().substringBefore("-volumes"), "Volumes"), - source = source - ) + source = source, + ), ) } } - return chapters + return chapters.toList() } private fun createBranchName(lang: String, type: String): String { @@ -246,7 +255,7 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex url }, preview = null, - source = source + source = source, ) } } @@ -260,7 +269,7 @@ class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(contex return context.redrawImageResponse(response, ::descramble) } - private val memo = hashMapOf() + private val memo = MutableIntObjectMap() private fun descramble(bitmap: Bitmap): Bitmap { val width = bitmap.width diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancms/pt/ModeScanlator.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancms/pt/ModeScanlator.kt index aa7bb128..da4b1f78 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancms/pt/ModeScanlator.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancms/pt/ModeScanlator.kt @@ -6,15 +6,15 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.site.heancms.HeanCms import org.koitharu.kotatsu.parsers.util.* -import org.koitharu.kotatsu.parsers.util.json.getFloatOrDefault -import org.koitharu.kotatsu.parsers.util.json.getStringOrNull -import org.koitharu.kotatsu.parsers.util.json.mapJSON -import org.koitharu.kotatsu.parsers.util.json.unescapeJson +import org.koitharu.kotatsu.parsers.util.json.* import java.text.SimpleDateFormat import java.util.* @MangaSourceParser("MODESCANLATOR", "ModeScanlator", "pt") -internal class ModeScanlator(context: MangaLoaderContext) : HeanCms(context, MangaSource.MODESCANLATOR, "modescanlator.com") { +internal class ModeScanlator( + context: MangaLoaderContext, +) : HeanCms(context, MangaSource.MODESCANLATOR, "modescanlator.com") { + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://api.") @@ -49,10 +49,11 @@ internal class ModeScanlator(context: MangaLoaderContext) : HeanCms(context, Man SortOrder.ALPHABETICAL_DESC -> append("title&order=asc") else -> append("latest&order=desc") } - append("&series_type=All&perPage=$pageSize") + append("&series_type=All&perPage=") + append(pageSize) append("&tags_ids=") append("[".urlEncoded()) - append(filter.tags.joinToString(",") { it.key }) + filter.tags.joinTo(this, ",") { it.key } append("]".urlEncoded()) } @@ -60,7 +61,7 @@ internal class ModeScanlator(context: MangaLoaderContext) : HeanCms(context, Man null -> {} } append("&page=") - append(page.toString()) + append(page) } val json = webClient.httpGet(url).parseJson() return json.getJSONArray("data").mapJSON { j -> @@ -78,10 +79,10 @@ internal class ModeScanlator(context: MangaLoaderContext) : HeanCms(context, Man url = urlManga.toRelativeUrl(domain), publicUrl = urlManga, rating = j.getFloatOrDefault("rating", RATING_UNKNOWN) / 5f, - isNsfw = true, + isNsfw = isNsfwSource, coverUrl = cover, tags = setOf(), - state = when (j.getString("status")) { + state = when (j.getStringOrNull("status")) { "Ongoing" -> MangaState.ONGOING "Completed" -> MangaState.FINISHED "Dropped" -> MangaState.ABANDONED @@ -100,7 +101,8 @@ internal class ModeScanlator(context: MangaLoaderContext) : HeanCms(context, Man val url = buildString { append("https://api.") append(domain) - append("/chapter/query?perPage=9999&series_id=" + manga.id) + append("/chapter/query?perPage=9999&series_id=") + append(manga.id) } val json = webClient.httpGet(url).parseJson() val dateFormat = SimpleDateFormat(datePattern, Locale.ENGLISH) @@ -135,14 +137,12 @@ internal class ModeScanlator(context: MangaLoaderContext) : HeanCms(context, Man val tags = doc.select("script").firstNotNullOf { script -> regex.find(script.html())?.groupValues?.getOrNull(1) }.unescapeJson() - return JSONArray(tags).mapJSON { + return JSONArray(tags).mapJSONToSet { MangaTag( key = it.getInt("id").toString(), title = it.getString("name").toTitleCase(sourceLocale), source = source, ) - }.toSet() + } } - } -