mirror of
https://github.com/tachiyomiorg/tachiyomi-extensions-inspector.git
synced 2024-10-31 22:45:06 +01:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
29e358953e | ||
|
1aa6775836 | ||
|
1f03ebad2b | ||
|
e301768a5d | ||
|
b0e09fe721 | ||
|
ad84ee8857 | ||
|
42a23ee871 | ||
|
2314d3e432 | ||
|
b220571647 |
7
.github/runner-files/ci-gradle.properties
vendored
7
.github/runner-files/ci-gradle.properties
vendored
@ -1,7 +0,0 @@
|
||||
org.gradle.daemon=false
|
||||
org.gradle.jvmargs=-Xmx5120m
|
||||
org.gradle.workers.max=5
|
||||
org.gradle.parallel=true
|
||||
|
||||
kotlin.incremental=false
|
||||
kotlin.compiler.execution.strategy=in-process
|
23
.github/workflows/build_pull_request.yml
vendored
23
.github/workflows/build_pull_request.yml
vendored
@ -3,19 +3,18 @@ name: CI Pull Request
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build pull request
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Cancel previous runs
|
||||
uses: styfle/cancel-workflow-action@0.9.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: Checkout pull request
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
@ -23,14 +22,10 @@ jobs:
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Copy CI gradle.properties
|
||||
run: |
|
||||
mkdir -p ~/.gradle
|
||||
cp .github/runner-files/ci-gradle.properties ~/.gradle/gradle.properties
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Generate android.jar
|
||||
run: |
|
||||
@ -39,4 +34,4 @@ jobs:
|
||||
- name: Build project
|
||||
uses: gradle/gradle-command-action@v2
|
||||
with:
|
||||
arguments: :server:shadowJar
|
||||
arguments: :inspector:shadowJar
|
||||
|
25
.github/workflows/build_push.yml
vendored
25
.github/workflows/build_push.yml
vendored
@ -3,7 +3,11 @@ name: CI build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@ -11,26 +15,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Cancel previous runs
|
||||
uses: styfle/cancel-workflow-action@0.9.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: Clone repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Copy CI gradle.properties
|
||||
run: |
|
||||
mkdir -p ~/.gradle
|
||||
cp .github/runner-files/ci-gradle.properties ~/.gradle/gradle.properties
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Generate android.jar
|
||||
run: |
|
||||
@ -39,4 +34,4 @@ jobs:
|
||||
- name: Build project
|
||||
uses: gradle/gradle-command-action@v2
|
||||
with:
|
||||
arguments: :server:shadowJar
|
||||
arguments: :inspector:shadowJar
|
||||
|
23
.github/workflows/publish.yml
vendored
23
.github/workflows/publish.yml
vendored
@ -5,19 +5,18 @@ on:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build artifacts and create draft release
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Cancel previous runs
|
||||
uses: styfle/cancel-workflow-action@0.9.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: Checkout ${{ github.ref }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
@ -25,14 +24,10 @@ jobs:
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Copy CI gradle.properties
|
||||
run: |
|
||||
mkdir -p ~/.gradle
|
||||
cp .github/runner-files/ci-gradle.properties ~/.gradle/gradle.properties
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
||||
- name: Generate android.jar
|
||||
run: |
|
||||
@ -41,7 +36,7 @@ jobs:
|
||||
- name: Build project
|
||||
uses: gradle/gradle-command-action@v2
|
||||
with:
|
||||
arguments: :server:shadowJar
|
||||
arguments: :inspector:shadowJar
|
||||
|
||||
- name: Upload Release
|
||||
uses: xresloader/upload-to-github-release@v1
|
||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -7,11 +7,3 @@ local.properties
|
||||
# Ignore Gradle build output directory
|
||||
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
|
||||
* 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 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
|
||||
* 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
|
||||
|
||||
|
@ -5,7 +5,8 @@ package xyz.nulldev.ts.config
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import ch.qos.logback.classic.Level
|
||||
import mu.KotlinLogging
|
||||
|
@ -1,10 +1,10 @@
|
||||
package android.text;
|
||||
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.safety.Whitelist;
|
||||
import org.jsoup.safety.Safelist;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
/**
|
||||
@ -18,7 +18,7 @@ import org.xml.sax.XMLReader;
|
||||
public class Html {
|
||||
|
||||
public static Spanned fromHtml(String source) {
|
||||
return new FakeSpanned(Jsoup.clean(source, Whitelist.none()));
|
||||
return new FakeSpanned(Jsoup.clean(source, Safelist.none()));
|
||||
}
|
||||
|
||||
public static Spanned fromHtml(String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler) {
|
||||
|
@ -5,7 +5,8 @@ package android.widget;
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
public class EditText {
|
||||
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
|
||||
* 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 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
|
||||
* 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;
|
||||
|
||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
|
@ -5,7 +5,8 @@ package androidx.preference;
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
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
|
||||
* 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 com.russhwolf.settings.ExperimentalSettingsApi
|
||||
@ -23,7 +24,7 @@ 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 javaPreferences = Preferences.userRoot().node("inspector/$key")
|
||||
private val preferences = JvmPreferencesSettings(javaPreferences)
|
||||
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
|
||||
* 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.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
|
||||
* 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.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
|
||||
* 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.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
|
||||
* 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;
|
||||
|
||||
|
@ -1,17 +1,15 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "1.6.10"
|
||||
kotlin("plugin.serialization") version "1.6.10" apply false
|
||||
kotlin("jvm") version "1.8.0"
|
||||
kotlin("plugin.serialization") version "1.8.0" apply false
|
||||
id("org.jmailen.kotlinter") version "3.9.0" apply false
|
||||
id("com.github.gmazzo.buildconfig") version "3.0.3" apply false
|
||||
id("com.github.johnrengelman.shadow") version "7.1.2" apply false
|
||||
id("com.github.ben-manes.versions") version "0.39.0"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
group = "suwayomi"
|
||||
|
||||
group = "tachiyomi"
|
||||
version = "1.0"
|
||||
|
||||
repositories {
|
||||
@ -25,22 +23,22 @@ allprojects {
|
||||
}
|
||||
|
||||
val projects = listOf(
|
||||
project(":AndroidCompat"),
|
||||
project(":AndroidCompat:Config"),
|
||||
project(":server")
|
||||
project(":AndroidCompat"),
|
||||
project(":AndroidCompat:Config"),
|
||||
project(":inspector")
|
||||
)
|
||||
|
||||
configure(projects) {
|
||||
apply(plugin = "org.jetbrains.kotlin.jvm")
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,19 +46,17 @@ configure(projects) {
|
||||
// Kotlin
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
implementation(kotlin("reflect"))
|
||||
testImplementation(kotlin("test"))
|
||||
|
||||
// coroutines
|
||||
val coroutinesVersion = "1.6.0"
|
||||
val coroutinesVersion = "1.6.4"
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$coroutinesVersion")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion")
|
||||
|
||||
val kotlinSerializationVersion = "1.3.2"
|
||||
val kotlinSerializationVersion = "1.4.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.11.0")
|
||||
|
||||
@ -72,17 +68,16 @@ configure(projects) {
|
||||
// ReactiveX
|
||||
implementation("io.reactivex:rxjava:1.3.8")
|
||||
implementation("io.reactivex:rxkotlin:1.0.0")
|
||||
implementation("com.jakewharton.rxrelay:rxrelay:1.2.0")
|
||||
|
||||
// JSoup
|
||||
implementation("org.jsoup:jsoup:1.14.3")
|
||||
implementation("org.jsoup:jsoup:1.15.3")
|
||||
|
||||
// dependency of :AndroidCompat:Config
|
||||
implementation("com.typesafe:config:1.4.2")
|
||||
implementation("io.github.config4k:config4k:0.4.2")
|
||||
|
||||
// dex2jar
|
||||
val dex2jarVersion = "v35"
|
||||
val dex2jarVersion = "v71"
|
||||
implementation("com.github.ThexXTURBOXx.dex2jar:dex-translator:$dex2jarVersion")
|
||||
implementation("com.github.ThexXTURBOXx.dex2jar:dex-tools:$dex2jarVersion")
|
||||
|
||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -15,37 +15,28 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
// okhttp
|
||||
val okhttpVersion = "4.9.3" // version is locked by Tachiyomi extensions
|
||||
val okhttpVersion = "5.0.0-alpha.11" // version is locked by Tachiyomi extensions
|
||||
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:$okhttpVersion")
|
||||
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:$okhttpVersion")
|
||||
implementation("com.squareup.okio:okio:3.0.0")
|
||||
|
||||
implementation("com.squareup.okio:okio:3.3.0")
|
||||
|
||||
// dependencies of Tachiyomi extensions, some are duplicate, keeping it here for reference
|
||||
implementation("com.github.inorichi.injekt:injekt-core:65b0440")
|
||||
implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
|
||||
implementation("io.reactivex:rxjava:1.3.8")
|
||||
implementation("org.jsoup:jsoup:1.14.3")
|
||||
implementation("org.jsoup:jsoup:1.15.3")
|
||||
implementation("app.cash.quickjs:quickjs-jvm:0.9.2")
|
||||
|
||||
|
||||
// Source models and interfaces from Tachiyomi 1.x
|
||||
// using source class from tachiyomi commit 9493577de27c40ce8b2b6122cc447d025e34c477 to not depend on tachiyomi.sourceapi
|
||||
// implementation("tachiyomi.sourceapi:source-api:1.1")
|
||||
|
||||
// AndroidCompat
|
||||
implementation(project(":AndroidCompat"))
|
||||
implementation(project(":AndroidCompat:Config"))
|
||||
|
||||
// uncomment to test extensions directly
|
||||
// implementation(fileTree("lib/"))
|
||||
|
||||
// Testing
|
||||
testImplementation(kotlin("test-junit5"))
|
||||
}
|
||||
|
||||
val MainClass = "suwayomi.tachidesk.MainKt"
|
||||
val MainClass = "inspector.MainKt"
|
||||
application {
|
||||
mainClass.set(MainClass)
|
||||
}
|
||||
@ -59,7 +50,7 @@ sourceSets {
|
||||
}
|
||||
|
||||
// should be bumped with each stable release
|
||||
val inspectorVersion = "v0.7.2"
|
||||
val inspectorVersion = "v1.4.3"
|
||||
|
||||
// counts commit count on master
|
||||
val inspectorRevision = runCatching {
|
||||
@ -80,7 +71,7 @@ val String.wrapped get() = """"$this""""
|
||||
|
||||
buildConfig {
|
||||
className("BuildConfig")
|
||||
packageName("suwayomi.server")
|
||||
packageName("inspector")
|
||||
|
||||
useKotlinOutput()
|
||||
|
||||
@ -93,13 +84,13 @@ tasks {
|
||||
shadowJar {
|
||||
manifest {
|
||||
attributes(
|
||||
mapOf(
|
||||
"Main-Class" to MainClass,
|
||||
"Implementation-Title" to rootProject.name,
|
||||
"Implementation-Vendor" to "The Tachiyomi Open Source Project",
|
||||
"Specification-Version" to inspectorVersion,
|
||||
"Implementation-Version" to inspectorRevision
|
||||
)
|
||||
mapOf(
|
||||
"Main-Class" to MainClass,
|
||||
"Implementation-Title" to rootProject.name,
|
||||
"Implementation-Vendor" to "The Tachiyomi Open Source Project",
|
||||
"Specification-Version" to inspectorVersion,
|
||||
"Implementation-Version" to inspectorRevision
|
||||
)
|
||||
)
|
||||
}
|
||||
archiveBaseName.set(rootProject.name)
|
||||
@ -110,10 +101,10 @@ tasks {
|
||||
withType<KotlinCompile> {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs = listOf(
|
||||
"-Xopt-in=kotlin.RequiresOptIn",
|
||||
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||
"-Xopt-in=kotlinx.coroutines.InternalCoroutinesApi",
|
||||
"-Xopt-in=kotlin.io.path.ExperimentalPathApi",
|
||||
"-Xopt-in=kotlin.RequiresOptIn",
|
||||
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||
"-Xopt-in=kotlinx.coroutines.InternalCoroutinesApi",
|
||||
"-Xopt-in=kotlin.io.path.ExperimentalPathApi",
|
||||
)
|
||||
}
|
||||
}
|
@ -5,7 +5,8 @@ package eu.kanade.tachiyomi
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
@ -5,34 +5,26 @@ package eu.kanade.tachiyomi
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.app.Application
|
||||
import eu.kanade.tachiyomi.network.JavaScriptEngine
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import kotlinx.serialization.json.Json
|
||||
import rx.Observable
|
||||
import rx.schedulers.Schedulers
|
||||
import uy.kohesive.injekt.api.InjektModule
|
||||
import uy.kohesive.injekt.api.InjektRegistrar
|
||||
import uy.kohesive.injekt.api.addSingleton
|
||||
import uy.kohesive.injekt.api.addSingletonFactory
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class AppModule(val app: Application) : InjektModule {
|
||||
|
||||
override fun InjektRegistrar.registerInjectables() {
|
||||
|
||||
addSingleton(app)
|
||||
|
||||
addSingletonFactory { NetworkHelper(app) }
|
||||
addSingletonFactory { JavaScriptEngine(app) }
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package eu.kanade.tachiyomi.network
|
||||
|
||||
import android.content.Context
|
||||
import app.cash.quickjs.QuickJs
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
|
||||
/**
|
||||
* Util for evaluating JavaScript in sources.
|
||||
*/
|
||||
class JavaScriptEngine(context: Context) {
|
||||
|
||||
/**
|
||||
* Evaluate arbitrary JavaScript code and get the result as a primtive type
|
||||
* (e.g., String, Int).
|
||||
*
|
||||
* @since extensions-lib 1.4
|
||||
* @param script JavaScript to execute.
|
||||
* @return Result of JavaScript code as a primitive type.
|
||||
*/
|
||||
@Suppress("UNUSED", "UNCHECKED_CAST")
|
||||
suspend fun <T> evaluate(script: String): T = withIOContext {
|
||||
QuickJs.create().use {
|
||||
it.evaluate(script) as T
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,8 @@ package eu.kanade.tachiyomi.network
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import okhttp3.Cookie
|
||||
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
|
||||
* 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 eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.network
|
||||
import okhttp3.CacheControl
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import java.util.concurrent.TimeUnit.MINUTES
|
||||
@ -23,6 +24,21 @@ fun GET(
|
||||
.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* @since extensions-lib 1.4
|
||||
*/
|
||||
fun GET(
|
||||
url: HttpUrl,
|
||||
headers: Headers = DEFAULT_HEADERS,
|
||||
cache: CacheControl = DEFAULT_CACHE_CONTROL,
|
||||
): Request {
|
||||
return Request.Builder()
|
||||
.url(url)
|
||||
.headers(headers)
|
||||
.cacheControl(cache)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun POST(
|
||||
url: String,
|
||||
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
|
||||
* 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.Response
|
@ -9,7 +9,7 @@ interface CatalogueSource : Source {
|
||||
/**
|
||||
* An ISO 639-1 compliant language code (two letters in lower case).
|
||||
*/
|
||||
val lang: String
|
||||
override val lang: String
|
||||
|
||||
/**
|
||||
* Whether the source has support for latest updates.
|
@ -29,11 +29,16 @@ class LocalSource(private val context: Context) : CatalogueSource {
|
||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||
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")
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ interface Source {
|
||||
*/
|
||||
val name: String
|
||||
|
||||
val lang: String
|
||||
get() = ""
|
||||
|
||||
/**
|
||||
* Returns an observable with the updated details for a manga.
|
||||
*
|
@ -3,7 +3,9 @@ package eu.kanade.tachiyomi.source.model
|
||||
sealed class Filter<T>(val name: String, var state: T) {
|
||||
open class Header(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 CheckBox(name: String, state: Boolean = false) : Filter<Boolean>(name, state)
|
||||
abstract class TriState(name: String, state: Int = STATE_IGNORE) : Filter<Int>(name, state) {
|
@ -20,6 +20,8 @@ interface SManga : Serializable {
|
||||
|
||||
var thumbnail_url: String?
|
||||
|
||||
var update_strategy: UpdateStrategy
|
||||
|
||||
var initialized: Boolean
|
||||
|
||||
fun copyFrom(other: SManga) {
|
@ -18,5 +18,7 @@ class SMangaImpl : SManga {
|
||||
|
||||
override var thumbnail_url: String? = null
|
||||
|
||||
override var update_strategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE
|
||||
|
||||
override var initialized: Boolean = false
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
|
||||
enum class UpdateStrategy {
|
||||
ALWAYS_UPDATE,
|
||||
ONLY_FETCH_ONCE
|
||||
}
|
@ -54,9 +54,10 @@ abstract class HttpSource : CatalogueSource {
|
||||
* Note the generated id sets the sign bit to 0.
|
||||
*/
|
||||
override val id by lazy {
|
||||
val key = "${name.toLowerCase()}/$lang/$versionId"
|
||||
val key = "${name.lowercase()}/$lang/$versionId"
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,7 +81,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
/**
|
||||
* Visible name of the source.
|
||||
*/
|
||||
override fun toString() = "$name (${lang.toUpperCase()})"
|
||||
override fun toString() = "$name (${lang.uppercase()})"
|
||||
|
||||
/**
|
||||
* Returns an observable containing a page with a list of manga. Normally it's not needed to
|
||||
@ -118,7 +119,11 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @param query the search query.
|
||||
* @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))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
@ -133,7 +138,11 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @param query the search query.
|
||||
* @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.
|
||||
@ -355,6 +364,28 @@ abstract class HttpSource : CatalogueSource {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the url of the provided manga
|
||||
*
|
||||
* @since extensions-lib 1.4
|
||||
* @param manga the manga
|
||||
* @return url of the manga
|
||||
*/
|
||||
open fun getMangaUrl(manga: SManga): String {
|
||||
return mangaDetailsRequest(manga).url.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the url of the provided chapter
|
||||
*
|
||||
* @since extensions-lib 1.4
|
||||
* @param chapter the chapter
|
||||
* @return url of the chapter
|
||||
*/
|
||||
open fun getChapterUrl(chapter: SChapter): String {
|
||||
return pageListRequest(chapter).url.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before inserting a new chapter into database. Use it if you need to override chapter
|
||||
* fields, like the title or the chapter number. Do not change anything to [manga].
|
||||
@ -362,8 +393,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @param chapter the chapter to be added.
|
||||
* @param manga the manga of the chapter.
|
||||
*/
|
||||
open fun prepareNewChapter(chapter: SChapter, manga: SManga) {
|
||||
}
|
||||
open fun prepareNewChapter(chapter: SChapter, manga: SManga) {}
|
||||
|
||||
/**
|
||||
* Returns the list of filters for the source.
|
@ -22,5 +22,5 @@ fun Element.attrOrText(css: String): String {
|
||||
* @param html the body of the response. Use only if the body was read before calling this method.
|
||||
*/
|
||||
fun Response.asJsoup(html: String? = null): Document {
|
||||
return Jsoup.parse(html ?: body!!.string(), request.url.toString())
|
||||
return Jsoup.parse(html ?: body.string(), request.url.toString())
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package eu.kanade.tachiyomi.util.lang
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
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
|
||||
@ -8,14 +8,18 @@ package suwayomi.tachidesk
|
||||
* 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 inspector.util.Extension
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import mu.KotlinLogging
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension
|
||||
import suwayomi.tachidesk.server.applicationSetup
|
||||
import org.kodein.di.DI
|
||||
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.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
@ -23,41 +27,53 @@ import kotlin.io.path.extension
|
||||
import kotlin.streams.asSequence
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
private val androidCompat by lazy { AndroidCompat() }
|
||||
|
||||
suspend fun main(args: Array<String>) {
|
||||
if (args.size < 3) {
|
||||
throw RuntimeException("Inspector must be given the path of apks directory, output json, and a tmp dir")
|
||||
}
|
||||
|
||||
applicationSetup()
|
||||
|
||||
val (apksPath, outputPath, tmpDirPath) = args
|
||||
|
||||
initApplication()
|
||||
|
||||
val tmpDir = File(tmpDirPath, "tmp").also { it.mkdir() }
|
||||
val extensions = Files.find(Paths.get(apksPath), 2, { _, fileAttributes -> fileAttributes.isRegularFile })
|
||||
.asSequence()
|
||||
.filter { it.extension == "apk" }
|
||||
.toList()
|
||||
val extensions =
|
||||
Files.find(Paths.get(apksPath), 2, { _, fileAttributes -> fileAttributes.isRegularFile })
|
||||
.asSequence()
|
||||
.filter { it.extension == "apk" }
|
||||
.toList()
|
||||
|
||||
logger.info("Found ${extensions.size} extensions")
|
||||
|
||||
val extensionsInfo = extensions.associate {
|
||||
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) }
|
||||
}
|
||||
|
||||
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
|
||||
data class SourceJson(
|
||||
private data class SourceJson(
|
||||
val name: String,
|
||||
val lang: String,
|
||||
val id: String,
|
||||
val baseUrl: String,
|
||||
val versionId: Int,
|
||||
val hasCloudflare: Short
|
||||
) {
|
||||
constructor(source: HttpSource) :
|
||||
this(
|
||||
@ -66,10 +82,5 @@ data class SourceJson(
|
||||
source.id.toString(),
|
||||
source.baseUrl,
|
||||
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
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceFactory
|
||||
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 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
|
||||
|
||||
object Extension {
|
||||
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 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")
|
||||
|
||||
dex2jar(apkFile, jarFile)
|
||||
|
||||
// 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 SourceFactory -> instance.createSources().filterIsInstance<HttpSource>()
|
||||
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
|
||||
*
|
||||
* 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/. */
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.Signature
|
||||
@ -32,8 +33,8 @@ object PackageTools {
|
||||
|
||||
const val EXTENSION_FEATURE = "tachiyomi.extension"
|
||||
const val METADATA_SOURCE_CLASS = "tachiyomi.extension.class"
|
||||
const val LIB_VERSION_MIN = 1.2
|
||||
const val LIB_VERSION_MAX = 1.3
|
||||
const val LIB_VERSION_MIN = 1.3
|
||||
const val LIB_VERSION_MAX = 1.4
|
||||
|
||||
/**
|
||||
* Convert dex to jar, a wrapper for the dex2jar library
|
||||
@ -57,7 +58,8 @@ object PackageTools {
|
||||
.skipExceptions(false)
|
||||
.to(jarFilePath)
|
||||
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(
|
||||
"""
|
||||
Detail Error Information in File $errorFile
|
@ -8,7 +8,7 @@
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="Exposed" level="ERROR"/>
|
||||
<logger name="Exposed" level="ERROR" />
|
||||
|
||||
<root level="INFO">
|
||||
<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,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,6 +1,5 @@
|
||||
rootProject.name = "Tachiyomi Extensions Inspector"
|
||||
|
||||
include("server")
|
||||
|
||||
include("AndroidCompat")
|
||||
include("AndroidCompat:Config")
|
||||
include("inspector")
|
||||
|
Loading…
Reference in New Issue
Block a user