999Hentai: update urls and some changes (#18953)
* update urls again * small update to filters * remove unnecessary function and add short title preference short title stolen from Nhentai ext * default off * add magazine info to description * add description from site * unify popular and search parsing * auto update cdn url
This commit is contained in:
		
							parent
							
								
									ff603c36d2
								
							
						
					
					
						commit
						850965dd3f
					
				@ -6,7 +6,7 @@ ext {
 | 
			
		||||
    extName = '999Hentai'
 | 
			
		||||
    pkgNameSuffix = 'all.ninenineninehentai'
 | 
			
		||||
    extClass = '.NineNineNineHentaiFactory'
 | 
			
		||||
    extVersionCode = 4
 | 
			
		||||
    extVersionCode = 5
 | 
			
		||||
    isNsfw = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,9 @@ import android.app.Application
 | 
			
		||||
import android.content.SharedPreferences
 | 
			
		||||
import androidx.preference.ListPreference
 | 
			
		||||
import androidx.preference.PreferenceScreen
 | 
			
		||||
import androidx.preference.SwitchPreferenceCompat
 | 
			
		||||
import eu.kanade.tachiyomi.extension.all.ninenineninehentai.Url.Companion.toAbsUrl
 | 
			
		||||
import eu.kanade.tachiyomi.network.GET
 | 
			
		||||
import eu.kanade.tachiyomi.network.POST
 | 
			
		||||
import eu.kanade.tachiyomi.network.asObservableSuccess
 | 
			
		||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
 | 
			
		||||
@ -16,10 +18,11 @@ 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.online.HttpSource
 | 
			
		||||
import eu.kanade.tachiyomi.util.asJsoup
 | 
			
		||||
import kotlinx.serialization.decodeFromString
 | 
			
		||||
import kotlinx.serialization.encodeToString
 | 
			
		||||
import kotlinx.serialization.json.Json
 | 
			
		||||
import okhttp3.Headers
 | 
			
		||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
 | 
			
		||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
 | 
			
		||||
import okhttp3.Request
 | 
			
		||||
import okhttp3.RequestBody
 | 
			
		||||
@ -39,15 +42,32 @@ open class NineNineNineHentai(
 | 
			
		||||
 | 
			
		||||
    override val name = "999Hentai"
 | 
			
		||||
 | 
			
		||||
    override val baseUrl = "https://999hentai.to"
 | 
			
		||||
    override val baseUrl = "https://999hentai.net"
 | 
			
		||||
 | 
			
		||||
    private val apiUrl = "https://hapi.allanime.day/api"
 | 
			
		||||
    private val apiUrl = "https://api.999hentai.net/api"
 | 
			
		||||
 | 
			
		||||
    override val supportsLatest = true
 | 
			
		||||
 | 
			
		||||
    private val json: Json by injectLazy()
 | 
			
		||||
 | 
			
		||||
    override val client = network.cloudflareClient.newBuilder()
 | 
			
		||||
        .addInterceptor { chain ->
 | 
			
		||||
            val request = chain.request()
 | 
			
		||||
            val url = request.url
 | 
			
		||||
 | 
			
		||||
            if (url.host != "127.0.0.1") {
 | 
			
		||||
                return@addInterceptor chain.proceed(request)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val newRequest = request.newBuilder()
 | 
			
		||||
                .url(
 | 
			
		||||
                    url.newBuilder()
 | 
			
		||||
                        .host(preference.cdnUrl)
 | 
			
		||||
                        .build(),
 | 
			
		||||
                ).build()
 | 
			
		||||
 | 
			
		||||
            return@addInterceptor chain.proceed(newRequest)
 | 
			
		||||
        }
 | 
			
		||||
        .rateLimit(1)
 | 
			
		||||
        .build()
 | 
			
		||||
 | 
			
		||||
@ -55,35 +75,21 @@ open class NineNineNineHentai(
 | 
			
		||||
        Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun headersBuilder() = super.headersBuilder()
 | 
			
		||||
        .set("Referer", "$baseUrl/")
 | 
			
		||||
 | 
			
		||||
    override fun popularMangaRequest(page: Int): Request {
 | 
			
		||||
        val payload = GraphQL(
 | 
			
		||||
            PopularVariables(size, page, 1, siteLang),
 | 
			
		||||
            POPULAR_QUERY,
 | 
			
		||||
        )
 | 
			
		||||
        ).toJsonRequestBody()
 | 
			
		||||
 | 
			
		||||
        val requestBody = payload.toJsonRequestBody()
 | 
			
		||||
 | 
			
		||||
        val apiHeaders = headersBuilder().buildApiHeaders(requestBody)
 | 
			
		||||
 | 
			
		||||
        return POST(apiUrl, apiHeaders, requestBody)
 | 
			
		||||
        return POST(apiUrl, headers, payload)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun popularMangaParse(response: Response): MangasPage {
 | 
			
		||||
        val res = response.parseAs<ApiPopularResponse>()
 | 
			
		||||
        val mangas = res.data.popular.edges
 | 
			
		||||
        val dateMap = preference.dateMap
 | 
			
		||||
        val entries = mangas.map { manga ->
 | 
			
		||||
            manga.uploadDate?.let { dateMap[manga.id] = it }
 | 
			
		||||
            manga.toSManga()
 | 
			
		||||
        }
 | 
			
		||||
        preference.dateMap = dateMap
 | 
			
		||||
        val hasNextPage = mangas.size == size
 | 
			
		||||
 | 
			
		||||
        return MangasPage(entries, hasNextPage)
 | 
			
		||||
    }
 | 
			
		||||
    override fun popularMangaParse(response: Response) = browseMangaParse<PopularResponse>(response)
 | 
			
		||||
 | 
			
		||||
    override fun latestUpdatesRequest(page: Int) = searchMangaRequest(page, "", FilterList())
 | 
			
		||||
 | 
			
		||||
    override fun latestUpdatesParse(response: Response) = searchMangaParse(response)
 | 
			
		||||
 | 
			
		||||
    override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
 | 
			
		||||
@ -114,42 +120,21 @@ open class NineNineNineHentai(
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
            SEARCH_QUERY,
 | 
			
		||||
        )
 | 
			
		||||
        ).toJsonRequestBody()
 | 
			
		||||
 | 
			
		||||
        val requestBody = payload.toJsonRequestBody()
 | 
			
		||||
 | 
			
		||||
        val apiHeaders = headersBuilder().buildApiHeaders(requestBody)
 | 
			
		||||
 | 
			
		||||
        return POST(apiUrl, apiHeaders, requestBody)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun searchMangaParse(response: Response): MangasPage {
 | 
			
		||||
        val res = response.parseAs<ApiSearchResponse>()
 | 
			
		||||
        val mangas = res.data.search.edges
 | 
			
		||||
        val dateMap = preference.dateMap
 | 
			
		||||
        val entries = mangas.map { manga ->
 | 
			
		||||
            manga.uploadDate?.let { dateMap[manga.id] = it }
 | 
			
		||||
            manga.toSManga()
 | 
			
		||||
        }
 | 
			
		||||
        preference.dateMap = dateMap
 | 
			
		||||
        val hasNextPage = mangas.size == size
 | 
			
		||||
 | 
			
		||||
        return MangasPage(entries, hasNextPage)
 | 
			
		||||
        return POST(apiUrl, headers, payload)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun searchMangaParse(response: Response) = browseMangaParse<SearchResponse>(response)
 | 
			
		||||
    override fun getFilterList() = getFilters()
 | 
			
		||||
 | 
			
		||||
    private fun mangaFromIDRequest(id: String): Request {
 | 
			
		||||
        val payload = GraphQL(
 | 
			
		||||
            IdVariables(id),
 | 
			
		||||
            DETAILS_QUERY,
 | 
			
		||||
        )
 | 
			
		||||
        ).toJsonRequestBody()
 | 
			
		||||
 | 
			
		||||
        val requestBody = payload.toJsonRequestBody()
 | 
			
		||||
 | 
			
		||||
        val apiHeaders = headersBuilder().buildApiHeaders(requestBody)
 | 
			
		||||
 | 
			
		||||
        return POST(apiUrl, apiHeaders, requestBody)
 | 
			
		||||
        return POST(apiUrl, headers, payload)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun searchMangaFromIDParse(response: Response): MangasPage {
 | 
			
		||||
@ -161,7 +146,7 @@ open class NineNineNineHentai(
 | 
			
		||||
                preference.dateMap = preference.dateMap.also { dateMap ->
 | 
			
		||||
                    manga.uploadDate?.let { dateMap[manga.id] = it }
 | 
			
		||||
                }
 | 
			
		||||
                manga.toSManga()
 | 
			
		||||
                manga.toSManga(preference.shortTitle)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        return MangasPage(listOfNotNull(manga), false)
 | 
			
		||||
@ -179,7 +164,7 @@ open class NineNineNineHentai(
 | 
			
		||||
            manga.uploadDate?.let { dateMap[manga.id] = it }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return manga.toSManga()
 | 
			
		||||
        return manga.toSManga(preference.shortTitle)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getMangaUrl(manga: SManga) = "$baseUrl/hchapter/${manga.url}"
 | 
			
		||||
@ -209,13 +194,9 @@ open class NineNineNineHentai(
 | 
			
		||||
        val payload = GraphQL(
 | 
			
		||||
            IdVariables(chapter.url),
 | 
			
		||||
            PAGES_QUERY,
 | 
			
		||||
        )
 | 
			
		||||
        ).toJsonRequestBody()
 | 
			
		||||
 | 
			
		||||
        val requestBody = payload.toJsonRequestBody()
 | 
			
		||||
 | 
			
		||||
        val apiHeaders = headersBuilder().buildApiHeaders(requestBody)
 | 
			
		||||
 | 
			
		||||
        return POST(apiUrl, apiHeaders, requestBody)
 | 
			
		||||
        return POST(apiUrl, headers, payload)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun pageListParse(response: Response): List<Page> {
 | 
			
		||||
@ -224,7 +205,8 @@ open class NineNineNineHentai(
 | 
			
		||||
        val pages = res.data.chapter.pages?.firstOrNull()
 | 
			
		||||
            ?: return emptyList()
 | 
			
		||||
 | 
			
		||||
        val cdn = pages.urlPart.toAbsUrl()
 | 
			
		||||
        val cdnUrl = "https://${getUpdatedCdn(res.data.chapter.id)}/"
 | 
			
		||||
        val cdn = pages.urlPart.toAbsUrl(cdnUrl)
 | 
			
		||||
 | 
			
		||||
        val selectedImages = when (preference.getString(PREF_IMG_QUALITY_KEY, "original")) {
 | 
			
		||||
            "medium" -> pages.qualityMedium?.mapIndexed { i, it ->
 | 
			
		||||
@ -238,6 +220,21 @@ open class NineNineNineHentai(
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getUpdatedCdn(chapterId: String): String {
 | 
			
		||||
        val url = "$baseUrl/hchapter/$chapterId"
 | 
			
		||||
        val document = client.newCall(GET(url, headers))
 | 
			
		||||
            .execute().use { it.asJsoup() }
 | 
			
		||||
 | 
			
		||||
        val cdnHost = document.selectFirst("meta[property=og:image]")
 | 
			
		||||
            ?.attr("content")
 | 
			
		||||
            ?.toHttpUrlOrNull()
 | 
			
		||||
            ?.host
 | 
			
		||||
 | 
			
		||||
        return cdnHost?.also {
 | 
			
		||||
            preference.cdnUrl = it
 | 
			
		||||
        } ?: preference.cdnUrl
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private inline fun <reified T> String.parseAs(): T =
 | 
			
		||||
        json.decodeFromString(this)
 | 
			
		||||
 | 
			
		||||
@ -251,17 +248,27 @@ open class NineNineNineHentai(
 | 
			
		||||
        json.encodeToString(this)
 | 
			
		||||
            .toRequestBody(JSON_MEDIA_TYPE)
 | 
			
		||||
 | 
			
		||||
    private fun Headers.Builder.buildApiHeaders(requestBody: RequestBody) = this
 | 
			
		||||
        .add("Content-Length", requestBody.contentLength().toString())
 | 
			
		||||
        .add("Content-Type", requestBody.contentType().toString())
 | 
			
		||||
        .build()
 | 
			
		||||
 | 
			
		||||
    private fun String?.parseDate(): Long {
 | 
			
		||||
        return runCatching {
 | 
			
		||||
            dateFormat.parse(this!!.trim())!!.time
 | 
			
		||||
        }.getOrDefault(0L)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private inline fun <reified T : BrowseResponse> browseMangaParse(response: Response): MangasPage {
 | 
			
		||||
        val res = response.parseAs<Data<T>>()
 | 
			
		||||
        val mangas = res.data.chapters.edges
 | 
			
		||||
        val dateMap = preference.dateMap
 | 
			
		||||
        val useShortTitle = preference.shortTitle
 | 
			
		||||
        val entries = mangas.map { manga ->
 | 
			
		||||
            manga.uploadDate?.let { dateMap[manga.id] = it }
 | 
			
		||||
            manga.toSManga(useShortTitle)
 | 
			
		||||
        }
 | 
			
		||||
        preference.dateMap = dateMap
 | 
			
		||||
        val hasNextPage = mangas.size == size
 | 
			
		||||
 | 
			
		||||
        return MangasPage(entries, hasNextPage)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun setupPreferenceScreen(screen: PreferenceScreen) {
 | 
			
		||||
        ListPreference(screen.context).apply {
 | 
			
		||||
            key = PREF_IMG_QUALITY_KEY
 | 
			
		||||
@ -271,6 +278,14 @@ open class NineNineNineHentai(
 | 
			
		||||
            setDefaultValue("original")
 | 
			
		||||
            summary = "%s"
 | 
			
		||||
        }.also(screen::addPreference)
 | 
			
		||||
 | 
			
		||||
        SwitchPreferenceCompat(screen.context).apply {
 | 
			
		||||
            key = PREF_SHORT_TITLE
 | 
			
		||||
            title = "Display Short Titles"
 | 
			
		||||
            summaryOff = "Showing Long Titles"
 | 
			
		||||
            summaryOn = "Showing short Titles"
 | 
			
		||||
            setDefaultValue(false)
 | 
			
		||||
        }.also(screen::addPreference)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var SharedPreferences.dateMap: MutableMap<String, String>
 | 
			
		||||
@ -287,6 +302,16 @@ open class NineNineNineHentai(
 | 
			
		||||
                .commit()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private var SharedPreferences.cdnUrl: String
 | 
			
		||||
        get() = getString(PREF_CDN_URL, DEFAULT_CDN) ?: DEFAULT_CDN
 | 
			
		||||
 | 
			
		||||
        @SuppressLint("ApplySharedPref")
 | 
			
		||||
        set(cdnUrl) {
 | 
			
		||||
            edit().putString(PREF_CDN_URL, cdnUrl).commit()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    private val SharedPreferences.shortTitle get() = getBoolean(PREF_SHORT_TITLE, false)
 | 
			
		||||
 | 
			
		||||
    override fun chapterListParse(response: Response) = throw UnsupportedOperationException("Not Used")
 | 
			
		||||
    override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not Used")
 | 
			
		||||
 | 
			
		||||
@ -300,6 +325,10 @@ open class NineNineNineHentai(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const val PREF_DATE_MAP_KEY = "pref_date_map"
 | 
			
		||||
        private const val PREF_CDN_URL = "pref_cdn_url"
 | 
			
		||||
        private const val PREF_IMG_QUALITY_KEY = "pref_image_quality"
 | 
			
		||||
        private const val PREF_SHORT_TITLE = "pref_short_title"
 | 
			
		||||
 | 
			
		||||
        private const val DEFAULT_CDN = "edge.fast4speed.rsvp"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,10 +6,6 @@ import kotlinx.serialization.SerialName
 | 
			
		||||
import kotlinx.serialization.Serializable
 | 
			
		||||
import java.util.Locale
 | 
			
		||||
 | 
			
		||||
typealias ApiPopularResponse = Data<PopularResponse>
 | 
			
		||||
 | 
			
		||||
typealias ApiSearchResponse = Data<SearchResponse>
 | 
			
		||||
 | 
			
		||||
typealias ApiDetailsResponse = Data<DetailsResponse>
 | 
			
		||||
 | 
			
		||||
typealias ApiPageListResponse = Data<PageList>
 | 
			
		||||
@ -20,15 +16,19 @@ data class Data<T>(val data: T)
 | 
			
		||||
@Serializable
 | 
			
		||||
data class Edges<T>(val edges: List<T>)
 | 
			
		||||
 | 
			
		||||
interface BrowseResponse {
 | 
			
		||||
    val chapters: Edges<ChapterResponse>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
data class PopularResponse(
 | 
			
		||||
    @SerialName("queryPopularChapters") val popular: Edges<ChapterResponse>,
 | 
			
		||||
)
 | 
			
		||||
    @SerialName("queryPopularChapters") override val chapters: Edges<ChapterResponse>,
 | 
			
		||||
) : BrowseResponse
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
data class SearchResponse(
 | 
			
		||||
    @SerialName("queryChapters") val search: Edges<ChapterResponse>,
 | 
			
		||||
)
 | 
			
		||||
    @SerialName("queryChapters") override val chapters: Edges<ChapterResponse>,
 | 
			
		||||
) : BrowseResponse
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
data class DetailsResponse(
 | 
			
		||||
@ -41,24 +41,27 @@ data class ChapterResponse(
 | 
			
		||||
    val name: String,
 | 
			
		||||
    val uploadDate: String? = null,
 | 
			
		||||
    val format: String? = null,
 | 
			
		||||
    val description: String? = null,
 | 
			
		||||
    val language: String? = null,
 | 
			
		||||
    val pages: Int? = null,
 | 
			
		||||
    @SerialName("firstPics") val cover: List<Url>? = emptyList(),
 | 
			
		||||
    val tags: List<Tag>? = emptyList(),
 | 
			
		||||
) {
 | 
			
		||||
    fun toSManga() = SManga.create().apply {
 | 
			
		||||
    fun toSManga(shortTitle: Boolean) = SManga.create().apply {
 | 
			
		||||
        url = id
 | 
			
		||||
        title = name
 | 
			
		||||
        title = if (shortTitle) name.replace(shortenTitleRegex, "").trim() else name
 | 
			
		||||
        thumbnail_url = cover?.firstOrNull()?.absUrl
 | 
			
		||||
        author = this@ChapterResponse.author
 | 
			
		||||
        artist = author
 | 
			
		||||
        genre = genres
 | 
			
		||||
        description = buildString {
 | 
			
		||||
            if (!this@ChapterResponse.description.isNullOrEmpty()) append(this@ChapterResponse.description.trim(), "\n\n")
 | 
			
		||||
            if (formatParsed != null) append("Format: ${formatParsed}\n")
 | 
			
		||||
            if (languageParsed != null) append("Language: $languageParsed\n")
 | 
			
		||||
            if (group != null) append("Group: $group\n")
 | 
			
		||||
            if (characters != null) append("Character(s): $characters\n")
 | 
			
		||||
            if (parody != null) append("Parody: $parody\n")
 | 
			
		||||
            if (magazine != null) append("Magazine: $magazine\n")
 | 
			
		||||
            if (pages != null) append("Pages: $pages\n")
 | 
			
		||||
        }
 | 
			
		||||
        status = SManga.COMPLETED
 | 
			
		||||
@ -69,6 +72,7 @@ data class ChapterResponse(
 | 
			
		||||
    private val formatParsed = when (format) {
 | 
			
		||||
        "artistcg" -> "ArtistCG"
 | 
			
		||||
        "gamecg" -> "GameCG"
 | 
			
		||||
        "imageset" -> "ImageSet"
 | 
			
		||||
        else -> format?.capitalize()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -94,12 +98,17 @@ data class ChapterResponse(
 | 
			
		||||
        ?.joinToString { it.tagName.capitalize() }
 | 
			
		||||
        ?.takeUnless { it.isEmpty() }
 | 
			
		||||
 | 
			
		||||
    private val magazine = tags?.filter { it.tagType == "magazine" }
 | 
			
		||||
        ?.joinToString { it.tagName.capitalize() }
 | 
			
		||||
        ?.takeUnless { it.isEmpty() }
 | 
			
		||||
 | 
			
		||||
    private val genres = tags?.filterNot { it.tagType in filterTags }
 | 
			
		||||
        ?.joinToString { it.tagName.capitalize() }
 | 
			
		||||
        ?.takeUnless { it.isEmpty() }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private val filterTags = listOf("artist", "group", "character", "parody")
 | 
			
		||||
        private val filterTags = listOf("artist", "group", "character", "parody", "magazine")
 | 
			
		||||
        private val shortenTitleRegex = Regex("""(\[[^]]*]|[({][^)}]*[)}])""")
 | 
			
		||||
 | 
			
		||||
        private fun String.capitalize(): String {
 | 
			
		||||
            return this.trim().split(" ").joinToString(" ") { word ->
 | 
			
		||||
@ -122,15 +131,15 @@ data class Url(val url: String) {
 | 
			
		||||
    val absUrl get() = url.toAbsUrl()
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        fun String.toAbsUrl(): String {
 | 
			
		||||
        fun String.toAbsUrl(baseUrl: String = loUrl): String {
 | 
			
		||||
            return if (this.matches(urlRegex)) {
 | 
			
		||||
                this
 | 
			
		||||
            } else {
 | 
			
		||||
                cdnUrl + this
 | 
			
		||||
                baseUrl + this
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private const val cdnUrl = "https://edge.fast4speed.rsvp/"
 | 
			
		||||
        private const val loUrl = "https://127.0.0.1/"
 | 
			
		||||
        private val urlRegex = Regex("^https?://.*")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -148,6 +157,7 @@ data class PageList(
 | 
			
		||||
 | 
			
		||||
@Serializable
 | 
			
		||||
data class PageUrl(
 | 
			
		||||
    @SerialName("_id") val id: String,
 | 
			
		||||
    @SerialName("pictureUrls") val pages: List<Pages?>? = emptyList(),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,6 @@ class SortFilter : SelectFilter(
 | 
			
		||||
    arrayOf(
 | 
			
		||||
        Pair("Update", ""),
 | 
			
		||||
        Pair("Popular", "Popular"),
 | 
			
		||||
        Pair("Top", "Top"),
 | 
			
		||||
        Pair("Name Ascending", "Name_ASC"),
 | 
			
		||||
        Pair("Name Descending", "Name_DESC"),
 | 
			
		||||
    ),
 | 
			
		||||
@ -45,6 +44,7 @@ class FormatFilter : SelectFilter(
 | 
			
		||||
        Pair("Doujinshi", "doujinshi"),
 | 
			
		||||
        Pair("ArtistCG", "artistcg"),
 | 
			
		||||
        Pair("GameCG", "gamecg"),
 | 
			
		||||
        Pair("ImageSet", "imageset"),
 | 
			
		||||
    ),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,7 @@ val POPULAR_QUERY: String = buildQuery {
 | 
			
		||||
                    name
 | 
			
		||||
                    uploadDate
 | 
			
		||||
                    format
 | 
			
		||||
                    description
 | 
			
		||||
                    language
 | 
			
		||||
                    pages
 | 
			
		||||
                    firstPics
 | 
			
		||||
@ -52,6 +53,7 @@ val SEARCH_QUERY: String = buildQuery {
 | 
			
		||||
                    name
 | 
			
		||||
                    uploadDate
 | 
			
		||||
                    format
 | 
			
		||||
                    description
 | 
			
		||||
                    language
 | 
			
		||||
                    pages
 | 
			
		||||
                    firstPics
 | 
			
		||||
@ -74,6 +76,7 @@ val DETAILS_QUERY: String = buildQuery {
 | 
			
		||||
                name
 | 
			
		||||
                uploadDate
 | 
			
		||||
                format
 | 
			
		||||
                description
 | 
			
		||||
                language
 | 
			
		||||
                pages
 | 
			
		||||
                firstPics
 | 
			
		||||
@ -91,6 +94,7 @@ val PAGES_QUERY: String = buildQuery {
 | 
			
		||||
            queryChapter(
 | 
			
		||||
                chapterId: %id
 | 
			
		||||
            ) {
 | 
			
		||||
                _id
 | 
			
		||||
                pictureUrls {
 | 
			
		||||
				    picCdn
 | 
			
		||||
				    pics
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user