فهرست منبع

update Mangasee due to webpage changes (#521)

Gilfar 8 سال پیش
والد
کامیت
36d4e1f7ef
1فایلهای تغییر یافته به همراه116 افزوده شده و 63 حذف شده
  1. 116 63
      app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangasee.kt

+ 116 - 63
app/src/main/java/eu/kanade/tachiyomi/data/source/online/english/Mangasee.kt

@@ -1,17 +1,21 @@
 package eu.kanade.tachiyomi.data.source.online.english
 
-import android.content.Context
 import eu.kanade.tachiyomi.data.database.models.Chapter
 import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.data.network.POST
 import eu.kanade.tachiyomi.data.source.EN
 import eu.kanade.tachiyomi.data.source.Language
+import eu.kanade.tachiyomi.data.source.model.MangasPage
 import eu.kanade.tachiyomi.data.source.model.Page
 import eu.kanade.tachiyomi.data.source.online.ParsedOnlineSource
 import eu.kanade.tachiyomi.util.asJsoup
+import okhttp3.FormBody
+import okhttp3.HttpUrl
+import okhttp3.Request
 import okhttp3.Response
 import org.jsoup.nodes.Document
 import org.jsoup.nodes.Element
-import java.util.*
+import java.text.SimpleDateFormat
 import java.util.regex.Pattern
 
 class Mangasee(override val id: Int) : ParsedOnlineSource() {
@@ -22,104 +26,128 @@ class Mangasee(override val id: Int) : ParsedOnlineSource() {
 
     override val lang: Language get() = EN
 
-    override val supportsLatest = false
+    override val supportsLatest = true
 
-    private val datePattern = Pattern.compile("(\\d+)\\s+(.*?)s? (from now|ago).*")
+    private val recentUpdatesPattern = Pattern.compile("(.*?)\\s(\\d+)")
 
-    private val dateFields = HashMap<String, Int>().apply {
-        put("second", Calendar.SECOND)
-        put("minute", Calendar.MINUTE)
-        put("hour", Calendar.HOUR)
-        put("day", Calendar.DATE)
-        put("week", Calendar.WEEK_OF_YEAR)
-        put("month", Calendar.MONTH)
-        put("year", Calendar.YEAR)
-    }
+    override fun popularMangaInitialUrl() = "$baseUrl/search/request.php?sortBy=popularity&sortOrder=descending"
+
+    override fun popularMangaSelector() = "div.requested > div.row"
 
-    private val dateRelationFields = HashMap<String, Int>().apply {
-        put("from now", 1)
-        put("ago", -1)
+    override fun popularMangaRequest(page: MangasPage): Request {
+        if (page.page == 1) {
+            page.url = popularMangaInitialUrl()
+        }
+        val (body, requestUrl) = convertQueryToPost(page)
+        return POST(requestUrl, headers, body.build())
     }
 
-    override fun popularMangaInitialUrl() = "$baseUrl/search_result.php?Action=Yes&order=popularity&numResultPerPage=20&sort=desc"
+    override fun popularMangaParse(response: Response, page: MangasPage) {
+        val document = response.asJsoup()
+        for (element in document.select(popularMangaSelector())) {
+            Manga.create(id).apply {
+                popularMangaFromElement(element, this)
+                page.mangas.add(this)
+            }
+        }
 
-    override fun popularMangaSelector() = "div.well > table > tbody > tr"
+        page.nextPageUrl = page.url
+    }
 
     override fun popularMangaFromElement(element: Element, manga: Manga) {
-        element.select("td > h2 > a").first().let {
-            manga.setUrlWithoutDomain("/${it.attr("href")}")
+        element.select("a.resultLink").first().let {
+            manga.setUrlWithoutDomain(it.attr("href"))
             manga.title = it.text()
         }
     }
 
-    override fun popularMangaNextPageSelector() = "ul.pagination > li > a:contains(Next)"
+    // Not used, overrides parent.
+    override fun popularMangaNextPageSelector() = ""
 
     override fun searchMangaInitialUrl(query: String, filters: List<Filter>) =
-            "$baseUrl/advanced-search/result.php?sortBy=alphabet&direction=ASC&textOnly=no&resPerPage=20&page=1&seriesName=$query&${filters.map { it.id + "=Yes" }.joinToString("&")}"
+            "$baseUrl/search/request.php?sortBy=popularity&sortOrder=descending&keyword=$query&genre=${filters.map { it.id }.joinToString(",")}"
+
+    override fun searchMangaSelector() = "div.searchResults > div.requested > div.row"
 
-    override fun searchMangaSelector() = "div.row > div > div > div > h1"
+    override fun searchMangaRequest(page: MangasPage, query: String, filters: List<Filter>): Request {
+        if (page.page == 1) {
+            page.url = searchMangaInitialUrl(query, filters)
+        }
+        val (body, requestUrl) = convertQueryToPost(page)
+        return POST(requestUrl, headers, body.build())
+    }
+
+    private fun convertQueryToPost(page: MangasPage): Pair<FormBody.Builder, String> {
+        val url = HttpUrl.parse(page.url)
+        val body = FormBody.Builder().add("page", page.page.toString())
+        for (i in 0..url.querySize() - 1) {
+            body.add(url.queryParameterName(i), url.queryParameterValue(i))
+        }
+        val requestUrl = url.scheme() + "://" + url.host() + url.encodedPath()
+        return Pair(body, requestUrl)
+    }
+
+    override fun searchMangaParse(response: Response, page: MangasPage, query: String, filters: List<Filter>) {
+        val document = response.asJsoup()
+        for (element in document.select(popularMangaSelector())) {
+            Manga.create(id).apply {
+                popularMangaFromElement(element, this)
+                page.mangas.add(this)
+            }
+        }
+
+        page.nextPageUrl = page.url
+    }
 
     override fun searchMangaFromElement(element: Element, manga: Manga) {
-        element.select("a").first().let {
-            manga.setUrlWithoutDomain("/${it.attr("href")}")
+        element.select("a.resultLink").first().let {
+            manga.setUrlWithoutDomain(it.attr("href"))
             manga.title = it.text()
         }
     }
 
-    override fun searchMangaNextPageSelector() = "ul.pagination > li > a:contains(Next)"
+    // Not used, overrides parent.
+    override fun searchMangaNextPageSelector() = ""
 
     override fun mangaDetailsParse(document: Document, manga: Manga) {
         val detailElement = document.select("div.well > div.row").first()
 
-        manga.author = detailElement.select("a[href^=../search_result.php?author_name=]").first()?.text()
-        manga.genre = detailElement.select("div > div.row > div:has(b:contains(Genre:)) > a").map { it.text() }.joinToString()
+        manga.author = detailElement.select("a[href^=/search/?author=]").first()?.text()
+        manga.genre = detailElement.select("span.details > div.row > div:has(b:contains(Genre(s))) > a").map { it.text() }.joinToString()
         manga.description = detailElement.select("strong:contains(Description:) + div").first()?.text()
-        manga.status = detailElement.select("div > div.row > div:has(b:contains(Scanlation Status:))").first()?.text().orEmpty().let { parseStatus(it) }
+        manga.status = detailElement.select("a[href^=/search/?status=]").first()?.text().orEmpty().let { parseStatus(it) }
         manga.thumbnail_url = detailElement.select("div > img").first()?.absUrl("src")
     }
 
     private fun parseStatus(status: String) = when {
-        status.contains("Ongoing") -> Manga.ONGOING
-        status.contains("Completed") -> Manga.COMPLETED
+        status.contains("Ongoing (Scan)") -> Manga.ONGOING
+        status.contains("Complete (Scan)") -> Manga.COMPLETED
         else -> Manga.UNKNOWN
     }
 
-    override fun chapterListSelector() = "div.row > div > div.row > div > div.row:has(a.chapter_link[alt])"
+    override fun chapterListSelector() = "div.chapter-list > a"
 
     override fun chapterFromElement(element: Element, chapter: Chapter) {
         val urlElement = element.select("a").first()
 
-        chapter.setUrlWithoutDomain("/${urlElement.attr("href")}")
-        chapter.name = urlElement.text()
-        chapter.date_upload = element.select("span").first()?.text()?.let { parseChapterDate(it) } ?: 0
+        chapter.setUrlWithoutDomain(urlElement.attr("href"))
+        chapter.name = element.select("span.chapterLabel").first().text()?.let { it } ?: ""
+        chapter.date_upload = element.select("time").first()?.attr("datetime")?.let { parseChapterDate(it) } ?: 0
     }
 
     private fun parseChapterDate(dateAsString: String): Long {
-        val m = datePattern.matcher(dateAsString)
-
-        if (m.matches()) {
-            val amount = Integer.parseInt(m.group(1))
-            val unit = m.group(2)
-            val relation = m.group(3)
-
-            return Calendar.getInstance().apply {
-                add(dateFields[unit]!!, dateRelationFields[relation]!! * amount)
-            }.time.time
-        } else {
-            return 0
-        }
+        return SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse(dateAsString).time
     }
 
     override fun pageListParse(response: Response, pages: MutableList<Page>) {
         val document = response.asJsoup()
         val url = response.request().url().toString().substringBeforeLast('/')
 
-        val series = document.select("input[name=series]").first().attr("value")
-        val chapter = document.select("input[name=chapter]").first().attr("value")
-        val index = document.select("input[name=index]").first().attr("value")
+        val series = document.select("input.IndexName").first().attr("value")
+        val chapter = document.select("span.CurChapter").first().text()
 
-        document.select("select[name=page] > option").forEach {
-            pages.add(Page(pages.size, "$url/?series=$series&chapter=$chapter&index=$index&page=${pages.size + 1}"))
+        document.select("div.ContainerNav").first().select("select.PageSelect > option").forEach {
+            pages.add(Page(pages.size, "$url/$series-chapter-$chapter-page-${pages.size + 1}.html"))
         }
         pages.getOrNull(0)?.imageUrl = imageUrlParse(document)
     }
@@ -128,7 +156,7 @@ class Mangasee(override val id: Int) : ParsedOnlineSource() {
     override fun pageListParse(document: Document, pages: MutableList<Page>) {
     }
 
-    override fun imageUrlParse(document: Document) = document.select("div > a > img").attr("src")
+    override fun imageUrlParse(document: Document): String = document.select("img.CurImage").attr("src")
 
     // [...document.querySelectorAll("label.triStateCheckBox input")].map(el => `Filter("${el.getAttribute('name')}", "${el.nextSibling.textContent.trim()}")`).join(',\n')
     // http://mangasee.co/advanced-search/
@@ -171,20 +199,45 @@ class Mangasee(override val id: Int) : ParsedOnlineSource() {
             Filter("Yuri", "Yuri")
     )
 
-    override fun latestUpdatesInitialUrl(): String {
-        throw UnsupportedOperationException("not implemented")
-    }
+    override fun latestUpdatesInitialUrl(): String = "http://mangaseeonline.net/home/latest.request.php"
+
+    // Not used, overrides parent.
+    override fun latestUpdatesNextPageSelector(): String = ""
+
+    override fun latestUpdatesSelector(): String = "a.latestSeries"
 
-    override fun latestUpdatesNextPageSelector(): String {
-        throw UnsupportedOperationException("not implemented")
+    override fun latestUpdatesRequest(page: MangasPage): Request {
+        if (page.page == 1) {
+            page.url = latestUpdatesInitialUrl()
+        }
+        val (body, requestUrl) = convertQueryToPost(page)
+        return POST(requestUrl, headers, body.build())
     }
 
-    override fun latestUpdatesFromElement(element: Element, manga: Manga) {
-        throw UnsupportedOperationException("not implemented")
+    override fun latestUpdatesParse(response: Response, page: MangasPage) {
+        val document = response.asJsoup()
+        for (element in document.select(latestUpdatesSelector())) {
+            Manga.create(id).apply {
+                latestUpdatesFromElement(element, this)
+                page.mangas.add(this)
+            }
+        }
+
+        page.nextPageUrl = page.url
     }
 
-    override fun latestUpdatesSelector(): String {
-        throw UnsupportedOperationException("not implemented")
+    override fun latestUpdatesFromElement(element: Element, manga: Manga) {
+        element.select("a.latestSeries").first().let {
+            val chapterUrl = it.attr("href")
+            val indexOfMangaUrl = chapterUrl.indexOf("-chapter-")
+            val indexOfLastPath = chapterUrl.lastIndexOf("/")
+            val mangaUrl = chapterUrl.substring(indexOfLastPath, indexOfMangaUrl)
+            val defaultText = it.select("p.clamp2").text();
+            val m = recentUpdatesPattern.matcher(defaultText)
+            val title = if (m.matches()) m.group(1) else defaultText
+            manga.setUrlWithoutDomain("/manga" + mangaUrl)
+            manga.title = title
+        }
     }
 
 }