mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-04 03:14:40 -05:00
apk installation
This commit is contained in:
@@ -2,32 +2,31 @@ package ir.armor.tachidesk
|
||||
|
||||
import com.googlecode.dex2jar.tools.Dex2jarCmd
|
||||
import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi
|
||||
import eu.kanade.tachiyomi.extension.model.Extension
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import io.javalin.Javalin
|
||||
import io.javalin.http.Context
|
||||
import ir.armor.tachidesk.database.DBMangaer
|
||||
import ir.armor.tachidesk.database.makeDataBaseTables
|
||||
import ir.armor.tachidesk.database.model.ExtensionDataClass
|
||||
import ir.armor.tachidesk.database.model.ExtensionsTable
|
||||
import ir.armor.tachidesk.database.model.SourcesTable
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.harawata.appdirs.AppDirsFactory
|
||||
import okhttp3.Request
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.net.URLClassLoader
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
|
||||
class Main {
|
||||
companion object {
|
||||
var lastExtensionCheck: Long = 0
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun downloadAPK(url: String, apkPath: String){
|
||||
fun downloadAPKFile(url: String, apkPath: String) {
|
||||
val request = Request.Builder().url(url).build()
|
||||
val response = NetworkHelper().client.newCall(request).execute();
|
||||
|
||||
@@ -38,9 +37,8 @@ class Main {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun testExtensionExecution(){
|
||||
val contentRoot = Config.dataRoot + "/extensions"
|
||||
File(contentRoot).mkdirs()
|
||||
fun testExtensionExecution() {
|
||||
File(Config.extensionsRoot).mkdirs()
|
||||
var sourcePkg = ""
|
||||
|
||||
// get list of extensions
|
||||
@@ -55,13 +53,13 @@ class Main {
|
||||
}
|
||||
|
||||
val apkFileName = apkToDownload.split("/").last()
|
||||
val apkFilePath = "$contentRoot/$apkFileName"
|
||||
val apkFilePath = "${Config.extensionsRoot}/$apkFileName"
|
||||
val zipDirPath = apkFilePath.substringBefore(".apk")
|
||||
val jarFilePath = "$zipDirPath.jar"
|
||||
val dexFilePath = "$zipDirPath.dex"
|
||||
|
||||
// download apk file
|
||||
downloadAPK(apkToDownload, apkFilePath)
|
||||
downloadAPKFile(apkToDownload, apkFilePath)
|
||||
|
||||
|
||||
val className = APKExtractor.extract_dex_and_read_className(apkFilePath, dexFilePath)
|
||||
@@ -76,40 +74,144 @@ class Main {
|
||||
mangasPage.mangas.forEach {
|
||||
println(it.title)
|
||||
}
|
||||
// exitProcess(0)
|
||||
}
|
||||
|
||||
fun extensionDatabaseIsEmtpy(): Boolean {
|
||||
return transaction {
|
||||
return@transaction ExtensionsTable.selectAll().count() == 0L
|
||||
}
|
||||
}
|
||||
|
||||
fun getExtensionList(offline: Boolean = false): List<ExtensionDataClass> {
|
||||
// update if 60 seconds has passed or requested offline and database is empty
|
||||
if (lastExtensionCheck + 60 * 1000 < System.currentTimeMillis() || (offline && extensionDatabaseIsEmtpy())) {
|
||||
println("Getting extensions list from the internet")
|
||||
lastExtensionCheck = System.currentTimeMillis()
|
||||
var foundExtensions: List<Extension.Available>
|
||||
runBlocking {
|
||||
val api = ExtensionGithubApi()
|
||||
foundExtensions = api.findExtensions()
|
||||
transaction {
|
||||
foundExtensions.forEach { foundExtension ->
|
||||
val extensionRecord = ExtensionsTable.select { ExtensionsTable.name eq foundExtension.name }.firstOrNull()
|
||||
if (extensionRecord != null) {
|
||||
// update the record
|
||||
ExtensionsTable.update({ ExtensionsTable.name eq foundExtension.name }) {
|
||||
it[name] = foundExtension.name
|
||||
it[pkgName] = foundExtension.pkgName
|
||||
it[versionName] = foundExtension.versionName
|
||||
it[versionCode] = foundExtension.versionCode
|
||||
it[lang] = foundExtension.lang
|
||||
it[isNsfw] = foundExtension.isNsfw
|
||||
it[apkName] = foundExtension.apkName
|
||||
it[iconUrl] = foundExtension.iconUrl
|
||||
}
|
||||
} else {
|
||||
// insert new record
|
||||
ExtensionsTable.insert {
|
||||
it[name] = foundExtension.name
|
||||
it[pkgName] = foundExtension.pkgName
|
||||
it[versionName] = foundExtension.versionName
|
||||
it[versionCode] = foundExtension.versionCode
|
||||
it[lang] = foundExtension.lang
|
||||
it[isNsfw] = foundExtension.isNsfw
|
||||
it[apkName] = foundExtension.apkName
|
||||
it[iconUrl] = foundExtension.iconUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return transaction {
|
||||
return@transaction ExtensionsTable.selectAll().map {
|
||||
ExtensionDataClass(
|
||||
it[ExtensionsTable.name],
|
||||
it[ExtensionsTable.pkgName],
|
||||
it[ExtensionsTable.versionName],
|
||||
it[ExtensionsTable.versionCode],
|
||||
it[ExtensionsTable.lang],
|
||||
it[ExtensionsTable.isNsfw],
|
||||
it[ExtensionsTable.apkName],
|
||||
it[ExtensionsTable.iconUrl],
|
||||
it[ExtensionsTable.installed],
|
||||
it[ExtensionsTable.classFQName]
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadApk(apkName: String): Int {
|
||||
val extension = getExtensionList(true).first { it.apkName == apkName }
|
||||
val fileNameWithoutType = apkName.substringBefore(".apk")
|
||||
val dirPathWithoutType = "${Config.extensionsRoot}/$apkName"
|
||||
|
||||
// check if we don't have the dex file already downloaded
|
||||
val dexPath = "${Config.extensionsRoot}/$fileNameWithoutType.jar"
|
||||
if (!File(dexPath).exists()) {
|
||||
runBlocking {
|
||||
val api = ExtensionGithubApi()
|
||||
val apkToDownload = api.getApkUrl(extension)
|
||||
|
||||
val apkFilePath = "$dirPathWithoutType.apk"
|
||||
val jarFilePath = "$dirPathWithoutType.jar"
|
||||
val dexFilePath = "$dirPathWithoutType.dex"
|
||||
|
||||
// download apk file
|
||||
downloadAPKFile(apkToDownload, apkFilePath)
|
||||
|
||||
|
||||
val className: String = APKExtractor.extract_dex_and_read_className(apkFilePath, dexFilePath)
|
||||
|
||||
// dex -> jar
|
||||
Dex2jarCmd.main(dexFilePath, "-o", jarFilePath, "--force")
|
||||
|
||||
File(apkFilePath).delete()
|
||||
|
||||
transaction {
|
||||
ExtensionsTable.update({ ExtensionsTable.name eq extension.name }) {
|
||||
it[installed] = true
|
||||
it[classFQName] = className
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return 201 // we downloaded successfully
|
||||
}
|
||||
else {
|
||||
return 302
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
// make sure data everything we need exists
|
||||
// make sure everything we need exists
|
||||
File(Config.dataRoot).mkdirs()
|
||||
File(Config.extensionsRoot).mkdirs()
|
||||
makeDataBaseTables()
|
||||
|
||||
|
||||
// val app = Javalin.create().start(4567)
|
||||
//
|
||||
// app.before() { ctx ->
|
||||
// ctx.header("Access-Control-Allow-Origin", "*")
|
||||
// }
|
||||
//
|
||||
// app.get("/api/v1/extensions") { ctx ->
|
||||
// runBlocking {
|
||||
// val api = ExtensionGithubApi()
|
||||
// val sources = api.findExtensions()
|
||||
// ctx.json(sources)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// app.get("/api/v1/extensions/install/:extensionURL") { ctx ->
|
||||
// ctx.pathParam("extensionURL")
|
||||
// })
|
||||
val app = Javalin.create().start(4567)
|
||||
|
||||
app.before() { ctx ->
|
||||
ctx.header("Access-Control-Allow-Origin", "*") // allow the client which is running on another port
|
||||
}
|
||||
|
||||
app.get("/api/v1/extensions") { ctx ->
|
||||
ctx.json(getExtensionList())
|
||||
}
|
||||
|
||||
|
||||
// ExtensionTable.new {
|
||||
// name = "khar"
|
||||
// pkgName = "eu.khar"
|
||||
// }
|
||||
app.get("/api/v1/extensions/install/:apkName") { ctx ->
|
||||
val apkName = ctx.pathParam("apkName")
|
||||
ctx.status(
|
||||
downloadApk(apkName)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user