Add support for Guya proxy. (#6090)
This commit is contained in:
parent
b56194102f
commit
c717e4e365
@ -5,7 +5,7 @@ ext {
|
|||||||
extName = 'Guya'
|
extName = 'Guya'
|
||||||
pkgNameSuffix = "en.guya"
|
pkgNameSuffix = "en.guya"
|
||||||
extClass = '.Guya'
|
extClass = '.Guya'
|
||||||
extVersionCode = 13
|
extVersionCode = 14
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,16 +70,30 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||||||
|
|
||||||
// Overridden to use our overload
|
// Overridden to use our overload
|
||||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||||
return clientBuilder().newCall(GET("$baseUrl/api/get_all_series/", headers))
|
return when {
|
||||||
|
manga.url.startsWith(PROXY_PREFIX) -> {
|
||||||
|
clientBuilder().newCall(proxyChapterListRequest(manga))
|
||||||
|
.asObservableSuccess()
|
||||||
|
.map { response ->
|
||||||
|
proxyMangaDetailsParse(response, manga)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
clientBuilder().newCall(chapterListRequest(manga))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
.map { response ->
|
.map { response ->
|
||||||
mangaDetailsParse(response, manga)
|
mangaDetailsParse(response, manga)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Called when the series is loaded, or when opening in browser
|
// Called when the series is loaded, or when opening in browser
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
return GET("$baseUrl/reader/series/${manga.url}/", headers)
|
return when {
|
||||||
|
manga.url.startsWith(PROXY_PREFIX) -> proxySeriesRequest(manga.url, false)
|
||||||
|
else -> GET("$baseUrl/reader/series/${manga.url}/", headers)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stub
|
// Stub
|
||||||
@ -89,7 +103,26 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||||||
|
|
||||||
private fun mangaDetailsParse(response: Response, manga: SManga): SManga {
|
private fun mangaDetailsParse(response: Response, manga: SManga): SManga {
|
||||||
val res = response.body()!!.string()
|
val res = response.body()!!.string()
|
||||||
return parseMangaFromJson(JSONObject(res).getJSONObject(manga.title), manga.title)
|
return parseMangaFromJson(JSONObject(res), "", manga.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||||
|
return when {
|
||||||
|
manga.url.startsWith(PROXY_PREFIX) -> {
|
||||||
|
clientBuilder().newCall(proxyChapterListRequest(manga))
|
||||||
|
.asObservableSuccess()
|
||||||
|
.map { response ->
|
||||||
|
proxyChapterListParse(response, manga)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
clientBuilder().newCall(chapterListRequest(manga))
|
||||||
|
.asObservableSuccess()
|
||||||
|
.map { response ->
|
||||||
|
chapterListParse(response, manga)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the chapter list based on the series being viewed
|
// Gets the chapter list based on the series being viewed
|
||||||
@ -97,20 +130,35 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||||||
return GET("$baseUrl/api/series/${manga.url}/", headers)
|
return GET("$baseUrl/api/series/${manga.url}/", headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called after the request
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
|
throw Exception("Unused")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called after the request
|
||||||
|
private fun chapterListParse(response: Response, manga: SManga): List<SChapter> {
|
||||||
val res = response.body()!!.string()
|
val res = response.body()!!.string()
|
||||||
return parseChapterList(res)
|
return parseChapterList(res, manga)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overridden fetch so that we use our overloaded method instead
|
// Overridden fetch so that we use our overloaded method instead
|
||||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||||
return clientBuilder().newCall(pageListRequest(chapter))
|
return when {
|
||||||
|
chapter.url.startsWith(PROXY_PREFIX) -> {
|
||||||
|
clientBuilder().newCall(proxyPageListRequest(chapter))
|
||||||
|
.asObservableSuccess()
|
||||||
|
.map { response ->
|
||||||
|
proxyPageListParse(response, chapter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
clientBuilder().newCall(pageListRequest(chapter))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
.map { response ->
|
.map { response ->
|
||||||
pageListParse(response, chapter)
|
pageListParse(response, chapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter): Request {
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
return GET("$baseUrl/api/series/${chapter.url.split("/")[0]}/", headers)
|
return GET("$baseUrl/api/series/${chapter.url.split("/")[0]}/", headers)
|
||||||
@ -145,14 +193,23 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||||
return if (query.startsWith(SLUG_PREFIX)) {
|
return when {
|
||||||
|
query.startsWith(SLUG_PREFIX) -> {
|
||||||
val slug = query.removePrefix(SLUG_PREFIX)
|
val slug = query.removePrefix(SLUG_PREFIX)
|
||||||
client.newCall(searchMangaRequest(page, query, filters))
|
client.newCall(searchMangaRequest(page, query, filters))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
.map { response ->
|
.map { response ->
|
||||||
searchMangaParseWithSlug(response, slug)
|
searchMangaParseWithSlug(response, slug)
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
query.startsWith(PROXY_PREFIX) && query.contains("/") -> {
|
||||||
|
client.newCall(proxySearchMangaRequest(page, query, filters))
|
||||||
|
.asObservableSuccess()
|
||||||
|
.map { response ->
|
||||||
|
proxySearchMangaParse(response, query)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
client.newCall(searchMangaRequest(page, query, filters))
|
client.newCall(searchMangaRequest(page, query, filters))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
.map { response ->
|
.map { response ->
|
||||||
@ -160,6 +217,7 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
return GET("$baseUrl/api/get_all_series/", headers)
|
return GET("$baseUrl/api/get_all_series/", headers)
|
||||||
@ -255,25 +313,142 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||||||
screen.addPreference(preference)
|
screen.addPreference(preference)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------- Proxy methods ------------------
|
||||||
|
|
||||||
|
private fun proxySeriesRequest(query: String, api: Boolean = true): Request {
|
||||||
|
val res = query.removePrefix(PROXY_PREFIX)
|
||||||
|
val options = res.split("/")
|
||||||
|
val proxyType = options[0]
|
||||||
|
val slug = options[1]
|
||||||
|
return if (api) {
|
||||||
|
GET("$baseUrl/proxy/api/$proxyType/series/$slug/", headers)
|
||||||
|
} else {
|
||||||
|
GET("$baseUrl/proxy/$proxyType/$slug/", headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun proxyMangaDetailsParse(response: Response, manga: SManga): SManga {
|
||||||
|
return mangaDetailsParse(response, manga)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun proxyChapterListRequest(manga: SManga): Request {
|
||||||
|
return proxySeriesRequest(manga.url)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun proxyChapterListParse(response: Response, manga: SManga): List<SChapter> {
|
||||||
|
return chapterListParse(response, manga)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun proxyPageListRequest(chapter: SChapter): Request {
|
||||||
|
val proxyUrl = chapter.url.removePrefix(PROXY_PREFIX)
|
||||||
|
return when {
|
||||||
|
proxyUrl.startsWith(NESTED_PROXY_API_PREFIX) -> {
|
||||||
|
GET("$baseUrl$proxyUrl", headers)
|
||||||
|
}
|
||||||
|
else -> proxySeriesRequest(chapter.url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun proxyPageListParse(response: Response, chapter: SChapter): List<Page> {
|
||||||
|
val res = response.body()!!.string()
|
||||||
|
val pages = if (chapter.url.removePrefix(PROXY_PREFIX).startsWith(NESTED_PROXY_API_PREFIX)) {
|
||||||
|
JSONArray(res)
|
||||||
|
} else {
|
||||||
|
val json = JSONObject(res)
|
||||||
|
val metadata = chapter.url.split("/").takeLast(2)
|
||||||
|
val chapterNum = metadata[0]
|
||||||
|
val groupNum = metadata[1]
|
||||||
|
json.getJSONObject("chapters")
|
||||||
|
.getJSONObject(chapterNum)
|
||||||
|
.getJSONObject("groups")
|
||||||
|
.getJSONArray(groupNum)
|
||||||
|
}
|
||||||
|
val pageArray = ArrayList<Page>()
|
||||||
|
for (i in 0 until pages.length()) {
|
||||||
|
val page = if (pages.optJSONObject(i) != null) {
|
||||||
|
pages.getJSONObject(i).getString("src")
|
||||||
|
} else {
|
||||||
|
pages[i]
|
||||||
|
}
|
||||||
|
pageArray.add(Page(i + 1, "", page.toString()))
|
||||||
|
}
|
||||||
|
return pageArray
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun proxySearchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
|
return proxySeriesRequest(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun proxySearchMangaParse(response: Response, query: String): MangasPage {
|
||||||
|
return MangasPage(
|
||||||
|
arrayListOf(parseMangaFromJson(JSONObject(response.body()!!.string()), query)),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// ------------- Helpers and whatnot ---------------
|
// ------------- Helpers and whatnot ---------------
|
||||||
|
|
||||||
private fun parseChapterList(payload: String): List<SChapter> {
|
private fun parseChapterList(payload: String, manga: SManga): List<SChapter> {
|
||||||
val sortKey = "preferred_sort"
|
val sortKey = "preferred_sort"
|
||||||
val response = JSONObject(payload)
|
val response = JSONObject(payload)
|
||||||
val chapters = response.getJSONObject("chapters")
|
val chapters = response.getJSONObject("chapters")
|
||||||
|
val mapping = response.getJSONObject("groups")
|
||||||
|
|
||||||
val chapterList = ArrayList<SChapter>()
|
val chapterList = ArrayList<SChapter>()
|
||||||
|
|
||||||
val iter = chapters.keys()
|
val iter = chapters.keys()
|
||||||
|
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
val chapter = iter.next()
|
val chapterNum = iter.next()
|
||||||
val chapterObj = chapters.getJSONObject(chapter)
|
val chapterObj = chapters.getJSONObject(chapterNum)
|
||||||
var preferredSort = response.getJSONArray(sortKey)
|
when {
|
||||||
if (chapterObj.has(sortKey)) {
|
chapterObj.has(sortKey) -> {
|
||||||
preferredSort = chapterObj.getJSONArray(sortKey)
|
chapterList.add(
|
||||||
|
parseChapterFromJson(
|
||||||
|
chapterObj,
|
||||||
|
chapterNum,
|
||||||
|
chapterObj.getJSONArray(sortKey),
|
||||||
|
response.getString("slug")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
response.has(sortKey) -> {
|
||||||
|
chapterList.add(
|
||||||
|
parseChapterFromJson(
|
||||||
|
chapterObj,
|
||||||
|
chapterNum,
|
||||||
|
response.getJSONArray(sortKey),
|
||||||
|
response.getString("slug")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val groups = chapterObj.getJSONObject("groups")
|
||||||
|
val groupsIter = groups.keys()
|
||||||
|
|
||||||
|
while (groupsIter.hasNext()) {
|
||||||
|
val chapter = SChapter.create()
|
||||||
|
val groupNum = groupsIter.next()
|
||||||
|
|
||||||
|
chapter.scanlator = mapping.getString(groupNum)
|
||||||
|
if (chapterObj.has("release_date")) {
|
||||||
|
chapter.date_upload =
|
||||||
|
chapterObj.getJSONObject("release_date").getLong(groupNum) * 1000
|
||||||
|
}
|
||||||
|
chapter.name = chapterNum + " - " + chapterObj.getString("title")
|
||||||
|
chapter.chapter_number = chapterNum.toFloat()
|
||||||
|
chapter.url =
|
||||||
|
if (groups.optJSONArray(groupNum) != null) {
|
||||||
|
val mangaUrl = manga.url
|
||||||
|
"$mangaUrl/$chapterNum/$groupNum"
|
||||||
|
} else {
|
||||||
|
val url = groups.getString(groupNum)
|
||||||
|
"$PROXY_PREFIX$url"
|
||||||
|
}
|
||||||
|
chapterList.add(chapter)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
chapterList.add(parseChapterFromJson(chapterObj, chapter, preferredSort, response.getString("slug")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return chapterList.reversed()
|
return chapterList.reversed()
|
||||||
@ -288,7 +463,7 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
val series = iter.next()
|
val series = iter.next()
|
||||||
val json = payload.getJSONObject(series)
|
val json = payload.getJSONObject(series)
|
||||||
val manga = parseMangaFromJson(json, series)
|
val manga = parseMangaFromJson(json, "", series)
|
||||||
mangas.add(manga)
|
mangas.add(manga)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,14 +471,16 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Takes a json of the manga to parse
|
// Takes a json of the manga to parse
|
||||||
private fun parseMangaFromJson(json: JSONObject, title: String): SManga {
|
private fun parseMangaFromJson(json: JSONObject, slug: String, title: String = ""): SManga {
|
||||||
val manga = SManga.create()
|
val manga = SManga.create()
|
||||||
manga.title = title
|
manga.title = if (title.isNotEmpty()) title else json.getString("title")
|
||||||
manga.artist = json.getString("artist")
|
manga.artist = json.optString("artist", "Unknown")
|
||||||
manga.author = json.getString("author")
|
manga.author = json.optString("author", "Unknown")
|
||||||
manga.description = json.getString("description")
|
manga.description = json.optString("description", "None")
|
||||||
manga.url = json.getString("slug")
|
manga.url = if (slug.startsWith(PROXY_PREFIX)) slug else json.getString("slug")
|
||||||
manga.thumbnail_url = "$baseUrl/" + json.getString("cover")
|
|
||||||
|
val cover = json.optString("cover", "")
|
||||||
|
manga.thumbnail_url = if (cover.startsWith("http")) cover else "$baseUrl/$cover"
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,5 +618,7 @@ open class Guya : ConfigurableSource, HttpSource() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val SLUG_PREFIX = "slug:"
|
const val SLUG_PREFIX = "slug:"
|
||||||
|
const val PROXY_PREFIX = "proxy:"
|
||||||
|
const val NESTED_PROXY_API_PREFIX = "/proxy/api/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user