more QoL fixes for MangaDex (#18672)

* fix spelling for villainess in en translations

* custom user agent + more md@h logging

adds a custom user agent setting primarily intended for testing
do note that spoofing to be a different browser might fetch you trouble
as MangaDex's new hotlink/bot abusers can kick in action

also add logging to figure out which MD@H node users are hitting
as currently, the fallback was not observed to be changing even after
a while; leading to user's keep failing to fetch images

* more improvements

make the `Extra` header more verbose
use a `customUserAgent` sharedpreferences variable so that code looks
cleaner
move the useragent logic into an interceptor so that there is no
need for restarting the app after every useragent change

* completely switch to useragent interceptor

removes builder header modification
remove additional logging while testing (didn't really work as
expected since I kept hitting uploads.mangadex.org anyhow,
+ the interceptor logs weren't useful otherwise)
switch to hardcoding version code in header since it wasn't working
as expected...
add linting from android studio gradle release build

* increment extVersionCode

* oopsie be careful of comments

* properly close unsuccessful requests to mdah node

need to ensure this so that it doesn't crash (which has happened before)

inb4 this is why the fallback url never works....
This commit is contained in:
nicki 2023-10-23 11:45:32 -05:00 committed by GitHub
parent b5e30c3e35
commit fc7598bdcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 5 deletions

View File

@ -137,10 +137,14 @@ theme_time_travel=Time Travel
theme_traditional_games=Traditional Games
theme_vampires=Vampires
theme_video_games=Video Games
theme_villainess=Vilania
theme_villainess=Villainess
theme_virtual_reality=Virtual Reality
theme_zombies=Zombies
try_using_first_volume_cover=Attempt to use the first volume cover as cover
try_using_first_volume_cover_summary=May need to manually refresh entries already in library. Otherwise, clear database to have new covers to show up.
unable_to_process_chapter_request=Unable to process Chapter request. HTTP code: %d
uploaded_by=Uploaded by %s
set_custom_useragent=Set custom User-Agent
set_custom_useragent_summary=Keep it as default
set_custom_useragent_dialog=\n\nSpecify a custom user agent\n After each modification, the application needs to be restarted.\n\nDefault value:\n%s
set_custom_useragent_error_invalid=Invalid User-Agent: %s

View File

@ -6,7 +6,7 @@ ext {
extName = 'MangaDex'
pkgNameSuffix = 'all.mangadex'
extClass = '.MangaDexFactory'
extVersionCode = 189
extVersionCode = 190
isNsfw = true
}

View File

@ -138,6 +138,13 @@ object MDConstants {
return "${altTitlesInDescPref}_$dexLang"
}
private const val customUserAgentPref = "customUserAgent"
fun getCustomUserAgentPrefKey(dexLang: String): String {
return "${customUserAgentPref}_$dexLang"
}
val defaultUserAgent = "Tachiyomi " + System.getProperty("http.agent")
private const val tagGroupContent = "content"
private const val tagGroupFormat = "format"
private const val tagGroupGenre = "genre"

View File

@ -2,11 +2,14 @@ package eu.kanade.tachiyomi.extension.all.mangadex
import android.app.Application
import android.content.SharedPreferences
import android.os.Build
import android.widget.Toast
import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import androidx.preference.MultiSelectListPreference
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.AppInfo
import eu.kanade.tachiyomi.extension.all.mangadex.dto.AggregateDto
import eu.kanade.tachiyomi.extension.all.mangadex.dto.AggregateVolume
import eu.kanade.tachiyomi.extension.all.mangadex.dto.AtHomeDto
@ -56,13 +59,23 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
private val helper = MangaDexHelper(lang)
final override fun headersBuilder() = Headers.Builder()
.add("Referer", "$baseUrl/")
.add("User-Agent", "Tachiyomi " + System.getProperty("http.agent"))
final override fun headersBuilder(): Headers.Builder {
val extraHeader = "Android/${Build.VERSION.RELEASE} " +
"Tachiyomi/${AppInfo.getVersionName()} " +
"MangaDex/1.4.190"
val builder = super.headersBuilder().apply {
set("Referer", "$baseUrl/")
set("Extra", extraHeader)
}
return builder
}
override val client = network.client.newBuilder()
.rateLimit(3)
.addInterceptor(MdAtHomeReportInterceptor(network.client, headers))
.addInterceptor(MdUserAgentInterceptor(preferences, dexLang))
.build()
init {
@ -745,6 +758,30 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
}
}
val userAgentPref = EditTextPreference(screen.context).apply {
key = MDConstants.getCustomUserAgentPrefKey(dexLang)
title = helper.intl["set_custom_useragent"]
summary = helper.intl["set_custom_useragent_summary"]
dialogMessage = helper.intl.format(
"set_custom_useragent_dialog",
MDConstants.defaultUserAgent,
)
setDefaultValue(MDConstants.defaultUserAgent)
setOnPreferenceChangeListener { _, newValue ->
try {
Headers.Builder().add("User-Agent", newValue as String)
summary = newValue
true
} catch (e: Throwable) {
val errorMessage = helper.intl.format("set_custom_useragent_error_invalid", e.message)
Toast.makeText(screen.context, errorMessage, Toast.LENGTH_LONG).show()
false
}
}
}
screen.addPreference(coverQualityPref)
screen.addPreference(tryUsingFirstVolumeCoverPref)
screen.addPreference(dataSaverPref)
@ -754,6 +791,7 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
screen.addPreference(originalLanguagePref)
screen.addPreference(blockedGroupsPref)
screen.addPreference(blockedUploaderPref)
screen.addPreference(userAgentPref)
}
override fun getFilterList(): FilterList =
@ -828,6 +866,12 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
private val SharedPreferences.altTitlesInDesc
get() = getBoolean(MDConstants.getAltTitlesInDescPrefKey(dexLang), false)
private val SharedPreferences.customUserAgent
get() = getString(
MDConstants.getCustomUserAgentPrefKey(dexLang),
MDConstants.defaultUserAgent,
)
/**
* Previous versions of the extension allowed invalid UUID values to be stored in the
* preferences. This method clear invalid UUIDs in case the user have updated from

View File

@ -36,6 +36,8 @@ class MdAtHomeReportInterceptor(
return response
}
Log.e("MangaDex", "Connecting to MD@Home node at $url")
val result = ImageReportDto(
url = url,
success = response.isSuccessful,
@ -61,6 +63,8 @@ class MdAtHomeReportInterceptor(
return response
}
response.close()
Log.e("MangaDex", "Error connecting to MD@Home node, fallback to uploads server")
val fallbackUrl = MDConstants.cdnUrl.toHttpUrl().newBuilder()

View File

@ -0,0 +1,47 @@
package eu.kanade.tachiyomi.extension.all.mangadex
import android.content.SharedPreferences
import okhttp3.Interceptor
import okhttp3.Response
import java.io.IOException
/**
* Interceptor to set custom useragent for MangaDex
*/
class MdUserAgentInterceptor(
private val preferences: SharedPreferences,
private val dexLang: String,
) : Interceptor {
private val SharedPreferences.customUserAgent
get() = getString(
MDConstants.getCustomUserAgentPrefKey(dexLang),
MDConstants.defaultUserAgent,
)
private fun getUserAgent(): String? {
return preferences.customUserAgent
}
override fun intercept(chain: Interceptor.Chain): Response {
try {
val originalRequest = chain.request()
val newUserAgent = getUserAgent() ?: return chain.proceed(originalRequest)
val originalHeaders = originalRequest.headers
val modifiedHeaders = originalHeaders.newBuilder()
.set("User-Agent", newUserAgent)
.build()
return chain.proceed(
originalRequest.newBuilder()
.headers(modifiedHeaders)
.build(),
)
} catch (e: Exception) {
throw IOException("MdUserAgentInterceptor failed with error: ${e.message}")
}
}
}