diff --git a/src/all/bilibili/build.gradle b/src/all/bilibili/build.gradle index eebffc8e8..e63be226d 100644 --- a/src/all/bilibili/build.gradle +++ b/src/all/bilibili/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'BILIBILI' pkgNameSuffix = 'all.bilibili' extClass = '.BilibiliFactory' - extVersionCode = 3 + extVersionCode = 4 } dependencies { diff --git a/src/all/bilibili/src/eu/kanade/tachiyomi/extension/all/bilibili/Bilibili.kt b/src/all/bilibili/src/eu/kanade/tachiyomi/extension/all/bilibili/Bilibili.kt index f09906f33..f5a9519df 100644 --- a/src/all/bilibili/src/eu/kanade/tachiyomi/extension/all/bilibili/Bilibili.kt +++ b/src/all/bilibili/src/eu/kanade/tachiyomi/extension/all/bilibili/Bilibili.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.extension.all.bilibili import android.app.Application import android.content.SharedPreferences -import android.util.Log import androidx.preference.ListPreference import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.lib.ratelimit.SpecificHostRateLimitInterceptor @@ -21,6 +20,7 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.json.buildJsonObject import kotlinx.serialization.json.put import okhttp3.Headers +import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaType @@ -39,7 +39,7 @@ import java.util.Locale abstract class Bilibili( override val name: String, final override val baseUrl: String, - override val lang: String + final override val lang: String ) : HttpSource(), ConfigurableSource { override val supportsLatest = true @@ -56,31 +56,70 @@ abstract class Bilibili( .add("Origin", baseUrl) .add("Referer", "$baseUrl/") - protected open val statusLabel: String = "Status" + private val apiLang: String = when (lang) { + "zh-Hans" -> "cn" + else -> lang + } - protected open val sortLabel: String = "Sort by" + protected open val statusLabel: String = when (lang) { + "zh", "zh-Hans" -> "进度" + else -> "Status" + } - protected open val genreLabel: String = "Genre" + protected open val sortLabel: String = when (lang) { + "zh", "zh-Hans" -> "排序" + "id" -> "Urutkan dengan" + else -> "Sort by" + } - protected open val areaLabel: String = "Area" + protected open val genreLabel: String = when (lang) { + "zh", "zh-Hans" -> "题材" + else -> "Genre" + } - protected open val priceLabel: String = "Price" + protected open val areaLabel: String = when (lang) { + "zh", "zh-Hans" -> "地区" + else -> "Area" + } - protected open val episodePrefix: String = "Ep. " + protected open val priceLabel: String = when (lang) { + "zh", "zh-Hans" -> "收费" + "id" -> "Harga" + else -> "Price" + } + + protected open val episodePrefix: String = when (lang) { + "zh", "zh-Hans" -> "" + else -> "Ep. " + } protected open val defaultPopularSort: Int = 1 protected open val defaultLatestSort: Int = 2 - protected open val hasPaidChaptersWarning: String = "This series has paid chapters that " + - "were filtered out from the chapter list. Use the BILIBILI website or the official app " + - "to read them for now." + protected open val hasPaidChaptersWarning: String = when (lang) { + "zh", "zh-Hans" -> "此漫画的付费章节已从章节列表中过滤,暂时请用网页端或官方app阅读。" + else -> + "This series has paid chapters that were filtered out from the chapter list. " + + "Use the BILIBILI website or the official app to read them for now." + } - protected open val imageQualityPrefTitle: String = "Chapter image quality" + protected open val imageQualityPrefTitle: String = when (lang) { + "zh", "zh-Hans" -> "章节图片质量" + "id" -> "Kualitas gambar" + else -> "Chapter image quality" + } - protected open val imageQualityPrefEntries: Array = arrayOf("Raw", "HD", "SD") + protected open val imageQualityPrefEntries: Array = when (lang) { + "zh", "zh-Hans" -> arrayOf("原图", "高", "低") + else -> arrayOf("Raw", "HD", "SD") + } - protected open val imageFormatPrefTitle: String = "Chapter image format" + protected open val imageFormatPrefTitle: String = when (lang) { + "zh", "zh-Hans" -> "章节图片格式" + "id" -> "Format gambar" + else -> "Chapter image format" + } private val preferences: SharedPreferences by lazy { Injekt.get().getSharedPreferences("source_$id", 0x0000) @@ -112,11 +151,13 @@ abstract class Bilibili( .add("Content-Type", requestBody.contentType().toString()) .build() - return POST( - "$baseUrl/$BASE_API_ENDPOINT/ClassPage?device=pc&platform=web", - headers = newHeaders, - body = requestBody - ) + val apiUrl = "$baseUrl/$BASE_API_ENDPOINT/ClassPage".toHttpUrl().newBuilder() + .addQueryParameter("device", "pc") + .addQueryParameter("platform", "web") + .addLanguageParameters() + .toString() + + return POST(apiUrl, newHeaders, requestBody) } override fun popularMangaParse(response: Response): MangasPage { @@ -156,11 +197,13 @@ abstract class Bilibili( .add("Content-Type", requestBody.contentType().toString()) .build() - return POST( - "$baseUrl/$BASE_API_ENDPOINT/ClassPage?device=pc&platform=web", - headers = newHeaders, - body = requestBody - ) + val apiUrl = "$baseUrl/$BASE_API_ENDPOINT/ClassPage".toHttpUrl().newBuilder() + .addQueryParameter("device", "pc") + .addQueryParameter("platform", "web") + .addLanguageParameters() + .toString() + + return POST(apiUrl, newHeaders, requestBody) } override fun latestUpdatesParse(response: Response): MangasPage { @@ -223,25 +266,26 @@ abstract class Bilibili( } } val requestBody = jsonPayload.toString().toRequestBody(JSON_MEDIA_TYPE) - Log.d("Bilibili", jsonPayload.toString()) val refererUrl = if (query.isBlank()) "$baseUrl/genre" else "$baseUrl/search".toHttpUrl().newBuilder() .addQueryParameter("keyword", query) .toString() + val newHeaders = headersBuilder() .add("Content-Length", requestBody.contentLength().toString()) .add("Content-Type", requestBody.contentType().toString()) .set("Referer", refererUrl) .build() - val apiPath = if (query.isBlank()) "ClassPage" else "Search" + val apiUrl = "$baseUrl/$BASE_API_ENDPOINT/".toHttpUrl().newBuilder() + .addPathSegment(if (query.isBlank()) "ClassPage" else "Search") + .addQueryParameter("device", "pc") + .addQueryParameter("platform", "web") + .addLanguageParameters() + .toString() - return POST( - "$baseUrl/$BASE_API_ENDPOINT/$apiPath?device=pc&platform=web", - headers = newHeaders, - body = requestBody - ) + return POST(apiUrl, newHeaders, requestBody) } override fun searchMangaParse(response: Response): MangasPage { @@ -304,11 +348,13 @@ abstract class Bilibili( .set("Referer", baseUrl + mangaUrl) .build() - return POST( - "$baseUrl/$BASE_API_ENDPOINT/ComicDetail?device=pc&platform=web", - headers = newHeaders, - body = requestBody - ) + val apiUrl = "$baseUrl/$BASE_API_ENDPOINT/ComicDetail".toHttpUrl().newBuilder() + .addQueryParameter("device", "pc") + .addQueryParameter("platform", "web") + .addLanguageParameters() + .toString() + + return POST(apiUrl, newHeaders, requestBody) } override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply { @@ -364,11 +410,13 @@ abstract class Bilibili( .set("Referer", baseUrl + chapter.url) .build() - return POST( - "$baseUrl/$BASE_API_ENDPOINT/GetImageIndex?device=pc&platform=web", - headers = newHeaders, - body = requestBody - ) + val apiUrl = "$baseUrl/$BASE_API_ENDPOINT/GetImageIndex".toHttpUrl().newBuilder() + .addQueryParameter("device", "pc") + .addQueryParameter("platform", "web") + .addLanguageParameters() + .toString() + + return POST(apiUrl, newHeaders, requestBody) } override fun pageListParse(response: Response): List { @@ -401,11 +449,13 @@ abstract class Bilibili( .add("Content-Type", requestBody.contentType().toString()) .build() - return POST( - "$baseUrl/$BASE_API_ENDPOINT/ImageToken?device=pc&platform=web", - headers = newHeaders, - body = requestBody - ) + val apiUrl = "$baseUrl/$BASE_API_ENDPOINT/ImageToken".toHttpUrl().newBuilder() + .addQueryParameter("device", "pc") + .addQueryParameter("platform", "web") + .addLanguageParameters() + .toString() + + return POST(apiUrl, newHeaders, requestBody) } override fun imageUrlParse(response: Response): String = "" @@ -504,6 +554,15 @@ abstract class Bilibili( return response } + private fun HttpUrl.Builder.addLanguageParameters(): HttpUrl.Builder = let { + if (name == "BILIBILI COMICS") { + addQueryParameter("lang", apiLang) + addQueryParameter("sys_lang", apiLang) + } + + return@let it + } + private inline fun Response.parseAs(): BilibiliResultDto = use { json.decodeFromString(it.body?.string().orEmpty()) } diff --git a/src/all/bilibili/src/eu/kanade/tachiyomi/extension/all/bilibili/BilibiliFactory.kt b/src/all/bilibili/src/eu/kanade/tachiyomi/extension/all/bilibili/BilibiliFactory.kt index 09d26bb45..f25f89471 100644 --- a/src/all/bilibili/src/eu/kanade/tachiyomi/extension/all/bilibili/BilibiliFactory.kt +++ b/src/all/bilibili/src/eu/kanade/tachiyomi/extension/all/bilibili/BilibiliFactory.kt @@ -5,12 +5,17 @@ import eu.kanade.tachiyomi.source.SourceFactory class BilibiliFactory : SourceFactory { override fun createSources(): List = listOf( - BilibiliComics(), + BilibiliComicsEn(), + BilibiliComicsCn(), + BilibiliComicsId(), BilibiliManga() ) } -class BilibiliComics : Bilibili("BILIBILI COMICS", "https://www.bilibilicomics.com", "en") { +abstract class BilibiliComics(lang: String) : + Bilibili("BILIBILI COMICS", "https://www.bilibilicomics.com", lang) + +class BilibiliComicsEn : BilibiliComics("en") { override fun getAllGenres(): Array = arrayOf( BilibiliTag("All", -1), @@ -32,33 +37,67 @@ class BilibiliComics : Bilibili("BILIBILI COMICS", "https://www.bilibilicomics.c ) } -class BilibiliManga : Bilibili("哔哩哔哩漫画", "https://manga.bilibili.com", "zh") { +class BilibiliComicsCn : BilibiliComics("zh-Hans") { - override val statusLabel: String = "进度" + override fun getAllSortOptions(): Array = arrayOf("为你推荐", "人气推荐", "更新时间") - override val sortLabel: String = "排序" + override fun getAllStatus(): Array = arrayOf("全部", "连载中", "已完结") - override val genreLabel: String = "题材" + override fun getAllPrices(): Array = arrayOf("全部", "免费", "付费") - override val areaLabel: String = "地区" + override fun getAllGenres(): Array = arrayOf( + BilibiliTag("全部", -1), + BilibiliTag("校园", 18), + BilibiliTag("都市", 9), + BilibiliTag("耽美", 3), + BilibiliTag("少女", 20), + BilibiliTag("恋爱", 13), + BilibiliTag("奇幻", 11), + BilibiliTag("热血", 19), + BilibiliTag("冒险", 22), + BilibiliTag("古风", 12), + BilibiliTag("百合", 16), + BilibiliTag("玄幻", 30), + BilibiliTag("悬疑", 41), + BilibiliTag("科幻", 8) + ) +} - override val priceLabel: String = "收费" +class BilibiliComicsId : BilibiliComics("id") { - override val episodePrefix: String = "" + override fun getAllSortOptions(): Array = arrayOf("Kamu Mungkin Suka", "Populer", "Terbaru") + + override fun getAllStatus(): Array = arrayOf("Semua", "Berlangsung", "Tamat") + + override fun getAllPrices(): Array = arrayOf("Semua", "Bebas", "Dibayar") + + override fun getAllGenres(): Array = arrayOf( + BilibiliTag("Semua", -1), + BilibiliTag("Aksi", 19), + BilibiliTag("Fantasi Timur", 30), + BilibiliTag("Fantasi", 11), + BilibiliTag("Historis", 12), + BilibiliTag("Horror", 23), + BilibiliTag("Kampus", 18), + BilibiliTag("Komedi", 14), + BilibiliTag("Menegangkan", 41), + BilibiliTag("Remaja", 20), + BilibiliTag("Romantis", 13) + ) +} + +class BilibiliManga : Bilibili( + "哔哩哔哩漫画", + "https://manga.bilibili.com", + "zh-Hans" +) { + + override val id: Long = 3561131545129718586 override val defaultPopularSort: Int = 0 override val defaultLatestSort: Int = 1 - override val hasPaidChaptersWarning: String = "此漫画的付费章节已从章节列表中过滤," + - "暂时请用网页端或官方app阅读。" - - override val imageQualityPrefTitle: String = "章节图片质量" - - override val imageQualityPrefEntries: Array = arrayOf("原图", "高", "低") - - override val imageFormatPrefTitle: String = "章节图片格式" - override fun getAllStatus(): Array = arrayOf("全部", "连载", "完结") override fun getAllSortOptions(): Array = arrayOf("人气推荐", "更新时间", "追漫人数", "上架时间")