Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbe29941df | ||
|
|
2720e445ea | ||
|
|
49ba579a59 |
@@ -19,8 +19,8 @@ android {
|
|||||||
applicationId "xyz.quaver.pupil"
|
applicationId "xyz.quaver.pupil"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 51
|
versionCode 52
|
||||||
versionName "4.15"
|
versionName "4.17"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
@@ -54,20 +54,19 @@ dependencies {
|
|||||||
|
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.14.0"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0"
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation 'androidx.preference:preference:1.1.0'
|
implementation 'androidx.preference:preference:1.1.1'
|
||||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||||
implementation "androidx.biometric:biometric:1.0.1"
|
implementation "androidx.biometric:biometric:1.0.1"
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
||||||
implementation 'com.google.android.material:material:1.2.0-alpha05'
|
implementation 'com.google.android.material:material:1.3.0-alpha01'
|
||||||
implementation 'com.google.firebase:firebase-core:17.2.3'
|
implementation 'com.google.firebase:firebase-core:17.4.3'
|
||||||
implementation 'com.google.firebase:firebase-perf:19.0.5'
|
implementation 'com.google.firebase:firebase-perf:19.0.7'
|
||||||
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
|
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
|
||||||
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
|
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
|
||||||
implementation 'com.github.clans:fab:1.6.4'
|
implementation 'com.github.clans:fab:1.6.4'
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":51,"versionName":"4.15","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}]
|
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":52,"versionName":"4.17","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}]
|
||||||
@@ -59,6 +59,13 @@ class Pupil : MultiDexApplication() {
|
|||||||
preference.edit().remove("dl_location").apply()
|
preference.edit().remove("dl_location").apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!preference.getBoolean("low_quality_reset", false)) {
|
||||||
|
preference.edit()
|
||||||
|
.putBoolean("low_quality", true)
|
||||||
|
.putBoolean("low_quality_reset", true)
|
||||||
|
.apply()
|
||||||
|
}
|
||||||
|
|
||||||
histories = Histories(File(ContextCompat.getDataDir(this), "histories.json"))
|
histories = Histories(File(ContextCompat.getDataDir(this), "histories.json"))
|
||||||
favorites = Histories(File(ContextCompat.getDataDir(this), "favorites.json"))
|
favorites = Histories(File(ContextCompat.getDataDir(this), "favorites.json"))
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ import io.fabric.sdk.android.Fabric
|
|||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import kotlinx.android.synthetic.main.activity_main_content.*
|
import kotlinx.android.synthetic.main.activity_main_content.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.serialization.list
|
import kotlinx.serialization.builtins.list
|
||||||
import xyz.quaver.hitomi.GalleryBlock
|
import xyz.quaver.hitomi.GalleryBlock
|
||||||
import xyz.quaver.hitomi.doSearch
|
import xyz.quaver.hitomi.doSearch
|
||||||
import xyz.quaver.hitomi.getGalleryIDsFromNozomi
|
import xyz.quaver.hitomi.getGalleryIDsFromNozomi
|
||||||
@@ -367,6 +367,29 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
with(main_fab_random) {
|
||||||
|
setImageResource(R.drawable.shuffle_variant)
|
||||||
|
setOnClickListener {
|
||||||
|
runBlocking {
|
||||||
|
withTimeoutOrNull(100) {
|
||||||
|
galleryIDs?.await()
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
if (it?.isEmpty() == false) {
|
||||||
|
val galleryID = it.random()
|
||||||
|
|
||||||
|
val intent = Intent(this@MainActivity, ReaderActivity::class.java).apply {
|
||||||
|
putExtra("galleryID", galleryID)
|
||||||
|
}
|
||||||
|
|
||||||
|
startActivity(intent)
|
||||||
|
|
||||||
|
histories.add(galleryID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
with(main_fab_id) {
|
with(main_fab_id) {
|
||||||
setImageResource(R.drawable.numeric)
|
setImageResource(R.drawable.numeric)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.android.synthetic.main.settings_activity.*
|
import kotlinx.android.synthetic.main.settings_activity.*
|
||||||
import kotlinx.serialization.list
|
import kotlinx.serialization.builtins.list
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
import net.rdrei.android.dirchooser.DirectoryChooserActivity
|
import net.rdrei.android.dirchooser.DirectoryChooserActivity
|
||||||
import xyz.quaver.pupil.Pupil
|
import xyz.quaver.pupil.Pupil
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import android.util.SparseArray
|
|||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.crashlytics.android.Crashlytics
|
import com.crashlytics.android.Crashlytics
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.io.InputStream
|
|
||||||
import xyz.quaver.Code
|
import xyz.quaver.Code
|
||||||
import xyz.quaver.hitomi.GalleryBlock
|
import xyz.quaver.hitomi.GalleryBlock
|
||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
@@ -35,10 +34,11 @@ import xyz.quaver.pupil.util.getCachedGallery
|
|||||||
import xyz.quaver.pupil.util.getDownloadDirectory
|
import xyz.quaver.pupil.util.getDownloadDirectory
|
||||||
import xyz.quaver.pupil.util.isParentOf
|
import xyz.quaver.pupil.util.isParentOf
|
||||||
import xyz.quaver.pupil.util.json
|
import xyz.quaver.pupil.util.json
|
||||||
|
import java.io.BufferedInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
import java.io.InputStream
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.concurrent.locks.Lock
|
import java.util.concurrent.locks.Lock
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ class Cache(context: Context) : ContextWrapper(context) {
|
|||||||
it.createNewFile()
|
it.createNewFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
data.use {
|
BufferedInputStream(data).use {
|
||||||
it.copyTo(FileOutputStream(cache))
|
it.copyTo(FileOutputStream(cache))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,11 +46,10 @@ import xyz.quaver.pupil.R
|
|||||||
import xyz.quaver.pupil.ui.ReaderActivity
|
import xyz.quaver.pupil.ui.ReaderActivity
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue
|
import java.util.concurrent.LinkedBlockingQueue
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@UseExperimental(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class DownloadWorker private constructor(context: Context) : ContextWrapper(context) {
|
class DownloadWorker private constructor(context: Context) : ContextWrapper(context) {
|
||||||
|
|
||||||
private val preferences : SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
private val preferences : SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
@@ -164,7 +163,10 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
.connectTimeout(0, TimeUnit.SECONDS)
|
.connectTimeout(0, TimeUnit.SECONDS)
|
||||||
.addInterceptor(interceptor)
|
.addInterceptor(interceptor)
|
||||||
.readTimeout(0, TimeUnit.SECONDS)
|
.readTimeout(0, TimeUnit.SECONDS)
|
||||||
.dispatcher(Dispatcher(Executors.newFixedThreadPool(4)))
|
.dispatcher(Dispatcher().apply {
|
||||||
|
maxRequests = 4
|
||||||
|
maxRequestsPerHost = 4
|
||||||
|
})
|
||||||
.proxy(proxy)
|
.proxy(proxy)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@@ -222,7 +224,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
imageUrlFromImage(
|
imageUrlFromImage(
|
||||||
galleryID,
|
galleryID,
|
||||||
reader.galleryInfo.files[index],
|
reader.galleryInfo.files[index],
|
||||||
lowQuality
|
!lowQuality
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
addHeader("Referer", getReferer(galleryID))
|
addHeader("Referer", getReferer(galleryID))
|
||||||
@@ -240,6 +242,8 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
}.build()
|
}.build()
|
||||||
|
|
||||||
client.newCall(request).enqueue(callback)
|
client.newCall(request).enqueue(callback)
|
||||||
|
|
||||||
|
Log.i("PUPILD", "DOWNLOADING ($galleryID, $index) from ${request.url()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch {
|
private fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
|||||||
@@ -18,13 +18,14 @@
|
|||||||
|
|
||||||
package xyz.quaver.pupil.util
|
package xyz.quaver.pupil.util
|
||||||
|
|
||||||
import kotlinx.serialization.list
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.builtins.list
|
||||||
|
import kotlinx.serialization.builtins.serializer
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class Histories(private val file: File) : ArrayList<Int>() {
|
class Histories(private val file: File) : ArrayList<Int>() {
|
||||||
|
|
||||||
val serializer = Int.serializer().list
|
val serializer: KSerializer<List<Int>> = Int.serializer().list
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (!file.exists())
|
if (!file.exists())
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ import android.content.Context
|
|||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.builtins.list
|
||||||
import kotlinx.serialization.json.JsonConfiguration
|
|
||||||
import kotlinx.serialization.list
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import android.annotation.SuppressLint
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
@UseExperimental(ExperimentalStdlibApi::class)
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
fun String.wordCapitalize() : String {
|
fun String.wordCapitalize() : String {
|
||||||
val result = ArrayList<String>()
|
val result = ArrayList<String>()
|
||||||
|
|
||||||
|
|||||||
8
app/src/main/res/drawable/shuffle_variant.xml
Normal file
8
app/src/main/res/drawable/shuffle_variant.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<!-- drawable/shuffle_variant.xml -->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="24dp"
|
||||||
|
android:width="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path android:fillColor="#fff" android:pathData="M17,3L22.25,7.5L17,12L22.25,16.5L17,21V18H14.26L11.44,15.18L13.56,13.06L15.5,15H17V12L17,9H15.5L6.5,18H2V15H5.26L14.26,6H17V3M2,6H6.5L9.32,8.82L7.2,10.94L5.26,9H2V6Z" />
|
||||||
|
</vector>
|
||||||
@@ -100,6 +100,13 @@
|
|||||||
app:fab_label="@string/main_jump_title"
|
app:fab_label="@string/main_jump_title"
|
||||||
app:fab_size="mini"/>
|
app:fab_size="mini"/>
|
||||||
|
|
||||||
|
<com.github.clans.fab.FloatingActionButton
|
||||||
|
android:id="@+id/main_fab_random"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:fab_label="@string/main_fab_random"
|
||||||
|
app:fab_size="mini"/>
|
||||||
|
|
||||||
<com.github.clans.fab.FloatingActionButton
|
<com.github.clans.fab.FloatingActionButton
|
||||||
android:id="@+id/main_fab_id"
|
android:id="@+id/main_fab_id"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -140,4 +140,5 @@
|
|||||||
<string name="import_old_galleries_folder_not_readable">フォルダを読めません</string>
|
<string name="import_old_galleries_folder_not_readable">フォルダを読めません</string>
|
||||||
<string name="import_old_galleries_notification">旧ギャラリーインポート中…</string>
|
<string name="import_old_galleries_notification">旧ギャラリーインポート中…</string>
|
||||||
<string name="import_old_galleries_notification_done">インポート完了</string>
|
<string name="import_old_galleries_notification_done">インポート完了</string>
|
||||||
|
<string name="main_fab_random">ランダムギャラリーを開く</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -140,4 +140,5 @@
|
|||||||
<string name="import_old_galleries_folder_not_readable">폴더를 읽을 수 없습니다</string>
|
<string name="import_old_galleries_folder_not_readable">폴더를 읽을 수 없습니다</string>
|
||||||
<string name="import_old_galleries_notification">이전 버전 갤러리 가져오는 중…</string>
|
<string name="import_old_galleries_notification">이전 버전 갤러리 가져오는 중…</string>
|
||||||
<string name="import_old_galleries_notification_done">가져오기 완료</string>
|
<string name="import_old_galleries_notification_done">가져오기 완료</string>
|
||||||
|
<string name="main_fab_random">무작위 갤러리 열기</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -69,6 +69,7 @@
|
|||||||
<string name="main_jump_message">Current page: %1$d\nMaximum page: %2$d</string>
|
<string name="main_jump_message">Current page: %1$d\nMaximum page: %2$d</string>
|
||||||
<string name="main_open_gallery_by_id">Open Gallery by ID</string>
|
<string name="main_open_gallery_by_id">Open Gallery by ID</string>
|
||||||
<string name="reader_failed_to_find_gallery">Failed to open gallery</string>
|
<string name="reader_failed_to_find_gallery">Failed to open gallery</string>
|
||||||
|
<string name="main_fab_random">Open a random gallery</string>
|
||||||
<string name="main_fab_cancel">Cancel all downloads</string>
|
<string name="main_fab_cancel">Cancel all downloads</string>
|
||||||
|
|
||||||
<string name="main_move">Move to page %1$d</string>
|
<string name="main_move">Move to page %1$d</string>
|
||||||
|
|||||||
@@ -50,7 +50,8 @@
|
|||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
app:key="low_quality"
|
app:key="low_quality"
|
||||||
app:title="@string/settings_low_quality"
|
app:title="@string/settings_low_quality"
|
||||||
app:summary="@string/settings_low_quality_summary"/>
|
app:summary="@string/settings_low_quality_summary"
|
||||||
|
app:defaultValue="true"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.61'
|
ext.kotlin_version = '1.3.72'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
maven { url 'https://maven.fabric.io/public' }
|
maven { url 'https://maven.fabric.io/public' }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.6.1'
|
classpath 'com.android.tools.build:gradle:3.6.3'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ dependencies {
|
|||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.14.0"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0"
|
||||||
implementation 'org.jsoup:jsoup:1.12.1'
|
implementation 'org.jsoup:jsoup:1.12.1'
|
||||||
testImplementation 'junit:junit:4.13'
|
testImplementation 'junit:junit:4.13'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,20 @@
|
|||||||
|
|
||||||
package xyz.quaver
|
package xyz.quaver
|
||||||
|
|
||||||
|
import kotlinx.serialization.UnstableDefault
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
import java.net.Proxy
|
import java.net.Proxy
|
||||||
|
|
||||||
var proxy = Proxy.NO_PROXY
|
var proxy = Proxy.NO_PROXY
|
||||||
|
|
||||||
|
@OptIn(UnstableDefault::class)
|
||||||
|
var json = Json {
|
||||||
|
isLenient = true
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
serializeSpecialFloatingPointValues = true
|
||||||
|
useArrayPolymorphism = true
|
||||||
|
}
|
||||||
|
|
||||||
fun availableInHiyobi(galleryID: Int) : Boolean {
|
fun availableInHiyobi(galleryID: Int) : Boolean {
|
||||||
return try {
|
return try {
|
||||||
xyz.quaver.hiyobi.getReader(galleryID)
|
xyz.quaver.hiyobi.getReader(galleryID)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package xyz.quaver.hitomi
|
package xyz.quaver.hitomi
|
||||||
|
|
||||||
import kotlinx.serialization.json.Json
|
import xyz.quaver.json
|
||||||
import xyz.quaver.proxy
|
import xyz.quaver.proxy
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ const val protocol = "https:"
|
|||||||
|
|
||||||
@Suppress("EXPERIMENTAL_API_USAGE")
|
@Suppress("EXPERIMENTAL_API_USAGE")
|
||||||
fun getGalleryInfo(galleryID: Int) =
|
fun getGalleryInfo(galleryID: Int) =
|
||||||
Json.nonstrict.parse(
|
json.parse(
|
||||||
GalleryInfo.serializer(),
|
GalleryInfo.serializer(),
|
||||||
URL("$protocol//$domain/galleries/$galleryID.js").openConnection(proxy).getInputStream().use {
|
URL("$protocol//$domain/galleries/$galleryID.js").openConnection(proxy).getInputStream().use {
|
||||||
it.reader().readText()
|
it.reader().readText()
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ fun sha256(data: ByteArray) : ByteArray {
|
|||||||
return MessageDigest.getInstance("SHA-256").digest(data)
|
return MessageDigest.getInstance("SHA-256").digest(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
fun hashTerm(term: String) : UByteArray {
|
fun hashTerm(term: String) : UByteArray {
|
||||||
return sha256(term.toByteArray()).toUByteArray().sliceArray(0 until 4)
|
return sha256(term.toByteArray()).toUByteArray().sliceArray(0 until 4)
|
||||||
}
|
}
|
||||||
@@ -258,9 +258,9 @@ fun getURLAtRange(url: String, range: LongRange) : ByteArray? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
data class Node(val keys: List<UByteArray>, val datas: List<Pair<Long, Int>>, val subNodeAddresses: List<Long>)
|
data class Node(val keys: List<UByteArray>, val datas: List<Pair<Long, Int>>, val subNodeAddresses: List<Long>)
|
||||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
fun decodeNode(data: ByteArray) : Node {
|
fun decodeNode(data: ByteArray) : Node {
|
||||||
val buffer = ByteBuffer
|
val buffer = ByteBuffer
|
||||||
.wrap(data)
|
.wrap(data)
|
||||||
@@ -302,7 +302,7 @@ fun decodeNode(data: ByteArray) : Node {
|
|||||||
return Node(keys, datas, subNodeAddresses)
|
return Node(keys, datas, subNodeAddresses)
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
fun bSearch(field: String, key: UByteArray, node: Node) : Pair<Long, Int>? {
|
fun bSearch(field: String, key: UByteArray, node: Node) : Pair<Long, Int>? {
|
||||||
fun compareArrayBuffers(dv1: UByteArray, dv2: UByteArray) : Int {
|
fun compareArrayBuffers(dv1: UByteArray, dv2: UByteArray) : Int {
|
||||||
val top = Math.min(dv1.size, dv2.size)
|
val top = Math.min(dv1.size, dv2.size)
|
||||||
|
|||||||
@@ -17,14 +17,14 @@
|
|||||||
package xyz.quaver.hiyobi
|
package xyz.quaver.hiyobi
|
||||||
|
|
||||||
import kotlinx.serialization.UnstableDefault
|
import kotlinx.serialization.UnstableDefault
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.builtins.list
|
||||||
import kotlinx.serialization.list
|
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import xyz.quaver.Code
|
import xyz.quaver.Code
|
||||||
import xyz.quaver.hitomi.GalleryFiles
|
import xyz.quaver.hitomi.GalleryFiles
|
||||||
import xyz.quaver.hitomi.GalleryInfo
|
import xyz.quaver.hitomi.GalleryInfo
|
||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
import xyz.quaver.hitomi.protocol
|
import xyz.quaver.hitomi.protocol
|
||||||
|
import xyz.quaver.json
|
||||||
import xyz.quaver.proxy
|
import xyz.quaver.proxy
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
@@ -62,14 +62,14 @@ fun renewCookie() : String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseExperimental(UnstableDefault::class)
|
@OptIn(UnstableDefault::class)
|
||||||
fun getReader(galleryID: Int) : Reader {
|
fun getReader(galleryID: Int) : Reader {
|
||||||
val reader = "https://$hiyobi/reader/$galleryID"
|
val reader = "https://$hiyobi/reader/$galleryID"
|
||||||
val url = "https://cdn.hiyobi.me/data/json/${galleryID}_list.json"
|
val url = "https://cdn.hiyobi.me/data/json/${galleryID}_list.json"
|
||||||
|
|
||||||
val title = Jsoup.connect(reader).proxy(proxy).get().title()
|
val title = Jsoup.connect(reader).proxy(proxy).get().title()
|
||||||
|
|
||||||
val galleryFiles = Json.nonstrict.parse(
|
val galleryFiles = json.parse(
|
||||||
GalleryFiles.serializer().list,
|
GalleryFiles.serializer().list,
|
||||||
with(URL(url).openConnection(proxy) as HttpsURLConnection) {
|
with(URL(url).openConnection(proxy) as HttpsURLConnection) {
|
||||||
setRequestProperty("User-Agent", user_agent)
|
setRequestProperty("User-Agent", user_agent)
|
||||||
|
|||||||
Reference in New Issue
Block a user