Add missing chapters at MangasProject. (#2637)
Add missing chapters at MangasProject
This commit is contained in:
parent
c3984f4887
commit
57efc954a9
|
@ -5,7 +5,7 @@ ext {
|
||||||
appName = 'Tachiyomi: mangásPROJECT'
|
appName = 'Tachiyomi: mangásPROJECT'
|
||||||
pkgNameSuffix = 'pt.mangasproject'
|
pkgNameSuffix = 'pt.mangasproject'
|
||||||
extClass = '.MangasProjectFactory'
|
extClass = '.MangasProjectFactory'
|
||||||
extVersionCode = 8
|
extVersionCode = 9
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
|
import okhttp3.HttpUrl
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
@ -24,10 +25,12 @@ import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
abstract class MangasProject(override val name: String,
|
abstract class MangasProject(
|
||||||
override val baseUrl: String) : HttpSource() {
|
override val name: String,
|
||||||
|
override val baseUrl: String
|
||||||
|
) : HttpSource() {
|
||||||
|
|
||||||
override val lang = "pt"
|
override val lang = "pt-BR"
|
||||||
|
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
|
@ -51,16 +54,12 @@ abstract class MangasProject(override val name: String,
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
val result = response.asJsonObject()
|
val result = response.asJsonObject()
|
||||||
|
|
||||||
// If "most_read" have boolean false value, then it doesn't have next page.
|
|
||||||
if (!result["most_read"]!!.isJsonArray)
|
|
||||||
return MangasPage(emptyList(), false)
|
|
||||||
|
|
||||||
val popularMangas = result["most_read"].array
|
val popularMangas = result["most_read"].array
|
||||||
.map { popularMangaItemParse(it.obj) }
|
.map { popularMangaItemParse(it.obj) }
|
||||||
|
|
||||||
val page = response.request().url().queryParameter("page")!!.toInt()
|
val hasNextPage = response.request().url().queryParameter("page")!!.toInt() < 10
|
||||||
|
|
||||||
return MangasPage(popularMangas, page < 10)
|
return MangasPage(popularMangas, hasNextPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun popularMangaItemParse(obj: JsonObject) = SManga.create().apply {
|
private fun popularMangaItemParse(obj: JsonObject) = SManga.create().apply {
|
||||||
|
@ -74,17 +73,14 @@ abstract class MangasProject(override val name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||||
if (response.code() == 500)
|
|
||||||
return MangasPage(emptyList(), false)
|
|
||||||
|
|
||||||
val result = response.asJsonObject()
|
val result = response.asJsonObject()
|
||||||
|
|
||||||
val latestMangas = result["releases"].array
|
val latestMangas = result["releases"].array
|
||||||
.map { latestMangaItemParse(it.obj) }
|
.map { latestMangaItemParse(it.obj) }
|
||||||
|
|
||||||
val page = response.request().url().queryParameter("page")!!.toInt()
|
val hasNextPage = response.request().url().queryParameter("page")!!.toInt() < 5
|
||||||
|
|
||||||
return MangasPage(latestMangas, page < 5)
|
return MangasPage(latestMangas, hasNextPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun latestMangaItemParse(obj: JsonObject) = SManga.create().apply {
|
private fun latestMangaItemParse(obj: JsonObject) = SManga.create().apply {
|
||||||
|
@ -123,9 +119,8 @@ abstract class MangasProject(override val name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
val newHeaders = Headers.Builder()
|
val newHeaders = headersBuilder()
|
||||||
.add("User-Agent", USER_AGENT)
|
.removeAll("X-Requested-With")
|
||||||
.add("Referer", baseUrl)
|
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return GET(baseUrl + manga.url, newHeaders)
|
return GET(baseUrl + manga.url, newHeaders)
|
||||||
|
@ -145,30 +140,21 @@ abstract class MangasProject(override val name: String,
|
||||||
.substringAfter("Completo")
|
.substringAfter("Completo")
|
||||||
.substringBefore("+")
|
.substringBefore("+")
|
||||||
.split("&")
|
.split("&")
|
||||||
.map { it.trim() }
|
.groupBy({ it.contains("(Arte)") }, {
|
||||||
|
it.replace(" (Arte)", "")
|
||||||
val seriesAuthor = seriesAuthors
|
.trim()
|
||||||
.filter { !it.contains("(Arte)") }
|
.split(", ")
|
||||||
.joinToString("; ") {
|
|
||||||
it.split(", ")
|
|
||||||
.reversed()
|
.reversed()
|
||||||
.joinToString(" ")
|
.joinToString(" ")
|
||||||
}
|
})
|
||||||
|
|
||||||
return SManga.create().apply {
|
return SManga.create().apply {
|
||||||
thumbnail_url = seriesData.select("div.series-img > div.cover > img").attr("src")
|
thumbnail_url = seriesData.select("div.series-img > div.cover > img").attr("src")
|
||||||
description = seriesData.select("span.series-desc").text()
|
description = seriesData.select("span.series-desc").text()
|
||||||
|
|
||||||
status = parseStatus(seriesBlocked, isCompleted)
|
status = parseStatus(seriesBlocked, isCompleted)
|
||||||
author = seriesAuthor
|
author = seriesAuthors[false]?.joinToString("; ") ?: author
|
||||||
artist = seriesAuthors.filter { it.contains("(Arte)") }
|
artist = seriesAuthors[true]?.joinToString("; ") ?: author
|
||||||
.map { it.replace("\\(Arte\\)".toRegex(), "").trim() }
|
|
||||||
.joinToString("; ") {
|
|
||||||
it.split(", ")
|
|
||||||
.reversed()
|
|
||||||
.joinToString(" ")
|
|
||||||
}
|
|
||||||
.ifEmpty { seriesAuthor }
|
|
||||||
genre = seriesData.select("div#series-data ul.tags li")
|
genre = seriesData.select("div#series-data ul.tags li")
|
||||||
.joinToString { it.text() }
|
.joinToString { it.text() }
|
||||||
}
|
}
|
||||||
|
@ -215,7 +201,7 @@ abstract class MangasProject(override val name: String,
|
||||||
|
|
||||||
while (result["chapters"]!!.isJsonArray) {
|
while (result["chapters"]!!.isJsonArray) {
|
||||||
chapters += result["chapters"].array
|
chapters += result["chapters"].array
|
||||||
.map { chapterListItemParse(it.obj) }
|
.flatMap { chapterListItemParse(it.obj) }
|
||||||
.toMutableList()
|
.toMutableList()
|
||||||
|
|
||||||
val newRequest = chapterListRequestPaginated(mangaUrl, mangaId, ++page)
|
val newRequest = chapterListRequestPaginated(mangaUrl, mangaId, ++page)
|
||||||
|
@ -225,32 +211,37 @@ abstract class MangasProject(override val name: String,
|
||||||
return chapters
|
return chapters
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chapterListItemParse(obj: JsonObject): SChapter {
|
private fun chapterListItemParse(obj: JsonObject): List<SChapter> {
|
||||||
val scan = obj["releases"].obj.entrySet().first().value.obj
|
|
||||||
val chapterName = obj["chapter_name"]!!.string
|
val chapterName = obj["chapter_name"]!!.string
|
||||||
|
|
||||||
return SChapter.create().apply {
|
return obj["releases"].obj.entrySet().map {
|
||||||
|
val release = it.value.obj
|
||||||
|
|
||||||
|
SChapter.create().apply {
|
||||||
name = "Cap. ${obj["number"].string}" + (if (chapterName == "") "" else " - $chapterName")
|
name = "Cap. ${obj["number"].string}" + (if (chapterName == "") "" else " - $chapterName")
|
||||||
date_upload = parseChapterDate(obj["date_created"].string.substringBefore("T"))
|
date_upload = parseChapterDate(obj["date_created"].string.substringBefore("T"))
|
||||||
scanlator = scan["scanlators"]!!.array
|
scanlator = release["scanlators"]!!.array
|
||||||
.joinToString { it.obj["name"].string }
|
.map { scanObj -> scanObj.obj["name"].string }
|
||||||
url = scan["link"].string
|
.sorted()
|
||||||
|
.joinToString()
|
||||||
|
url = release["link"].string
|
||||||
chapter_number = obj["number"].string.toFloatOrNull() ?: 0f
|
chapter_number = obj["number"].string.toFloatOrNull() ?: 0f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun parseChapterDate(date: String?) : Long {
|
private fun parseChapterDate(date: String?) : Long {
|
||||||
return try {
|
return try {
|
||||||
SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse(date).time
|
DATE_FORMATTER.parse(date).time
|
||||||
} catch (e: ParseException) {
|
} catch (e: ParseException) {
|
||||||
0L
|
0L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter): Request {
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
val newHeaders = Headers.Builder()
|
val newHeaders = headersBuilder()
|
||||||
.add("User-Agent", USER_AGENT)
|
.set("Referer", baseUrl + chapter.url)
|
||||||
.add("Referer", baseUrl + chapter.url)
|
.removeAll("X-Requested-With")
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return GET(baseUrl + chapter.url, newHeaders)
|
return GET(baseUrl + chapter.url, newHeaders)
|
||||||
|
@ -276,38 +267,44 @@ abstract class MangasProject(override val name: String,
|
||||||
return result
|
return result
|
||||||
|
|
||||||
val document = result.asJsoup()
|
val document = result.asJsoup()
|
||||||
val readerSrc = document.select("script[src*=\"reader.\"]")
|
val token = document.select("script[src*=\"reader.\"]")
|
||||||
?.attr("src") ?: ""
|
?.let {
|
||||||
|
HttpUrl.parse(it.attr("abs:src"))!!
|
||||||
val token = TOKEN_REGEX.find(readerSrc)?.groupValues?.get(1) ?: ""
|
.queryParameter("token")
|
||||||
|
} ?: throw Exception("Não foi possível obter o token de leitura.")
|
||||||
if (token.isEmpty())
|
|
||||||
throw Exception("Não foi possível obter o token de leitura.")
|
|
||||||
|
|
||||||
return chain.proceed(pageListApiRequest(request.url().toString(), token))
|
return chain.proceed(pageListApiRequest(request.url().toString(), token))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
val result = response.asJsonObject()
|
val result = response.asJsonObject()
|
||||||
|
val chapterUrl = response.request().header("Referer")!!
|
||||||
|
|
||||||
return result["images"].array
|
return result["images"].array
|
||||||
.filter { it.string.startsWith("http") }
|
.filter { it.string.startsWith("http") }
|
||||||
.mapIndexed { i, obj -> Page(i, "", obj.string)}
|
.mapIndexed { i, obj -> Page(i, chapterUrl, obj.string)}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fetchImageUrl(page: Page): Observable<String> {
|
override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!)
|
||||||
return Observable.just(page.imageUrl!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String = ""
|
override fun imageUrlParse(response: Response): String = ""
|
||||||
|
|
||||||
|
override fun imageRequest(page: Page): Request {
|
||||||
|
val newHeaders = headersBuilder()
|
||||||
|
.set("Referer", page.url)
|
||||||
|
.removeAll("X-Requested-With")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return GET(page.imageUrl!!, newHeaders)
|
||||||
|
}
|
||||||
|
|
||||||
private fun Response.asJsonObject(): JsonObject = JSON_PARSER.parse(body()!!.string()).obj
|
private fun Response.asJsonObject(): JsonObject = JSON_PARSER.parse(body()!!.string()).obj
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36"
|
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36"
|
||||||
|
|
||||||
private val TOKEN_REGEX = "token=(.*)&id".toRegex()
|
|
||||||
|
|
||||||
private val JSON_PARSER by lazy { JsonParser() }
|
private val JSON_PARSER by lazy { JsonParser() }
|
||||||
|
|
||||||
|
private val DATE_FORMATTER by lazy { SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,4 +18,7 @@ class LeitorNet : MangasProject("Leitor.net", "https://leitor.net") {
|
||||||
override val id: Long = 2225174659569980836
|
override val id: Long = 2225174659569980836
|
||||||
}
|
}
|
||||||
|
|
||||||
class MangaLivre : MangasProject("MangaLivre", "https://mangalivre.net")
|
class MangaLivre : MangasProject("MangaLivre", "https://mangalivre.net") {
|
||||||
|
// Hardcode the id because the language wasn't specific.
|
||||||
|
override val id: Long = 4762777556012432014
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue