diff --git a/multisrc/overrides/bilibili/bilibilicomics/AndroidManifest.xml b/multisrc/overrides/bilibili/bilibilicomics/AndroidManifest.xml
index 47787bc19..3b9ee6b2f 100644
--- a/multisrc/overrides/bilibili/bilibilicomics/AndroidManifest.xml
+++ b/multisrc/overrides/bilibili/bilibilicomics/AndroidManifest.xml
@@ -14,25 +14,13 @@
-
+
-
+
+
+
-
-
-
+
diff --git a/multisrc/overrides/bilibili/bilibilicomics/src/BilibiliComicsFactory.kt b/multisrc/overrides/bilibili/bilibilicomics/src/BilibiliComicsFactory.kt
index 22f2f3ad1..f9e8c9cc6 100644
--- a/multisrc/overrides/bilibili/bilibilicomics/src/BilibiliComicsFactory.kt
+++ b/multisrc/overrides/bilibili/bilibilicomics/src/BilibiliComicsFactory.kt
@@ -31,6 +31,7 @@ import okhttp3.Response
import okio.Buffer
import java.io.IOException
import java.net.URLDecoder
+import java.util.Calendar
class BilibiliComicsFactory : SourceFactory {
override fun createSources() = listOf(
@@ -67,6 +68,9 @@ abstract class BilibiliComics(lang: String) : Bilibili(
private var accessTokenCookie: BilibiliAccessTokenCookie? = null
+ private val dayOfWeek: Int
+ get() = Calendar.getInstance().get(Calendar.DAY_OF_WEEK) - 1
+
override fun latestUpdatesRequest(page: Int): Request {
val jsonPayload = buildJsonObject { put("day", dayOfWeek) }
val requestBody = jsonPayload.toString().toRequestBody(JSON_MEDIA_TYPE)
diff --git a/multisrc/overrides/bilibili/bilibilimanga/AndroidManifest.xml b/multisrc/overrides/bilibili/bilibilimanga/AndroidManifest.xml
index 36b5bd4bf..5603a61fe 100644
--- a/multisrc/overrides/bilibili/bilibilimanga/AndroidManifest.xml
+++ b/multisrc/overrides/bilibili/bilibilimanga/AndroidManifest.xml
@@ -14,15 +14,12 @@
-
+
-
+
+
+
+
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/Bilibili.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/Bilibili.kt
index 62906a1b9..ceb755e6e 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/Bilibili.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/Bilibili.kt
@@ -34,7 +34,6 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
-import java.util.Calendar
import java.util.Locale
abstract class Bilibili(
@@ -46,7 +45,7 @@ abstract class Bilibili(
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
- .addInterceptor(::expiredTokenIntercept)
+ .addInterceptor(::expiredImageTokenIntercept)
.rateLimitHost(baseUrl.toHttpUrl(), 1)
.rateLimitHost(CDN_URL.toHttpUrl(), 2)
.rateLimitHost(COVER_CDN_URL.toHttpUrl(), 2)
@@ -76,9 +75,6 @@ abstract class Bilibili(
protected open val signedIn: Boolean = false
- protected val dayOfWeek: Int
- get() = Calendar.getInstance().get(Calendar.DAY_OF_WEEK) - 1
-
override fun popularMangaRequest(page: Int): Request = searchMangaRequest(
page = page,
query = "",
@@ -100,11 +96,9 @@ abstract class Bilibili(
override fun latestUpdatesParse(response: Response): MangasPage = searchMangaParse(response)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
- if (query.startsWith(PREFIX_ID_SEARCH) && query.matches(ID_SEARCH_PATTERN)) {
- val comicId = query
- .removePrefix(PREFIX_ID_SEARCH)
- .removePrefix("mc")
- return mangaDetailsApiRequest("/detail/mc$comicId")
+ ID_SEARCH_PATTERN.matchEntire(query)?.let {
+ val (id) = it.destructured
+ return mangaDetailsApiRequest("/detail/mc$id")
}
val price = filters.firstInstanceOrNull()?.state ?: 0
@@ -144,12 +138,13 @@ abstract class Bilibili(
}
override fun searchMangaParse(response: Response): MangasPage {
- if (response.request.url.toString().contains("ComicDetail")) {
+ val requestUrl = response.request.url.toString()
+ if (requestUrl.contains("ComicDetail")) {
val comic = mangaDetailsParse(response)
return MangasPage(listOf(comic), hasNextPage = false)
}
- if (response.request.url.toString().contains("ClassPage")) {
+ if (requestUrl.contains("ClassPage")) {
val result = response.parseAs>()
if (result.code != 0) {
@@ -210,8 +205,7 @@ abstract class Bilibili(
}
override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply {
- val result = response.parseAs()
- val comic = result.data!!
+ val comic = response.parseAs().data!!
title = comic.title
author = comic.authorName.joinToString()
@@ -231,7 +225,7 @@ abstract class Bilibili(
append("\n• ${intl.totalChapterCount}: ${intl.localize(comic.episodeList.size)}")
if (comic.updateWeekdays.isNotEmpty() && status == SManga.ONGOING) {
- append("\n• ${intl.updatedEvery}: ${intl.getWeekdays(comic.updateWeekdays)}")
+ append("\n• ${intl.getUpdateDays(comic.updateWeekdays)}")
}
}
thumbnail_url = comic.verticalCover
@@ -254,9 +248,8 @@ abstract class Bilibili(
}
protected open fun chapterFromObject(episode: BilibiliEpisodeDto, comicId: Int): SChapter = SChapter.create().apply {
- name = intl.episodePrefix + episode.shortTitle +
- (if (episode.title.isNotBlank()) " - " + episode.title else "")
- date_upload = episode.publicationTime.substringBefore("T").toDate()
+ name = episode.shortTitle.plus(if (episode.title.isNotBlank()) " - ${episode.title}" else "")
+ date_upload = episode.publicationTime.toDate()
url = "/mc$comicId/${episode.id}"
}
@@ -373,46 +366,45 @@ abstract class Bilibili(
return FilterList(filters)
}
- private fun expiredTokenIntercept(chain: Interceptor.Chain): Response {
+ private fun expiredImageTokenIntercept(chain: Interceptor.Chain): Response {
val response = chain.proceed(chain.request())
// Get a new image token if the current one expired.
if (response.code == 403 && chain.request().url.toString().contains(CDN_URL)) {
+ response.close()
val imagePath = chain.request().url.toString()
.substringAfter(CDN_URL)
.substringBefore("?token=")
val imageTokenRequest = imageTokenRequest(listOf(imagePath))
val imageTokenResponse = chain.proceed(imageTokenRequest)
val imageTokenResult = imageTokenResponse.parseAs>()
+ imageTokenResponse.close()
- val newPage = imageTokenResult.data!![0]
+ val newPage = imageTokenResult.data!!.first()
val newPageUrl = "${newPage.url}?token=${newPage.token}"
val newRequest = imageRequest(Page(0, "", newPageUrl))
- imageTokenResponse.close()
- response.close()
return chain.proceed(newRequest)
}
return response
}
- protected val SharedPreferences.chapterImageQuality
+ private val SharedPreferences.chapterImageQuality
get() = when (getString("${IMAGE_QUALITY_PREF_KEY}_$lang", IMAGE_QUALITY_PREF_DEFAULT_VALUE)!!) {
- "raw" -> "1600w"
- "hd" -> "1000w"
- "sd" -> "800w_50q"
- else -> "raw+"
+ "hd" -> "1600w"
+ "sd" -> "1000w"
+ "low" -> "800w_50q"
+ else -> "raw"
}
- protected val SharedPreferences.chapterImageFormat
+ private val SharedPreferences.chapterImageFormat
get() = getString("${IMAGE_FORMAT_PREF_KEY}_$lang", IMAGE_FORMAT_PREF_DEFAULT_VALUE)!!
- private inline fun List<*>.firstInstanceOrNull(): R? =
- filterIsInstance().firstOrNull()
+ private inline fun List<*>.firstInstanceOrNull(): R? = firstOrNull { it is R } as? R
- protected open fun HttpUrl.Builder.addCommonParameters(): HttpUrl.Builder = let {
+ protected open fun HttpUrl.Builder.addCommonParameters(): HttpUrl.Builder = apply {
if (name == "BILIBILI COMICS") {
addQueryParameter("lang", apiLang)
addQueryParameter("sys_lang", apiLang)
@@ -420,8 +412,6 @@ abstract class Bilibili(
addQueryParameter("device", "pc")
addQueryParameter("platform", "web")
-
- return@let it
}
protected inline fun Response.parseAs(): BilibiliResultDto = use {
@@ -447,10 +437,10 @@ abstract class Bilibili(
private const val SEARCH_PER_PAGE = 9
const val PREFIX_ID_SEARCH = "id:"
- private val ID_SEARCH_PATTERN = "^id:(mc)?(\\d+)$".toRegex()
+ private val ID_SEARCH_PATTERN = "^${PREFIX_ID_SEARCH}mc(\\d+)$".toRegex()
private const val IMAGE_QUALITY_PREF_KEY = "chapterImageQuality"
- private val IMAGE_QUALITY_PREF_ENTRY_VALUES = arrayOf("raw+", "raw", "hd", "sd")
+ private val IMAGE_QUALITY_PREF_ENTRY_VALUES = arrayOf("raw", "hd", "sd", "low")
private val IMAGE_QUALITY_PREF_DEFAULT_VALUE = IMAGE_QUALITY_PREF_ENTRY_VALUES[1]
private const val IMAGE_FORMAT_PREF_KEY = "chapterImageFormat"
@@ -461,7 +451,7 @@ abstract class Bilibili(
const val THUMBNAIL_RESOLUTION = "@512w.jpg"
private val DATE_FORMATTER by lazy {
- SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
+ SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH)
}
private const val EMOJI_LOCKED = "\uD83D\uDD12"
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliDto.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliDto.kt
index 970ba7372..bf267e067 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliDto.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliDto.kt
@@ -65,7 +65,7 @@ data class BilibiliImageDto(
) {
fun url(quality: String, format: String): String {
- val imageWidth = if (quality == "raw+") "${width}w" else quality
+ val imageWidth = if (quality == "raw") "${width}w" else quality
return "$path@$imageWidth.$format"
}
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliGenerator.kt
index cfe8d7565..073795dbd 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliGenerator.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliGenerator.kt
@@ -10,7 +10,7 @@ class BilibiliGenerator : ThemeSourceGenerator {
override val themeClass = "Bilibili"
- override val baseVersionCode: Int = 7
+ override val baseVersionCode: Int = 8
override val sources = listOf(
MultiLang(
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliIntl.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliIntl.kt
index 09892ac58..375c51aa2 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliIntl.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliIntl.kt
@@ -43,12 +43,6 @@ class BilibiliIntl(private val lang: String) {
else -> "Price"
}
- val episodePrefix: String = when (lang) {
- CHINESE, SIMPLIFIED_CHINESE -> ""
- SPANISH -> "Cap. "
- else -> "Ep. "
- }
-
fun hasPaidChaptersWarning(chapterCount: Int): String = when (lang) {
CHINESE, SIMPLIFIED_CHINESE ->
"${Bilibili.EMOJI_WARNING} 此漫画有 ${chapterCount.localized} 个付费章节,已在目录中隐藏。" +
@@ -73,8 +67,8 @@ class BilibiliIntl(private val lang: String) {
}
val imageQualityPrefEntries: Array = when (lang) {
- CHINESE, SIMPLIFIED_CHINESE -> arrayOf("原图+", "原图 (1600w)", "高 (1000w)", "低 (800w)")
- else -> arrayOf("Raw+", "Raw (1600w)", "HD (1000w)", "SD (800w)")
+ CHINESE, SIMPLIFIED_CHINESE -> arrayOf("原图", "高清 (1600w)", "标清 (1000w)", "低清 (800w)")
+ else -> arrayOf("Raw", "HD (1600w)", "SD (1000w)", "Low (800w)")
}
val imageFormatPrefTitle: String = when (lang) {
@@ -191,18 +185,27 @@ class BilibiliIntl(private val lang: String) {
else -> "Total chapter count"
}
- val updatedEvery: String = when (lang) {
- CHINESE, SIMPLIFIED_CHINESE -> "每周更新时间"
- SPANISH -> "Actualizado en"
- else -> "Updated every"
+ private val updatesDaily: String = when (lang) {
+ CHINESE, SIMPLIFIED_CHINESE -> "每日更新"
+ SPANISH -> "Actualizaciones diarias"
+ else -> "Updates daily"
}
- fun getWeekdays(dayIndexes: List): String {
- val weekdays = dateFormatSymbols.weekdays
- .filter(String::isNotBlank)
- .map { dayName -> dayName.replaceFirstChar { it.uppercase(locale) } }
+ private fun updatesEvery(days: String): String = when (lang) {
+ CHINESE, SIMPLIFIED_CHINESE -> "${days}更新"
+ SPANISH -> "Actualizaciones todos los $days"
+ else -> "Updates every $days"
+ }
- return dayIndexes.joinToString { weekdays[it] }
+ fun getUpdateDays(dayIndexes: List): String {
+ val shortWeekDays = dateFormatSymbols.shortWeekdays.filterNot(String::isBlank)
+ if (dayIndexes.size == shortWeekDays.size) return updatesDaily
+ val shortWeekDaysUpperCased = shortWeekDays.map {
+ it.replaceFirstChar { char -> char.uppercase(locale) }
+ }
+
+ val days = dayIndexes.joinToString { shortWeekDaysUpperCased[it] }
+ return updatesEvery(days)
}
fun localize(value: Int) = value.localized
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliUrlActivity.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliUrlActivity.kt
index eeb968411..88cde4983 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliUrlActivity.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/bilibili/BilibiliUrlActivity.kt
@@ -23,7 +23,8 @@ class BilibiliUrlActivity : Activity() {
val pathSegments = intent?.data?.pathSegments
if (pathSegments != null && pathSegments.size > 1) {
- val titleId = if (pathSegments.size == 3) pathSegments[2] else pathSegments[1]
+ // Mobile site of https://manga.bilibili.com starts with path "m"
+ val titleId = if (pathSegments[0] == "m") pathSegments[2] else pathSegments[1]
val mainIntent = Intent().apply {
action = "eu.kanade.tachiyomi.SEARCH"