Add hiyobi image booster
This commit is contained in:
@@ -11,6 +11,7 @@ import kotlinx.coroutines.runBlocking
|
|||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import xyz.quaver.hiyobi.getReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,16 +39,7 @@ class ExampleInstrumentedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ExperimentalUnsignedTypes
|
|
||||||
fun test_doSearch() {
|
fun test_doSearch() {
|
||||||
Log.d("TEST", "Starting...")
|
getReader(1414061)
|
||||||
|
|
||||||
runBlocking {
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
Log.d("TEST", "This is started! wow")
|
|
||||||
}.join()
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d("TEST", "Finished! ...Really?")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
package xyz.quaver.pupil
|
package xyz.quaver.pupil
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
import kotlinx.android.synthetic.main.activity_gallery.*
|
import kotlinx.android.synthetic.main.activity_gallery.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
import xyz.quaver.hitomi.getReader
|
import xyz.quaver.hitomi.getReader
|
||||||
import xyz.quaver.hitomi.getReferer
|
import xyz.quaver.hitomi.getReferer
|
||||||
|
import xyz.quaver.hiyobi.hiyobi
|
||||||
import xyz.quaver.pupil.adapters.GalleryAdapter
|
import xyz.quaver.pupil.adapters.GalleryAdapter
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
import java.lang.Exception
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
|
||||||
@@ -32,9 +36,20 @@ class GalleryActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
setContentView(R.layout.activity_gallery)
|
setContentView(R.layout.activity_gallery)
|
||||||
|
|
||||||
|
supportActionBar?.title = intent.getStringExtra("GALLERY_TITLE")
|
||||||
|
|
||||||
galleryID = intent.getIntExtra("GALLERY_ID", 0)
|
galleryID = intent.getIntExtra("GALLERY_ID", 0)
|
||||||
CoroutineScope(Dispatchers.Unconfined).launch {
|
CoroutineScope(Dispatchers.Unconfined).launch {
|
||||||
reader = async(Dispatchers.IO) {
|
reader = async(Dispatchers.IO) {
|
||||||
|
val preference = PreferenceManager.getDefaultSharedPreferences(this@GalleryActivity)
|
||||||
|
if (preference.getBoolean("use_hiyobi", false)) {
|
||||||
|
try {
|
||||||
|
xyz.quaver.hiyobi.getReader(galleryID)
|
||||||
|
Log.d("Pupil", "Using Hiyobi.me")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
getReader(galleryID)
|
||||||
|
}
|
||||||
|
}
|
||||||
getReader(galleryID)
|
getReader(galleryID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,17 +93,15 @@ class GalleryActivity : AppCompatActivity() {
|
|||||||
val reader = reader.await()
|
val reader = reader.await()
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
supportActionBar?.title = reader.title
|
|
||||||
|
|
||||||
with(gallery_progressbar) {
|
with(gallery_progressbar) {
|
||||||
max = reader.images.size
|
max = reader.size
|
||||||
progress = 0
|
progress = 0
|
||||||
|
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.images.chunked(8).forEach { chunked ->
|
reader.chunked(8).forEach { chunked ->
|
||||||
chunked.map {
|
chunked.map {
|
||||||
async(Dispatchers.IO) {
|
async(Dispatchers.IO) {
|
||||||
val url = if (it.second?.haswebp == 1) webpUrlFromUrl(it.first) else it.first
|
val url = if (it.second?.haswebp == 1) webpUrlFromUrl(it.first) else it.first
|
||||||
|
|||||||
@@ -176,9 +176,10 @@ class MainActivity : AppCompatActivity() {
|
|||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
with(main_recyclerview) {
|
with(main_recyclerview) {
|
||||||
adapter = GalleryBlockAdapter(galleries).apply {
|
adapter = GalleryBlockAdapter(galleries).apply {
|
||||||
setClickListener {
|
setClickListener { galleryID, title ->
|
||||||
val intent = Intent(this@MainActivity, GalleryActivity::class.java)
|
val intent = Intent(this@MainActivity, GalleryActivity::class.java)
|
||||||
intent.putExtra("GALLERY_ID", it)
|
intent.putExtra("GALLERY_ID", galleryID)
|
||||||
|
intent.putExtra("GALLERY_TITLE", title)
|
||||||
|
|
||||||
//TODO: Maybe sprinke some transitions will be nice :D
|
//TODO: Maybe sprinke some transitions will be nice :D
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Bitmap?
|
|||||||
class ViewHolder(val view: CardView) : RecyclerView.ViewHolder(view)
|
class ViewHolder(val view: CardView) : RecyclerView.ViewHolder(view)
|
||||||
class ProgressViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view)
|
class ProgressViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view)
|
||||||
|
|
||||||
private var callback: ((Int) -> Unit)? = null
|
private var callback: ((Int, String) -> Unit)? = null
|
||||||
fun setClickListener(callback: ((Int) -> Unit)?) {
|
fun setClickListener(callback: ((Int, String) -> Unit)?) {
|
||||||
this.callback = callback
|
this.callback = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Bitmap?
|
|||||||
val series = gallery.series.ifEmpty { listOf("N/A") }
|
val series = gallery.series.ifEmpty { listOf("N/A") }
|
||||||
|
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
callback?.invoke(gallery.id)
|
callback?.invoke(gallery.id, gallery.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
galleryblock_thumbnail.setImageBitmap(thumbnail)
|
galleryblock_thumbnail.setImageBitmap(thumbnail)
|
||||||
|
|||||||
BIN
app/src/main/res/drawable/side_nav_bar.png
Normal file
BIN
app/src/main/res/drawable/side_nav_bar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@@ -30,4 +30,14 @@
|
|||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
app:title="Image loading">
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
app:key="use_hiyobi"
|
||||||
|
app:title="Use hiyobi.me"
|
||||||
|
app:summary="Use hiyobi.me to improve image loading speed if available"/>
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
</androidx.preference.PreferenceScreen>
|
</androidx.preference.PreferenceScreen>
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package xyz.quaver.hitomi
|
package xyz.quaver.hitomi
|
||||||
|
|
||||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonConfiguration
|
import kotlinx.serialization.json.JsonConfiguration
|
||||||
import kotlinx.serialization.list
|
import kotlinx.serialization.list
|
||||||
import kotlinx.serialization.parseList
|
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
@@ -18,10 +16,7 @@ data class GalleryInfo(
|
|||||||
val name: String,
|
val name: String,
|
||||||
val height: Int
|
val height: Int
|
||||||
)
|
)
|
||||||
data class Reader(
|
typealias Reader = List<Pair<URL, GalleryInfo?>>
|
||||||
val title: String,
|
|
||||||
val images: List<Pair<URL, GalleryInfo?>>
|
|
||||||
)
|
|
||||||
//Set header `Referer` to reader url to avoid 403 error
|
//Set header `Referer` to reader url to avoid 403 error
|
||||||
fun getReader(galleryID: Int) : Reader {
|
fun getReader(galleryID: Int) : Reader {
|
||||||
val readerUrl = "https://hitomi.la/reader/$galleryID.html"
|
val readerUrl = "https://hitomi.la/reader/$galleryID.html"
|
||||||
@@ -29,8 +24,6 @@ fun getReader(galleryID: Int) : Reader {
|
|||||||
|
|
||||||
val doc = Jsoup.connect(readerUrl).get()
|
val doc = Jsoup.connect(readerUrl).get()
|
||||||
|
|
||||||
val title = doc.selectFirst("title").text()
|
|
||||||
|
|
||||||
val images = doc.select(".img-url").map {
|
val images = doc.select(".img-url").map {
|
||||||
URL(protocol + urlFromURL(it.text()))
|
URL(protocol + urlFromURL(it.text()))
|
||||||
}
|
}
|
||||||
@@ -49,5 +42,5 @@ fun getReader(galleryID: Int) : Reader {
|
|||||||
if (images.size > galleryInfo.size)
|
if (images.size > galleryInfo.size)
|
||||||
galleryInfo.addAll(arrayOfNulls(images.size - galleryInfo.size))
|
galleryInfo.addAll(arrayOfNulls(images.size - galleryInfo.size))
|
||||||
|
|
||||||
return Reader(title, images zip galleryInfo)
|
return images zip galleryInfo
|
||||||
}
|
}
|
||||||
47
libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt
Normal file
47
libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package xyz.quaver.hiyobi
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonConfiguration
|
||||||
|
import kotlinx.serialization.json.content
|
||||||
|
import xyz.quaver.hitomi.Reader
|
||||||
|
import java.net.URL
|
||||||
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
|
||||||
|
const val hiyobi = "xn--9w3b15m8vo.asia"
|
||||||
|
const val user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36"
|
||||||
|
|
||||||
|
var cookie: String = ""
|
||||||
|
|
||||||
|
fun renewCookie() : String {
|
||||||
|
val url = "https://$hiyobi/"
|
||||||
|
|
||||||
|
with(URL(url).openConnection() as HttpsURLConnection) {
|
||||||
|
setRequestProperty("User-Agent", user_agent)
|
||||||
|
connectTimeout = 2000
|
||||||
|
connect()
|
||||||
|
return headerFields["Set-Cookie"]!![0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getReader(galleryId: Int) : Reader {
|
||||||
|
val url = "https://$hiyobi/data/json/${galleryId}_list.json"
|
||||||
|
|
||||||
|
if (cookie.isEmpty())
|
||||||
|
cookie = renewCookie()
|
||||||
|
|
||||||
|
val json = Json(JsonConfiguration.Stable).parseJson(
|
||||||
|
with(URL(url).openConnection() as HttpsURLConnection) {
|
||||||
|
setRequestProperty("User-Agent", user_agent)
|
||||||
|
setRequestProperty("Cookie", cookie)
|
||||||
|
connectTimeout = 2000
|
||||||
|
connect()
|
||||||
|
|
||||||
|
inputStream.bufferedReader().use { it.readText() }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return json.jsonArray.map {
|
||||||
|
val name = it.jsonObject["name"]!!.content
|
||||||
|
Pair(URL("https://$hiyobi/data/$galleryId/$name"), null)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,4 +61,9 @@ class UnitTest {
|
|||||||
|
|
||||||
print(reader)
|
print(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_hiyobi() {
|
||||||
|
xyz.quaver.hiyobi.getReader(1414061)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user