mirror of
https://github.com/mihonapp/mihon.git
synced 2025-07-01 05:27:50 +02:00
Fix gallery browsing
This commit is contained in:
@ -11,7 +11,9 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||
import eu.kanade.tachiyomi.util.launchUI
|
||||
import eu.kanade.tachiyomi.util.powerManager
|
||||
import eu.kanade.tachiyomi.util.toast
|
||||
import eu.kanade.tachiyomi.util.wifiManager
|
||||
import exh.EH_METADATA_SOURCE_ID
|
||||
import exh.EXH_SOURCE_ID
|
||||
@ -117,6 +119,11 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val theContext = context
|
||||
launchUI {
|
||||
theContext.toast("Sync complete!")
|
||||
}
|
||||
} catch(e: IgnoredException) {
|
||||
//Do not display error as this error has already been reported
|
||||
Timber.w(e, "Ignoring exception!")
|
||||
|
@ -160,8 +160,12 @@ open class ExGalleryMetadata : RealmObject(), SearchableGalleryMetadata {
|
||||
companion object {
|
||||
private fun splitGalleryUrl(url: String)
|
||||
= url.let {
|
||||
Uri.parse(it).pathSegments
|
||||
.filterNot(String::isNullOrBlank)
|
||||
//Only parse URL if is full URL
|
||||
val pathSegments = if(it.startsWith("http"))
|
||||
Uri.parse(it).pathSegments
|
||||
else
|
||||
it.split('/')
|
||||
pathSegments.filterNot(String::isNullOrBlank)
|
||||
}
|
||||
|
||||
fun galleryId(url: String) = splitGalleryUrl(url).let { it[it.size - 2] }
|
||||
|
@ -89,7 +89,7 @@ open class NHentaiMetadata : RealmObject(), SearchableGalleryMetadata {
|
||||
if(mediaId != null)
|
||||
NHentaiMetadata.typeToExtension(thumbnailImageType)?.let {
|
||||
manga.thumbnail_url = "https://t.nhentai.net/galleries/$mediaId/${
|
||||
if(Injekt.get<PreferencesHelper>().eh_useHighQualityThumbs().getOrDefault())
|
||||
if(Injekt.get<PreferencesHelper>().eh_nh_useHighQualityThumbs().getOrDefault())
|
||||
"cover"
|
||||
else
|
||||
"thumb"
|
||||
|
65
app/src/main/java/exh/uconfig/ConfiguringDialogController.kt
Normal file
65
app/src/main/java/exh/uconfig/ConfiguringDialogController.kt
Normal file
@ -0,0 +1,65 @@
|
||||
package exh.uconfig
|
||||
|
||||
import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.util.launchUI
|
||||
import eu.kanade.tachiyomi.util.toast
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class ConfiguringDialogController : DialogController() {
|
||||
private var materialDialog: MaterialDialog? = null
|
||||
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog.Builder(activity!!)
|
||||
.title("Uploading settings to server")
|
||||
.content("Please wait, this may take some time...")
|
||||
.progress(true, 0)
|
||||
.cancelable(false)
|
||||
.build().also {
|
||||
materialDialog = it
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttach(view: View) {
|
||||
super.onAttach(view)
|
||||
thread {
|
||||
try {
|
||||
EHConfigurator().configureAll()
|
||||
launchUI {
|
||||
activity?.toast("Settings successfully uploaded!")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity?.let {
|
||||
it.runOnUiThread {
|
||||
MaterialDialog.Builder(it)
|
||||
.title("Configuration failed!")
|
||||
.content("An error occurred during the configuration process: " + e.message)
|
||||
.positiveText("Ok")
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
launchUI {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
super.onDestroyView(view)
|
||||
materialDialog = null
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
finish()
|
||||
}
|
||||
|
||||
fun finish() {
|
||||
router.popController(this)
|
||||
}
|
||||
}
|
||||
|
125
app/src/main/java/exh/uconfig/EHConfigurator.kt
Normal file
125
app/src/main/java/exh/uconfig/EHConfigurator.kt
Normal file
@ -0,0 +1,125 @@
|
||||
package exh.uconfig
|
||||
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import exh.EH_SOURCE_ID
|
||||
import exh.EXH_SOURCE_ID
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class EHConfigurator {
|
||||
private val prefs: PreferencesHelper by injectLazy()
|
||||
private val sources: SourceManager by injectLazy()
|
||||
|
||||
private val configuratorClient = OkHttpClient.Builder().build()
|
||||
|
||||
private fun EHentai.requestWithCreds(sp: Int = 1) = Request.Builder()
|
||||
.addHeader("Cookie", cookiesHeader(sp))
|
||||
|
||||
private fun EHentai.execProfileActions(action: String,
|
||||
name: String,
|
||||
set: String,
|
||||
sp: Int)
|
||||
= configuratorClient.newCall(requestWithCreds(sp)
|
||||
.url(uconfigUrl)
|
||||
.post(FormBody.Builder()
|
||||
.add("profile_action", action)
|
||||
.add("profile_name", name)
|
||||
.add("profile_set", set)
|
||||
.build())
|
||||
.build())
|
||||
.execute().asJsoup()
|
||||
|
||||
private val EHentai.uconfigUrl get() = baseUrl + UCONFIG_URL
|
||||
|
||||
fun configureAll() {
|
||||
val ehSource = sources.get(EH_SOURCE_ID) as EHentai
|
||||
val exhSource = sources.get(EXH_SOURCE_ID) as EHentai
|
||||
|
||||
//Get hath perks
|
||||
val perksPage = configuratorClient.newCall(ehSource.requestWithCreds()
|
||||
.url(HATH_PERKS_URL)
|
||||
.build())
|
||||
.execute().asJsoup()
|
||||
|
||||
val hathPerks = EHHathPerksResponse()
|
||||
|
||||
perksPage.select(".stuffbox tr").forEach {
|
||||
val name = it.child(0).text().toLowerCase()
|
||||
val purchased = it.child(2).getElementsByTag("form").isEmpty()
|
||||
|
||||
when(name) {
|
||||
//Thumbnail rows
|
||||
"more thumbs" -> hathPerks.moreThumbs = purchased
|
||||
"thumbs up" -> hathPerks.thumbsUp = purchased
|
||||
"all thumbs" -> hathPerks.allThumbs = purchased
|
||||
|
||||
//Pagination sizing
|
||||
"paging enlargement i" -> hathPerks.pagingEnlargementI = purchased
|
||||
"paging enlargement ii" -> hathPerks.pagingEnlargementII = purchased
|
||||
"paging enlargement iii" -> hathPerks.pagingEnlargementIII = purchased
|
||||
}
|
||||
}
|
||||
|
||||
Timber.d("Hath perks: $hathPerks")
|
||||
|
||||
configure(ehSource, hathPerks)
|
||||
configure(exhSource, hathPerks)
|
||||
}
|
||||
|
||||
fun configure(source: EHentai, hathPerks: EHHathPerksResponse) {
|
||||
//Delete old app profiles
|
||||
val scanReq = source.requestWithCreds().url(source.uconfigUrl).build()
|
||||
val resp = configuratorClient.newCall(scanReq).execute().asJsoup()
|
||||
var lastDoc = resp
|
||||
resp.select(PROFILE_SELECTOR).forEach {
|
||||
if(it.text() == PROFILE_NAME) {
|
||||
val id = it.attr("value")
|
||||
//Delete old profile
|
||||
lastDoc = source.execProfileActions("delete", "", id, id.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
//Find available profile slot
|
||||
val availableProfiles = (1 .. 3).toMutableList()
|
||||
lastDoc.select(PROFILE_SELECTOR).forEach {
|
||||
availableProfiles.remove(it.attr("value").toInt())
|
||||
}
|
||||
|
||||
//No profile slots left :(
|
||||
if(availableProfiles.isEmpty())
|
||||
throw IllegalStateException("You are out of profile slots on ${source.name}, please delete a profile!")
|
||||
|
||||
//Create profile in available slot
|
||||
val slot = availableProfiles.first()
|
||||
source.execProfileActions("create",
|
||||
PROFILE_NAME,
|
||||
slot.toString(),
|
||||
1)
|
||||
|
||||
//Build new profile
|
||||
val form = EhUConfigBuilder().build(hathPerks)
|
||||
|
||||
//Send new profile to server
|
||||
configuratorClient.newCall(source.requestWithCreds(sp = slot)
|
||||
.url(source.uconfigUrl)
|
||||
.post(form)
|
||||
.build()).execute()
|
||||
|
||||
//Persist slot
|
||||
source.spPref().set(slot)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PROFILE_NAME = "TachiyomiEH App"
|
||||
private const val UCONFIG_URL = "/uconfig.php"
|
||||
//Always use E-H here as EXH does not have a perks page
|
||||
private const val HATH_PERKS_URL = "https://e-hentai.org/hathperks.php"
|
||||
private const val PROFILE_SELECTOR = "[name=profile_set] > option"
|
||||
}
|
||||
}
|
15
app/src/main/java/exh/uconfig/EHHathPerksResponse.kt
Normal file
15
app/src/main/java/exh/uconfig/EHHathPerksResponse.kt
Normal file
@ -0,0 +1,15 @@
|
||||
package exh.uconfig
|
||||
|
||||
class EHHathPerksResponse {
|
||||
var moreThumbs = false
|
||||
var thumbsUp = false
|
||||
var allThumbs = false
|
||||
|
||||
var pagingEnlargementI = false
|
||||
var pagingEnlargementII = false
|
||||
var pagingEnlargementIII = false
|
||||
|
||||
override fun toString()
|
||||
= "EHHathPerksResponse(moreThumbs=$moreThumbs, thumbsUp=$thumbsUp, allThumbs=$allThumbs, pagingEnlargementI=$pagingEnlargementI, pagingEnlargementII=$pagingEnlargementII, pagingEnlargementIII=$pagingEnlargementIII)"
|
||||
}
|
||||
|
142
app/src/main/java/exh/uconfig/EhUConfigBuilder.kt
Normal file
142
app/src/main/java/exh/uconfig/EhUConfigBuilder.kt
Normal file
@ -0,0 +1,142 @@
|
||||
package exh.uconfig
|
||||
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import okhttp3.FormBody
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class EhUConfigBuilder {
|
||||
private val prefs: PreferencesHelper by injectLazy()
|
||||
|
||||
fun build(hathPerks: EHHathPerksResponse): FormBody {
|
||||
val configItems = mutableListOf<ConfigItem>()
|
||||
|
||||
configItems += when(prefs.imageQuality()
|
||||
.getOrDefault()
|
||||
.toLowerCase()) {
|
||||
"ovrs_2400" -> Entry.ImageSize.`2400`
|
||||
"ovrs_1600" -> Entry.ImageSize.`1600`
|
||||
"high" -> Entry.ImageSize.`1280`
|
||||
"med" -> Entry.ImageSize.`980`
|
||||
"low" -> Entry.ImageSize.`780`
|
||||
"auto" -> Entry.ImageSize.AUTO
|
||||
else -> Entry.ImageSize.AUTO
|
||||
}
|
||||
|
||||
configItems += if(prefs.useHentaiAtHome().getOrDefault())
|
||||
Entry.UseHentaiAtHome.YES
|
||||
else
|
||||
Entry.UseHentaiAtHome.NO
|
||||
|
||||
configItems += if(prefs.useJapaneseTitle().getOrDefault())
|
||||
Entry.TitleDisplayLanguage.JAPANESE
|
||||
else
|
||||
Entry.TitleDisplayLanguage.DEFAULT
|
||||
|
||||
configItems += if(prefs.eh_useOriginalImages().getOrDefault())
|
||||
Entry.UseOriginalImages.YES
|
||||
else
|
||||
Entry.UseOriginalImages.NO
|
||||
|
||||
configItems += when {
|
||||
hathPerks.allThumbs -> Entry.ThumbnailRows.`40`
|
||||
hathPerks.thumbsUp -> Entry.ThumbnailRows.`20`
|
||||
hathPerks.moreThumbs -> Entry.ThumbnailRows.`10`
|
||||
else -> Entry.ThumbnailRows.`4`
|
||||
}
|
||||
|
||||
configItems += when {
|
||||
hathPerks.pagingEnlargementIII -> Entry.SearchResultsCount.`200`
|
||||
hathPerks.pagingEnlargementII -> Entry.SearchResultsCount.`100`
|
||||
hathPerks.pagingEnlargementI -> Entry.SearchResultsCount.`50`
|
||||
else -> Entry.SearchResultsCount.`25`
|
||||
}
|
||||
|
||||
configItems += Entry.DisplayMode()
|
||||
configItems += Entry.UseMPV()
|
||||
configItems += Entry.ShowPopularRightNowPane()
|
||||
|
||||
//Actually build form body
|
||||
val formBody = FormBody.Builder()
|
||||
configItems.forEach {
|
||||
formBody.add(it.key, it.value)
|
||||
}
|
||||
formBody.add("apply", "Apply")
|
||||
return formBody.build()
|
||||
}
|
||||
}
|
||||
|
||||
object Entry {
|
||||
enum class UseHentaiAtHome(override val value: String): ConfigItem {
|
||||
YES("0"),
|
||||
NO("1");
|
||||
|
||||
override val key = "uh"
|
||||
}
|
||||
|
||||
enum class ImageSize(override val value: String): ConfigItem {
|
||||
AUTO("0"),
|
||||
`2400`("5"),
|
||||
`1600`("4"),
|
||||
`1280`("3"),
|
||||
`980`("2"),
|
||||
`780`("1");
|
||||
|
||||
override val key = "xr"
|
||||
}
|
||||
|
||||
enum class TitleDisplayLanguage(override val value: String): ConfigItem {
|
||||
DEFAULT("0"),
|
||||
JAPANESE("1");
|
||||
|
||||
override val key = "tl"
|
||||
}
|
||||
|
||||
//Locked to list mode as that's what the parser and toplists use
|
||||
class DisplayMode: ConfigItem {
|
||||
override val key = "dm"
|
||||
override val value = "0"
|
||||
}
|
||||
|
||||
enum class SearchResultsCount(override val value: String): ConfigItem {
|
||||
`25`("0"),
|
||||
`50`("1"),
|
||||
`100`("2"),
|
||||
`200`("3");
|
||||
|
||||
override val key = "rc"
|
||||
}
|
||||
|
||||
enum class ThumbnailRows(override val value: String): ConfigItem {
|
||||
`4`("0"),
|
||||
`10`("1"),
|
||||
`20`("2"),
|
||||
`40`("3");
|
||||
|
||||
override val key = "tr"
|
||||
}
|
||||
|
||||
enum class UseOriginalImages(override val value: String): ConfigItem {
|
||||
NO("0"),
|
||||
YES("1");
|
||||
|
||||
override val key = "oi"
|
||||
}
|
||||
|
||||
//Locked to no MPV as that's what the parser uses
|
||||
class UseMPV: ConfigItem {
|
||||
override val key = "qb"
|
||||
override val value = "0"
|
||||
}
|
||||
|
||||
//Locked to no popular pane as we can't parse it
|
||||
class ShowPopularRightNowPane: ConfigItem {
|
||||
override val key = "pp"
|
||||
override val value = "1"
|
||||
}
|
||||
}
|
||||
|
||||
interface ConfigItem {
|
||||
val key: String
|
||||
val value: String
|
||||
}
|
Reference in New Issue
Block a user