RisensTeam - update for their new API (#4233)
This commit is contained in:
parent
f9bf91b65b
commit
e4af261b5a
|
@ -5,7 +5,7 @@ ext {
|
||||||
extName = 'Risens Team'
|
extName = 'Risens Team'
|
||||||
pkgNameSuffix = 'ru.risensteam'
|
pkgNameSuffix = 'ru.risensteam'
|
||||||
extClass = '.RisensTeam'
|
extClass = '.RisensTeam'
|
||||||
extVersionCode = 1
|
extVersionCode = 2
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,33 @@
|
||||||
package eu.kanade.tachiyomi.extension.ru.risensteam
|
package eu.kanade.tachiyomi.extension.ru.risensteam
|
||||||
|
|
||||||
import com.github.salomonbrys.kotson.fromJson
|
import com.github.salomonbrys.kotson.fromJson
|
||||||
|
import com.github.salomonbrys.kotson.get
|
||||||
import com.github.salomonbrys.kotson.int
|
import com.github.salomonbrys.kotson.int
|
||||||
|
import com.github.salomonbrys.kotson.nullString
|
||||||
import com.github.salomonbrys.kotson.string
|
import com.github.salomonbrys.kotson.string
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonArray
|
||||||
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import java.text.ParseException
|
||||||
import okhttp3.MultipartBody
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
|
import okhttp3.MediaType
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import rx.Observable
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
|
|
||||||
class RisensTeam : ParsedHttpSource() {
|
class RisensTeam : HttpSource() {
|
||||||
override fun pageListParse(document: Document): List<Page> = throw Exception("Not Used")
|
|
||||||
|
|
||||||
override val name = "Risens Team"
|
override val name = "Risens Team"
|
||||||
|
|
||||||
|
@ -31,111 +37,106 @@ class RisensTeam : ParsedHttpSource() {
|
||||||
|
|
||||||
override val supportsLatest = false
|
override val supportsLatest = false
|
||||||
|
|
||||||
|
override val versionId: Int = 2
|
||||||
|
|
||||||
private val gson by lazy { Gson() }
|
private val gson by lazy { Gson() }
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request =
|
// Popular (source only returns manga sorted by latest)
|
||||||
GET("$baseUrl/manga/page/$page/", headers)
|
|
||||||
|
override fun popularMangaRequest(page: Int): Request {
|
||||||
|
return GET("https://risens.team/api/title/list?type=1", headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mangaFromJson(json: JsonElement): SManga {
|
||||||
|
return SManga.create().apply {
|
||||||
|
url = "${json["id"].int}/${json["furl"].string}"
|
||||||
|
title = json["title"].string
|
||||||
|
thumbnail_url = baseUrl + json["poster"].string
|
||||||
|
description = json["description"].nullString
|
||||||
|
status = try { if (json["active"].int == 1) SManga.ONGOING else SManga.UNKNOWN } catch (_: Exception) { SManga.UNKNOWN }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
|
val mangas = gson.fromJson<JsonArray>(response.body()!!.string())
|
||||||
|
.map { json -> mangaFromJson(json) }
|
||||||
|
|
||||||
|
return MangasPage(mangas, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Latest
|
||||||
|
|
||||||
|
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException("Not used")
|
||||||
|
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
|
||||||
|
|
||||||
|
// Search
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
return POST(baseUrl, headers, buildRequestBody(query, page))
|
val rbody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), """{"queryString":"$query","limit":3}""")
|
||||||
|
return POST("$baseUrl/api/title/search", headers, rbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildRequestBody(query: String, page: Int): RequestBody {
|
override fun searchMangaParse(response: Response): MangasPage = popularMangaParse(response)
|
||||||
return MultipartBody.Builder()
|
|
||||||
.setType(MultipartBody.FORM)
|
// Details
|
||||||
.addFormDataPart("do", "search")
|
|
||||||
.addFormDataPart("subaction", "search")
|
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||||
.addFormDataPart("story", query)
|
return client.newCall(apiMangaDetailsRequest(manga))
|
||||||
.addFormDataPart("catlist[]", "33")
|
.asObservableSuccess()
|
||||||
.addFormDataPart("search_start", (page - 1).toString())
|
.map { response ->
|
||||||
.build()
|
mangaDetailsParse(response).apply { initialized = true }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaSelector() = ".mb-2:not([align])"
|
private fun apiMangaDetailsRequest(manga: SManga): Request {
|
||||||
|
return GET("$baseUrl/api/title/show/${manga.url.substringBefore("/")}")
|
||||||
override fun searchMangaSelector() = ".card.h-100"
|
|
||||||
|
|
||||||
override fun popularMangaFromElement(element: Element): SManga {
|
|
||||||
val manga = SManga.create()
|
|
||||||
val coverElem = element.select(".card-img-top").first()
|
|
||||||
val imgUrl = coverElem.attr("src")
|
|
||||||
manga.thumbnail_url = baseUrl + if (imgUrl.contains("/pagespeed_static/")) coverElem.attr("data-pagespeed-lazy-src") else imgUrl
|
|
||||||
manga.setUrlWithoutDomain(element.select("b-link").first().attr("to"))
|
|
||||||
manga.title = coverElem.attr("alt").split('/').first().replace("(Манга)", "").trim()
|
|
||||||
|
|
||||||
return manga
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaFromElement(element: Element): SManga {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
val manga = SManga.create()
|
return GET("$baseUrl/title/${manga.url}")
|
||||||
val coverElem = element.select(".card-img-top").first()
|
|
||||||
manga.thumbnail_url = coverElem.attr("src")
|
|
||||||
manga.setUrlWithoutDomain(coverElem.parent().attr("href"))
|
|
||||||
manga.title = coverElem.attr("alt").split('/').first().replace("(Манга)", "").trim()
|
|
||||||
|
|
||||||
return manga
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaNextPageSelector() = "b-list-group-item.next > a"
|
override fun mangaDetailsParse(response: Response): SManga {
|
||||||
|
return mangaFromJson(gson.fromJson<JsonObject>(response.body()!!.string()))
|
||||||
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
|
||||||
|
|
||||||
override fun mangaDetailsParse(document: Document): SManga {
|
|
||||||
val manga = SManga.create()
|
|
||||||
manga.thumbnail_url = baseUrl + document.select("b-img[fluid]").first().attr("src")
|
|
||||||
manga.genre = document.select("td:containsOwn(Жанр:) + td > a").joinToString { it.ownText() }
|
|
||||||
manga.description = document.select(".news-body").text()
|
|
||||||
manga.status = when (document.select("td:containsOwn(Состояние:) + td").first().ownText()) {
|
|
||||||
"Выход продолжается" -> SManga.ONGOING
|
|
||||||
"Выход завершён", "Выход завершен" -> SManga.COMPLETED
|
|
||||||
else -> SManga.UNKNOWN
|
|
||||||
}
|
|
||||||
return manga
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Chapters
|
||||||
|
|
||||||
|
override fun chapterListRequest(manga: SManga): Request = apiMangaDetailsRequest(manga)
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val document = response.asJsoup()
|
return gson.fromJson<JsonObject>(response.body()!!.string())["entities"].asJsonArray.map { json ->
|
||||||
|
SChapter.create().apply {
|
||||||
val id = document.select("#reader").first().attr("src").split("?id=").last().toInt()
|
url = json["id"].int.toString()
|
||||||
val jsonData = client.newCall(GET(baseUrl + MANGA_API_URL + id)).execute().body()!!.string()
|
name = listOfNotNull(json["label"].nullString, json["name"].nullString).joinToString(" - ")
|
||||||
val jsonArray = gson.fromJson<List<JsonObject>>(jsonData)
|
date_upload = json["updated_at"].toDate()
|
||||||
val chapters = mutableListOf<SChapter>()
|
}
|
||||||
jsonArray.forEach {
|
|
||||||
val chapter = SChapter.create()
|
|
||||||
chapter.url = CHAPTER_API_URL + it["id"].int
|
|
||||||
chapter.name = "Глава ${it["chapter"].string}"
|
|
||||||
chapter.chapter_number = it["chapter"].string.toFloat()
|
|
||||||
chapters.add(chapter)
|
|
||||||
}
|
}
|
||||||
return chapters.reversed()
|
}
|
||||||
|
|
||||||
|
private val simpleDateFormat by lazy {
|
||||||
|
SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JsonElement.toDate(): Long {
|
||||||
|
val date = this.nullString ?: return 0
|
||||||
|
return try {
|
||||||
|
simpleDateFormat.parse(date)?.time ?: 0
|
||||||
|
} catch (e: ParseException) {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pages
|
||||||
|
|
||||||
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
|
return GET("$baseUrl/api/yandex/chapter/${chapter.url}", headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
val jsonData = response.body()!!.string()
|
return gson.fromJson<JsonArray>(response.body()!!.string())
|
||||||
val jsonArray = gson.fromJson<List<String>>(jsonData)
|
.mapIndexed { i, json -> Page(i, "", json.string) }
|
||||||
val pages = mutableListOf<Page>()
|
|
||||||
jsonArray.forEachIndexed { index, imageUrl ->
|
|
||||||
pages.add(Page(index, imageUrl = imageUrl))
|
|
||||||
}
|
|
||||||
return pages
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int): Request = throw Exception("Not Used")
|
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
||||||
|
|
||||||
override fun chapterFromElement(element: Element): SChapter = throw Exception("Not Used")
|
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = throw Exception("Not Used")
|
|
||||||
|
|
||||||
override fun chapterListSelector() = throw Exception("Not Used")
|
|
||||||
|
|
||||||
override fun latestUpdatesNextPageSelector() = throw Exception("Not Used")
|
|
||||||
|
|
||||||
override fun latestUpdatesFromElement(element: Element): SManga = throw Exception("Not Used")
|
|
||||||
|
|
||||||
override fun latestUpdatesSelector() = throw Exception("Not Used")
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val MANGA_API_URL = "/risensteam/api/manga.php?id="
|
|
||||||
const val CHAPTER_API_URL = "/risensteam/api/chapter.php?id="
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue