Add support for Guya proxy. (#6090)
This commit is contained in:
		
							parent
							
								
									b56194102f
								
							
						
					
					
						commit
						c717e4e365
					
				@ -5,7 +5,7 @@ ext {
 | 
			
		||||
    extName = 'Guya'
 | 
			
		||||
    pkgNameSuffix = "en.guya"
 | 
			
		||||
    extClass = '.Guya'
 | 
			
		||||
    extVersionCode = 13
 | 
			
		||||
    extVersionCode = 14
 | 
			
		||||
    libVersion = '1.2'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -70,16 +70,30 @@ open class Guya : ConfigurableSource, HttpSource() {
 | 
			
		||||
 | 
			
		||||
    // Overridden to use our overload
 | 
			
		||||
    override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
 | 
			
		||||
        return clientBuilder().newCall(GET("$baseUrl/api/get_all_series/", headers))
 | 
			
		||||
            .asObservableSuccess()
 | 
			
		||||
            .map { response ->
 | 
			
		||||
                mangaDetailsParse(response, manga)
 | 
			
		||||
        return when {
 | 
			
		||||
            manga.url.startsWith(PROXY_PREFIX) -> {
 | 
			
		||||
                clientBuilder().newCall(proxyChapterListRequest(manga))
 | 
			
		||||
                    .asObservableSuccess()
 | 
			
		||||
                    .map { response ->
 | 
			
		||||
                        proxyMangaDetailsParse(response, manga)
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
            else -> {
 | 
			
		||||
                clientBuilder().newCall(chapterListRequest(manga))
 | 
			
		||||
                    .asObservableSuccess()
 | 
			
		||||
                    .map { response ->
 | 
			
		||||
                        mangaDetailsParse(response, manga)
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Called when the series is loaded, or when opening in browser
 | 
			
		||||
    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
 | 
			
		||||
@ -89,7 +103,26 @@ open class Guya : ConfigurableSource, HttpSource() {
 | 
			
		||||
 | 
			
		||||
    private fun mangaDetailsParse(response: Response, manga: SManga): SManga {
 | 
			
		||||
        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
 | 
			
		||||
@ -97,19 +130,34 @@ open class Guya : ConfigurableSource, HttpSource() {
 | 
			
		||||
        return GET("$baseUrl/api/series/${manga.url}/", headers)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Called after the request
 | 
			
		||||
    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()
 | 
			
		||||
        return parseChapterList(res)
 | 
			
		||||
        return parseChapterList(res, manga)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Overridden fetch so that we use our overloaded method instead
 | 
			
		||||
    override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
 | 
			
		||||
        return clientBuilder().newCall(pageListRequest(chapter))
 | 
			
		||||
            .asObservableSuccess()
 | 
			
		||||
            .map { response ->
 | 
			
		||||
                pageListParse(response, chapter)
 | 
			
		||||
        return when {
 | 
			
		||||
            chapter.url.startsWith(PROXY_PREFIX) -> {
 | 
			
		||||
                clientBuilder().newCall(proxyPageListRequest(chapter))
 | 
			
		||||
                    .asObservableSuccess()
 | 
			
		||||
                    .map { response ->
 | 
			
		||||
                        proxyPageListParse(response, chapter)
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
            else -> {
 | 
			
		||||
                clientBuilder().newCall(pageListRequest(chapter))
 | 
			
		||||
                    .asObservableSuccess()
 | 
			
		||||
                    .map { response ->
 | 
			
		||||
                        pageListParse(response, chapter)
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun pageListRequest(chapter: SChapter): Request {
 | 
			
		||||
@ -145,19 +193,29 @@ open class Guya : ConfigurableSource, HttpSource() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
 | 
			
		||||
        return if (query.startsWith(SLUG_PREFIX)) {
 | 
			
		||||
            val slug = query.removePrefix(SLUG_PREFIX)
 | 
			
		||||
            client.newCall(searchMangaRequest(page, query, filters))
 | 
			
		||||
                .asObservableSuccess()
 | 
			
		||||
                .map { response ->
 | 
			
		||||
                    searchMangaParseWithSlug(response, slug)
 | 
			
		||||
                }
 | 
			
		||||
        } else {
 | 
			
		||||
            client.newCall(searchMangaRequest(page, query, filters))
 | 
			
		||||
                .asObservableSuccess()
 | 
			
		||||
                .map { response ->
 | 
			
		||||
                    searchMangaParse(response, query)
 | 
			
		||||
                }
 | 
			
		||||
        return when {
 | 
			
		||||
            query.startsWith(SLUG_PREFIX) -> {
 | 
			
		||||
                val slug = query.removePrefix(SLUG_PREFIX)
 | 
			
		||||
                client.newCall(searchMangaRequest(page, query, filters))
 | 
			
		||||
                    .asObservableSuccess()
 | 
			
		||||
                    .map { response ->
 | 
			
		||||
                        searchMangaParseWithSlug(response, slug)
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
            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))
 | 
			
		||||
                    .asObservableSuccess()
 | 
			
		||||
                    .map { response ->
 | 
			
		||||
                        searchMangaParse(response, query)
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -255,25 +313,142 @@ open class Guya : ConfigurableSource, HttpSource() {
 | 
			
		||||
        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 ---------------
 | 
			
		||||
 | 
			
		||||
    private fun parseChapterList(payload: String): List<SChapter> {
 | 
			
		||||
    private fun parseChapterList(payload: String, manga: SManga): List<SChapter> {
 | 
			
		||||
        val sortKey = "preferred_sort"
 | 
			
		||||
        val response = JSONObject(payload)
 | 
			
		||||
        val chapters = response.getJSONObject("chapters")
 | 
			
		||||
        val mapping = response.getJSONObject("groups")
 | 
			
		||||
 | 
			
		||||
        val chapterList = ArrayList<SChapter>()
 | 
			
		||||
 | 
			
		||||
        val iter = chapters.keys()
 | 
			
		||||
 | 
			
		||||
        while (iter.hasNext()) {
 | 
			
		||||
            val chapter = iter.next()
 | 
			
		||||
            val chapterObj = chapters.getJSONObject(chapter)
 | 
			
		||||
            var preferredSort = response.getJSONArray(sortKey)
 | 
			
		||||
            if (chapterObj.has(sortKey)) {
 | 
			
		||||
                preferredSort = chapterObj.getJSONArray(sortKey)
 | 
			
		||||
            val chapterNum = iter.next()
 | 
			
		||||
            val chapterObj = chapters.getJSONObject(chapterNum)
 | 
			
		||||
            when {
 | 
			
		||||
                chapterObj.has(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()
 | 
			
		||||
@ -288,7 +463,7 @@ open class Guya : ConfigurableSource, HttpSource() {
 | 
			
		||||
        while (iter.hasNext()) {
 | 
			
		||||
            val series = iter.next()
 | 
			
		||||
            val json = payload.getJSONObject(series)
 | 
			
		||||
            val manga = parseMangaFromJson(json, series)
 | 
			
		||||
            val manga = parseMangaFromJson(json, "", series)
 | 
			
		||||
            mangas.add(manga)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -296,14 +471,16 @@ open class Guya : ConfigurableSource, HttpSource() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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()
 | 
			
		||||
        manga.title = title
 | 
			
		||||
        manga.artist = json.getString("artist")
 | 
			
		||||
        manga.author = json.getString("author")
 | 
			
		||||
        manga.description = json.getString("description")
 | 
			
		||||
        manga.url = json.getString("slug")
 | 
			
		||||
        manga.thumbnail_url = "$baseUrl/" + json.getString("cover")
 | 
			
		||||
        manga.title = if (title.isNotEmpty()) title else json.getString("title")
 | 
			
		||||
        manga.artist = json.optString("artist", "Unknown")
 | 
			
		||||
        manga.author = json.optString("author", "Unknown")
 | 
			
		||||
        manga.description = json.optString("description", "None")
 | 
			
		||||
        manga.url = if (slug.startsWith(PROXY_PREFIX)) slug else json.getString("slug")
 | 
			
		||||
 | 
			
		||||
        val cover = json.optString("cover", "")
 | 
			
		||||
        manga.thumbnail_url = if (cover.startsWith("http")) cover else "$baseUrl/$cover"
 | 
			
		||||
        return manga
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -441,5 +618,7 @@ open class Guya : ConfigurableSource, HttpSource() {
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        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