Fix search, update URLs and change icon. (#1151)
| @ -5,8 +5,13 @@ ext { | ||||
|     appName = 'Tachiyomi: Union Mangás' | ||||
|     pkgNameSuffix = 'pt.unionmangas' | ||||
|     extClass = '.UnionMangas' | ||||
|     extVersionCode = 5 | ||||
|     extVersionCode = 6 | ||||
|     libVersion = '1.2' | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
|     compileOnly 'com.google.code.gson:gson:2.8.2' | ||||
|     compileOnly 'com.github.salomonbrys.kotson:kotson:2.5.0' | ||||
| } | ||||
| 
 | ||||
| apply from: "$rootDir/common.gradle" | ||||
|  | ||||
| Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 3.0 KiB | 
| Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.7 KiB | 
| Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 3.8 KiB | 
| Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 6.8 KiB | 
| Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 10 KiB | 
| Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 48 KiB | 
| @ -1,15 +1,15 @@ | ||||
| package eu.kanade.tachiyomi.extension.pt.unionmangas | ||||
| 
 | ||||
| import com.github.salomonbrys.kotson.array | ||||
| import com.github.salomonbrys.kotson.obj | ||||
| import com.github.salomonbrys.kotson.string | ||||
| import com.google.gson.JsonObject | ||||
| import com.google.gson.JsonParser | ||||
| import eu.kanade.tachiyomi.network.GET | ||||
| import eu.kanade.tachiyomi.network.POST | ||||
| import eu.kanade.tachiyomi.source.model.FilterList | ||||
| 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.model.* | ||||
| import eu.kanade.tachiyomi.source.online.ParsedHttpSource | ||||
| import okhttp3.FormBody | ||||
| import okhttp3.Headers | ||||
| import okhttp3.Request | ||||
| import okhttp3.* | ||||
| import org.jsoup.nodes.Document | ||||
| import org.jsoup.nodes.Element | ||||
| import java.text.ParseException | ||||
| @ -35,100 +35,101 @@ class UnionMangas : ParsedHttpSource() { | ||||
|                     .writeTimeout(3, TimeUnit.MINUTES) | ||||
|                     .build() | ||||
| 
 | ||||
|     private val catalogHeaders = Headers.Builder().apply { | ||||
|         add("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64)") | ||||
|         add("Host", "unionmangas.top") | ||||
|         add("Referer", baseUrl) | ||||
|     }.build() | ||||
| 
 | ||||
|     override fun popularMangaSelector(): String = "div.bloco-manga" | ||||
|     private val catalogHeaders = Headers.Builder() | ||||
|             .apply { | ||||
|                 add("User-Agent", USER_AGENT) | ||||
|                 add("Origin", baseUrl) | ||||
|                 add("Referer", "$baseUrl/ini") | ||||
|             } | ||||
|             .build() | ||||
| 
 | ||||
|     override fun popularMangaRequest(page: Int): Request { | ||||
|         val pageStr = if (page != 1) "/$page" else "" | ||||
|         return GET("$baseUrl/mangas/visualizacoes$pageStr", catalogHeaders) | ||||
|         return GET("$baseUrl/lista-mangas/visualizacoes$pageStr", catalogHeaders) | ||||
|     } | ||||
| 
 | ||||
|     override fun popularMangaFromElement(element: Element): SManga { | ||||
|         val manga = SManga.create() | ||||
|         manga.thumbnail_url = element.select("a img").first()?.attr("src") | ||||
|         element.select("a").last().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
|             manga.title = it.text().replace(LANG_REGEX.toRegex(), "") | ||||
|         } | ||||
|     override fun popularMangaSelector(): String = "div.bloco-manga" | ||||
| 
 | ||||
|         return manga | ||||
|     override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply { | ||||
|         title = removeLanguage(element.select("a").last().text()) | ||||
|         thumbnail_url = element.select("a img").first()?.attr("src") | ||||
|         setUrlWithoutDomain(element.select("a").last().attr("href")) | ||||
|     } | ||||
| 
 | ||||
|     override fun popularMangaNextPageSelector() = ".pagination li:contains(Next)" | ||||
| 
 | ||||
|     override fun latestUpdatesSelector() = "div.row[style] div.col-md-12[style]" | ||||
| 
 | ||||
|     override fun latestUpdatesRequest(page: Int): Request { | ||||
|         val form = FormBody.Builder().apply { | ||||
|             add("pagina", page.toString()) | ||||
|         } | ||||
|         val form = FormBody.Builder() | ||||
|                 .add("pagina", page.toString()) | ||||
|                 .build() | ||||
| 
 | ||||
|         return POST("$baseUrl/assets/noticias.php", headers, form.build()) | ||||
|         val newHeaders = catalogHeaders.newBuilder() | ||||
|                 .set("X-Requested-With", "XMLHttpRequest") | ||||
|                 .build() | ||||
| 
 | ||||
|         return POST("$baseUrl/assets/noticias.php", newHeaders, form) | ||||
|     } | ||||
| 
 | ||||
|     override fun latestUpdatesFromElement(element: Element): SManga { | ||||
|         // return popularMangaFromElement(element) | ||||
|         val manga = SManga.create() | ||||
|         val infoElements = element.select("a.link-titulo") | ||||
|         manga.thumbnail_url = infoElements.first()?.select("img")?.attr("src") | ||||
|         infoElements.last().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
|             manga.title = it.text().replace(LANG_REGEX.toRegex(), "") | ||||
|         } | ||||
|     override fun latestUpdatesSelector() = "div.row[style] div.col-md-12[style]" | ||||
| 
 | ||||
|         return manga | ||||
|     override fun latestUpdatesFromElement(element: Element): SManga { | ||||
|         val infoElement = element.select("a.link-titulo") | ||||
| 
 | ||||
|         return SManga.create().apply { | ||||
|             title = removeLanguage(infoElement.last().text()) | ||||
|             thumbnail_url = infoElement.first()?.select("img")?.attr("src") | ||||
|             setUrlWithoutDomain(infoElement.last().attr("href")) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun latestUpdatesNextPageSelector() = "div#linha-botao-mais" | ||||
| 
 | ||||
|     override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { | ||||
|         return GET("$baseUrl/busca/$query/$page", headers) | ||||
|         val newHeaders = catalogHeaders.newBuilder() | ||||
|                 .set("X-Requested-With", "XMLHttpRequest") | ||||
|                 .build() | ||||
| 
 | ||||
|         val url = HttpUrl.parse("$baseUrl/assets/busca.php")!!.newBuilder() | ||||
|                 .addQueryParameter("q", query) | ||||
| 
 | ||||
|         return GET(url.toString(), newHeaders) | ||||
|     } | ||||
| 
 | ||||
|     override fun searchMangaSelector() = ".bloco-manga" | ||||
|     override fun searchMangaParse(response: Response): MangasPage { | ||||
|         val result = response.asJsonObject() | ||||
| 
 | ||||
|     override fun searchMangaFromElement(element: Element): SManga { | ||||
|         val manga = SManga.create() | ||||
|         val thumbnailElement = element.select("a img.img-thumbnail").first() | ||||
|         manga.thumbnail_url = thumbnailElement.attr("src").replace("com.br", "top") | ||||
|         element.select("a").last().let { | ||||
|             manga.setUrlWithoutDomain(it.attr("href")) | ||||
|             manga.title = it.text().replace(LANG_REGEX.toRegex(), "") | ||||
|         } | ||||
|         val mangas = result["items"].array.map { searchMangaFromObject(it.obj) } | ||||
| 
 | ||||
|         return manga | ||||
|         return MangasPage(mangas, false) | ||||
|     } | ||||
| 
 | ||||
|     override fun searchMangaNextPageSelector() = "ul.pagination li:not(.active)" | ||||
|     private fun searchMangaFromObject(obj: JsonObject): SManga = SManga.create().apply { | ||||
|         title = obj["titulo"].string | ||||
|         thumbnail_url = obj["imagem"].string | ||||
|         setUrlWithoutDomain("$baseUrl/manga/${obj["url"].string}") | ||||
|     } | ||||
| 
 | ||||
|     override fun mangaDetailsRequest(manga: SManga): Request = GET(baseUrl + manga.url, catalogHeaders) | ||||
| 
 | ||||
|     override fun mangaDetailsParse(document: Document): SManga { | ||||
|         val infoElement = document.select("div.tamanho-bloco-perfil").first() | ||||
|         val elAuthor = infoElement.select("div.row:eq(2) div.col-md-8:eq(4)").first() | ||||
|         val elArtist = infoElement.select("div.row:eq(2) div.col-md-8:eq(5)").first() | ||||
|         val elGenre = infoElement.select("div.row:eq(2) div.col-md-8:eq(3)").first() | ||||
|         val elStatus =  infoElement.select("div.row:eq(2) div.col-md-8:eq(6)").first() | ||||
|         val elDescription = infoElement.select("div.row:eq(2) div.col-md-8:eq(8)").first() | ||||
|         val imgThumbnail = infoElement.select(".img-thumbnail").first() | ||||
|         val elTitle = infoElement.select("h2").first() | ||||
| 
 | ||||
|         val manga = SManga.create() | ||||
| 
 | ||||
|         val author = infoElement.select("div.row:eq(2) div.col-md-8:eq(4)").first()?.text() | ||||
|         manga.author = removeLabel(author) | ||||
| 
 | ||||
|         val artist = infoElement.select("div.row:eq(2) div.col-md-8:eq(5)").first()?.text() | ||||
|         manga.artist = removeLabel(artist) | ||||
| 
 | ||||
|         val genre = infoElement.select("div.row:eq(2) div.col-md-8:eq(3)").first()?.text() | ||||
|         manga.genre = removeLabel(genre) | ||||
| 
 | ||||
|         manga.status = infoElement.select("div.row:eq(2) div.col-md-8:eq(6)").first()?.text().orEmpty().let { parseStatus(it) } | ||||
| 
 | ||||
|         manga.description = infoElement.select("div.row:eq(2) div.col-md-8:eq(8)").first()?.text() | ||||
|         manga.thumbnail_url = infoElement.select(".img-thumbnail").first()?.attr("src") | ||||
| 
 | ||||
|         // Need to grab title again because the ellipsize in search. | ||||
|         manga.title = infoElement.select("h2").first()!!.text().replace(LANG_REGEX.toRegex(), "") | ||||
| 
 | ||||
|         return manga | ||||
|         return SManga.create().apply { | ||||
|             title = removeLanguage(elTitle!!.text()) | ||||
|             author = removeLabel(elAuthor?.text()) | ||||
|             artist = removeLabel(elArtist?.text()) | ||||
|             genre = removeLabel(elGenre?.text()) | ||||
|             status = parseStatus(elStatus?.text().orEmpty()) | ||||
|             description = elDescription?.text() | ||||
|             thumbnail_url = imgThumbnail?.attr("src") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun parseStatus(status: String) = when { | ||||
| @ -137,9 +138,7 @@ class UnionMangas : ParsedHttpSource() { | ||||
|         else -> SManga.UNKNOWN | ||||
|     } | ||||
| 
 | ||||
|     private fun removeLabel(text: String?): String { | ||||
|         return text!!.substring(text.indexOf(":") + 1) | ||||
|     } | ||||
|     override fun chapterListRequest(manga: SManga): Request = GET(baseUrl + manga.url, catalogHeaders) | ||||
| 
 | ||||
|     override fun chapterListSelector() = "div.row.lancamento-linha" | ||||
| 
 | ||||
| @ -147,23 +146,16 @@ class UnionMangas : ParsedHttpSource() { | ||||
|         val firstColumn = element.select("div.col-md-6:eq(0)") | ||||
|         val secondColumn = element.select("div.col-md-6:eq(1)") | ||||
| 
 | ||||
|         val chapter = SChapter.create() | ||||
|         chapter.setUrlWithoutDomain(firstColumn.select("a").first().attr("href")) | ||||
|         chapter.name = firstColumn.select("a").first().text() | ||||
|         chapter.date_upload = firstColumn.select("span").last()?.text()?.let { parseChapterDate(it) } ?: 0 | ||||
|         chapter.scanlator = secondColumn?.text() | ||||
| 
 | ||||
|         return chapter | ||||
|     } | ||||
| 
 | ||||
|     private fun parseChapterDate(date: String) : Long { | ||||
|         return try { | ||||
|             SimpleDateFormat("(dd/MM/yyyy)", Locale.ENGLISH).parse(date).time | ||||
|         } catch (e: ParseException) { | ||||
|             0L | ||||
|         return SChapter.create().apply { | ||||
|             name = firstColumn.select("a").first().text() | ||||
|             scanlator = secondColumn?.text() | ||||
|             date_upload = parseChapterDate(firstColumn.select("span").last()!!.text()) | ||||
|             setUrlWithoutDomain(firstColumn.select("a").first().attr("href")) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun pageListRequest(chapter: SChapter): Request = GET(baseUrl + chapter.url, catalogHeaders) | ||||
| 
 | ||||
|     override fun pageListParse(document: Document): List<Page> { | ||||
|         val pages = document.select("img.img-responsive.img-manga") | ||||
| 
 | ||||
| @ -174,7 +166,28 @@ class UnionMangas : ParsedHttpSource() { | ||||
| 
 | ||||
|     override fun imageUrlParse(document: Document) = "" | ||||
| 
 | ||||
|     override fun searchMangaSelector() = throw Exception("This method should not be called!") | ||||
| 
 | ||||
|     override fun searchMangaFromElement(element: Element): SManga = throw Exception("This method should not be called!") | ||||
| 
 | ||||
|     override fun searchMangaNextPageSelector() = throw Exception("This method should not be called!") | ||||
| 
 | ||||
|     private fun removeLanguage(text: String): String = text.replace("(Pt-Br)", "", true).trim() | ||||
| 
 | ||||
|     private fun removeLabel(text: String?): String = text!!.substringAfter(":").trim() | ||||
| 
 | ||||
|     private fun parseChapterDate(date: String) : Long { | ||||
|         return try { | ||||
|             SimpleDateFormat("(dd/MM/yyyy)", Locale.ENGLISH).parse(date).time | ||||
|         } catch (e: ParseException) { | ||||
|             0L | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun Response.asJsonObject(): JsonObject = JSON_PARSER.parse(body()!!.string()).obj | ||||
| 
 | ||||
|     companion object { | ||||
|         private const val LANG_REGEX = "( )?\\(Pt-Br\\)" | ||||
|         private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36" | ||||
|         private val JSON_PARSER by lazy { JsonParser() } | ||||
|     } | ||||
| } | ||||
|  | ||||
 Alessandro Jean
						Alessandro Jean