diff --git a/src/en/spyfakku/build.gradle b/src/en/spyfakku/build.gradle index 1579d0650..f574bf580 100644 --- a/src/en/spyfakku/build.gradle +++ b/src/en/spyfakku/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'SpyFakku' extClass = '.SpyFakku' - extVersionCode = 5 + extVersionCode = 6 isNsfw = true } diff --git a/src/en/spyfakku/src/eu/kanade/tachiyomi/extension/en/spyfakku/SpyFakku.kt b/src/en/spyfakku/src/eu/kanade/tachiyomi/extension/en/spyfakku/SpyFakku.kt index 89cfd3eab..5c1866282 100644 --- a/src/en/spyfakku/src/eu/kanade/tachiyomi/extension/en/spyfakku/SpyFakku.kt +++ b/src/en/spyfakku/src/eu/kanade/tachiyomi/extension/en/spyfakku/SpyFakku.kt @@ -11,14 +11,6 @@ import eu.kanade.tachiyomi.source.model.UpdateStrategy import eu.kanade.tachiyomi.source.online.HttpSource import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.contentOrNull -import kotlinx.serialization.json.decodeFromJsonElement -import kotlinx.serialization.json.int -import kotlinx.serialization.json.jsonArray -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.jsonPrimitive -import kotlinx.serialization.json.long import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Request import okhttp3.Response @@ -32,11 +24,11 @@ class SpyFakku : HttpSource() { override val name = "SpyFakku" - override val baseUrl = "https://w1.fakku.cc" + override val baseUrl = "https://fakku.cc" - private val baseImageUrl = "https://i1.fakku.cc/image" + private val baseImageUrl = "https://cdn.fakku.cc/image" - private val baseApiEnd = "/__data.json" + private val baseApiUrl = "$baseUrl/api" override val lang = "en" @@ -53,75 +45,28 @@ class SpyFakku : HttpSource() { .set("Origin", baseUrl) override fun popularMangaRequest(page: Int): Request { - return GET("$baseUrl$baseApiEnd?sort=released_at&page=$page", headers) + return GET("$baseApiUrl/library?sort=released_at&page=$page", headers) } override fun popularMangaParse(response: Response): MangasPage { val library = response.parseAs() - val data = getMangasDatas(library.data) - val mangas = data.first.map(::popularManga) + val mangas = library.archives.map(::popularManga) - val hasNextPage = data.second + val hasNextPage = library.archives.isNotEmpty() return MangasPage(mangas, hasNextPage) } - private fun getMangasDatas(data: List): Pair, Boolean> { - val indexes = json.decodeFromJsonElement(data[0].jsonObject) - val indexesIndexes = json.decodeFromJsonElement>(data[indexes.archives]) - val hasNext = (data[indexes.page].jsonPrimitive.int * 24) < data[indexes.total].jsonPrimitive.int - - return indexesIndexes.map { - val hentaiIndexes = json.decodeFromJsonElement(data[it]) - val id = data[hentaiIndexes.id].jsonPrimitive.content - val hash = data[hentaiIndexes.hash].jsonPrimitive.content - val title = data[hentaiIndexes.title].jsonPrimitive.content - - ShortHentai(id, hash, title) - } to hasNext - } - - private fun getManga(data: List): Hentai { - fun getNameIndex(index: Int?, decode: (JsonElement) -> T): List? { - return index?.let { idx -> - data[idx].jsonArray.map { el -> decode(data[el.jsonPrimitive.int]) } - } - } - - fun JsonElement.toName(): String = this.jsonPrimitive.content - - val hentaiIndexes = json.decodeFromJsonElement(data[0]) - val id = data[hentaiIndexes.id].jsonPrimitive.int - val hash = data[hentaiIndexes.hash].jsonPrimitive.content - val title = data[hentaiIndexes.title].jsonPrimitive.content - val description = data[hentaiIndexes.description].jsonPrimitive.contentOrNull - val released_at = data[hentaiIndexes.released_at].jsonPrimitive.content - val created_at = data[hentaiIndexes.created_at].jsonPrimitive.content - val pages = data[hentaiIndexes.pages].jsonPrimitive.int - val size = data[hentaiIndexes.size].jsonPrimitive.long - - val publishers = getNameIndex(hentaiIndexes.publishers) { data[json.decodeFromJsonElement(it).name].toName() } - val artists = getNameIndex(hentaiIndexes.artists) { data[json.decodeFromJsonElement(it).name].toName() } - val circles = getNameIndex(hentaiIndexes.circles) { data[json.decodeFromJsonElement(it).name].toName() } - val magazines = getNameIndex(hentaiIndexes.magazines) { data[json.decodeFromJsonElement(it).name].toName() } - val parodies = getNameIndex(hentaiIndexes.parodies) { data[json.decodeFromJsonElement(it).name].toName() } - val events = getNameIndex(hentaiIndexes.events) { data[json.decodeFromJsonElement(it).name].toName() } - val tags = getNameIndex(hentaiIndexes.tags) { data[json.decodeFromJsonElement(it).name].toName() } - val images = getNameIndex(hentaiIndexes.images) { data[json.decodeFromJsonElement(it).filename].toName() }!! - - return Hentai(id, hash, title, description, released_at, created_at, pages, size, publishers, artists, circles, magazines, parodies, events, tags, images) - } - private fun popularManga(hentai: ShortHentai) = SManga.create().apply { - setUrlWithoutDomain("$baseUrl/g/${hentai.id}" + baseApiEnd) + setUrlWithoutDomain("$baseUrl/g/${hentai.id}") title = hentai.title thumbnail_url = "$baseImageUrl/${hentai.hash}/1/c" } override fun searchMangaParse(response: Response) = popularMangaParse(response) override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - val url = "$baseUrl$baseApiEnd".toHttpUrl().newBuilder().apply { + val url = "$baseApiUrl/library".toHttpUrl().newBuilder().apply { val terms = mutableListOf(query.trim()) filters.forEach { filter -> @@ -150,13 +95,13 @@ class SpyFakku : HttpSource() { } override fun mangaDetailsRequest(manga: SManga): Request { - manga.url = Regex("^/archive/(\\d+)/.*").replace(manga.url) { "/g/${it.groupValues[1]}" } - return GET(baseUrl + manga.url, headers) + manga.url = Regex("^/archive/(\\d+)/.*").replace(manga.url) { "/g/${it.groupValues[1]}" }.replace("/__data.json", "") + return GET(baseApiUrl + manga.url, headers) } override fun pageListRequest(chapter: SChapter): Request { - chapter.url = Regex("^/archive/(\\d+)/.*").replace(chapter.url) { "/g/${it.groupValues[1]}" } - return GET(baseUrl + chapter.url, headers) + chapter.url = Regex("^/archive/(\\d+)/.*").replace(chapter.url) { "/g/${it.groupValues[1]}" }.replace("/__data.json", "") + return GET(baseApiUrl + chapter.url, headers) } override fun getFilterList() = getFilters() @@ -165,34 +110,34 @@ class SpyFakku : HttpSource() { private val releasedAtFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).apply { timeZone = TimeZone.getTimeZone("UTC") } - private val createdAtFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS", Locale.ENGLISH).apply { + private val createdAtFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).apply { timeZone = TimeZone.getTimeZone("UTC") } private fun Hentai.toSManga() = SManga.create().apply { title = this@toSManga.title url = "/g/$id" - author = (circles?.emptyToNull() ?: artists)?.joinToString() - artist = artists?.joinToString() - genre = tags?.joinToString() + author = (circles?.emptyToNull() ?: artists)?.joinToString { it.name } + artist = artists?.joinToString { it.name } + genre = tags?.joinToString { it.name } thumbnail_url = "$baseImageUrl/$hash/1/c" description = buildString { this@toSManga.description?.let { append(this@toSManga.description, "\n\n") } - circles?.emptyToNull()?.joinToString()?.let { + circles?.emptyToNull()?.joinToString { it.name }?.let { append("Circles: ", it, "\n") } - publishers?.emptyToNull()?.joinToString()?.let { + publishers?.emptyToNull()?.joinToString { it.name }?.let { append("Publishers: ", it, "\n") } - magazines?.emptyToNull()?.joinToString()?.let { + magazines?.emptyToNull()?.joinToString { it.name }?.let { append("Magazines: ", it, "\n") } - events?.emptyToNull()?.joinToString()?.let { + events?.emptyToNull()?.joinToString { it.name }?.let { append("Events: ", it, "\n\n") } - parodies?.emptyToNull()?.joinToString()?.let { + parodies?.emptyToNull()?.joinToString { it.name }?.let { append("Parodies: ", it, "\n") } append("Pages: ", pages, "\n\n") @@ -224,24 +169,24 @@ class SpyFakku : HttpSource() { } override fun mangaDetailsParse(response: Response): SManga { - return getManga(response.parseAs().data).toSManga() + return response.parseAs().toSManga() } private fun Collection.emptyToNull(): Collection? { return this.ifEmpty { null } } - override fun getMangaUrl(manga: SManga) = baseUrl + manga.url.removeSuffix(baseApiEnd) + override fun getMangaUrl(manga: SManga) = baseUrl + manga.url override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga) override fun chapterListParse(response: Response): List { - val hentai = getManga(response.parseAs().data) + val hentai = response.parseAs() return listOf( SChapter.create().apply { name = "Chapter" - url = "/g/${hentai.id}" + baseApiEnd + url = "/g/${hentai.id}" date_upload = try { releasedAtFormat.parse(hentai.released_at)!!.time } catch (e: Exception) { @@ -251,17 +196,17 @@ class SpyFakku : HttpSource() { ) } - override fun getChapterUrl(chapter: SChapter) = baseUrl + chapter.url.removeSuffix(baseApiEnd) + override fun getChapterUrl(chapter: SChapter) = baseUrl + chapter.url override fun pageListParse(response: Response): List { - val hentai = getManga(response.parseAs().data) + val hentai = response.parseAs() val images = hentai.images return images.mapIndexed { index, it -> - Page(index, imageUrl = "$baseImageUrl/${hentai.hash}/$it") + Page(index, imageUrl = "$baseImageUrl/${hentai.hash}/${it.filename}") } } private inline fun Response.parseAs(): T { - return json.decodeFromString(body.string().substringAfter("\n")) + return json.decodeFromString(body.string()) } override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException() diff --git a/src/en/spyfakku/src/eu/kanade/tachiyomi/extension/en/spyfakku/SpyFakkuDto.kt b/src/en/spyfakku/src/eu/kanade/tachiyomi/extension/en/spyfakku/SpyFakkuDto.kt index e53499f7f..731b4fecc 100644 --- a/src/en/spyfakku/src/eu/kanade/tachiyomi/extension/en/spyfakku/SpyFakkuDto.kt +++ b/src/en/spyfakku/src/eu/kanade/tachiyomi/extension/en/spyfakku/SpyFakkuDto.kt @@ -1,46 +1,10 @@ package eu.kanade.tachiyomi.extension.en.spyfakku import kotlinx.serialization.Serializable -import kotlinx.serialization.json.JsonElement @Serializable class HentaiLib( - val data: List, -) - -@Serializable -class Indexes( - val archives: Int, - val page: Int, - val limit: Int, - val total: Int, -) - -@Serializable -class ShortHentaiIndexes( - val id: Int, - val hash: Int, - val title: Int, -) - -@Serializable -class HentaiIndexes( - val id: Int, - val hash: Int, - val title: Int, - val description: Int, - val released_at: Int, - val created_at: Int, - val pages: Int, - val size: Int, - val publishers: Int?, - val artists: Int?, - val circles: Int?, - val magazines: Int?, - val parodies: Int?, - val events: Int?, - val tags: Int?, - val images: Int, + val archives: List, ) @Serializable @@ -52,30 +16,30 @@ class Hentai( val released_at: String, val created_at: String, val pages: Int, - val size: Long = 0L, - val publishers: List?, - val artists: List?, - val circles: List?, - val magazines: List?, - val parodies: List?, - val events: List?, - val tags: List?, - val images: List, + val size: Int = 0, + val publishers: List?, + val artists: List?, + val circles: List?, + val magazines: List?, + val parodies: List?, + val events: List?, + val tags: List?, + val images: List, ) @Serializable class ShortHentai( - val id: String, + val id: Int, val hash: String, val title: String, ) @Serializable -class ImageIndex( - val filename: Int, +class Image( + val filename: String, ) @Serializable -class NameIndex( - val name: Int, +class Name( + val name: String, )