mirror of
https://github.com/tachiyomiorg/tachiyomi-extensions-inspector.git
synced 2024-10-31 22:45:06 +01:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
29e358953e | ||
|
1aa6775836 |
4
.github/workflows/build_pull_request.yml
vendored
4
.github/workflows/build_pull_request.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout pull request
|
- name: Checkout pull request
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
@ -34,4 +34,4 @@ jobs:
|
|||||||
- name: Build project
|
- name: Build project
|
||||||
uses: gradle/gradle-command-action@v2
|
uses: gradle/gradle-command-action@v2
|
||||||
with:
|
with:
|
||||||
arguments: :server:shadowJar
|
arguments: :inspector:shadowJar
|
||||||
|
4
.github/workflows/build_push.yml
vendored
4
.github/workflows/build_push.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Clone repo
|
- name: Clone repo
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/wrapper-validation-action@v1
|
uses: gradle/wrapper-validation-action@v1
|
||||||
@ -34,4 +34,4 @@ jobs:
|
|||||||
- name: Build project
|
- name: Build project
|
||||||
uses: gradle/gradle-command-action@v2
|
uses: gradle/gradle-command-action@v2
|
||||||
with:
|
with:
|
||||||
arguments: :server:shadowJar
|
arguments: :inspector:shadowJar
|
||||||
|
4
.github/workflows/publish.yml
vendored
4
.github/workflows/publish.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout ${{ github.ref }}
|
- name: Checkout ${{ github.ref }}
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.ref }}
|
ref: ${{ github.ref }}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ jobs:
|
|||||||
- name: Build project
|
- name: Build project
|
||||||
uses: gradle/gradle-command-action@v2
|
uses: gradle/gradle-command-action@v2
|
||||||
with:
|
with:
|
||||||
arguments: :server:shadowJar
|
arguments: :inspector:shadowJar
|
||||||
|
|
||||||
- name: Upload Release
|
- name: Upload Release
|
||||||
uses: xresloader/upload-to-github-release@v1
|
uses: xresloader/upload-to-github-release@v1
|
||||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -7,11 +7,3 @@ local.properties
|
|||||||
# Ignore Gradle build output directory
|
# Ignore Gradle build output directory
|
||||||
build
|
build
|
||||||
|
|
||||||
server/src/main/resources/webUI
|
|
||||||
server/tmp/
|
|
||||||
server/tachiserver-data/
|
|
||||||
|
|
||||||
# bundle asset downlaods
|
|
||||||
OpenJDK*.zip
|
|
||||||
electron-*.zip
|
|
||||||
rcedit-*
|
|
||||||
|
@ -5,7 +5,8 @@ package xyz.nulldev.ts.config
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import ch.qos.logback.classic.Level
|
import ch.qos.logback.classic.Level
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
|
@ -5,7 +5,8 @@ package xyz.nulldev.ts.config
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ package xyz.nulldev.ts.config
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import ch.qos.logback.classic.Level
|
import ch.qos.logback.classic.Level
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
|
@ -5,7 +5,8 @@ package android.widget;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
public class EditText {
|
public class EditText {
|
||||||
public EditText(android.content.Context context) { throw new RuntimeException("Stub!"); }
|
public EditText(android.content.Context context) { throw new RuntimeException("Stub!"); }
|
||||||
|
@ -5,7 +5,8 @@ package android.widget;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
public class Toast {
|
public class Toast {
|
||||||
public static final int LENGTH_LONG = 1;
|
public static final int LENGTH_LONG = 1;
|
||||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ package xyz.nulldev.androidcompat.io.sharedprefs
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import com.russhwolf.settings.ExperimentalSettingsApi
|
import com.russhwolf.settings.ExperimentalSettingsApi
|
||||||
@ -23,7 +24,7 @@ import java.util.prefs.Preferences
|
|||||||
|
|
||||||
@OptIn(ExperimentalSettingsImplementation::class, ExperimentalSerializationApi::class, ExperimentalSettingsApi::class)
|
@OptIn(ExperimentalSettingsImplementation::class, ExperimentalSerializationApi::class, ExperimentalSettingsApi::class)
|
||||||
class JavaSharedPreferences(key: String) : SharedPreferences {
|
class JavaSharedPreferences(key: String) : SharedPreferences {
|
||||||
private val javaPreferences = Preferences.userRoot().node("suwayomi/tachidesk/$key")
|
private val javaPreferences = Preferences.userRoot().node("inspector/$key")
|
||||||
private val preferences = JvmPreferencesSettings(javaPreferences)
|
private val preferences = JvmPreferencesSettings(javaPreferences)
|
||||||
private val listeners = mutableMapOf<SharedPreferences.OnSharedPreferenceChangeListener, PreferenceChangeListener>()
|
private val listeners = mutableMapOf<SharedPreferences.OnSharedPreferenceChangeListener, PreferenceChangeListener>()
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ package xyz.nulldev.androidcompat.replace.java.text;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import com.ibm.icu.text.DisplayContext;
|
import com.ibm.icu.text.DisplayContext;
|
||||||
import com.ibm.icu.util.Currency;
|
import com.ibm.icu.util.Currency;
|
||||||
|
@ -5,7 +5,8 @@ package xyz.nulldev.androidcompat.replace.java.text;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import com.ibm.icu.text.DateFormatSymbols;
|
import com.ibm.icu.text.DateFormatSymbols;
|
||||||
import com.ibm.icu.text.DisplayContext;
|
import com.ibm.icu.text.DisplayContext;
|
||||||
|
@ -5,7 +5,8 @@ package xyz.nulldev.androidcompat.replace.java.util;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import com.ibm.icu.text.DateFormat;
|
import com.ibm.icu.text.DateFormat;
|
||||||
import com.ibm.icu.util.ULocale;
|
import com.ibm.icu.util.ULocale;
|
||||||
|
@ -5,7 +5,8 @@ package xyz.nulldev.androidcompat.replace.java.util;
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import com.ibm.icu.util.ULocale;
|
import com.ibm.icu.util.ULocale;
|
||||||
|
|
||||||
|
@ -9,8 +9,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "suwayomi"
|
group = "tachiyomi"
|
||||||
|
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
@ -24,9 +23,9 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val projects = listOf(
|
val projects = listOf(
|
||||||
project(":AndroidCompat"),
|
project(":AndroidCompat"),
|
||||||
project(":AndroidCompat:Config"),
|
project(":AndroidCompat:Config"),
|
||||||
project(":server")
|
project(":inspector")
|
||||||
)
|
)
|
||||||
|
|
||||||
configure(projects) {
|
configure(projects) {
|
||||||
@ -47,7 +46,6 @@ configure(projects) {
|
|||||||
// Kotlin
|
// Kotlin
|
||||||
implementation(kotlin("stdlib-jdk8"))
|
implementation(kotlin("stdlib-jdk8"))
|
||||||
implementation(kotlin("reflect"))
|
implementation(kotlin("reflect"))
|
||||||
testImplementation(kotlin("test"))
|
|
||||||
|
|
||||||
// coroutines
|
// coroutines
|
||||||
val coroutinesVersion = "1.6.4"
|
val coroutinesVersion = "1.6.4"
|
||||||
|
@ -21,7 +21,6 @@ dependencies {
|
|||||||
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:$okhttpVersion")
|
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:$okhttpVersion")
|
||||||
implementation("com.squareup.okio:okio:3.3.0")
|
implementation("com.squareup.okio:okio:3.3.0")
|
||||||
|
|
||||||
|
|
||||||
// dependencies of Tachiyomi extensions, some are duplicate, keeping it here for reference
|
// dependencies of Tachiyomi extensions, some are duplicate, keeping it here for reference
|
||||||
implementation("com.github.inorichi.injekt:injekt-core:65b0440")
|
implementation("com.github.inorichi.injekt:injekt-core:65b0440")
|
||||||
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
|
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
|
||||||
@ -35,12 +34,9 @@ dependencies {
|
|||||||
|
|
||||||
// uncomment to test extensions directly
|
// uncomment to test extensions directly
|
||||||
// implementation(fileTree("lib/"))
|
// implementation(fileTree("lib/"))
|
||||||
|
|
||||||
// Testing
|
|
||||||
testImplementation(kotlin("test-junit5"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val MainClass = "suwayomi.tachidesk.MainKt"
|
val MainClass = "inspector.MainKt"
|
||||||
application {
|
application {
|
||||||
mainClass.set(MainClass)
|
mainClass.set(MainClass)
|
||||||
}
|
}
|
||||||
@ -75,7 +71,7 @@ val String.wrapped get() = """"$this""""
|
|||||||
|
|
||||||
buildConfig {
|
buildConfig {
|
||||||
className("BuildConfig")
|
className("BuildConfig")
|
||||||
packageName("suwayomi.server")
|
packageName("inspector")
|
||||||
|
|
||||||
useKotlinOutput()
|
useKotlinOutput()
|
||||||
|
|
||||||
@ -88,13 +84,13 @@ tasks {
|
|||||||
shadowJar {
|
shadowJar {
|
||||||
manifest {
|
manifest {
|
||||||
attributes(
|
attributes(
|
||||||
mapOf(
|
mapOf(
|
||||||
"Main-Class" to MainClass,
|
"Main-Class" to MainClass,
|
||||||
"Implementation-Title" to rootProject.name,
|
"Implementation-Title" to rootProject.name,
|
||||||
"Implementation-Vendor" to "The Tachiyomi Open Source Project",
|
"Implementation-Vendor" to "The Tachiyomi Open Source Project",
|
||||||
"Specification-Version" to inspectorVersion,
|
"Specification-Version" to inspectorVersion,
|
||||||
"Implementation-Version" to inspectorRevision
|
"Implementation-Version" to inspectorRevision
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
archiveBaseName.set(rootProject.name)
|
archiveBaseName.set(rootProject.name)
|
@ -5,7 +5,8 @@ package eu.kanade.tachiyomi
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
@ -5,36 +5,26 @@ package eu.kanade.tachiyomi
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import eu.kanade.tachiyomi.network.JavaScriptEngine
|
import eu.kanade.tachiyomi.network.JavaScriptEngine
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import rx.Observable
|
|
||||||
import rx.schedulers.Schedulers
|
|
||||||
import uy.kohesive.injekt.api.InjektModule
|
import uy.kohesive.injekt.api.InjektModule
|
||||||
import uy.kohesive.injekt.api.InjektRegistrar
|
import uy.kohesive.injekt.api.InjektRegistrar
|
||||||
import uy.kohesive.injekt.api.addSingleton
|
import uy.kohesive.injekt.api.addSingleton
|
||||||
import uy.kohesive.injekt.api.addSingletonFactory
|
import uy.kohesive.injekt.api.addSingletonFactory
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
|
|
||||||
class AppModule(val app: Application) : InjektModule {
|
class AppModule(val app: Application) : InjektModule {
|
||||||
|
|
||||||
override fun InjektRegistrar.registerInjectables() {
|
override fun InjektRegistrar.registerInjectables() {
|
||||||
|
|
||||||
addSingleton(app)
|
addSingleton(app)
|
||||||
|
|
||||||
addSingletonFactory { NetworkHelper(app) }
|
addSingletonFactory { NetworkHelper(app) }
|
||||||
addSingletonFactory { JavaScriptEngine(app) }
|
addSingletonFactory { JavaScriptEngine(app) }
|
||||||
|
|
||||||
addSingletonFactory { Json { ignoreUnknownKeys = true } }
|
addSingletonFactory { Json { ignoreUnknownKeys = true } }
|
||||||
|
|
||||||
// Asynchronously init expensive components for a faster cold start
|
|
||||||
rxAsync { get<NetworkHelper>() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rxAsync(block: () -> Unit) {
|
|
||||||
Observable.fromCallable { block() }.subscribeOn(Schedulers.computation()).subscribe()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package eu.kanade.tachiyomi
|
||||||
|
|
||||||
|
class BuildConfig {
|
||||||
|
companion object {
|
||||||
|
const val VERSION_NAME = inspector.BuildConfig.NAME
|
||||||
|
val VERSION_CODE = inspector.BuildConfig.REVISION.trimStart('r').toInt()
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,8 @@ package eu.kanade.tachiyomi.network
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import okhttp3.Cookie
|
import okhttp3.Cookie
|
||||||
import okhttp3.CookieJar
|
import okhttp3.CookieJar
|
@ -5,7 +5,8 @@ package eu.kanade.tachiyomi.network
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor
|
import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor
|
@ -38,6 +38,7 @@ fun GET(
|
|||||||
.cacheControl(cache)
|
.cacheControl(cache)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun POST(
|
fun POST(
|
||||||
url: String,
|
url: String,
|
||||||
headers: Headers = DEFAULT_HEADERS,
|
headers: Headers = DEFAULT_HEADERS,
|
@ -5,7 +5,8 @@ package eu.kanade.tachiyomi.network.interceptor
|
|||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
@ -29,11 +29,16 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
|||||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
override fun fetchSearchManga(
|
||||||
|
page: Int,
|
||||||
|
query: String,
|
||||||
|
filters: FilterList
|
||||||
|
): Observable<MangasPage> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
|||||||
|
package eu.kanade.tachiyomi.source
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import rx.Observable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A basic interface for creating a source. It could be an online source, a local source, etc...
|
||||||
|
*/
|
||||||
|
interface Source {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id for the source. Must be unique.
|
||||||
|
*/
|
||||||
|
val id: Long
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the source.
|
||||||
|
*/
|
||||||
|
val name: String
|
||||||
|
|
||||||
|
val lang: String
|
||||||
|
get() = ""
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable with the updated details for a manga.
|
||||||
|
*
|
||||||
|
* @param manga the manga to update.
|
||||||
|
*/
|
||||||
|
fun fetchMangaDetails(manga: SManga): Observable<SManga>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable with all the available chapters for a manga.
|
||||||
|
*
|
||||||
|
* @param manga the manga to update.
|
||||||
|
*/
|
||||||
|
fun fetchChapterList(manga: SManga): Observable<List<SChapter>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable with the list of pages a chapter has.
|
||||||
|
*
|
||||||
|
* @param chapter the chapter.
|
||||||
|
*/
|
||||||
|
fun fetchPageList(chapter: SChapter): Observable<List<Page>>
|
||||||
|
}
|
@ -3,7 +3,9 @@ package eu.kanade.tachiyomi.source.model
|
|||||||
sealed class Filter<T>(val name: String, var state: T) {
|
sealed class Filter<T>(val name: String, var state: T) {
|
||||||
open class Header(name: String) : Filter<Any>(name, 0)
|
open class Header(name: String) : Filter<Any>(name, 0)
|
||||||
open class Separator(name: String = "") : Filter<Any>(name, 0)
|
open class Separator(name: String = "") : Filter<Any>(name, 0)
|
||||||
abstract class Select<V>(name: String, val values: Array<V>, state: Int = 0) : Filter<Int>(name, state)
|
abstract class Select<V>(name: String, val values: Array<V>, state: Int = 0) :
|
||||||
|
Filter<Int>(name, state)
|
||||||
|
|
||||||
abstract class Text(name: String, state: String = "") : Filter<String>(name, state)
|
abstract class Text(name: String, state: String = "") : Filter<String>(name, state)
|
||||||
abstract class CheckBox(name: String, state: Boolean = false) : Filter<Boolean>(name, state)
|
abstract class CheckBox(name: String, state: Boolean = false) : Filter<Boolean>(name, state)
|
||||||
abstract class TriState(name: String, state: Int = STATE_IGNORE) : Filter<Int>(name, state) {
|
abstract class TriState(name: String, state: Int = STATE_IGNORE) : Filter<Int>(name, state) {
|
@ -56,7 +56,8 @@ abstract class HttpSource : CatalogueSource {
|
|||||||
override val id by lazy {
|
override val id by lazy {
|
||||||
val key = "${name.lowercase()}/$lang/$versionId"
|
val key = "${name.lowercase()}/$lang/$versionId"
|
||||||
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
val bytes = MessageDigest.getInstance("MD5").digest(key.toByteArray())
|
||||||
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }.reduce(Long::or) and Long.MAX_VALUE
|
(0..7).map { bytes[it].toLong() and 0xff shl 8 * (7 - it) }
|
||||||
|
.reduce(Long::or) and Long.MAX_VALUE
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,7 +119,11 @@ abstract class HttpSource : CatalogueSource {
|
|||||||
* @param query the search query.
|
* @param query the search query.
|
||||||
* @param filters the list of filters to apply.
|
* @param filters the list of filters to apply.
|
||||||
*/
|
*/
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
override fun fetchSearchManga(
|
||||||
|
page: Int,
|
||||||
|
query: String,
|
||||||
|
filters: FilterList
|
||||||
|
): Observable<MangasPage> {
|
||||||
return client.newCall(searchMangaRequest(page, query, filters))
|
return client.newCall(searchMangaRequest(page, query, filters))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
.map { response ->
|
.map { response ->
|
||||||
@ -133,7 +138,11 @@ abstract class HttpSource : CatalogueSource {
|
|||||||
* @param query the search query.
|
* @param query the search query.
|
||||||
* @param filters the list of filters to apply.
|
* @param filters the list of filters to apply.
|
||||||
*/
|
*/
|
||||||
protected abstract fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request
|
protected abstract fun searchMangaRequest(
|
||||||
|
page: Int,
|
||||||
|
query: String,
|
||||||
|
filters: FilterList
|
||||||
|
): Request
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the response from the site and returns a [MangasPage] object.
|
* Parses the response from the site and returns a [MangasPage] object.
|
@ -4,4 +4,5 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block)
|
suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) =
|
||||||
|
withContext(Dispatchers.IO, block)
|
@ -1,4 +1,4 @@
|
|||||||
package suwayomi.tachidesk
|
package inspector
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) Contributors to the Suwayomi project
|
* Copyright (C) Contributors to the Suwayomi project
|
||||||
@ -8,14 +8,18 @@ package suwayomi.tachidesk
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor
|
import eu.kanade.tachiyomi.App
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
|
import inspector.util.Extension
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
import suwayomi.tachidesk.manga.impl.extension.Extension
|
import org.kodein.di.DI
|
||||||
import suwayomi.tachidesk.server.applicationSetup
|
import org.kodein.di.conf.global
|
||||||
|
import xyz.nulldev.androidcompat.AndroidCompat
|
||||||
|
import xyz.nulldev.androidcompat.AndroidCompatInitializer
|
||||||
|
import xyz.nulldev.ts.config.ConfigKodeinModule
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
@ -23,41 +27,53 @@ import kotlin.io.path.extension
|
|||||||
import kotlin.streams.asSequence
|
import kotlin.streams.asSequence
|
||||||
|
|
||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
|
private val androidCompat by lazy { AndroidCompat() }
|
||||||
|
|
||||||
suspend fun main(args: Array<String>) {
|
suspend fun main(args: Array<String>) {
|
||||||
if (args.size < 3) {
|
if (args.size < 3) {
|
||||||
throw RuntimeException("Inspector must be given the path of apks directory, output json, and a tmp dir")
|
throw RuntimeException("Inspector must be given the path of apks directory, output json, and a tmp dir")
|
||||||
}
|
}
|
||||||
|
|
||||||
applicationSetup()
|
|
||||||
|
|
||||||
val (apksPath, outputPath, tmpDirPath) = args
|
val (apksPath, outputPath, tmpDirPath) = args
|
||||||
|
|
||||||
|
initApplication()
|
||||||
|
|
||||||
val tmpDir = File(tmpDirPath, "tmp").also { it.mkdir() }
|
val tmpDir = File(tmpDirPath, "tmp").also { it.mkdir() }
|
||||||
val extensions = Files.find(Paths.get(apksPath), 2, { _, fileAttributes -> fileAttributes.isRegularFile })
|
val extensions =
|
||||||
.asSequence()
|
Files.find(Paths.get(apksPath), 2, { _, fileAttributes -> fileAttributes.isRegularFile })
|
||||||
.filter { it.extension == "apk" }
|
.asSequence()
|
||||||
.toList()
|
.filter { it.extension == "apk" }
|
||||||
|
.toList()
|
||||||
|
|
||||||
logger.info("Found ${extensions.size} extensions")
|
logger.info("Found ${extensions.size} extensions")
|
||||||
|
|
||||||
val extensionsInfo = extensions.associate {
|
val extensionsInfo = extensions.associate {
|
||||||
logger.debug("Installing $it")
|
logger.debug("Installing $it")
|
||||||
val (pkgName, sources) = Extension.installAPK(tmpDir) { it.toFile() }
|
val (pkgName, sources) = Extension.installApk(tmpDir) { it.toFile() }
|
||||||
pkgName to sources.map { source -> SourceJson(source) }
|
pkgName to sources.map { source -> SourceJson(source) }
|
||||||
}
|
}
|
||||||
|
|
||||||
File(outputPath).writeText(Json.encodeToString(extensionsInfo))
|
File(outputPath).writeText(Json.encodeToString(extensionsInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initApplication() {
|
||||||
|
logger.info("Running Inspector ${BuildConfig.VERSION} revision ${BuildConfig.REVISION}")
|
||||||
|
|
||||||
|
// Load config API
|
||||||
|
DI.global.addImport(ConfigKodeinModule().create())
|
||||||
|
// Load Android compatibility dependencies
|
||||||
|
AndroidCompatInitializer().init()
|
||||||
|
// start app
|
||||||
|
androidCompat.startApp(App())
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SourceJson(
|
private data class SourceJson(
|
||||||
val name: String,
|
val name: String,
|
||||||
val lang: String,
|
val lang: String,
|
||||||
val id: String,
|
val id: String,
|
||||||
val baseUrl: String,
|
val baseUrl: String,
|
||||||
val versionId: Int,
|
val versionId: Int,
|
||||||
val hasCloudflare: Short
|
|
||||||
) {
|
) {
|
||||||
constructor(source: HttpSource) :
|
constructor(source: HttpSource) :
|
||||||
this(
|
this(
|
||||||
@ -66,10 +82,5 @@ data class SourceJson(
|
|||||||
source.id.toString(),
|
source.id.toString(),
|
||||||
source.baseUrl,
|
source.baseUrl,
|
||||||
source.versionId,
|
source.versionId,
|
||||||
source.client.interceptors
|
|
||||||
.any { it is CloudflareInterceptor }
|
|
||||||
.toShort()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Boolean.toShort(): Short = if (this) 1 else 0
|
|
@ -1,29 +1,33 @@
|
|||||||
package suwayomi.tachidesk.manga.impl.extension
|
package inspector.util
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) Contributors to the Suwayomi project
|
* Copyright (C) Contributors to the Suwayomi project
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceFactory
|
import eu.kanade.tachiyomi.source.SourceFactory
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
|
import inspector.util.PackageTools.EXTENSION_FEATURE
|
||||||
|
import inspector.util.PackageTools.LIB_VERSION_MAX
|
||||||
|
import inspector.util.PackageTools.LIB_VERSION_MIN
|
||||||
|
import inspector.util.PackageTools.METADATA_SOURCE_CLASS
|
||||||
|
import inspector.util.PackageTools.dex2jar
|
||||||
|
import inspector.util.PackageTools.getPackageInfo
|
||||||
|
import inspector.util.PackageTools.loadExtensionSources
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
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_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.loadExtensionSources
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
object Extension {
|
object Extension {
|
||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
|
|
||||||
suspend fun installAPK(tmpDir: File, fetcher: suspend () -> File): Pair<String, List<HttpSource>> {
|
suspend fun installApk(
|
||||||
|
tmpDir: File,
|
||||||
|
fetcher: suspend () -> File
|
||||||
|
): Pair<String, List<HttpSource>> {
|
||||||
val apkFile = fetcher()
|
val apkFile = fetcher()
|
||||||
|
|
||||||
val jarFile = File(tmpDir, "${apkFile.nameWithoutExtension}.jar")
|
val jarFile = File(tmpDir, "${apkFile.nameWithoutExtension}.jar")
|
||||||
@ -43,14 +47,19 @@ object Extension {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val className = packageInfo.packageName + packageInfo.applicationInfo.metaData.getString(METADATA_SOURCE_CLASS)
|
val className = packageInfo.packageName + packageInfo.applicationInfo.metaData.getString(
|
||||||
|
METADATA_SOURCE_CLASS
|
||||||
|
)
|
||||||
|
|
||||||
logger.trace("Main class for extension is $className")
|
logger.trace("Main class for extension is $className")
|
||||||
|
|
||||||
dex2jar(apkFile, jarFile)
|
dex2jar(apkFile, jarFile)
|
||||||
|
|
||||||
// collect sources from the extension
|
// collect sources from the extension
|
||||||
return packageInfo.packageName to when (val instance = loadExtensionSources(jarFile.absolutePath, className)) {
|
return packageInfo.packageName to when (
|
||||||
|
val instance =
|
||||||
|
loadExtensionSources(jarFile.absolutePath, className)
|
||||||
|
) {
|
||||||
is Source -> listOf(instance).filterIsInstance<HttpSource>()
|
is Source -> listOf(instance).filterIsInstance<HttpSource>()
|
||||||
is SourceFactory -> instance.createSources().filterIsInstance<HttpSource>()
|
is SourceFactory -> instance.createSources().filterIsInstance<HttpSource>()
|
||||||
else -> throw RuntimeException("Unknown source class type! ${instance.javaClass}")
|
else -> throw RuntimeException("Unknown source class type! ${instance.javaClass}")
|
@ -1,11 +1,12 @@
|
|||||||
package suwayomi.tachidesk.manga.impl.util
|
package inspector.util
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) Contributors to the Suwayomi project
|
* Copyright (C) Contributors to the Suwayomi project
|
||||||
*
|
*
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* 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
|
* 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/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.Signature
|
import android.content.pm.Signature
|
||||||
@ -57,7 +58,8 @@ object PackageTools {
|
|||||||
.skipExceptions(false)
|
.skipExceptions(false)
|
||||||
.to(jarFilePath)
|
.to(jarFilePath)
|
||||||
if (handler.hasException()) {
|
if (handler.hasException()) {
|
||||||
val errorFile: Path = jarFilePath.parent.resolve("${dexFile.nameWithoutExtension}-error.txt")
|
val errorFile: Path =
|
||||||
|
jarFilePath.parent.resolve("${dexFile.nameWithoutExtension}-error.txt")
|
||||||
logger.error(
|
logger.error(
|
||||||
"""
|
"""
|
||||||
Detail Error Information in File $errorFile
|
Detail Error Information in File $errorFile
|
@ -8,7 +8,7 @@
|
|||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<logger name="Exposed" level="ERROR"/>
|
<logger name="Exposed" level="ERROR" />
|
||||||
|
|
||||||
<root level="INFO">
|
<root level="INFO">
|
||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
@ -1,8 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi
|
|
||||||
|
|
||||||
class BuildConfig {
|
|
||||||
companion object {
|
|
||||||
const val VERSION_NAME = suwayomi.server.BuildConfig.NAME
|
|
||||||
val VERSION_CODE = suwayomi.server.BuildConfig.REVISION.trimStart('r').toInt()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.source
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
|
||||||
import eu.kanade.tachiyomi.util.awaitSingle
|
|
||||||
import rx.Observable
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A basic interface for creating a source. It could be an online source, a local source, etc.
|
|
||||||
*/
|
|
||||||
interface Source {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ID for the source. Must be unique.
|
|
||||||
*/
|
|
||||||
val id: Long
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the source.
|
|
||||||
*/
|
|
||||||
val name: String
|
|
||||||
|
|
||||||
val lang: String
|
|
||||||
get() = ""
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the updated details for a manga.
|
|
||||||
*
|
|
||||||
* @since extensions-lib 1.4
|
|
||||||
* @param manga the manga to update.
|
|
||||||
* @return the updated manga.
|
|
||||||
*/
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
suspend fun getMangaDetails(manga: SManga): SManga {
|
|
||||||
return fetchMangaDetails(manga).awaitSingle()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all the available chapters for a manga.
|
|
||||||
*
|
|
||||||
* @since extensions-lib 1.4
|
|
||||||
* @param manga the manga to update.
|
|
||||||
* @return the chapters for the manga.
|
|
||||||
*/
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
suspend fun getChapterList(manga: SManga): List<SChapter> {
|
|
||||||
return fetchChapterList(manga).awaitSingle()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the list of pages a chapter has. Pages should be returned
|
|
||||||
* in the expected order; the index is ignored.
|
|
||||||
*
|
|
||||||
* @since extensions-lib 1.4
|
|
||||||
* @param chapter the chapter.
|
|
||||||
* @return the pages for the chapter.
|
|
||||||
*/
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
suspend fun getPageList(chapter: SChapter): List<Page> {
|
|
||||||
return fetchPageList(chapter).awaitSingle()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an observable with the updated details for a manga.
|
|
||||||
*
|
|
||||||
* @param manga the manga to update.
|
|
||||||
*/
|
|
||||||
@Deprecated(
|
|
||||||
"Use the non-RxJava API instead",
|
|
||||||
ReplaceWith("getMangaDetails"),
|
|
||||||
)
|
|
||||||
fun fetchMangaDetails(manga: SManga): Observable<SManga> = throw IllegalStateException(
|
|
||||||
"Not used",
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an observable with all the available chapters for a manga.
|
|
||||||
*
|
|
||||||
* @param manga the manga to update.
|
|
||||||
*/
|
|
||||||
@Deprecated(
|
|
||||||
"Use the non-RxJava API instead",
|
|
||||||
ReplaceWith("getChapterList"),
|
|
||||||
)
|
|
||||||
fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = throw IllegalStateException(
|
|
||||||
"Not used",
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an observable with the list of pages a chapter has. Pages should be returned
|
|
||||||
* in the expected order; the index is ignored.
|
|
||||||
*
|
|
||||||
* @param chapter the chapter.
|
|
||||||
*/
|
|
||||||
@Deprecated(
|
|
||||||
"Use the non-RxJava API instead",
|
|
||||||
ReplaceWith("getPageList"),
|
|
||||||
)
|
|
||||||
fun fetchPageList(chapter: SChapter): Observable<List<Page>> = Observable.empty()
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.source.online
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.source.Source
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A source that may handle opening an SManga for a given URI.
|
|
||||||
*
|
|
||||||
* @since extensions-lib 1.5
|
|
||||||
*/
|
|
||||||
interface ResolvableSource : Source {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether this source may potentially handle the given URI.
|
|
||||||
*
|
|
||||||
* @since extensions-lib 1.5
|
|
||||||
*/
|
|
||||||
fun canResolveUri(uri: String): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called if canHandleUri is true. Returns the corresponding SManga, if possible.
|
|
||||||
*
|
|
||||||
* @since extensions-lib 1.5
|
|
||||||
*/
|
|
||||||
suspend fun getManga(uri: String): SManga?
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.util
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CancellableContinuation
|
|
||||||
import kotlinx.coroutines.InternalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
||||||
import rx.Observable
|
|
||||||
import rx.Subscriber
|
|
||||||
import rx.Subscription
|
|
||||||
import kotlin.coroutines.resume
|
|
||||||
import kotlin.coroutines.resumeWithException
|
|
||||||
|
|
||||||
suspend fun <T> Observable<T>.awaitSingle(): T = single().awaitOne()
|
|
||||||
|
|
||||||
@OptIn(InternalCoroutinesApi::class)
|
|
||||||
private suspend fun <T> Observable<T>.awaitOne(): T = suspendCancellableCoroutine { cont ->
|
|
||||||
cont.unsubscribeOnCancellation(
|
|
||||||
subscribe(
|
|
||||||
object : Subscriber<T>() {
|
|
||||||
override fun onStart() {
|
|
||||||
request(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNext(t: T) {
|
|
||||||
cont.resume(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCompleted() {
|
|
||||||
if (cont.isActive) {
|
|
||||||
cont.resumeWithException(
|
|
||||||
IllegalStateException(
|
|
||||||
"Should have invoked onNext",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
|
||||||
/*
|
|
||||||
* Rx1 observable throws NoSuchElementException if cancellation happened before
|
|
||||||
* element emission. To mitigate this we try to atomically resume continuation with exception:
|
|
||||||
* if resume failed, then we know that continuation successfully cancelled itself
|
|
||||||
*/
|
|
||||||
val token = cont.tryResumeWithException(e)
|
|
||||||
if (token != null) {
|
|
||||||
cont.completeResume(token)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> CancellableContinuation<T>.unsubscribeOnCancellation(sub: Subscription) =
|
|
||||||
invokeOnCancellation { sub.unsubscribe() }
|
|
@ -1,44 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.util.lang
|
|
||||||
|
|
||||||
import java.security.MessageDigest
|
|
||||||
|
|
||||||
object Hash {
|
|
||||||
|
|
||||||
private val chars = charArrayOf(
|
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
|
||||||
'a', 'b', 'c', 'd', 'e', 'f'
|
|
||||||
)
|
|
||||||
|
|
||||||
private val MD5 get() = MessageDigest.getInstance("MD5")
|
|
||||||
|
|
||||||
private val SHA256 get() = MessageDigest.getInstance("SHA-256")
|
|
||||||
|
|
||||||
fun sha256(bytes: ByteArray): String {
|
|
||||||
return encodeHex(SHA256.digest(bytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sha256(string: String): String {
|
|
||||||
return sha256(string.toByteArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun md5(bytes: ByteArray): String {
|
|
||||||
return encodeHex(MD5.digest(bytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun md5(string: String): String {
|
|
||||||
return md5(string.toByteArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun encodeHex(data: ByteArray): String {
|
|
||||||
val l = data.size
|
|
||||||
val out = CharArray(l shl 1)
|
|
||||||
var i = 0
|
|
||||||
var j = 0
|
|
||||||
while (i < l) {
|
|
||||||
out[j++] = chars[(240 and data[i].toInt()).ushr(4)]
|
|
||||||
out[j++] = chars[15 and data[i].toInt()]
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return String(out)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package suwayomi.tachidesk.server
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 eu.kanade.tachiyomi.App
|
|
||||||
import mu.KotlinLogging
|
|
||||||
import org.kodein.di.DI
|
|
||||||
import org.kodein.di.conf.global
|
|
||||||
import suwayomi.server.BuildConfig
|
|
||||||
import xyz.nulldev.androidcompat.AndroidCompat
|
|
||||||
import xyz.nulldev.androidcompat.AndroidCompatInitializer
|
|
||||||
import xyz.nulldev.ts.config.ConfigKodeinModule
|
|
||||||
|
|
||||||
private val logger = KotlinLogging.logger {}
|
|
||||||
|
|
||||||
val androidCompat by lazy { AndroidCompat() }
|
|
||||||
|
|
||||||
fun applicationSetup() {
|
|
||||||
logger.info("Running Inspector ${BuildConfig.VERSION} revision ${BuildConfig.REVISION}")
|
|
||||||
|
|
||||||
// Load config API
|
|
||||||
DI.global.addImport(ConfigKodeinModule().create())
|
|
||||||
// Load Android compatibility dependencies
|
|
||||||
AndroidCompatInitializer().init()
|
|
||||||
// start app
|
|
||||||
androidCompat.startApp(App())
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
# Server ip and port bindings
|
|
||||||
server.ip = "0.0.0.0"
|
|
||||||
server.port = 4567
|
|
||||||
|
|
||||||
# Socks5 proxy
|
|
||||||
server.socksProxy = false
|
|
||||||
server.socksProxyHost = ""
|
|
||||||
server.socksProxyPort = ""
|
|
||||||
|
|
||||||
# misc
|
|
||||||
server.debugLogsEnabled = true
|
|
||||||
server.systemTrayEnabled = false
|
|
||||||
server.initialOpenInBrowserEnabled = true
|
|
@ -1,5 +1,5 @@
|
|||||||
rootProject.name = "Tachiyomi Extensions Inspector"
|
rootProject.name = "Tachiyomi Extensions Inspector"
|
||||||
|
|
||||||
include("server")
|
|
||||||
include("AndroidCompat")
|
include("AndroidCompat")
|
||||||
include("AndroidCompat:Config")
|
include("AndroidCompat:Config")
|
||||||
|
include("inspector")
|
||||||
|
Loading…
Reference in New Issue
Block a user