Fix gallery browsing

This commit is contained in:
NerdNumber9
2018-02-12 16:22:54 -05:00
parent 47966d89f2
commit 2b7c0e8e80
13 changed files with 442 additions and 103 deletions

View File

@ -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!")

View File

@ -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] }

View File

@ -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"

View 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)
}
}

View 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"
}
}

View 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)"
}

View 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
}