Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a325440f24 | |||
| 14072bb5a0 | |||
| 7fc33ba8db | |||
| 47e51b6615 | |||
| 857562eaff | |||
| bace854b50 | |||
| e4a404472d | |||
| 7bfa215b4c | |||
| ab7af4b80b | |||
| 2c7ebd8ece | |||
| c96da79058 | |||
| 8f09ebacf5 | |||
| e21f3b9c75 | |||
| 37eeef06e2 | |||
| b7fe56687c | |||
| 60565729ca | |||
| 36f4e1c340 | |||
| abc2a5214b | |||
| a29010e0d7 | |||
| db99ab66ae | |||
| 84cc73c149 | |||
| 10a29cab33 | |||
| 849e2f103a | |||
| 6c22fe193a | |||
| e69dbbf418 | |||
| dfa59a1691 | |||
| 5023e96301 | |||
| 224c24ee9f | |||
| e3b154cf9e | |||
| d249867c4c | |||
| b56045e984 | |||
| 3777cc646e | |||
| aa5a1083d0 | |||
| 2ae5e0742e | |||
| e5e875c54a | |||
| 1a99ec76e4 | |||
| 1b122d1157 | |||
| 77f2f8cc18 | |||
| f0a99980b6 | |||
| b0d43ffe69 | |||
| 16cb0184a4 | |||
| f211a33ea3 | |||
| 440c815189 | |||
| 25829aacfd | |||
| 700a739f95 | |||
| d9620bec05 |
@@ -23,7 +23,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Cancel previous runs
|
||||
uses: styfle/cancel-workflow-action@0.5.0
|
||||
uses: styfle/cancel-workflow-action@0.9.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
@@ -48,14 +48,14 @@ jobs:
|
||||
- name: Download android.jar
|
||||
run: |
|
||||
cd master
|
||||
curl https://raw.githubusercontent.com/AriaMoradi/Tachidesk/android-jar/android.jar -o AndroidCompat/lib/android.jar
|
||||
curl https://raw.githubusercontent.com/Suwayomi/Tachidesk/android-jar/android.jar -o AndroidCompat/lib/android.jar
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
**/react/node_modules
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/react/yarn.lock') }}
|
||||
**/webUI/node_modules
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/webUI/yarn.lock') }}
|
||||
|
||||
- name: Build and copy webUI, Build Jar
|
||||
uses: eskatos/gradle-command-action@v1
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Cancel previous runs
|
||||
uses: styfle/cancel-workflow-action@0.5.0
|
||||
uses: styfle/cancel-workflow-action@0.9.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
@@ -50,19 +50,19 @@ jobs:
|
||||
- name: Download android.jar
|
||||
run: |
|
||||
cd master
|
||||
curl https://raw.githubusercontent.com/AriaMoradi/Tachidesk/android-jar/android.jar -o AndroidCompat/lib/android.jar
|
||||
curl https://raw.githubusercontent.com/Suwayomi/Tachidesk/android-jar/android.jar -o AndroidCompat/lib/android.jar
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
**/react/node_modules
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/react/yarn.lock') }}
|
||||
**/webUI/node_modules
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/webUI/yarn.lock') }}
|
||||
|
||||
- name: Build and copy webUI, Build Jar
|
||||
uses: eskatos/gradle-command-action@v1
|
||||
env:
|
||||
TachideskBuildType: "Preview"
|
||||
ProductBuildType: "Preview"
|
||||
with:
|
||||
build-root-directory: master
|
||||
wrapper-directory: master
|
||||
@@ -127,3 +127,7 @@ jobs:
|
||||
owner: "Suwayomi"
|
||||
repo: "Tachidesk-preview"
|
||||
tag: ${{ steps.GenTagName.outputs.value }}
|
||||
|
||||
- name: Run Docker build workflow
|
||||
run: |
|
||||
curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.DEPLOY_PREVIEW_TOKEN }}" -d '{"ref":"main", "inputs":{"tachidesk_release_type": "preview"}}' https://api.github.com/repos/suwayomi/docker-tachidesk/actions/workflows/build_container_images.yml/dispatches
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Cancel previous runs
|
||||
uses: styfle/cancel-workflow-action@0.5.0
|
||||
uses: styfle/cancel-workflow-action@0.9.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
@@ -49,19 +49,19 @@ jobs:
|
||||
- name: Download android.jar
|
||||
run: |
|
||||
cd master
|
||||
curl https://raw.githubusercontent.com/AriaMoradi/Tachidesk/android-jar/android.jar -o AndroidCompat/lib/android.jar
|
||||
curl https://raw.githubusercontent.com/Suwayomi/Tachidesk/android-jar/android.jar -o AndroidCompat/lib/android.jar
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
**/react/node_modules
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/react/yarn.lock') }}
|
||||
**/webUI/node_modules
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/webUI/yarn.lock') }}
|
||||
|
||||
- name: Build and copy webUI, Build Jar
|
||||
uses: eskatos/gradle-command-action@v1
|
||||
env:
|
||||
TachideskBuildType: "Stable"
|
||||
ProductBuildType: "Stable"
|
||||
with:
|
||||
build-root-directory: master
|
||||
wrapper-directory: master
|
||||
@@ -85,3 +85,8 @@ jobs:
|
||||
tags: true
|
||||
draft: true
|
||||
verbose: true
|
||||
|
||||
- name: Run Docker build workflow
|
||||
run: |
|
||||
curl -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.DEPLOY_PREVIEW_TOKEN }}" -d '{"ref":"main", "inputs":{"tachidesk_release_type": "stable"}}' https://api.github.com/repos/suwayomi/docker-tachidesk/actions/workflows/build_container_images.yml/dispatches
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ gradle.properties
|
||||
# Ignore Gradle build output directory
|
||||
build
|
||||
|
||||
server/src/main/resources/react
|
||||
server/src/main/resources/webUI
|
||||
server/tmp/
|
||||
server/tachiserver-data/
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import net.harawata.appdirs.AppDirsFactory
|
||||
val ApplicationRootDir: String
|
||||
get(): String {
|
||||
return System.getProperty(
|
||||
"suwayomi.server.rootDir",
|
||||
"suwayomi.tachidesk.server.rootDir",
|
||||
AppDirsFactory.getInstance().getUserDataDir("Tachidesk", null, null)
|
||||
)
|
||||
}
|
||||
@@ -17,4 +17,4 @@ fun setLogLevel(level: Level) {
|
||||
}
|
||||
|
||||
fun debugLogsEnabled(config: Config)
|
||||
= System.getProperty("suwayomi.server.debugLogsEnabled", config.getString("server.debugLogsEnabled")).toBoolean()
|
||||
= System.getProperty("suwayomi.tachidesk.server.debugLogsEnabled", config.getString("server.debugLogsEnabled")).toBoolean()
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
plugins {
|
||||
application
|
||||
kotlin("plugin.serialization")
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +47,17 @@ dependencies {
|
||||
implementation("org.mozilla:rhino-runtime:1.7.13")
|
||||
// 'org.mozilla:rhino-engine' provides the same interface as 'javax.script' a.k.a Nashorn
|
||||
implementation("org.mozilla:rhino-engine:1.7.13")
|
||||
|
||||
// Kotlin wrapper around Java Preferences, makes certain things easier
|
||||
val multiplatformSettingsVersion = "0.7.7"
|
||||
implementation("com.russhwolf:multiplatform-settings-jvm:$multiplatformSettingsVersion")
|
||||
implementation("com.russhwolf:multiplatform-settings-serialization-jvm:$multiplatformSettingsVersion")
|
||||
}
|
||||
|
||||
tasks {
|
||||
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions.freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn")
|
||||
}
|
||||
}
|
||||
|
||||
//def fatJarTask = tasks.getByPath(':AndroidCompat:JVMPatch:fatJar')
|
||||
|
||||
+9
-10
@@ -38,7 +38,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import xyz.nulldev.androidcompat.info.ApplicationInfoImpl;
|
||||
import xyz.nulldev.androidcompat.io.AndroidFiles;
|
||||
import xyz.nulldev.androidcompat.io.sharedprefs.JsonSharedPreferences;
|
||||
import xyz.nulldev.androidcompat.io.sharedprefs.JavaSharedPreferences;
|
||||
import xyz.nulldev.androidcompat.service.ServiceSupport;
|
||||
import xyz.nulldev.androidcompat.util.KodeinGlobalHelper;
|
||||
|
||||
@@ -165,23 +165,22 @@ public class CustomContext extends Context implements DIAware {
|
||||
/** Fake shared prefs! **/
|
||||
private Map<String, SharedPreferences> prefs = new HashMap<>(); //Cache
|
||||
|
||||
private File sharedPrefsFileFromString(String s) {
|
||||
return new File(androidFiles.getPrefsDir(), s + ".json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized SharedPreferences getSharedPreferences(String s, int i) {
|
||||
SharedPreferences preferences = prefs.get(s);
|
||||
//Create new shared preferences if one does not exist
|
||||
if(preferences == null) {
|
||||
preferences = getSharedPreferences(sharedPrefsFileFromString(s), i);
|
||||
preferences = new JavaSharedPreferences(s);
|
||||
prefs.put(s, preferences);
|
||||
}
|
||||
return preferences;
|
||||
}
|
||||
|
||||
public SharedPreferences getSharedPreferences(File file, int mode) {
|
||||
return new JsonSharedPreferences(file);
|
||||
@Override
|
||||
public SharedPreferences getSharedPreferences(@NotNull File file, int mode) {
|
||||
String path = file.getAbsolutePath().replace('\\', '/');
|
||||
int firstSlash = path.indexOf("/");
|
||||
return new JavaSharedPreferences(path.substring(firstSlash));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -191,8 +190,8 @@ public class CustomContext extends Context implements DIAware {
|
||||
|
||||
@Override
|
||||
public boolean deleteSharedPreferences(String name) {
|
||||
prefs.remove(name);
|
||||
return sharedPrefsFileFromString(name).delete();
|
||||
JavaSharedPreferences item = (JavaSharedPreferences) prefs.remove(name);
|
||||
return item.deleteAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,8 +26,6 @@ class AndroidFiles(val configManager: ConfigManager = GlobalConfigManager) {
|
||||
val downloadCacheDir: File get() = registerFile(filesConfig.downloadCacheDir)
|
||||
val databasesDir: File get() = registerFile(filesConfig.databasesDir)
|
||||
|
||||
val prefsDir: File get() = registerFile(filesConfig.prefsDir)
|
||||
|
||||
val packagesDir: File get() = registerFile(filesConfig.packageDir)
|
||||
|
||||
fun registerFile(file: String): File {
|
||||
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
package xyz.nulldev.androidcompat.io.sharedprefs
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import com.russhwolf.settings.ExperimentalSettingsApi
|
||||
import com.russhwolf.settings.ExperimentalSettingsImplementation
|
||||
import com.russhwolf.settings.JvmPreferencesSettings
|
||||
import com.russhwolf.settings.serialization.decodeValue
|
||||
import com.russhwolf.settings.serialization.encodeValue
|
||||
import com.russhwolf.settings.set
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.SerializationException
|
||||
import kotlinx.serialization.builtins.SetSerializer
|
||||
import kotlinx.serialization.builtins.nullable
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import java.util.prefs.PreferenceChangeListener
|
||||
import java.util.prefs.Preferences
|
||||
|
||||
@OptIn(ExperimentalSettingsImplementation::class, ExperimentalSerializationApi::class, ExperimentalSettingsApi::class)
|
||||
class JavaSharedPreferences(key: String) : SharedPreferences {
|
||||
private val javaPreferences = Preferences.userRoot().node("suwayomi/tachidesk/$key")
|
||||
private val preferences = JvmPreferencesSettings(javaPreferences)
|
||||
private val listeners = mutableMapOf<SharedPreferences.OnSharedPreferenceChangeListener, PreferenceChangeListener>()
|
||||
|
||||
// TODO: 2021-05-29 Need to find a way to get this working with all pref types
|
||||
override fun getAll(): MutableMap<String, *> {
|
||||
return preferences.keys.associateWith { preferences.getStringOrNull(it) }.toMutableMap()
|
||||
}
|
||||
|
||||
override fun getString(key: String, defValue: String?): String? {
|
||||
return if (defValue != null) {
|
||||
preferences.getString(key, defValue)
|
||||
} else {
|
||||
preferences.getStringOrNull(key)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getStringSet(key: String, defValues: MutableSet<String>?): MutableSet<String>? {
|
||||
try {
|
||||
return if (defValues != null) {
|
||||
preferences.decodeValue(SetSerializer(String.serializer()).nullable, key, defValues)
|
||||
} else {
|
||||
preferences.decodeValue(SetSerializer(String.serializer()).nullable, key, null)
|
||||
}?.toMutableSet()
|
||||
} catch (e: SerializationException) {
|
||||
throw ClassCastException("$key was not a StringSet")
|
||||
}
|
||||
}
|
||||
|
||||
override fun getInt(key: String, defValue: Int): Int {
|
||||
return preferences.getInt(key, defValue)
|
||||
}
|
||||
|
||||
override fun getLong(key: String, defValue: Long): Long {
|
||||
return preferences.getLong(key, defValue)
|
||||
}
|
||||
|
||||
override fun getFloat(key: String, defValue: Float): Float {
|
||||
return preferences.getFloat(key, defValue)
|
||||
}
|
||||
|
||||
override fun getBoolean(key: String, defValue: Boolean): Boolean {
|
||||
return preferences.getBoolean(key, defValue)
|
||||
}
|
||||
|
||||
override fun contains(key: String): Boolean {
|
||||
return key in preferences.keys
|
||||
}
|
||||
|
||||
override fun edit(): SharedPreferences.Editor {
|
||||
return Editor(preferences)
|
||||
}
|
||||
|
||||
class Editor(private val preferences: JvmPreferencesSettings) : SharedPreferences.Editor {
|
||||
val itemsToAdd = mutableMapOf<String, Any>()
|
||||
|
||||
override fun putString(key: String, value: String?): SharedPreferences.Editor {
|
||||
if (value != null) {
|
||||
itemsToAdd[key] = value
|
||||
} else {
|
||||
remove(key)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
override fun putStringSet(
|
||||
key: String,
|
||||
values: MutableSet<String>?
|
||||
): SharedPreferences.Editor {
|
||||
if (values != null) {
|
||||
itemsToAdd[key] = values
|
||||
} else {
|
||||
remove(key)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
override fun putInt(key: String, value: Int): SharedPreferences.Editor {
|
||||
itemsToAdd[key] = value
|
||||
return this
|
||||
}
|
||||
|
||||
override fun putLong(key: String, value: Long): SharedPreferences.Editor {
|
||||
itemsToAdd[key] = value
|
||||
return this
|
||||
}
|
||||
|
||||
override fun putFloat(key: String, value: Float): SharedPreferences.Editor {
|
||||
itemsToAdd[key] = value
|
||||
return this
|
||||
}
|
||||
|
||||
override fun putBoolean(key: String, value: Boolean): SharedPreferences.Editor {
|
||||
itemsToAdd[key] = value
|
||||
return this
|
||||
}
|
||||
|
||||
override fun remove(key: String): SharedPreferences.Editor {
|
||||
itemsToAdd.remove(key)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun clear(): SharedPreferences.Editor {
|
||||
itemsToAdd.clear()
|
||||
return this
|
||||
}
|
||||
|
||||
override fun commit(): Boolean {
|
||||
addToPreferences()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
addToPreferences()
|
||||
}
|
||||
|
||||
private fun addToPreferences() {
|
||||
itemsToAdd.forEach { (key, value) ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
when (value) {
|
||||
is Set<*> -> preferences.encodeValue(SetSerializer(String.serializer()), key, value as Set<String>)
|
||||
else -> {
|
||||
preferences[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun registerOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
|
||||
val javaListener = PreferenceChangeListener {
|
||||
listener.onSharedPreferenceChanged(this, it.key)
|
||||
}
|
||||
listeners[listener] = javaListener
|
||||
javaPreferences.addPreferenceChangeListener(javaListener)
|
||||
}
|
||||
|
||||
override fun unregisterOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
|
||||
val registeredListener = listeners.remove(listener)
|
||||
if (registeredListener != null) {
|
||||
javaPreferences.removePreferenceChangeListener(registeredListener)
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteAll(): Boolean {
|
||||
javaPreferences.removeNode()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ Here is a list of current features:
|
||||
- A library to save your mangas and categories to put them into.
|
||||
- Searching and browsing installed sources.
|
||||
- A decent chapter reader.
|
||||
- Ability to download Mangas for offline read(This partially works)
|
||||
- Ability to download Mangas for offline read
|
||||
- Backup and restore support powered by Tachiyomi Legacy Backups
|
||||
|
||||
**Note:** Keep in mind that Tachidesk is alpha software and can break rarely and/or with each update. See [Troubleshooting](https://github.com/Suwayomi/Tachidesk/wiki/Troubleshooting) if it happens.
|
||||
|
||||
@@ -2,6 +2,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.4.32"
|
||||
kotlin("plugin.serialization") version "1.4.32" apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -50,6 +51,10 @@ configure(projects) {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$coroutinesVersion")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion")
|
||||
|
||||
val kotlinSerializationVersion = "1.1.0"
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinSerializationVersion")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:$kotlinSerializationVersion")
|
||||
|
||||
|
||||
// Dependency Injection
|
||||
implementation("org.kodein.di:kodein-di-conf-jvm:7.5.0")
|
||||
|
||||
@@ -1 +1 @@
|
||||
jre\bin\java -Dsuwayomi.server.debugLogsEnabled=true -jar Tachidesk.jar
|
||||
jre\bin\java -Dsuwayomi.tachidesk.server.debugLogsEnabled=true -jar Tachidesk.jar
|
||||
|
||||
@@ -1 +1 @@
|
||||
jre\bin\javaw "-Dsuwayomi.server.webInterface=electron" "-Dsuwayomi.server.electronPath=electron/electron.exe" -jar Tachidesk.jar
|
||||
jre\bin\javaw "-Dsuwayomi.tachidesk.server.webInterface=electron" "-Dsuwayomi.tachidesk.server.electronPath=electron/electron.exe" -jar Tachidesk.jar
|
||||
|
||||
@@ -22,9 +22,9 @@ jre_dir="jdk8u292-b10-jre"
|
||||
|
||||
echo "creating windows bundle"
|
||||
|
||||
jar=$(ls ../server/build/Tachidesk-*.jar)
|
||||
jar=$(ls ../server/build/*.jar | tail -n1)
|
||||
jar_name=$(echo $jar | cut -d'/' -f4)
|
||||
release_name=$(echo $jar_name | cut -d'.' -f4 --complement)-$arch
|
||||
release_name=$(echo $jar_name | sed 's/.jar//')-$arch
|
||||
|
||||
|
||||
# make release dir
|
||||
|
||||
@@ -73,7 +73,7 @@ dependencies {
|
||||
testImplementation(kotlin("test-junit5"))
|
||||
}
|
||||
|
||||
val MainClass = "suwayomi.MainKt"
|
||||
val MainClass = "suwayomi.tachidesk.MainKt"
|
||||
application {
|
||||
mainClass.set(MainClass)
|
||||
|
||||
@@ -93,11 +93,11 @@ sourceSets {
|
||||
}
|
||||
|
||||
// should be bumped with each stable release
|
||||
val tachideskVersion = "v0.4.0"
|
||||
val tachideskVersion = System.getenv("ProductVersion") ?: "v0.4.3"
|
||||
|
||||
// counts commit count on master
|
||||
val tachideskRevision = runCatching {
|
||||
Runtime
|
||||
System.getenv("ProductRevision") ?: Runtime
|
||||
.getRuntime()
|
||||
.exec("git rev-list HEAD --count")
|
||||
.let { process ->
|
||||
@@ -107,7 +107,6 @@ val tachideskRevision = runCatching {
|
||||
}
|
||||
process.destroy()
|
||||
"r" + output.trim()
|
||||
|
||||
}
|
||||
}.getOrDefault("r0")
|
||||
|
||||
@@ -119,7 +118,7 @@ buildConfig {
|
||||
buildConfigField("String", "NAME", rootProject.name)
|
||||
buildConfigField("String", "VERSION", tachideskVersion)
|
||||
buildConfigField("String", "REVISION", tachideskRevision)
|
||||
buildConfigField("String", "BUILD_TYPE", if (System.getenv("TachideskBuildType") == "Stable") "Stable" else "Preview")
|
||||
buildConfigField("String", "BUILD_TYPE", if (System.getenv("ProductBuildType") == "Stable") "Stable" else "Preview")
|
||||
buildConfigField("long", "BUILD_TIME", Instant.now().epochSecond.toString())
|
||||
|
||||
buildConfigField("String", "GITHUB", "https://github.com/Suwayomi/Tachidesk")
|
||||
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.tachiyomi.source
|
||||
package eu.kanade.tachiyomi.animesource
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||
import rx.Observable
|
||||
|
||||
interface AnimeCatalogueSource : AnimeSource {
|
||||
@@ -30,7 +30,7 @@ interface AnimeCatalogueSource : AnimeSource {
|
||||
* @param query the search query.
|
||||
* @param filters the list of filters to apply.
|
||||
*/
|
||||
fun fetchSearchAnime(page: Int, query: String, filters: FilterList): Observable<AnimesPage>
|
||||
fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage>
|
||||
|
||||
/**
|
||||
* Returns an observable containing a page with a list of latest anime updates.
|
||||
@@ -42,5 +42,5 @@ interface AnimeCatalogueSource : AnimeSource {
|
||||
/**
|
||||
* Returns the list of filters for the source.
|
||||
*/
|
||||
fun getFilterList(): FilterList
|
||||
fun getFilterList(): AnimeFilterList
|
||||
}
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.kanade.tachiyomi.source
|
||||
package eu.kanade.tachiyomi.animesource
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SAnime
|
||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import rx.Observable
|
||||
|
||||
/**
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.tachiyomi.source
|
||||
package eu.kanade.tachiyomi.animesource
|
||||
|
||||
/**
|
||||
* A factory for creating sources at runtime.
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
package eu.kanade.tachiyomi.source
|
||||
package eu.kanade.tachiyomi.animesource
|
||||
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.source.model.SAnime
|
||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
||||
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
||||
import rx.Observable
|
||||
|
||||
open class AnimeSourceManager(private val context: Context) {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.tachiyomi.source
|
||||
package eu.kanade.tachiyomi.animesource
|
||||
|
||||
import android.support.v7.preference.PreferenceScreen
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package eu.kanade.tachiyomi.animesource.model
|
||||
|
||||
sealed class AnimeFilter<T>(val name: String, var state: T) {
|
||||
open class Header(name: String) : AnimeFilter<Any>(name, 0)
|
||||
open class Separator(name: String = "") : AnimeFilter<Any>(name, 0)
|
||||
abstract class Select<V>(name: String, val values: Array<V>, state: Int = 0) : AnimeFilter<Int>(name, state)
|
||||
abstract class Text(name: String, state: String = "") : AnimeFilter<String>(name, state)
|
||||
abstract class CheckBox(name: String, state: Boolean = false) : AnimeFilter<Boolean>(name, state)
|
||||
abstract class TriState(name: String, state: Int = STATE_IGNORE) : AnimeFilter<Int>(name, state) {
|
||||
fun isIgnored() = state == STATE_IGNORE
|
||||
fun isIncluded() = state == STATE_INCLUDE
|
||||
fun isExcluded() = state == STATE_EXCLUDE
|
||||
|
||||
companion object {
|
||||
const val STATE_IGNORE = 0
|
||||
const val STATE_INCLUDE = 1
|
||||
const val STATE_EXCLUDE = 2
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Group<V>(name: String, state: List<V>) : AnimeFilter<List<V>>(name, state)
|
||||
|
||||
abstract class Sort(name: String, val values: Array<String>, state: Selection? = null) :
|
||||
AnimeFilter<Sort.Selection?>(name, state) {
|
||||
data class Selection(val index: Int, val ascending: Boolean)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is AnimeFilter<*>) return false
|
||||
|
||||
return name == other.name && state == other.state
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = name.hashCode()
|
||||
result = 31 * result + (state?.hashCode() ?: 0)
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package eu.kanade.tachiyomi.animesource.model
|
||||
|
||||
data class AnimeFilterList(val list: List<AnimeFilter<*>>) : List<AnimeFilter<*>> by list {
|
||||
|
||||
constructor(vararg fs: AnimeFilter<*>) : this(if (fs.isNotEmpty()) fs.asList() else emptyList())
|
||||
}
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
package eu.kanade.tachiyomi.animesource.model
|
||||
|
||||
data class AnimesPage(val animes: List<SAnime>, val hasNextPage: Boolean)
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
package eu.kanade.tachiyomi.animesource.model
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
package eu.kanade.tachiyomi.animesource.model
|
||||
|
||||
class SAnimeImpl : SAnime {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
package eu.kanade.tachiyomi.animesource.model
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
package eu.kanade.tachiyomi.animesource.model
|
||||
|
||||
class SEpisodeImpl : SEpisode {
|
||||
|
||||
+9
-9
@@ -1,15 +1,15 @@
|
||||
package eu.kanade.tachiyomi.source.online
|
||||
package eu.kanade.tachiyomi.animesource.online
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.network.newCallWithProgress
|
||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.model.SAnime
|
||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
@@ -118,7 +118,7 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
|
||||
* @param query the search query.
|
||||
* @param filters the list of filters to apply.
|
||||
*/
|
||||
override fun fetchSearchAnime(page: Int, query: String, filters: FilterList): Observable<AnimesPage> {
|
||||
override fun fetchSearchAnime(page: Int, query: String, filters: AnimeFilterList): Observable<AnimesPage> {
|
||||
return client.newCall(searchAnimeRequest(page, query, filters))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
@@ -133,7 +133,7 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
|
||||
* @param query the search query.
|
||||
* @param filters the list of filters to apply.
|
||||
*/
|
||||
protected abstract fun searchAnimeRequest(page: Int, query: String, filters: FilterList): Request
|
||||
protected abstract fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request
|
||||
|
||||
/**
|
||||
* Parses the response from the site and returns a [AnimesPage] object.
|
||||
@@ -380,7 +380,7 @@ abstract class AnimeHttpSource : AnimeCatalogueSource {
|
||||
/**
|
||||
* Returns the list of filters for the source.
|
||||
*/
|
||||
override fun getFilterList() = FilterList()
|
||||
override fun getFilterList() = AnimeFilterList()
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63"
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import rx.Observable
|
||||
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
package eu.kanade.tachiyomi.source.online
|
||||
package eu.kanade.tachiyomi.animesource.online
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.model.SAnime
|
||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
@@ -1,12 +0,0 @@
|
||||
package suwayomi.anime.impl.extension.github
|
||||
|
||||
data class OnlineExtension(
|
||||
val name: String,
|
||||
val pkgName: String,
|
||||
val versionName: String,
|
||||
val versionCode: Int,
|
||||
val lang: String,
|
||||
val isNsfw: Boolean,
|
||||
val apkName: String,
|
||||
val iconUrl: String
|
||||
)
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package suwayomi
|
||||
package suwayomi.tachidesk
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -7,8 +7,8 @@ package suwayomi
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import suwayomi.server.JavalinSetup.javalinSetup
|
||||
import suwayomi.server.applicationSetup
|
||||
import suwayomi.tachidesk.server.JavalinSetup.javalinSetup
|
||||
import suwayomi.tachidesk.server.applicationSetup
|
||||
|
||||
fun main() {
|
||||
applicationSetup()
|
||||
+15
-15
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime
|
||||
package suwayomi.tachidesk.anime
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -8,20 +8,20 @@ package suwayomi.anime
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import io.javalin.Javalin
|
||||
import suwayomi.anime.impl.Anime.getAnime
|
||||
import suwayomi.anime.impl.Anime.getAnimeThumbnail
|
||||
import suwayomi.anime.impl.AnimeList.getAnimeList
|
||||
import suwayomi.anime.impl.Episode.getEpisode
|
||||
import suwayomi.anime.impl.Episode.getEpisodeList
|
||||
import suwayomi.anime.impl.Episode.modifyEpisode
|
||||
import suwayomi.anime.impl.Source.getAnimeSource
|
||||
import suwayomi.anime.impl.Source.getSourceList
|
||||
import suwayomi.anime.impl.extension.Extension.getExtensionIcon
|
||||
import suwayomi.anime.impl.extension.Extension.installExtension
|
||||
import suwayomi.anime.impl.extension.Extension.uninstallExtension
|
||||
import suwayomi.anime.impl.extension.Extension.updateExtension
|
||||
import suwayomi.anime.impl.extension.ExtensionsList.getExtensionList
|
||||
import suwayomi.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.anime.impl.Anime.getAnime
|
||||
import suwayomi.tachidesk.anime.impl.Anime.getAnimeThumbnail
|
||||
import suwayomi.tachidesk.anime.impl.AnimeList.getAnimeList
|
||||
import suwayomi.tachidesk.anime.impl.Episode.getEpisode
|
||||
import suwayomi.tachidesk.anime.impl.Episode.getEpisodeList
|
||||
import suwayomi.tachidesk.anime.impl.Episode.modifyEpisode
|
||||
import suwayomi.tachidesk.anime.impl.Source.getAnimeSource
|
||||
import suwayomi.tachidesk.anime.impl.Source.getSourceList
|
||||
import suwayomi.tachidesk.anime.impl.extension.Extension.getExtensionIcon
|
||||
import suwayomi.tachidesk.anime.impl.extension.Extension.installExtension
|
||||
import suwayomi.tachidesk.anime.impl.extension.Extension.uninstallExtension
|
||||
import suwayomi.tachidesk.anime.impl.extension.Extension.updateExtension
|
||||
import suwayomi.tachidesk.anime.impl.extension.ExtensionsList.getExtensionList
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
|
||||
object AnimeAPI {
|
||||
fun defineEndpoints(app: Javalin) {
|
||||
+14
-14
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.impl
|
||||
package suwayomi.tachidesk.anime.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -7,25 +7,25 @@ package suwayomi.anime.impl
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.SAnime
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.conf.global
|
||||
import org.kodein.di.instance
|
||||
import suwayomi.anime.impl.AnimeList.proxyThumbnailUrl
|
||||
import suwayomi.anime.impl.Source.getAnimeSource
|
||||
import suwayomi.anime.impl.util.GetAnimeHttpSource.getAnimeHttpSource
|
||||
import suwayomi.anime.model.dataclass.AnimeDataClass
|
||||
import suwayomi.anime.model.table.AnimeStatus
|
||||
import suwayomi.anime.model.table.AnimeTable
|
||||
import suwayomi.server.ApplicationDirs
|
||||
import suwayomi.tachidesk.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.impl.util.network.await
|
||||
import suwayomi.tachidesk.impl.util.storage.CachedImageResponse.clearCachedImage
|
||||
import suwayomi.tachidesk.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.anime.impl.AnimeList.proxyThumbnailUrl
|
||||
import suwayomi.tachidesk.anime.impl.Source.getAnimeSource
|
||||
import suwayomi.tachidesk.anime.impl.util.GetAnimeHttpSource.getAnimeHttpSource
|
||||
import suwayomi.tachidesk.anime.model.dataclass.AnimeDataClass
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeStatus
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeTable
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.manga.impl.util.network.await
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.CachedImageResponse.clearCachedImage
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.server.ApplicationDirs
|
||||
import java.io.InputStream
|
||||
|
||||
object Anime {
|
||||
@@ -102,7 +102,7 @@ object Anime {
|
||||
fetchedAnime.description,
|
||||
fetchedAnime.genre,
|
||||
AnimeStatus.valueOf(fetchedAnime.status).name,
|
||||
false,
|
||||
animeEntry[AnimeTable.inLibrary],
|
||||
getAnimeSource(animeEntry[AnimeTable.sourceReference]),
|
||||
true
|
||||
)
|
||||
+8
-8
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.impl
|
||||
package suwayomi.tachidesk.anime.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -7,16 +7,16 @@ package suwayomi.anime.impl
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||
import org.jetbrains.exposed.sql.insertAndGetId
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.anime.impl.util.GetAnimeHttpSource.getAnimeHttpSource
|
||||
import suwayomi.anime.model.dataclass.AnimeDataClass
|
||||
import suwayomi.anime.model.dataclass.PagedAnimeListDataClass
|
||||
import suwayomi.anime.model.table.AnimeStatus
|
||||
import suwayomi.anime.model.table.AnimeTable
|
||||
import suwayomi.tachidesk.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.anime.impl.util.GetAnimeHttpSource.getAnimeHttpSource
|
||||
import suwayomi.tachidesk.anime.model.dataclass.AnimeDataClass
|
||||
import suwayomi.tachidesk.anime.model.dataclass.PagedAnimeListDataClass
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeStatus
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeTable
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
|
||||
object AnimeList {
|
||||
fun proxyThumbnailUrl(animeId: Int): String {
|
||||
+10
-10
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.impl
|
||||
package suwayomi.tachidesk.anime.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -7,8 +7,8 @@ package suwayomi.anime.impl
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SAnime
|
||||
import eu.kanade.tachiyomi.source.model.SEpisode
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||
import org.jetbrains.exposed.sql.SortOrder.DESC
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.deleteWhere
|
||||
@@ -16,13 +16,13 @@ import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import suwayomi.anime.impl.Anime.getAnime
|
||||
import suwayomi.anime.impl.util.GetAnimeHttpSource.getAnimeHttpSource
|
||||
import suwayomi.anime.model.dataclass.EpisodeDataClass
|
||||
import suwayomi.anime.model.table.AnimeTable
|
||||
import suwayomi.anime.model.table.EpisodeTable
|
||||
import suwayomi.anime.model.table.toDataClass
|
||||
import suwayomi.tachidesk.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.anime.impl.Anime.getAnime
|
||||
import suwayomi.tachidesk.anime.impl.util.GetAnimeHttpSource.getAnimeHttpSource
|
||||
import suwayomi.tachidesk.anime.model.dataclass.EpisodeDataClass
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeTable
|
||||
import suwayomi.tachidesk.anime.model.table.EpisodeTable
|
||||
import suwayomi.tachidesk.anime.model.table.toDataClass
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
|
||||
object Episode {
|
||||
/** get episode list when showing an anime */
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.impl
|
||||
package suwayomi.tachidesk.anime.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -11,11 +11,11 @@ import mu.KotlinLogging
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.anime.impl.extension.Extension.getExtensionIconUrl
|
||||
import suwayomi.anime.impl.util.GetAnimeHttpSource.getAnimeHttpSource
|
||||
import suwayomi.anime.model.dataclass.AnimeSourceDataClass
|
||||
import suwayomi.anime.model.table.AnimeExtensionTable
|
||||
import suwayomi.anime.model.table.AnimeSourceTable
|
||||
import suwayomi.tachidesk.anime.impl.extension.Extension.getExtensionIconUrl
|
||||
import suwayomi.tachidesk.anime.impl.util.GetAnimeHttpSource.getAnimeHttpSource
|
||||
import suwayomi.tachidesk.anime.model.dataclass.AnimeSourceDataClass
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeExtensionTable
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeSourceTable
|
||||
|
||||
object Source {
|
||||
private val logger = KotlinLogging.logger {}
|
||||
+21
-21
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.impl.extension
|
||||
package suwayomi.tachidesk.anime.impl.extension
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -8,11 +8,11 @@ package suwayomi.anime.impl.extension
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.animesource.AnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.AnimeSourceFactory
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.source.AnimeSource
|
||||
import eu.kanade.tachiyomi.source.AnimeSourceFactory
|
||||
import mu.KotlinLogging
|
||||
import okhttp3.Request
|
||||
import okio.buffer
|
||||
@@ -25,23 +25,23 @@ import org.jetbrains.exposed.sql.update
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.conf.global
|
||||
import org.kodein.di.instance
|
||||
import suwayomi.anime.impl.extension.ExtensionsList.extensionTableAsDataClass
|
||||
import suwayomi.anime.impl.extension.github.ExtensionGithubApi
|
||||
import suwayomi.anime.impl.util.PackageTools.EXTENSION_FEATURE
|
||||
import suwayomi.anime.impl.util.PackageTools.LIB_VERSION_MAX
|
||||
import suwayomi.anime.impl.util.PackageTools.LIB_VERSION_MIN
|
||||
import suwayomi.anime.impl.util.PackageTools.METADATA_NSFW
|
||||
import suwayomi.anime.impl.util.PackageTools.METADATA_SOURCE_CLASS
|
||||
import suwayomi.anime.impl.util.PackageTools.dex2jar
|
||||
import suwayomi.anime.impl.util.PackageTools.getPackageInfo
|
||||
import suwayomi.anime.impl.util.PackageTools.getSignatureHash
|
||||
import suwayomi.anime.impl.util.PackageTools.loadExtensionSources
|
||||
import suwayomi.anime.impl.util.PackageTools.trustedSignatures
|
||||
import suwayomi.anime.model.table.AnimeExtensionTable
|
||||
import suwayomi.anime.model.table.AnimeSourceTable
|
||||
import suwayomi.server.ApplicationDirs
|
||||
import suwayomi.tachidesk.impl.util.network.await
|
||||
import suwayomi.tachidesk.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.anime.impl.extension.ExtensionsList.extensionTableAsDataClass
|
||||
import suwayomi.tachidesk.anime.impl.extension.github.ExtensionGithubApi
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.EXTENSION_FEATURE
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.LIB_VERSION_MAX
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.LIB_VERSION_MIN
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.METADATA_NSFW
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.METADATA_SOURCE_CLASS
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.dex2jar
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.getPackageInfo
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.getSignatureHash
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.loadExtensionSources
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.trustedSignatures
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeExtensionTable
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeSourceTable
|
||||
import suwayomi.tachidesk.manga.impl.util.network.await
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.server.ApplicationDirs
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.impl.extension
|
||||
package suwayomi.tachidesk.anime.impl.extension
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -14,11 +14,11 @@ import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import suwayomi.anime.impl.extension.Extension.getExtensionIconUrl
|
||||
import suwayomi.anime.impl.extension.github.ExtensionGithubApi
|
||||
import suwayomi.anime.impl.extension.github.OnlineExtension
|
||||
import suwayomi.anime.model.dataclass.AnimeExtensionDataClass
|
||||
import suwayomi.anime.model.table.AnimeExtensionTable
|
||||
import suwayomi.tachidesk.anime.impl.extension.Extension.getExtensionIconUrl
|
||||
import suwayomi.tachidesk.anime.impl.extension.github.ExtensionGithubApi
|
||||
import suwayomi.tachidesk.anime.impl.extension.github.OnlineExtension
|
||||
import suwayomi.tachidesk.anime.model.dataclass.AnimeExtensionDataClass
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeExtensionTable
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
object ExtensionsList {
|
||||
+9
-10
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.impl.extension.github
|
||||
package suwayomi.tachidesk.anime.impl.extension.github
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -13,23 +13,22 @@ import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import okhttp3.Request
|
||||
import suwayomi.anime.model.dataclass.AnimeExtensionDataClass
|
||||
import suwayomi.tachidesk.impl.util.network.UnzippingInterceptor
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.LIB_VERSION_MAX
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.LIB_VERSION_MIN
|
||||
import suwayomi.tachidesk.anime.model.dataclass.AnimeExtensionDataClass
|
||||
import suwayomi.tachidesk.manga.impl.util.network.UnzippingInterceptor
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
object ExtensionGithubApi {
|
||||
const val BASE_URL = "https://raw.githubusercontent.com"
|
||||
const val REPO_URL_PREFIX = "$BASE_URL/jmir1/tachiyomi-extensions/repo"
|
||||
|
||||
private const val LIB_VERSION_MIN = 1.3
|
||||
private const val LIB_VERSION_MAX = 1.3
|
||||
private const val BASE_URL = "https://raw.githubusercontent.com"
|
||||
private const val REPO_URL_PREFIX = "$BASE_URL/jmir1/tachiyomi-extensions/repo"
|
||||
|
||||
private fun parseResponse(json: JsonArray): List<OnlineExtension> {
|
||||
return json
|
||||
.map { it.asJsonObject }
|
||||
.filter { element ->
|
||||
val versionName = element["version"].string
|
||||
val libVersion = versionName.substringBeforeLast('.').toDouble()
|
||||
val libVersion = versionName.substringBeforeLast('.').toInt()
|
||||
libVersion in LIB_VERSION_MIN..LIB_VERSION_MAX
|
||||
}
|
||||
.map { element ->
|
||||
@@ -69,7 +68,7 @@ object ExtensionGithubApi {
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun getRepo(): com.google.gson.JsonArray {
|
||||
private fun getRepo(): JsonArray {
|
||||
val request = Request.Builder()
|
||||
.url("$REPO_URL_PREFIX/index.json.gz")
|
||||
.build()
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package suwayomi.tachidesk.anime.impl.extension.github
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
data class OnlineExtension(
|
||||
val name: String,
|
||||
val pkgName: String,
|
||||
val versionName: String,
|
||||
val versionCode: Int,
|
||||
val lang: String,
|
||||
val isNsfw: Boolean,
|
||||
val apkName: String,
|
||||
val iconUrl: String
|
||||
)
|
||||
+8
-8
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.impl.util
|
||||
package suwayomi.tachidesk.anime.impl.util
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -7,18 +7,18 @@ package suwayomi.anime.impl.util
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import eu.kanade.tachiyomi.source.AnimeSource
|
||||
import eu.kanade.tachiyomi.source.AnimeSourceFactory
|
||||
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
|
||||
import eu.kanade.tachiyomi.animesource.AnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.AnimeSourceFactory
|
||||
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.conf.global
|
||||
import org.kodein.di.instance
|
||||
import suwayomi.anime.impl.util.PackageTools.loadExtensionSources
|
||||
import suwayomi.anime.model.table.AnimeExtensionTable
|
||||
import suwayomi.anime.model.table.AnimeSourceTable
|
||||
import suwayomi.server.ApplicationDirs
|
||||
import suwayomi.tachidesk.anime.impl.util.PackageTools.loadExtensionSources
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeExtensionTable
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeSourceTable
|
||||
import suwayomi.tachidesk.server.ApplicationDirs
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
object GetAnimeHttpSource {
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.impl.util
|
||||
package suwayomi.tachidesk.anime.impl.util
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -22,7 +22,7 @@ import org.kodein.di.conf.global
|
||||
import org.kodein.di.instance
|
||||
import org.w3c.dom.Element
|
||||
import org.w3c.dom.Node
|
||||
import suwayomi.server.ApplicationDirs
|
||||
import suwayomi.tachidesk.server.ApplicationDirs
|
||||
import xyz.nulldev.androidcompat.pm.InstalledPackage.Companion.toList
|
||||
import xyz.nulldev.androidcompat.pm.toPackageInfo
|
||||
import java.io.File
|
||||
@@ -40,8 +40,8 @@ object PackageTools {
|
||||
const val METADATA_SOURCE_CLASS = "tachiyomi.animeextension.class"
|
||||
const val METADATA_SOURCE_FACTORY = "tachiyomi.animeextension.factory"
|
||||
const val METADATA_NSFW = "tachiyomi.animeextension.nsfw"
|
||||
const val LIB_VERSION_MIN = 1.3
|
||||
const val LIB_VERSION_MAX = 1.3
|
||||
const val LIB_VERSION_MIN = 10
|
||||
const val LIB_VERSION_MAX = 10
|
||||
|
||||
private const val officialSignature = "50ab1d1e3a20d204d0ad6d334c7691c632e41b98dfa132bf385695fdfa63839c" // jmir1's key
|
||||
var trustedSignatures = mutableSetOf<String>() + officialSignature
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.model.dataclass
|
||||
package suwayomi.tachidesk.anime.model.dataclass
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -7,7 +7,7 @@ package suwayomi.anime.model.dataclass
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import suwayomi.anime.model.table.AnimeStatus
|
||||
import suwayomi.tachidesk.anime.model.table.AnimeStatus
|
||||
|
||||
data class AnimeDataClass(
|
||||
val id: Int,
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.model.dataclass
|
||||
package suwayomi.tachidesk.anime.model.dataclass
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.model.dataclass
|
||||
package suwayomi.tachidesk.anime.model.dataclass
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.model.dataclass
|
||||
package suwayomi.tachidesk.anime.model.dataclass
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.model.table
|
||||
package suwayomi.tachidesk.anime.model.table
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.model.table
|
||||
package suwayomi.tachidesk.anime.model.table
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.model.table
|
||||
package suwayomi.tachidesk.anime.model.table
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -7,12 +7,12 @@ package suwayomi.anime.model.table
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SAnime
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
import org.jetbrains.exposed.sql.ResultRow
|
||||
import suwayomi.tachidesk.impl.MangaList.proxyThumbnailUrl
|
||||
import suwayomi.tachidesk.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.model.table.MangaStatus.Companion
|
||||
import suwayomi.tachidesk.manga.impl.MangaList.proxyThumbnailUrl
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.MangaStatus.Companion
|
||||
|
||||
object AnimeTable : IntIdTable() {
|
||||
val url = varchar("url", 2048)
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package suwayomi.anime.model.table
|
||||
package suwayomi.tachidesk.anime.model.table
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -11,7 +11,7 @@ import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
import org.jetbrains.exposed.sql.ResultRow
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.anime.model.dataclass.EpisodeDataClass
|
||||
import suwayomi.tachidesk.anime.model.dataclass.EpisodeDataClass
|
||||
|
||||
object EpisodeTable : IntIdTable() {
|
||||
val url = varchar("url", 2048)
|
||||
@@ -1,3 +0,0 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy.models
|
||||
|
||||
data class DHistory(val url: String, val lastRead: Long)
|
||||
@@ -1,28 +0,0 @@
|
||||
package suwayomi.tachidesk.impl.download
|
||||
|
||||
import org.jetbrains.exposed.sql.ResultRow
|
||||
import java.util.concurrent.LinkedBlockingQueue
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
data class Download(
|
||||
val chapter: ResultRow,
|
||||
)
|
||||
|
||||
private val downloadQueue = LinkedBlockingQueue<Download>()
|
||||
|
||||
class Downloader {
|
||||
|
||||
fun start() {
|
||||
TODO()
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package suwayomi.tachidesk.impl.extension.github
|
||||
|
||||
data class OnlineExtension(
|
||||
val name: String,
|
||||
val pkgName: String,
|
||||
val versionName: String,
|
||||
val versionCode: Int,
|
||||
val lang: String,
|
||||
val isNsfw: Boolean,
|
||||
val apkName: String,
|
||||
val iconUrl: String
|
||||
)
|
||||
+105
-36
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk
|
||||
package suwayomi.tachidesk.manga
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -8,36 +8,39 @@ package suwayomi.tachidesk
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import io.javalin.Javalin
|
||||
import suwayomi.server.JavalinSetup.future
|
||||
import suwayomi.server.impl.About
|
||||
import suwayomi.tachidesk.impl.Category
|
||||
import suwayomi.tachidesk.impl.CategoryManga.addMangaToCategory
|
||||
import suwayomi.tachidesk.impl.CategoryManga.getCategoryMangaList
|
||||
import suwayomi.tachidesk.impl.CategoryManga.getMangaCategories
|
||||
import suwayomi.tachidesk.impl.CategoryManga.removeMangaFromCategory
|
||||
import suwayomi.tachidesk.impl.Chapter.getChapter
|
||||
import suwayomi.tachidesk.impl.Chapter.getChapterList
|
||||
import suwayomi.tachidesk.impl.Chapter.modifyChapter
|
||||
import suwayomi.tachidesk.impl.Library.addMangaToLibrary
|
||||
import suwayomi.tachidesk.impl.Library.getLibraryMangas
|
||||
import suwayomi.tachidesk.impl.Library.removeMangaFromLibrary
|
||||
import suwayomi.tachidesk.impl.Manga.getManga
|
||||
import suwayomi.tachidesk.impl.Manga.getMangaThumbnail
|
||||
import suwayomi.tachidesk.impl.MangaList.getMangaList
|
||||
import suwayomi.tachidesk.impl.Page.getPageImage
|
||||
import suwayomi.tachidesk.impl.Search.sourceFilters
|
||||
import suwayomi.tachidesk.impl.Search.sourceGlobalSearch
|
||||
import suwayomi.tachidesk.impl.Search.sourceSearch
|
||||
import suwayomi.tachidesk.impl.Source.getSource
|
||||
import suwayomi.tachidesk.impl.Source.getSourceList
|
||||
import suwayomi.tachidesk.impl.backup.BackupFlags
|
||||
import suwayomi.tachidesk.impl.backup.legacy.LegacyBackupExport.createLegacyBackup
|
||||
import suwayomi.tachidesk.impl.backup.legacy.LegacyBackupImport.restoreLegacyBackup
|
||||
import suwayomi.tachidesk.impl.extension.Extension.getExtensionIcon
|
||||
import suwayomi.tachidesk.impl.extension.Extension.installExtension
|
||||
import suwayomi.tachidesk.impl.extension.Extension.uninstallExtension
|
||||
import suwayomi.tachidesk.impl.extension.Extension.updateExtension
|
||||
import suwayomi.tachidesk.impl.extension.ExtensionsList.getExtensionList
|
||||
import suwayomi.tachidesk.manga.impl.Category
|
||||
import suwayomi.tachidesk.manga.impl.CategoryManga.addMangaToCategory
|
||||
import suwayomi.tachidesk.manga.impl.CategoryManga.getCategoryMangaList
|
||||
import suwayomi.tachidesk.manga.impl.CategoryManga.getMangaCategories
|
||||
import suwayomi.tachidesk.manga.impl.CategoryManga.removeMangaFromCategory
|
||||
import suwayomi.tachidesk.manga.impl.Chapter.getChapter
|
||||
import suwayomi.tachidesk.manga.impl.Chapter.getChapterList
|
||||
import suwayomi.tachidesk.manga.impl.Chapter.modifyChapter
|
||||
import suwayomi.tachidesk.manga.impl.Chapter.modifyChapterMeta
|
||||
import suwayomi.tachidesk.manga.impl.Library.addMangaToLibrary
|
||||
import suwayomi.tachidesk.manga.impl.Library.getLibraryMangas
|
||||
import suwayomi.tachidesk.manga.impl.Library.removeMangaFromLibrary
|
||||
import suwayomi.tachidesk.manga.impl.Manga.getManga
|
||||
import suwayomi.tachidesk.manga.impl.Manga.getMangaThumbnail
|
||||
import suwayomi.tachidesk.manga.impl.Manga.modifyMangaMeta
|
||||
import suwayomi.tachidesk.manga.impl.MangaList.getMangaList
|
||||
import suwayomi.tachidesk.manga.impl.Page.getPageImage
|
||||
import suwayomi.tachidesk.manga.impl.Search.sourceFilters
|
||||
import suwayomi.tachidesk.manga.impl.Search.sourceGlobalSearch
|
||||
import suwayomi.tachidesk.manga.impl.Search.sourceSearch
|
||||
import suwayomi.tachidesk.manga.impl.Source.getSource
|
||||
import suwayomi.tachidesk.manga.impl.Source.getSourceList
|
||||
import suwayomi.tachidesk.manga.impl.backup.BackupFlags
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.LegacyBackupExport.createLegacyBackup
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.LegacyBackupImport.restoreLegacyBackup
|
||||
import suwayomi.tachidesk.manga.impl.download.DownloadManager
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension.getExtensionIcon
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension.installExtension
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension.uninstallExtension
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension.updateExtension
|
||||
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList.getExtensionList
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.impl.About
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
@@ -184,6 +187,18 @@ object TachideskAPI {
|
||||
ctx.json(future { getChapterList(mangaId, onlineFetch) })
|
||||
}
|
||||
|
||||
// used to modify a manga's meta paramaters
|
||||
app.patch("/api/v1/manga/:mangaId/meta") { ctx ->
|
||||
val mangaId = ctx.pathParam("mangaId").toInt()
|
||||
|
||||
val key = ctx.formParam("key")!!
|
||||
val value = ctx.formParam("value")!!
|
||||
|
||||
modifyMangaMeta(mangaId, key, value)
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
|
||||
// used to display a chapter, get a chapter in order to show it's pages
|
||||
app.get("/api/v1/manga/:mangaId/chapter/:chapterIndex") { ctx ->
|
||||
val chapterIndex = ctx.pathParam("chapterIndex").toInt()
|
||||
@@ -206,6 +221,19 @@ object TachideskAPI {
|
||||
ctx.status(200)
|
||||
}
|
||||
|
||||
// used to modify a chapter's meta paramaters
|
||||
app.patch("/api/v1/manga/:mangaId/chapter/:chapterIndex/meta") { ctx ->
|
||||
val chapterIndex = ctx.pathParam("chapterIndex").toInt()
|
||||
val mangaId = ctx.pathParam("mangaId").toInt()
|
||||
|
||||
val key = ctx.formParam("key")!!
|
||||
val value = ctx.formParam("value")!!
|
||||
|
||||
modifyChapterMeta(mangaId, chapterIndex, key, value)
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
|
||||
// get page at index "index"
|
||||
app.get("/api/v1/manga/:mangaId/chapter/:chapterIndex/page/:index") { ctx ->
|
||||
val mangaId = ctx.pathParam("mangaId").toInt()
|
||||
@@ -383,15 +411,56 @@ object TachideskAPI {
|
||||
// Download queue stats
|
||||
app.ws("/api/v1/downloads") { ws ->
|
||||
ws.onConnect { ctx ->
|
||||
// TODO: send current stat
|
||||
// TODO: add to downlad subscribers
|
||||
DownloadManager.addClient(ctx)
|
||||
DownloadManager.notifyClient(ctx)
|
||||
}
|
||||
ws.onMessage {
|
||||
// TODO: send current stat
|
||||
ws.onMessage { ctx ->
|
||||
DownloadManager.handleRequest(ctx)
|
||||
}
|
||||
ws.onClose { ctx ->
|
||||
// TODO: remove from subscribers
|
||||
DownloadManager.removeClient(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// Start the downloader
|
||||
app.get("/api/v1/downloads/start") { ctx ->
|
||||
DownloadManager.start()
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
|
||||
// Stop the downloader
|
||||
app.get("/api/v1/downloads/stop") { ctx ->
|
||||
DownloadManager.stop()
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
|
||||
// clear download queue
|
||||
app.get("/api/v1/downloads/clear") { ctx ->
|
||||
DownloadManager.clear()
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
|
||||
// Queue chapter for download
|
||||
app.get("/api/v1/download/:mangaId/chapter/:chapterIndex") { ctx ->
|
||||
val chapterIndex = ctx.pathParam("chapterIndex").toInt()
|
||||
val mangaId = ctx.pathParam("mangaId").toInt()
|
||||
|
||||
DownloadManager.enqueue(chapterIndex, mangaId)
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
|
||||
// delete chapter from download queue
|
||||
app.delete("/api/v1/download/:mangaId/chapter/:chapterIndex") { ctx ->
|
||||
val chapterIndex = ctx.pathParam("chapterIndex").toInt()
|
||||
val mangaId = ctx.pathParam("mangaId").toInt()
|
||||
|
||||
DownloadManager.unqueue(chapterIndex, mangaId)
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl
|
||||
package suwayomi.tachidesk.manga.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -14,11 +14,11 @@ import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import suwayomi.tachidesk.impl.CategoryManga.removeMangaFromCategory
|
||||
import suwayomi.tachidesk.model.dataclass.CategoryDataClass
|
||||
import suwayomi.tachidesk.model.table.CategoryMangaTable
|
||||
import suwayomi.tachidesk.model.table.CategoryTable
|
||||
import suwayomi.tachidesk.model.table.toDataClass
|
||||
import suwayomi.tachidesk.manga.impl.CategoryManga.removeMangaFromCategory
|
||||
import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryTable
|
||||
import suwayomi.tachidesk.manga.model.table.toDataClass
|
||||
|
||||
object Category {
|
||||
/**
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl
|
||||
package suwayomi.tachidesk.manga.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -14,12 +14,12 @@ import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import suwayomi.tachidesk.model.dataclass.CategoryDataClass
|
||||
import suwayomi.tachidesk.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.model.table.CategoryMangaTable
|
||||
import suwayomi.tachidesk.model.table.CategoryTable
|
||||
import suwayomi.tachidesk.model.table.MangaTable
|
||||
import suwayomi.tachidesk.model.table.toDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryTable
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.toDataClass
|
||||
|
||||
object CategoryManga {
|
||||
fun addMangaToCategory(mangaId: Int, categoryId: Int) {
|
||||
+103
-52
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl
|
||||
package suwayomi.tachidesk.manga.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -9,6 +9,7 @@ package suwayomi.tachidesk.impl
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.sql.SortOrder.DESC
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.deleteWhere
|
||||
@@ -16,14 +17,16 @@ import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import suwayomi.tachidesk.impl.Manga.getManga
|
||||
import suwayomi.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.model.dataclass.ChapterDataClass
|
||||
import suwayomi.tachidesk.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.model.table.MangaTable
|
||||
import suwayomi.tachidesk.model.table.PageTable
|
||||
import suwayomi.tachidesk.model.table.toDataClass
|
||||
import suwayomi.tachidesk.manga.impl.Manga.getManga
|
||||
import suwayomi.tachidesk.manga.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterMetaTable
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.PageTable
|
||||
import suwayomi.tachidesk.manga.model.table.toDataClass
|
||||
import java.time.Instant
|
||||
|
||||
object Chapter {
|
||||
/** get chapter list when showing a manga */
|
||||
@@ -88,7 +91,7 @@ object Chapter {
|
||||
// clear any orphaned chapters that are in the db but not in `chapterList`
|
||||
val dbChapterCount = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count() }
|
||||
if (dbChapterCount > chapterCount) { // we got some clean up due
|
||||
val dbChapterList = transaction { ChapterTable.select { ChapterTable.manga eq mangaId } }
|
||||
val dbChapterList = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.toList() }
|
||||
|
||||
dbChapterList.forEach {
|
||||
if (it[ChapterTable.chapterIndex] >= chapterList.size ||
|
||||
@@ -122,9 +125,15 @@ object Chapter {
|
||||
dbChapter[ChapterTable.isRead],
|
||||
dbChapter[ChapterTable.isBookmarked],
|
||||
dbChapter[ChapterTable.lastPageRead],
|
||||
dbChapter[ChapterTable.lastReadAt],
|
||||
|
||||
chapterCount - index,
|
||||
chapterList.size
|
||||
dbChapter[ChapterTable.isDownloaded],
|
||||
|
||||
dbChapter[ChapterTable.pageCount],
|
||||
|
||||
chapterList.size,
|
||||
meta = getChapterMetaMap(dbChapter[ChapterTable.id])
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -136,54 +145,69 @@ object Chapter {
|
||||
(ChapterTable.chapterIndex eq chapterIndex) and (ChapterTable.manga eq mangaId)
|
||||
}.first()
|
||||
}
|
||||
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
|
||||
val source = getHttpSource(mangaEntry[MangaTable.sourceReference])
|
||||
|
||||
val pageList = source.fetchPageList(
|
||||
SChapter.create().apply {
|
||||
url = chapterEntry[ChapterTable.url]
|
||||
name = chapterEntry[ChapterTable.name]
|
||||
}
|
||||
).awaitSingle()
|
||||
return if (!chapterEntry[ChapterTable.isDownloaded]) {
|
||||
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
|
||||
val source = getHttpSource(mangaEntry[MangaTable.sourceReference])
|
||||
|
||||
val chapterId = chapterEntry[ChapterTable.id].value
|
||||
val chapterCount = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count() }
|
||||
val pageList = source.fetchPageList(
|
||||
SChapter.create().apply {
|
||||
url = chapterEntry[ChapterTable.url]
|
||||
name = chapterEntry[ChapterTable.name]
|
||||
}
|
||||
).awaitSingle()
|
||||
|
||||
// update page list for this chapter
|
||||
transaction {
|
||||
pageList.forEach { page ->
|
||||
val pageEntry = transaction { PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }.firstOrNull() }
|
||||
if (pageEntry == null) {
|
||||
PageTable.insert {
|
||||
it[index] = page.index
|
||||
it[url] = page.url
|
||||
it[imageUrl] = page.imageUrl
|
||||
it[chapter] = chapterId
|
||||
}
|
||||
} else {
|
||||
PageTable.update({ (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }) {
|
||||
it[url] = page.url
|
||||
it[imageUrl] = page.imageUrl
|
||||
val chapterId = chapterEntry[ChapterTable.id].value
|
||||
val chapterCount = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count() }
|
||||
|
||||
// update page list for this chapter
|
||||
transaction {
|
||||
pageList.forEach { page ->
|
||||
val pageEntry = transaction { PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }.firstOrNull() }
|
||||
if (pageEntry == null) {
|
||||
PageTable.insert {
|
||||
it[index] = page.index
|
||||
it[url] = page.url
|
||||
it[imageUrl] = page.imageUrl
|
||||
it[chapter] = chapterId
|
||||
}
|
||||
} else {
|
||||
PageTable.update({ (PageTable.chapter eq chapterId) and (PageTable.index eq page.index) }) {
|
||||
it[url] = page.url
|
||||
it[imageUrl] = page.imageUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val pageCount = pageList.count()
|
||||
|
||||
transaction {
|
||||
ChapterTable.update({ (ChapterTable.manga eq mangaId) and (ChapterTable.chapterIndex eq chapterIndex) }) {
|
||||
it[ChapterTable.pageCount] = pageCount
|
||||
}
|
||||
}
|
||||
return ChapterDataClass(
|
||||
chapterEntry[ChapterTable.url],
|
||||
chapterEntry[ChapterTable.name],
|
||||
chapterEntry[ChapterTable.date_upload],
|
||||
chapterEntry[ChapterTable.chapter_number],
|
||||
chapterEntry[ChapterTable.scanlator],
|
||||
mangaId,
|
||||
chapterEntry[ChapterTable.isRead],
|
||||
chapterEntry[ChapterTable.isBookmarked],
|
||||
chapterEntry[ChapterTable.lastPageRead],
|
||||
chapterEntry[ChapterTable.lastReadAt],
|
||||
|
||||
chapterEntry[ChapterTable.chapterIndex],
|
||||
chapterEntry[ChapterTable.isDownloaded],
|
||||
pageCount,
|
||||
chapterCount.toInt(),
|
||||
getChapterMetaMap(chapterEntry[ChapterTable.id])
|
||||
)
|
||||
} else {
|
||||
ChapterTable.toDataClass(chapterEntry)
|
||||
}
|
||||
|
||||
return ChapterDataClass(
|
||||
chapterEntry[ChapterTable.url],
|
||||
chapterEntry[ChapterTable.name],
|
||||
chapterEntry[ChapterTable.date_upload],
|
||||
chapterEntry[ChapterTable.chapter_number],
|
||||
chapterEntry[ChapterTable.scanlator],
|
||||
mangaId,
|
||||
chapterEntry[ChapterTable.isRead],
|
||||
chapterEntry[ChapterTable.isBookmarked],
|
||||
chapterEntry[ChapterTable.lastPageRead],
|
||||
|
||||
chapterEntry[ChapterTable.chapterIndex],
|
||||
chapterCount.toInt(),
|
||||
pageList.count()
|
||||
)
|
||||
}
|
||||
|
||||
fun modifyChapter(mangaId: Int, chapterIndex: Int, isRead: Boolean?, isBookmarked: Boolean?, markPrevRead: Boolean?, lastPageRead: Int?) {
|
||||
@@ -198,6 +222,7 @@ object Chapter {
|
||||
}
|
||||
lastPageRead?.also {
|
||||
update[ChapterTable.lastPageRead] = it
|
||||
update[ChapterTable.lastReadAt] = Instant.now().epochSecond
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,4 +234,30 @@ object Chapter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getChapterMetaMap(chapter: EntityID<Int>): Map<String, String> {
|
||||
return transaction {
|
||||
ChapterMetaTable.select { ChapterMetaTable.ref eq chapter }
|
||||
.associate { it[ChapterMetaTable.key] to it[ChapterMetaTable.value] }
|
||||
}
|
||||
}
|
||||
|
||||
fun modifyChapterMeta(mangaId: Int, chapterIndex: Int, key: String, value: String) {
|
||||
transaction {
|
||||
val chapter = ChapterTable.select { (ChapterTable.manga eq mangaId) and (ChapterTable.chapterIndex eq chapterIndex) }
|
||||
.first()[ChapterTable.id]
|
||||
val meta = transaction { ChapterMetaTable.select { (ChapterMetaTable.ref eq chapter) and (ChapterMetaTable.key eq key) } }.firstOrNull()
|
||||
if (meta == null) {
|
||||
ChapterMetaTable.insert {
|
||||
it[ChapterMetaTable.key] = key
|
||||
it[ChapterMetaTable.value] = value
|
||||
it[ChapterMetaTable.ref] = chapter
|
||||
}
|
||||
} else {
|
||||
ChapterMetaTable.update {
|
||||
it[ChapterMetaTable.value] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl
|
||||
package suwayomi.tachidesk.manga.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -13,12 +13,12 @@ import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import suwayomi.tachidesk.impl.Manga.getManga
|
||||
import suwayomi.tachidesk.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.model.table.CategoryMangaTable
|
||||
import suwayomi.tachidesk.model.table.CategoryTable
|
||||
import suwayomi.tachidesk.model.table.MangaTable
|
||||
import suwayomi.tachidesk.model.table.toDataClass
|
||||
import suwayomi.tachidesk.manga.impl.Manga.getManga
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryTable
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.toDataClass
|
||||
|
||||
object Library {
|
||||
// TODO: `Category.isLanding` is to handle the default categories a new library manga gets,
|
||||
+45
-13
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl
|
||||
package suwayomi.tachidesk.manga.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -9,23 +9,27 @@ package suwayomi.tachidesk.impl
|
||||
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.conf.global
|
||||
import org.kodein.di.instance
|
||||
import suwayomi.server.ApplicationDirs
|
||||
import suwayomi.tachidesk.impl.MangaList.proxyThumbnailUrl
|
||||
import suwayomi.tachidesk.impl.Source.getSource
|
||||
import suwayomi.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.impl.util.network.await
|
||||
import suwayomi.tachidesk.impl.util.storage.CachedImageResponse.clearCachedImage
|
||||
import suwayomi.tachidesk.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.model.table.MangaStatus
|
||||
import suwayomi.tachidesk.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.impl.MangaList.proxyThumbnailUrl
|
||||
import suwayomi.tachidesk.manga.impl.Source.getSource
|
||||
import suwayomi.tachidesk.manga.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.manga.impl.util.network.await
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.CachedImageResponse.clearCachedImage
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.MangaMetaTable
|
||||
import suwayomi.tachidesk.manga.model.table.MangaStatus
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
import suwayomi.tachidesk.server.ApplicationDirs
|
||||
import java.io.InputStream
|
||||
|
||||
object Manga {
|
||||
@@ -57,6 +61,7 @@ object Manga {
|
||||
MangaStatus.valueOf(mangaEntry[MangaTable.status]).name,
|
||||
mangaEntry[MangaTable.inLibrary],
|
||||
getSource(mangaEntry[MangaTable.sourceReference]),
|
||||
getMangaMetaMap(mangaEntry[MangaTable.id]),
|
||||
false
|
||||
)
|
||||
} else { // initialize manga
|
||||
@@ -102,13 +107,40 @@ object Manga {
|
||||
fetchedManga.description,
|
||||
fetchedManga.genre,
|
||||
MangaStatus.valueOf(fetchedManga.status).name,
|
||||
false,
|
||||
mangaEntry[MangaTable.inLibrary],
|
||||
getSource(mangaEntry[MangaTable.sourceReference]),
|
||||
getMangaMetaMap(mangaEntry[MangaTable.id]),
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getMangaMetaMap(manga: EntityID<Int>): Map<String, String> {
|
||||
return transaction {
|
||||
MangaMetaTable.select { MangaMetaTable.ref eq manga }
|
||||
.associate { it[MangaMetaTable.key] to it[MangaMetaTable.value] }
|
||||
}
|
||||
}
|
||||
|
||||
fun modifyMangaMeta(mangaId: Int, key: String, value: String) {
|
||||
transaction {
|
||||
val manga = MangaMetaTable.select { (MangaTable.id eq mangaId) }
|
||||
.first()[MangaTable.id]
|
||||
val meta = transaction { MangaMetaTable.select { (MangaMetaTable.ref eq manga) and (MangaMetaTable.key eq key) } }.firstOrNull()
|
||||
if (meta == null) {
|
||||
MangaMetaTable.insert {
|
||||
it[MangaMetaTable.key] = key
|
||||
it[MangaMetaTable.value] = value
|
||||
it[MangaMetaTable.ref] = manga
|
||||
}
|
||||
} else {
|
||||
MangaMetaTable.update {
|
||||
it[MangaMetaTable.value] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val applicationDirs by DI.global.instance<ApplicationDirs>()
|
||||
suspend fun getMangaThumbnail(mangaId: Int): Pair<InputStream, String> {
|
||||
val saveDir = applicationDirs.mangaThumbnailsRoot
|
||||
+10
-8
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl
|
||||
package suwayomi.tachidesk.manga.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -11,12 +11,13 @@ import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import org.jetbrains.exposed.sql.insertAndGetId
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.model.dataclass.PagedMangaListDataClass
|
||||
import suwayomi.tachidesk.model.table.MangaStatus
|
||||
import suwayomi.tachidesk.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.impl.Manga.getMangaMetaMap
|
||||
import suwayomi.tachidesk.manga.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.MangaStatus
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
|
||||
object MangaList {
|
||||
fun proxyThumbnailUrl(mangaId: Int): String {
|
||||
@@ -89,7 +90,8 @@ object MangaList {
|
||||
mangaEntry[MangaTable.description],
|
||||
mangaEntry[MangaTable.genre],
|
||||
MangaStatus.valueOf(mangaEntry[MangaTable.status]).name,
|
||||
mangaEntry[MangaTable.inLibrary]
|
||||
mangaEntry[MangaTable.inLibrary],
|
||||
meta = getMangaMetaMap(mangaEntry[MangaTable.id])
|
||||
)
|
||||
}
|
||||
}
|
||||
+9
-9
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl
|
||||
package suwayomi.tachidesk.manga.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -16,14 +16,14 @@ import org.jetbrains.exposed.sql.update
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.conf.global
|
||||
import org.kodein.di.instance
|
||||
import suwayomi.server.ApplicationDirs
|
||||
import suwayomi.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.impl.util.storage.SafePath
|
||||
import suwayomi.tachidesk.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.model.table.MangaTable
|
||||
import suwayomi.tachidesk.model.table.PageTable
|
||||
import suwayomi.tachidesk.manga.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.SafePath
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.PageTable
|
||||
import suwayomi.tachidesk.server.ApplicationDirs
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl
|
||||
package suwayomi.tachidesk.manga.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -7,10 +7,10 @@ package suwayomi.tachidesk.impl
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import suwayomi.tachidesk.impl.MangaList.processEntries
|
||||
import suwayomi.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.model.dataclass.PagedMangaListDataClass
|
||||
import suwayomi.tachidesk.manga.impl.MangaList.processEntries
|
||||
import suwayomi.tachidesk.manga.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass
|
||||
|
||||
object Search {
|
||||
// TODO
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl
|
||||
package suwayomi.tachidesk.manga.impl
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -11,11 +11,11 @@ import mu.KotlinLogging
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.tachidesk.impl.extension.Extension.getExtensionIconUrl
|
||||
import suwayomi.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.model.dataclass.SourceDataClass
|
||||
import suwayomi.tachidesk.model.table.ExtensionTable
|
||||
import suwayomi.tachidesk.model.table.SourceTable
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension.getExtensionIconUrl
|
||||
import suwayomi.tachidesk.manga.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.manga.model.dataclass.SourceDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.ExtensionTable
|
||||
import suwayomi.tachidesk.manga.model.table.SourceTable
|
||||
|
||||
object Source {
|
||||
private val logger = KotlinLogging.logger {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup
|
||||
package suwayomi.tachidesk.manga.impl.backup
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
+11
-11
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -11,16 +11,16 @@ import com.github.salomonbrys.kotson.registerTypeAdapter
|
||||
import com.github.salomonbrys.kotson.registerTypeHierarchyAdapter
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import suwayomi.tachidesk.impl.backup.legacy.models.DHistory
|
||||
import suwayomi.tachidesk.impl.backup.legacy.serializer.CategoryTypeAdapter
|
||||
import suwayomi.tachidesk.impl.backup.legacy.serializer.ChapterTypeAdapter
|
||||
import suwayomi.tachidesk.impl.backup.legacy.serializer.HistoryTypeAdapter
|
||||
import suwayomi.tachidesk.impl.backup.legacy.serializer.MangaTypeAdapter
|
||||
import suwayomi.tachidesk.impl.backup.legacy.serializer.TrackTypeAdapter
|
||||
import suwayomi.tachidesk.impl.backup.models.CategoryImpl
|
||||
import suwayomi.tachidesk.impl.backup.models.ChapterImpl
|
||||
import suwayomi.tachidesk.impl.backup.models.MangaImpl
|
||||
import suwayomi.tachidesk.impl.backup.models.TrackImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.models.DHistory
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.serializer.CategoryTypeAdapter
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.serializer.ChapterTypeAdapter
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.serializer.HistoryTypeAdapter
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.serializer.MangaTypeAdapter
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.serializer.TrackTypeAdapter
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.CategoryImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.ChapterImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.MangaImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.TrackImpl
|
||||
import java.util.Date
|
||||
|
||||
open class LegacyBackupBase {
|
||||
+13
-13
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -14,18 +14,18 @@ import com.google.gson.JsonObject
|
||||
import eu.kanade.tachiyomi.source.LocalSource
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.tachidesk.impl.Category.getCategoryList
|
||||
import suwayomi.tachidesk.impl.CategoryManga.getMangaCategories
|
||||
import suwayomi.tachidesk.impl.backup.BackupFlags
|
||||
import suwayomi.tachidesk.impl.backup.legacy.models.Backup
|
||||
import suwayomi.tachidesk.impl.backup.legacy.models.Backup.CURRENT_VERSION
|
||||
import suwayomi.tachidesk.impl.backup.models.CategoryImpl
|
||||
import suwayomi.tachidesk.impl.backup.models.ChapterImpl
|
||||
import suwayomi.tachidesk.impl.backup.models.Manga
|
||||
import suwayomi.tachidesk.impl.backup.models.MangaImpl
|
||||
import suwayomi.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.impl.Category.getCategoryList
|
||||
import suwayomi.tachidesk.manga.impl.CategoryManga.getMangaCategories
|
||||
import suwayomi.tachidesk.manga.impl.backup.BackupFlags
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.models.Backup
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.models.Backup.CURRENT_VERSION
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.CategoryImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.ChapterImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.Manga
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.MangaImpl
|
||||
import suwayomi.tachidesk.manga.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
|
||||
object LegacyBackupExport : LegacyBackupBase() {
|
||||
|
||||
+17
-17
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy
|
||||
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.google.gson.JsonArray
|
||||
@@ -13,22 +13,22 @@ import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import suwayomi.tachidesk.impl.Category.createCategory
|
||||
import suwayomi.tachidesk.impl.Category.getCategoryList
|
||||
import suwayomi.tachidesk.impl.backup.legacy.LegacyBackupValidator.ValidationResult
|
||||
import suwayomi.tachidesk.impl.backup.legacy.LegacyBackupValidator.validate
|
||||
import suwayomi.tachidesk.impl.backup.legacy.models.Backup
|
||||
import suwayomi.tachidesk.impl.backup.legacy.models.DHistory
|
||||
import suwayomi.tachidesk.impl.backup.models.CategoryImpl
|
||||
import suwayomi.tachidesk.impl.backup.models.Chapter
|
||||
import suwayomi.tachidesk.impl.backup.models.ChapterImpl
|
||||
import suwayomi.tachidesk.impl.backup.models.Manga
|
||||
import suwayomi.tachidesk.impl.backup.models.MangaImpl
|
||||
import suwayomi.tachidesk.impl.backup.models.Track
|
||||
import suwayomi.tachidesk.impl.backup.models.TrackImpl
|
||||
import suwayomi.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.impl.Category.createCategory
|
||||
import suwayomi.tachidesk.manga.impl.Category.getCategoryList
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.LegacyBackupValidator.ValidationResult
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.LegacyBackupValidator.validate
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.models.Backup
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.models.DHistory
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.CategoryImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.Chapter
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.ChapterImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.Manga
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.MangaImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.Track
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.TrackImpl
|
||||
import suwayomi.tachidesk.manga.impl.util.GetHttpSource.getHttpSource
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
import java.io.InputStream
|
||||
import java.util.Date
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -10,8 +10,8 @@ package suwayomi.tachidesk.impl.backup.legacy
|
||||
import com.google.gson.JsonObject
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.tachidesk.impl.backup.legacy.models.Backup
|
||||
import suwayomi.tachidesk.model.table.SourceTable
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.models.Backup
|
||||
import suwayomi.tachidesk.manga.model.table.SourceTable
|
||||
|
||||
object LegacyBackupValidator {
|
||||
data class ValidationResult(val missingSources: List<String>, val missingTrackers: List<String>)
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy.models
|
||||
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
@@ -0,0 +1,3 @@
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy.models
|
||||
|
||||
data class DHistory(val url: String, val lastRead: Long)
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy.serializer
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy.serializer
|
||||
|
||||
import com.github.salomonbrys.kotson.typeAdapter
|
||||
import com.google.gson.TypeAdapter
|
||||
import suwayomi.tachidesk.impl.backup.models.CategoryImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.CategoryImpl
|
||||
|
||||
/**
|
||||
* JSON Serializer used to write / read [CategoryImpl] to / from json
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy.serializer
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy.serializer
|
||||
|
||||
import com.github.salomonbrys.kotson.typeAdapter
|
||||
import com.google.gson.TypeAdapter
|
||||
import com.google.gson.stream.JsonToken
|
||||
import suwayomi.tachidesk.impl.backup.models.ChapterImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.ChapterImpl
|
||||
|
||||
/**
|
||||
* JSON Serializer used to write / read [ChapterImpl] to / from json
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy.serializer
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy.serializer
|
||||
|
||||
import com.github.salomonbrys.kotson.typeAdapter
|
||||
import com.google.gson.TypeAdapter
|
||||
import suwayomi.tachidesk.impl.backup.legacy.models.DHistory
|
||||
import suwayomi.tachidesk.manga.impl.backup.legacy.models.DHistory
|
||||
|
||||
/**
|
||||
* JSON Serializer used to write / read [DHistory] to / from json
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy.serializer
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy.serializer
|
||||
|
||||
import com.github.salomonbrys.kotson.typeAdapter
|
||||
import com.google.gson.TypeAdapter
|
||||
import suwayomi.tachidesk.impl.backup.models.MangaImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.MangaImpl
|
||||
|
||||
/**
|
||||
* JSON Serializer used to write / read [MangaImpl] to / from json
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
package suwayomi.tachidesk.impl.backup.legacy.serializer
|
||||
package suwayomi.tachidesk.manga.impl.backup.legacy.serializer
|
||||
|
||||
import com.github.salomonbrys.kotson.typeAdapter
|
||||
import com.google.gson.TypeAdapter
|
||||
import com.google.gson.stream.JsonToken
|
||||
import suwayomi.tachidesk.impl.backup.models.TrackImpl
|
||||
import suwayomi.tachidesk.manga.impl.backup.models.TrackImpl
|
||||
|
||||
/**
|
||||
* JSON Serializer used to write / read [TrackImpl] to / from json
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
class CategoryImpl : Category {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import java.io.Serializable
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
import org.jetbrains.exposed.sql.ResultRow
|
||||
import suwayomi.tachidesk.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||
|
||||
class ChapterImpl : Chapter {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
/**
|
||||
* Object containing the history statistics of a chapter
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
class LibraryManga : MangaImpl() {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
class MangaCategory {
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
class MangaChapter(val manga: Manga, val chapter: Chapter)
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
/**
|
||||
* Object containing manga, chapter and history
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
import org.jetbrains.exposed.sql.ResultRow
|
||||
import suwayomi.tachidesk.model.table.MangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
|
||||
open class MangaImpl : Manga {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.backup.models
|
||||
package suwayomi.tachidesk.manga.impl.backup.models
|
||||
|
||||
class TrackImpl : Track {
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package suwayomi.tachidesk.manga.impl.download
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import io.javalin.websocket.WsContext
|
||||
import io.javalin.websocket.WsMessageContext
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Downloading
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadStatus
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||
import suwayomi.tachidesk.manga.model.table.toDataClass
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
||||
object DownloadManager {
|
||||
private val clients = ConcurrentHashMap<String, WsContext>()
|
||||
private val downloadQueue = CopyOnWriteArrayList<DownloadChapter>()
|
||||
private var downloader: Downloader? = null
|
||||
|
||||
fun addClient(ctx: WsContext) {
|
||||
clients[ctx.sessionId] = ctx
|
||||
}
|
||||
|
||||
fun removeClient(ctx: WsContext) {
|
||||
clients.remove(ctx.sessionId)
|
||||
}
|
||||
|
||||
fun notifyClient(ctx: WsContext) {
|
||||
ctx.send(
|
||||
getStatus()
|
||||
)
|
||||
}
|
||||
|
||||
fun handleRequest(ctx: WsMessageContext) {
|
||||
when (ctx.message()) {
|
||||
"STATUS" -> notifyClient(ctx)
|
||||
else -> ctx.send(
|
||||
"""
|
||||
|Invalid command.
|
||||
|Supported commands are:
|
||||
| - STATUS
|
||||
| sends the current download status
|
||||
|""".trimMargin()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyAllClients() {
|
||||
val status = getStatus()
|
||||
clients.forEach {
|
||||
it.value.send(status)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStatus(): DownloadStatus {
|
||||
return DownloadStatus(
|
||||
if (downloader == null ||
|
||||
downloadQueue.none { it.state == Downloading }
|
||||
) "Stopped" else "Started",
|
||||
downloadQueue
|
||||
)
|
||||
}
|
||||
|
||||
fun enqueue(chapterIndex: Int, mangaId: Int) {
|
||||
if (downloadQueue.none { it.mangaId == mangaId && it.chapterIndex == chapterIndex }) {
|
||||
downloadQueue.add(
|
||||
DownloadChapter(
|
||||
chapterIndex,
|
||||
mangaId,
|
||||
chapter = ChapterTable.toDataClass(
|
||||
transaction {
|
||||
ChapterTable.select { (ChapterTable.manga eq mangaId) and (ChapterTable.chapterIndex eq chapterIndex) }
|
||||
.first()
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
start()
|
||||
}
|
||||
notifyAllClients()
|
||||
}
|
||||
|
||||
fun unqueue(chapterIndex: Int, mangaId: Int) {
|
||||
downloadQueue.removeIf { it.mangaId == mangaId && it.chapterIndex == chapterIndex }
|
||||
notifyAllClients()
|
||||
}
|
||||
|
||||
fun start() {
|
||||
if (downloader != null && !downloader?.isAlive!!) // doesn't exist or is dead
|
||||
downloader = null
|
||||
|
||||
if (downloader == null) {
|
||||
downloader = Downloader(downloadQueue) { notifyAllClients() }
|
||||
downloader!!.start()
|
||||
}
|
||||
|
||||
notifyAllClients()
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
downloader?.let {
|
||||
synchronized(it.shouldStop) {
|
||||
it.shouldStop = true
|
||||
}
|
||||
}
|
||||
downloader = null
|
||||
notifyAllClients()
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
stop()
|
||||
downloadQueue.clear()
|
||||
notifyAllClients()
|
||||
}
|
||||
}
|
||||
|
||||
enum class DownloaderState(val state: Int) {
|
||||
Stopped(0),
|
||||
Running(1),
|
||||
Paused(2),
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package suwayomi.tachidesk.manga.impl.download
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import suwayomi.tachidesk.manga.impl.Chapter.getChapter
|
||||
import suwayomi.tachidesk.manga.impl.Page.getPageImage
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadChapter
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Downloading
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Error
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Finished
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Queued
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
|
||||
class Downloader(private val downloadQueue: CopyOnWriteArrayList<DownloadChapter>, val notifier: () -> Unit) : Thread() {
|
||||
var shouldStop: Boolean = false
|
||||
|
||||
class DownloadShouldStopException : Exception()
|
||||
|
||||
fun step() {
|
||||
notifier()
|
||||
synchronized(shouldStop) {
|
||||
if (shouldStop) throw DownloadShouldStopException()
|
||||
}
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
do {
|
||||
val download = downloadQueue.firstOrNull {
|
||||
it.state == Queued ||
|
||||
(it.state == Error && it.tries < 3) // 3 re-tries per download
|
||||
} ?: break
|
||||
|
||||
try {
|
||||
download.state = Downloading
|
||||
step()
|
||||
|
||||
download.chapter = runBlocking { getChapter(download.chapterIndex, download.mangaId) }
|
||||
step()
|
||||
|
||||
val pageCount = download.chapter!!.pageCount
|
||||
for (pageNum in 0 until pageCount) {
|
||||
runBlocking { getPageImage(download.mangaId, download.chapterIndex, pageNum) }
|
||||
// TODO: retry on error with 2,4,8 seconds of wait
|
||||
// TODO: download multiple pages at once, possible solution: rx observer's strategy is used in Tachiyomi
|
||||
// TODO: fine grained download percentage
|
||||
download.progress = (pageNum + 1).toFloat() / pageCount
|
||||
step()
|
||||
}
|
||||
download.state = Finished
|
||||
transaction {
|
||||
ChapterTable.update({ (ChapterTable.manga eq download.mangaId) and (ChapterTable.chapterIndex eq download.chapterIndex) }) {
|
||||
it[isDownloaded] = true
|
||||
}
|
||||
}
|
||||
step()
|
||||
|
||||
downloadQueue.removeIf { it.mangaId == download.mangaId && it.chapterIndex == download.chapterIndex }
|
||||
step()
|
||||
} catch (e: DownloadShouldStopException) {
|
||||
println("Downloader was stopped")
|
||||
downloadQueue.filter { it.state == Downloading }.forEach { it.state = Queued }
|
||||
} catch (e: Exception) {
|
||||
println("Downloader faced an exception")
|
||||
downloadQueue.filter { it.state == Downloading }.forEach { it.state = Error; it.tries++ }
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
notifier()
|
||||
}
|
||||
} while (!shouldStop)
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package suwayomi.tachidesk.manga.impl.download.model
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import suwayomi.tachidesk.manga.impl.download.model.DownloadState.Queued
|
||||
import suwayomi.tachidesk.manga.model.dataclass.ChapterDataClass
|
||||
|
||||
class DownloadChapter(
|
||||
val chapterIndex: Int,
|
||||
val mangaId: Int,
|
||||
var state: DownloadState = Queued,
|
||||
var progress: Float = 0f,
|
||||
var tries: Int = 0,
|
||||
var chapter: ChapterDataClass? = null,
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
package suwayomi.tachidesk.manga.impl.download.model
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
enum class DownloadState(val state: Int) {
|
||||
Queued(0),
|
||||
Downloading(1),
|
||||
Finished(2),
|
||||
Error(3),
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package suwayomi.tachidesk.manga.impl.download.model
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
data class DownloadStatus(
|
||||
val status: String,
|
||||
val queue: List<DownloadChapter>,
|
||||
)
|
||||
+18
-18
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.extension
|
||||
package suwayomi.tachidesk.manga.impl.extension
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -25,23 +25,23 @@ import org.jetbrains.exposed.sql.update
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.conf.global
|
||||
import org.kodein.di.instance
|
||||
import suwayomi.server.ApplicationDirs
|
||||
import suwayomi.tachidesk.impl.extension.ExtensionsList.extensionTableAsDataClass
|
||||
import suwayomi.tachidesk.impl.extension.github.ExtensionGithubApi
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.EXTENSION_FEATURE
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.LIB_VERSION_MAX
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.LIB_VERSION_MIN
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.METADATA_NSFW
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.METADATA_SOURCE_CLASS
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.dex2jar
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.getPackageInfo
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.getSignatureHash
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.loadExtensionSources
|
||||
import suwayomi.tachidesk.impl.util.PackageTools.trustedSignatures
|
||||
import suwayomi.tachidesk.impl.util.network.await
|
||||
import suwayomi.tachidesk.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.model.table.ExtensionTable
|
||||
import suwayomi.tachidesk.model.table.SourceTable
|
||||
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList.extensionTableAsDataClass
|
||||
import suwayomi.tachidesk.manga.impl.extension.github.ExtensionGithubApi
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.EXTENSION_FEATURE
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MAX
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MIN
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.METADATA_NSFW
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.METADATA_SOURCE_CLASS
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.dex2jar
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.getPackageInfo
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.getSignatureHash
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.loadExtensionSources
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.trustedSignatures
|
||||
import suwayomi.tachidesk.manga.impl.util.network.await
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||
import suwayomi.tachidesk.manga.model.table.ExtensionTable
|
||||
import suwayomi.tachidesk.manga.model.table.SourceTable
|
||||
import suwayomi.tachidesk.server.ApplicationDirs
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.extension
|
||||
package suwayomi.tachidesk.manga.impl.extension
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -14,11 +14,11 @@ import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import suwayomi.tachidesk.impl.extension.Extension.getExtensionIconUrl
|
||||
import suwayomi.tachidesk.impl.extension.github.ExtensionGithubApi
|
||||
import suwayomi.tachidesk.impl.extension.github.OnlineExtension
|
||||
import suwayomi.tachidesk.model.dataclass.ExtensionDataClass
|
||||
import suwayomi.tachidesk.model.table.ExtensionTable
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension.getExtensionIconUrl
|
||||
import suwayomi.tachidesk.manga.impl.extension.github.ExtensionGithubApi
|
||||
import suwayomi.tachidesk.manga.impl.extension.github.OnlineExtension
|
||||
import suwayomi.tachidesk.manga.model.dataclass.ExtensionDataClass
|
||||
import suwayomi.tachidesk.manga.model.table.ExtensionTable
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
object ExtensionsList {
|
||||
+8
-12
@@ -1,4 +1,4 @@
|
||||
package suwayomi.tachidesk.impl.extension.github
|
||||
package suwayomi.tachidesk.manga.impl.extension.github
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
@@ -13,16 +13,14 @@ import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import okhttp3.Request
|
||||
import suwayomi.tachidesk.impl.util.network.UnzippingInterceptor
|
||||
import suwayomi.tachidesk.model.dataclass.ExtensionDataClass
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MAX
|
||||
import suwayomi.tachidesk.manga.impl.util.PackageTools.LIB_VERSION_MIN
|
||||
import suwayomi.tachidesk.manga.model.dataclass.ExtensionDataClass
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
object ExtensionGithubApi {
|
||||
const val BASE_URL = "https://raw.githubusercontent.com"
|
||||
const val REPO_URL_PREFIX = "$BASE_URL/tachiyomiorg/tachiyomi-extensions/repo"
|
||||
|
||||
private const val LIB_VERSION_MIN = 1.2
|
||||
private const val LIB_VERSION_MAX = 1.2
|
||||
private const val BASE_URL = "https://raw.githubusercontent.com"
|
||||
private const val REPO_URL_PREFIX = "$BASE_URL/tachiyomiorg/tachiyomi-extensions/repo"
|
||||
|
||||
private fun parseResponse(json: JsonArray): List<OnlineExtension> {
|
||||
return json
|
||||
@@ -61,17 +59,15 @@ object ExtensionGithubApi {
|
||||
.addNetworkInterceptor { chain ->
|
||||
val originalResponse = chain.proceed(chain.request())
|
||||
originalResponse.newBuilder()
|
||||
.header("Content-Encoding", "gzip")
|
||||
.header("Content-Type", "application/json")
|
||||
.build()
|
||||
}
|
||||
.addInterceptor(UnzippingInterceptor())
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun getRepo(): com.google.gson.JsonArray {
|
||||
private fun getRepo(): JsonArray {
|
||||
val request = Request.Builder()
|
||||
.url("$REPO_URL_PREFIX/index.json.gz")
|
||||
.url("$REPO_URL_PREFIX/index.min.json")
|
||||
.build()
|
||||
|
||||
val response = client.newCall(request).execute().use { response -> response.body!!.string() }
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package suwayomi.tachidesk.manga.impl.extension.github
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
data class OnlineExtension(
|
||||
val name: String,
|
||||
val pkgName: String,
|
||||
val versionName: String,
|
||||
val versionCode: Int,
|
||||
val lang: String,
|
||||
val isNsfw: Boolean,
|
||||
val apkName: String,
|
||||
val iconUrl: String
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user