diff --git a/src/id/maidmanga/build.gradle b/src/id/maidmanga/build.gradle index d783d6e12..238e65ce4 100644 --- a/src/id/maidmanga/build.gradle +++ b/src/id/maidmanga/build.gradle @@ -5,7 +5,7 @@ ext { appName = 'Tachiyomi: Maid - Manga' pkgNameSuffix = 'id.maidmanga' extClass = '.MaidManga' - extVersionCode = 2 + extVersionCode = 3 libVersion = '1.2' } diff --git a/src/id/maidmanga/src/eu/kanade/tachiyomi/extension/id/maidmanga/MaidManga.kt b/src/id/maidmanga/src/eu/kanade/tachiyomi/extension/id/maidmanga/MaidManga.kt index 3bedfe45f..923a18ce0 100644 --- a/src/id/maidmanga/src/eu/kanade/tachiyomi/extension/id/maidmanga/MaidManga.kt +++ b/src/id/maidmanga/src/eu/kanade/tachiyomi/extension/id/maidmanga/MaidManga.kt @@ -7,13 +7,11 @@ import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.ParsedHttpSource -import eu.kanade.tachiyomi.util.asJsoup import java.text.SimpleDateFormat +import java.util.Locale import okhttp3.HttpUrl import okhttp3.OkHttpClient import okhttp3.Request -import okhttp3.Response -import org.json.JSONObject import org.jsoup.nodes.Document import org.jsoup.nodes.Element @@ -29,50 +27,32 @@ class MaidManga : ParsedHttpSource() { override val client: OkHttpClient = network.cloudflareClient - override fun latestUpdatesSelector() = "h2:contains(Update Chapter) + div.row div.col-12" + private fun pagePathSegment(page: Int): String = if (page > 1) "page/$page/" else "" + + override fun latestUpdatesSelector() = searchMangaSelector() override fun latestUpdatesRequest(page: Int): Request { - // The site redirects page 1 -> url-without-page so we do this redirect early for optimization - val builtUrl = if (page == 1) baseUrl else "$baseUrl/page/$page/" - return GET(builtUrl) + return GET("$baseUrl/advanced-search/${pagePathSegment(page)}?order=popular") } - override fun latestUpdatesFromElement(element: Element): SManga { - val manga = SManga.create() - val item = element.select("h3 a") - val imgurl = element.select("div.limit img").attr("src").replace("?resize=100,140", "") - manga.url = item.attr("href") - manga.title = item.text() - manga.thumbnail_url = imgurl - return manga - } + override fun latestUpdatesFromElement(element: Element): SManga = searchMangaFromElement(element) - override fun latestUpdatesNextPageSelector() = "a:containsOwn(Berikutnya)" + override fun latestUpdatesNextPageSelector() = searchMangaNextPageSelector() override fun popularMangaRequest(page: Int): Request { - val builtUrl = if (page == 1) "$baseUrl/advanced-search/?order=popular" else "$baseUrl/advanced-search/page/$page/?order=popular" - return GET(builtUrl) + return GET("$baseUrl/advanced-search/${pagePathSegment(page)}?order=update") } - override fun popularMangaSelector() = "div.row div.col-6" + override fun popularMangaSelector() = searchMangaSelector() - override fun popularMangaFromElement(element: Element): SManga { - val manga = SManga.create() - val imgurl = element.select("div.card img").attr("src").replace("?resize=165,225", "") - manga.url = element.select("div.card a").attr("href") - manga.title = element.select("div.card img").attr("title") - manga.thumbnail_url = imgurl - return manga - } + override fun popularMangaFromElement(element: Element): SManga = searchMangaFromElement(element) - override fun popularMangaNextPageSelector() = latestUpdatesNextPageSelector() + override fun popularMangaNextPageSelector() = searchMangaNextPageSelector() override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - val builtUrl = if (page == 1) "$baseUrl/advanced-search/" else "$baseUrl/advanced-search/page/$page/" - val url = HttpUrl.parse(builtUrl)!!.newBuilder() + val url = HttpUrl.parse("$baseUrl/advanced-search/${pagePathSegment(page)}")!!.newBuilder() url.addQueryParameter("title", query) - url.addQueryParameter("page", page.toString()) - filters.forEach { filter -> + (if (filters.isEmpty()) getFilterList() else filters).forEach { filter -> when (filter) { is AuthorFilter -> { url.addQueryParameter("author", filter.state) @@ -96,115 +76,61 @@ class MaidManga : ParsedHttpSource() { } is GenreList -> { filter.state - .filter { it.state != Filter.TriState.STATE_IGNORE } + .filter { it.state } .forEach { url.addQueryParameter("genre[]", it.id) } } } } - return GET(url.build().toString(), headers) + return GET(url.toString(), headers) } - override fun searchMangaSelector() = popularMangaSelector() + override fun searchMangaSelector() = "div.flexbox2-item" - override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element) - - override fun searchMangaNextPageSelector() = latestUpdatesNextPageSelector() - - override fun mangaDetailsRequest(manga: SManga): Request { - if (manga.url.startsWith("http")) { - return GET(manga.url, headers) + override fun searchMangaFromElement(element: Element): SManga { + return SManga.create().apply { + setUrlWithoutDomain(element.select("div.flexbox2-content a").attr("href")) + title = element.select("div.flexbox2-title > span").first().text() + thumbnail_url = element.select("img").attr("abs:src") } - return super.mangaDetailsRequest(manga) } + override fun searchMangaNextPageSelector() = "div.pagination span.current + a" + override fun mangaDetailsParse(document: Document): SManga { - val stringBuilder = StringBuilder() - val infoElement = document.select("div.infox") - val author = document.select("span:contains(author)").text().substringAfter("Author: ").substringBefore(" (") - val manga = SManga.create() - val genres = mutableListOf() - val status = document.select("span:contains(Status)").text() - val desc = document.select("div.sinopsis p") - infoElement.select("div.gnr a").forEach { element -> - val genre = element.text() - genres.add(genre) + return SManga.create().apply { + genre = document.select("div.series-genres a").joinToString { it.text() } + description = document.select("div.series-synops").text() + thumbnail_url = document.select("div.series-thumb img").attr("abs:src") + status = parseStatus(document.select("div.block span.status").text()) + author = document.select("ul.series-infolist li b:contains(Author) + span").text() } - if (desc.size > 0) { - desc.forEach { - stringBuilder.append(it.text()) - if (it != desc.last()) - stringBuilder.append("\n\n") - } - manga.description = stringBuilder.toString() - } else - manga.description = document.select("div.sinopsis").text() - - manga.title = infoElement.select("h1").text() - manga.author = author - manga.artist = author - manga.status = parseStatus(status) - manga.genre = genres.joinToString(", ") - manga.description = stringBuilder.toString() - manga.thumbnail_url = document.select("div.bigcontent img").attr("src") - return manga } private fun parseStatus(status: String?) = when { status == null -> SManga.UNKNOWN - status.contains("Status: Ongoing") -> SManga.ONGOING - status.contains("Status: Completed") -> SManga.COMPLETED + status.contains("Ongoing") -> SManga.ONGOING + status.contains("Completed") -> SManga.COMPLETED else -> SManga.UNKNOWN } - override fun chapterListRequest(manga: SManga): Request { - if (manga.url.startsWith("http")) { - return GET(manga.url, headers) - } - return super.chapterListRequest(manga) - } - - override fun chapterListParse(response: Response): List { - val document = response.asJsoup() - val chapters = mutableListOf() - document.select(chapterListSelector()).map { chapters.add(chapterFromElement(it)) } - // Add date for latest chapter only - document.select("script.yoast-schema-graph").html() - .let { - val date = JSONObject(it).getJSONArray("@graph") - .getJSONObject(3).getString("dateModified") - chapters[0].date_upload = parseDate(date) - } - return chapters - } - private fun parseDate(date: String): Long { - return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse(date).time + return SimpleDateFormat("MMM d, yyyy", Locale("id")).parse(date).time } - override fun chapterListSelector() = "ul#chapter_list li a:contains(chapter)" + override fun chapterListSelector() = "ul.series-chapterlist div.flexch a" override fun chapterFromElement(element: Element): SChapter { - val urlElement = element.select("a:contains(chapter)") - val chapter = SChapter.create() - chapter.url = urlElement.attr("href") - chapter.name = urlElement.text() - return chapter - } - - override fun pageListRequest(chapter: SChapter): Request { - if (chapter.url.startsWith("http")) { - return GET(chapter.url, headers) + return SChapter.create().apply { + setUrlWithoutDomain(element.attr("href")) + name = element.select("span").first().ownText() + date_upload = parseDate(element.select("span.date").text()) } - return super.pageListRequest(chapter) } override fun pageListParse(document: Document): List { - val pages = mutableListOf() - document.select("div#readerarea img").forEach { - val url = it.attr("src") - pages.add(Page(pages.size, "", url)) + return document.select("div.reader-area img").mapIndexed { i, img -> + Page(i, "", img.attr("abs:src")) } - return pages } override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used") @@ -307,7 +233,7 @@ class MaidManga : ParsedHttpSource() { fun toUriPart() = vals[state].second } - private class Tag(val id: String, name: String) : Filter.TriState(name) + private class Tag(val id: String, name: String) : Filter.CheckBox(name) private class GenreList(genres: List) : Filter.Group("Genres", genres) }