mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Fix gallery browsing
This commit is contained in:
		@@ -249,6 +249,9 @@ dependencies {
 | 
			
		||||
 | 
			
		||||
    //RxJava 2 interop for Realm (EXH)
 | 
			
		||||
    implementation 'com.lvla.android:rxjava2-interop-kt:0.2.1'
 | 
			
		||||
 | 
			
		||||
    //Debug network interceptor (EXH)
 | 
			
		||||
    devImplementation "com.squareup.okhttp3:logging-interceptor:3.9.1"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
buildscript {
 | 
			
		||||
 
 | 
			
		||||
@@ -106,7 +106,7 @@
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name="exh.ui.intercept.InterceptActivity"
 | 
			
		||||
            android:excludeFromRecents="true"
 | 
			
		||||
            android:label="Tachiyomi">
 | 
			
		||||
            android:label="TachiyomiEH">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
                <action android:name="android.intent.action.VIEW"/>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -124,4 +124,12 @@ object PreferenceKeys {
 | 
			
		||||
    const val eh_showSyncIntro = "eh_show_sync_intro"
 | 
			
		||||
 | 
			
		||||
    const val eh_readOnlySync = "eh_sync_read_only"
 | 
			
		||||
 | 
			
		||||
    const val eh_useOrigImages = "eh_useOrigImages"
 | 
			
		||||
 | 
			
		||||
    const val eh_ehSettingsProfile = "eh_ehSettingsProfile"
 | 
			
		||||
 | 
			
		||||
    const val eh_exhSettingsProfile = "eh_exhSettingsProfile"
 | 
			
		||||
 | 
			
		||||
    const val eh_enableExHentai = "enable_exhentai"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -171,7 +171,7 @@ class PreferencesHelper(val context: Context) {
 | 
			
		||||
    fun migrateFlags() = rxPrefs.getInteger("migrate_flags", Int.MAX_VALUE)
 | 
			
		||||
 | 
			
		||||
    // --> EH
 | 
			
		||||
    fun enableExhentai() = rxPrefs.getBoolean("enable_exhentai", false)
 | 
			
		||||
    fun enableExhentai() = rxPrefs.getBoolean(Keys.eh_enableExHentai, false)
 | 
			
		||||
 | 
			
		||||
    fun secureEXH() = rxPrefs.getBoolean("secure_exh", true)
 | 
			
		||||
 | 
			
		||||
@@ -181,6 +181,8 @@ class PreferencesHelper(val context: Context) {
 | 
			
		||||
 | 
			
		||||
    fun useJapaneseTitle() = rxPrefs.getBoolean("use_jp_title", false)
 | 
			
		||||
 | 
			
		||||
    fun eh_useOriginalImages() = rxPrefs.getBoolean(Keys.eh_useOrigImages, false)
 | 
			
		||||
 | 
			
		||||
    fun ehSearchSize() = rxPrefs.getString("ex_search_size", "rc_0")
 | 
			
		||||
 | 
			
		||||
    fun thumbnailRows() = rxPrefs.getString("ex_thumb_rows", "tr_2")
 | 
			
		||||
@@ -195,6 +197,8 @@ class PreferencesHelper(val context: Context) {
 | 
			
		||||
    fun memberIdVal() = rxPrefs.getString("eh_ipb_member_id", null)
 | 
			
		||||
    fun passHashVal() = rxPrefs.getString("eh_ipb_pass_hash", null)
 | 
			
		||||
    fun igneousVal() = rxPrefs.getString("eh_igneous", null)
 | 
			
		||||
    fun eh_ehSettingsProfile() = rxPrefs.getInteger(Keys.eh_ehSettingsProfile, -1)
 | 
			
		||||
    fun eh_exhSettingsProfile() = rxPrefs.getInteger(Keys.eh_exhSettingsProfile, -1)
 | 
			
		||||
 | 
			
		||||
    //Lock
 | 
			
		||||
    fun lockHash() = rxPrefs.getString("lock_hash", null)
 | 
			
		||||
@@ -205,7 +209,7 @@ class PreferencesHelper(val context: Context) {
 | 
			
		||||
 | 
			
		||||
    fun lockUseFingerprint() = rxPrefs.getBoolean("lock_finger", false)
 | 
			
		||||
 | 
			
		||||
    fun eh_useHighQualityThumbs() = rxPrefs.getBoolean(Keys.eh_nh_useHighQualityThumbs, false)
 | 
			
		||||
    fun eh_nh_useHighQualityThumbs() = rxPrefs.getBoolean(Keys.eh_nh_useHighQualityThumbs, false)
 | 
			
		||||
 | 
			
		||||
    fun eh_showSyncIntro() = rxPrefs.getBoolean(Keys.eh_showSyncIntro, true)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,10 +21,7 @@ import exh.util.UriFilter
 | 
			
		||||
import exh.util.UriGroup
 | 
			
		||||
import exh.util.ignore
 | 
			
		||||
import exh.util.urlImportFetchSearchManga
 | 
			
		||||
import okhttp3.CacheControl
 | 
			
		||||
import okhttp3.Headers
 | 
			
		||||
import okhttp3.Request
 | 
			
		||||
import okhttp3.Response
 | 
			
		||||
import okhttp3.*
 | 
			
		||||
import org.jsoup.nodes.Document
 | 
			
		||||
import org.jsoup.nodes.Element
 | 
			
		||||
import rx.Observable
 | 
			
		||||
@@ -42,11 +39,14 @@ class EHentai(override val id: Long,
 | 
			
		||||
        else
 | 
			
		||||
            "http"
 | 
			
		||||
 | 
			
		||||
    override val baseUrl: String
 | 
			
		||||
    val domain: String
 | 
			
		||||
        get() = if(exh)
 | 
			
		||||
            "$schema://exhentai.org"
 | 
			
		||||
            "exhentai.org"
 | 
			
		||||
        else
 | 
			
		||||
            "$schema://e-hentai.org"
 | 
			
		||||
            "e-hentai.org"
 | 
			
		||||
 | 
			
		||||
    override val baseUrl: String
 | 
			
		||||
        get() = "$schema://$domain"
 | 
			
		||||
 | 
			
		||||
    override val lang = "all"
 | 
			
		||||
    override val supportsLatest = true
 | 
			
		||||
@@ -68,7 +68,7 @@ class EHentai(override val id: Long,
 | 
			
		||||
                        //Get title
 | 
			
		||||
                        it.select(".itd .it5 a").first()?.apply {
 | 
			
		||||
                            title = text()
 | 
			
		||||
                            setUrlWithoutDomain(addParam(attr("href"), "nw", "always"))
 | 
			
		||||
                            setUrlWithoutDomain(ExGalleryMetadata.normalizeUrl(attr("href")))
 | 
			
		||||
                        }
 | 
			
		||||
                        //Get image
 | 
			
		||||
                        it.select(".itd .it2").first()?.apply {
 | 
			
		||||
@@ -81,7 +81,6 @@ class EHentai(override val id: Long,
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    })
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        //Add to page if required
 | 
			
		||||
        val hasNextPage = select("a[onclick=return false]").last()?.let {
 | 
			
		||||
@@ -330,62 +329,32 @@ class EHentai(override val id: Long,
 | 
			
		||||
        return Pair(result as List<ParsedManga>, favNames!!)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val cookiesHeader by lazy {
 | 
			
		||||
    fun spPref() = if(exh)
 | 
			
		||||
        prefs.eh_exhSettingsProfile()
 | 
			
		||||
    else
 | 
			
		||||
        prefs.eh_ehSettingsProfile()
 | 
			
		||||
 | 
			
		||||
    fun rawCookies(sp: Int): Map<String, String> {
 | 
			
		||||
        val cookies: MutableMap<String, String> = mutableMapOf()
 | 
			
		||||
        if(prefs.enableExhentai().getOrDefault()) {
 | 
			
		||||
            cookies[LoginController.MEMBER_ID_COOKIE] = prefs.memberIdVal().get()!!
 | 
			
		||||
            cookies[LoginController.PASS_HASH_COOKIE] = prefs.passHashVal().get()!!
 | 
			
		||||
            cookies[LoginController.IGNEOUS_COOKIE] = prefs.igneousVal().get()!!
 | 
			
		||||
            cookies["sp"] = sp.toString()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Setup settings
 | 
			
		||||
        val settings = mutableListOf<String?>()
 | 
			
		||||
        //Image quality
 | 
			
		||||
        settings.add(when(prefs.imageQuality()
 | 
			
		||||
                .getOrDefault()
 | 
			
		||||
                .toLowerCase()) {
 | 
			
		||||
            "ovrs_2400" -> "xr_2400"
 | 
			
		||||
            "ovrs_1600" -> "xr_1600"
 | 
			
		||||
            "high" -> "xr_1280"
 | 
			
		||||
            "med" -> "xr_980"
 | 
			
		||||
            "low" -> "xr_780"
 | 
			
		||||
            "auto" -> null
 | 
			
		||||
            else -> null
 | 
			
		||||
        })
 | 
			
		||||
        //Use Hentai@Home
 | 
			
		||||
        settings.add(if(prefs.useHentaiAtHome().getOrDefault())
 | 
			
		||||
            null
 | 
			
		||||
        else
 | 
			
		||||
            "uh_n")
 | 
			
		||||
        //Japanese titles
 | 
			
		||||
        settings.add(if(prefs.useJapaneseTitle().getOrDefault())
 | 
			
		||||
            "tl_j"
 | 
			
		||||
        else
 | 
			
		||||
            null)
 | 
			
		||||
        //Do not show popular right now pane as we can't parse it
 | 
			
		||||
        settings.add("prn_n")
 | 
			
		||||
        //Paging size
 | 
			
		||||
        settings.add(prefs.ehSearchSize().getOrDefault())
 | 
			
		||||
        //Thumbnail rows
 | 
			
		||||
        settings.add(prefs.thumbnailRows().getOrDefault())
 | 
			
		||||
        //Session-less list display mode (for users without ExHentai)
 | 
			
		||||
        cookies["sl"] = "dm_0"
 | 
			
		||||
 | 
			
		||||
        cookies.put("uconfig", buildSettings(settings))
 | 
			
		||||
 | 
			
		||||
        buildCookies(cookies)
 | 
			
		||||
        return cookies
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun cookiesHeader(sp: Int = spPref().getOrDefault())
 | 
			
		||||
            = buildCookies(rawCookies(sp))
 | 
			
		||||
 | 
			
		||||
    //Headers
 | 
			
		||||
    override fun headersBuilder()
 | 
			
		||||
            = super.headersBuilder().add("Cookie", cookiesHeader)!!
 | 
			
		||||
 | 
			
		||||
    fun buildSettings(settings: List<String?>): String {
 | 
			
		||||
        return settings.filterNotNull().joinToString(separator = "-")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun buildCookies(cookies: Map<String, String>)
 | 
			
		||||
            = cookies.entries.joinToString(separator = "; ", postfix = ";") {
 | 
			
		||||
        "${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}"
 | 
			
		||||
    }
 | 
			
		||||
            = super.headersBuilder().add("Cookie", cookiesHeader())!!
 | 
			
		||||
 | 
			
		||||
    fun addParam(url: String, param: String, value: String)
 | 
			
		||||
            = Uri.parse(url)
 | 
			
		||||
@@ -394,11 +363,13 @@ class EHentai(override val id: Long,
 | 
			
		||||
            .toString()
 | 
			
		||||
 | 
			
		||||
    override val client = network.client.newBuilder()
 | 
			
		||||
            .cookieJar(CookieJar.NO_COOKIES)
 | 
			
		||||
            .addInterceptor { chain ->
 | 
			
		||||
                val newReq = chain
 | 
			
		||||
                        .request()
 | 
			
		||||
                        .newBuilder()
 | 
			
		||||
                        .addHeader("Cookie", cookiesHeader)
 | 
			
		||||
                        .removeHeader("Cookie")
 | 
			
		||||
                        .addHeader("Cookie", cookiesHeader())
 | 
			
		||||
                        .build()
 | 
			
		||||
 | 
			
		||||
                chain.proceed(newReq)
 | 
			
		||||
@@ -470,5 +441,11 @@ class EHentai(override val id: Long,
 | 
			
		||||
    companion object {
 | 
			
		||||
        val QUERY_PREFIX = "?f_apply=Apply+Filter"
 | 
			
		||||
        val TR_SUFFIX = "TR"
 | 
			
		||||
 | 
			
		||||
        fun buildCookies(cookies: Map<String, String>)
 | 
			
		||||
                = cookies.entries.joinToString(separator = "; ", postfix = ";") {
 | 
			
		||||
            "${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,12 @@ import android.widget.Toast
 | 
			
		||||
import com.afollestad.materialdialogs.MaterialDialog
 | 
			
		||||
import com.bluelinelabs.conductor.RouterTransaction
 | 
			
		||||
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
 | 
			
		||||
import com.f2prateek.rx.preferences.Preference
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
 | 
			
		||||
import eu.kanade.tachiyomi.util.toast
 | 
			
		||||
import exh.favorites.FavoritesIntroDialog
 | 
			
		||||
import exh.favorites.LocalFavoritesStorage
 | 
			
		||||
import exh.uconfig.ConfiguringDialogController
 | 
			
		||||
import exh.ui.login.LoginController
 | 
			
		||||
import exh.util.trans
 | 
			
		||||
import rx.android.schedulers.AndroidSchedulers
 | 
			
		||||
@@ -19,13 +21,22 @@ import rx.schedulers.Schedulers
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
class SettingsEhController : SettingsController() {
 | 
			
		||||
    private fun Preference<*>.reconfigureOnChange() {
 | 
			
		||||
        asObservable()
 | 
			
		||||
                .skip(1) //Skip first as it is emitted immediately
 | 
			
		||||
                .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                .subscribeUntilDestroy {
 | 
			
		||||
            ConfiguringDialogController().showDialog(router)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
 | 
			
		||||
        title = "E-Hentai"
 | 
			
		||||
 | 
			
		||||
        switchPreference {
 | 
			
		||||
            title = "Enable ExHentai"
 | 
			
		||||
            summaryOff = "Requires login"
 | 
			
		||||
            key = "enable_exhentai"
 | 
			
		||||
            key = PreferenceKeys.eh_enableExHentai
 | 
			
		||||
            isPersistent = false
 | 
			
		||||
            defaultValue = false
 | 
			
		||||
            preferences.enableExhentai()
 | 
			
		||||
@@ -33,8 +44,8 @@ class SettingsEhController : SettingsController() {
 | 
			
		||||
                    .subscribeOn(Schedulers.io())
 | 
			
		||||
                    .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
                    .subscribeUntilDestroy {
 | 
			
		||||
                isChecked = it
 | 
			
		||||
           }
 | 
			
		||||
                        isChecked = it
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
            onChange { newVal ->
 | 
			
		||||
                newVal as Boolean
 | 
			
		||||
@@ -55,7 +66,9 @@ class SettingsEhController : SettingsController() {
 | 
			
		||||
            summary = "Do you wish to load images through the Hentai@Home Network? Disabling this option will reduce the amount of pages you are able to view"
 | 
			
		||||
            key = "enable_hah"
 | 
			
		||||
            defaultValue = true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            preferences.useHentaiAtHome().reconfigureOnChange()
 | 
			
		||||
        }.dependency = PreferenceKeys.eh_enableExHentai
 | 
			
		||||
 | 
			
		||||
        switchPreference {
 | 
			
		||||
            title = "Show Japanese titles in search results"
 | 
			
		||||
@@ -63,7 +76,19 @@ class SettingsEhController : SettingsController() {
 | 
			
		||||
            summaryOff = "Currently showing English/Romanized titles in search results. Clear the chapter cache after changing this (in the Advanced section)"
 | 
			
		||||
            key = "use_jp_title"
 | 
			
		||||
            defaultValue = false
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            preferences.useJapaneseTitle().reconfigureOnChange()
 | 
			
		||||
        }.dependency = PreferenceKeys.eh_enableExHentai
 | 
			
		||||
 | 
			
		||||
        switchPreference {
 | 
			
		||||
            title = "Use original images"
 | 
			
		||||
            summaryOn = "Currently using original images"
 | 
			
		||||
            summaryOff = "Currently using resampled images"
 | 
			
		||||
            key = PreferenceKeys.eh_useOrigImages
 | 
			
		||||
            defaultValue = false
 | 
			
		||||
 | 
			
		||||
            preferences.eh_useOriginalImages().reconfigureOnChange()
 | 
			
		||||
        }.dependency = PreferenceKeys.eh_enableExHentai
 | 
			
		||||
 | 
			
		||||
        switchPreference {
 | 
			
		||||
            defaultValue = true
 | 
			
		||||
@@ -93,45 +118,9 @@ class SettingsEhController : SettingsController() {
 | 
			
		||||
                    "med",
 | 
			
		||||
                    "low"
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        listPreference {
 | 
			
		||||
            title = "Search result count per page"
 | 
			
		||||
            summary = "Requires the 'Paging Enlargement' hath perk"
 | 
			
		||||
            defaultValue = "rc_0"
 | 
			
		||||
            key = "ex_search_size"
 | 
			
		||||
            entries = arrayOf(
 | 
			
		||||
                    "25 results",
 | 
			
		||||
                    "50 results",
 | 
			
		||||
                    "100 results",
 | 
			
		||||
                    "200 results"
 | 
			
		||||
            )
 | 
			
		||||
            entryValues = arrayOf(
 | 
			
		||||
                    "rc_0",
 | 
			
		||||
                    "rc_1",
 | 
			
		||||
                    "rc_2",
 | 
			
		||||
                    "rc_3"
 | 
			
		||||
            )
 | 
			
		||||
        }.dependency = "enable_exhentai"
 | 
			
		||||
 | 
			
		||||
        listPreference {
 | 
			
		||||
            defaultValue = "tr_2"
 | 
			
		||||
            title = "Thumbnail rows"
 | 
			
		||||
            summary = "Affects loading speeds. It is recommended to set this to the maximum size your hath perks allow"
 | 
			
		||||
            key = "ex_thumb_rows"
 | 
			
		||||
            entries = arrayOf(
 | 
			
		||||
                    "4",
 | 
			
		||||
                    "10 (requires 'More Thumbs' hath perk)",
 | 
			
		||||
                    "20 (requires 'Thumbs Up' hath perk)",
 | 
			
		||||
                    "40 (requires 'All Thumbs' hath perk)"
 | 
			
		||||
            )
 | 
			
		||||
            entryValues = arrayOf(
 | 
			
		||||
                    "tr_2",
 | 
			
		||||
                    "tr_5",
 | 
			
		||||
                    "tr_10",
 | 
			
		||||
                    "tr_20"
 | 
			
		||||
            )
 | 
			
		||||
        }.dependency = "enable_exhentai"
 | 
			
		||||
            preferences.imageQuality().reconfigureOnChange()
 | 
			
		||||
        }.dependency = PreferenceKeys.eh_enableExHentai
 | 
			
		||||
 | 
			
		||||
        preferenceCategory {
 | 
			
		||||
            title = "Favorites sync"
 | 
			
		||||
 
 | 
			
		||||
@@ -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