Skip to content
This repository has been archived by the owner on Jan 16, 2024. It is now read-only.

Commit

Permalink
action
Browse files Browse the repository at this point in the history
  • Loading branch information
jing332 committed Jan 11, 2024
1 parent 202b129 commit c5fd7ab
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 83 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Project exclude paths
/.idea/
/.gradle/
/app/build/
/build/
Expand All @@ -16,4 +17,5 @@ alist-main
*.tgz
*.jar
*.zip
*.so

2 changes: 1 addition & 1 deletion .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 12 additions & 13 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ android {
buildConfig true
}

composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
signingConfigs {
release {
storeFile file(pro["KEY_PATH"])
Expand Down Expand Up @@ -100,7 +97,9 @@ android {
universalApk true
}
}

composeOptions {
kotlinCompilerExtensionVersion = "1.5.7"
}
compileOptions {
// coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17
Expand Down Expand Up @@ -141,11 +140,11 @@ dependencies {
implementation("com.github.jeziellago:compose-markdown:0.3.4")

implementation("androidx.documentfile:documentfile:1.0.1")
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.core:core-ktx:1.12.0")

implementation("io.coil-kt:coil-compose:2.4.0")
implementation("com.charleskorn.kaml:kaml:0.55.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")

// Room
implementation("androidx.room:room-runtime:$room_version")
Expand All @@ -156,12 +155,12 @@ dependencies {
// IO & NET
implementation 'com.squareup.okio:okio:3.3.0'
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.github.liangjingkanji:Net:3.5.8'
implementation 'com.github.liangjingkanji:Net:3.6.4'

implementation("com.google.android.exoplayer:exoplayer-core:2.19.0")
implementation("com.google.android.exoplayer:exoplayer-core:2.19.1")

implementation("org.apache.commons:commons-lang3:3.12.0")
implementation("com.github.FunnySaltyFish.ComposeDataSaver:data-saver:v1.1.6")
implementation("com.github.FunnySaltyFish.ComposeDataSaver:data-saver:v1.1.8")
implementation("com.louiscad.splitties:splitties-systemservices:3.0.0")
implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0")

Expand All @@ -171,12 +170,12 @@ dependencies {


implementation("androidx.constraintlayout:constraintlayout-compose:1.0.1")
implementation("androidx.navigation:navigation-compose:2.7.0")
implementation("androidx.navigation:navigation-compose:2.7.6")

implementation 'androidx.activity:activity-compose:1.7.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1'
implementation 'androidx.activity:activity-compose:1.8.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2'
// def composeBom = platform('androidx.compose:compose-bom:2023.06.01')
def composeBom = platform("dev.chrisbanes.compose:compose-bom:2023.07.00-alpha02")
def composeBom = platform("dev.chrisbanes.compose:compose-bom:2023.12.00-alpha04")
implementation composeBom
androidTestImplementation composeBom

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,25 @@ data class ServerLog(
@LogLevel val level: Int,
val message: String,
val description: String? = null,
)
) {
companion object {

@Suppress("RegExpRedundantEscape")
fun String.evalLog(): ServerLog? {
val logPattern = """(\w+)\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (.+)""".toRegex()
val result = logPattern.find(this)
if (result != null) {
val (level, time, msg) = result.destructured
val l = when (level[0].toString()) {
"D" -> LogLevel.DEBUG
"I" -> LogLevel.INFO
"W" -> LogLevel.WARN
"E" -> LogLevel.ERROR
else -> LogLevel.INFO
}
return ServerLog(level = l, message = msg, description = time)
}
return null
}
}
}
164 changes: 118 additions & 46 deletions app/src/main/java/com/github/jing332/alistandroid/model/alist/AList.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
package com.github.jing332.alistandroid.model.alist

import alistlib.Alistlib
import alistlib.Event
import android.annotation.SuppressLint
import android.content.Intent
import android.util.Log
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.github.jing332.alistandroid.R
import com.github.jing332.alistandroid.app
import com.github.jing332.alistandroid.constant.AppConst
import com.github.jing332.alistandroid.constant.LogLevel
import com.github.jing332.alistandroid.data.appDb
import com.github.jing332.alistandroid.data.entities.ServerLog
import com.github.jing332.alistandroid.data.entities.ServerLog.Companion.evalLog
import com.github.jing332.alistandroid.service.AlistService
import com.github.jing332.alistandroid.util.FileUtils.readAllText
import com.github.jing332.alistandroid.util.StringUtils.removeAnsiCodes
import com.github.jing332.alistandroid.util.ToastUtils.longToast
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.decodeFromStream
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import java.io.File
import java.io.IOException
import kotlin.coroutines.coroutineContext

object AList {
const val ACTION_STATUS_CHANGED =
Expand All @@ -25,6 +31,10 @@ object AList {
const val TYPE_HTTPS = "https"
const val TYPE_UNIX = "unix"

private val execPath by lazy {
context.applicationInfo.nativeLibraryDir + File.separator + "libalist.so"
}

val context = app

val dataPath: String
Expand All @@ -37,71 +47,133 @@ object AList {
* 是否有服务正在运行
*/
val hasRunning: Boolean
get() = when {
Alistlib.isRunning(TYPE_HTTP) -> true
Alistlib.isRunning(TYPE_HTTPS) -> true
Alistlib.isRunning(TYPE_UNIX) -> true
else -> false
}
get() = false

fun init() {
Alistlib.setConfigData(dataPath)
// Alistlib.setConfigData(dataPath)
// Alistlib.setConfigDebug(BuildConfig.DEBUG)
Alistlib.setConfigLogStd(true)

Alistlib.init(object : Event {
override fun onShutdown(type: String) {
notifyStatusChanged()
}

override fun onStartError(type: String, msg: String) {
appDb.serverLogDao.insert(
ServerLog(
level = LogLevel.ERROR,
message = "${type}: $msg"
)
)
notifyStatusChanged()
}
// Alistlib.setConfigLogStd(true)

}) { level, msg ->
Log.i(AlistService.TAG, "level=${level}, msg=$msg")
appDb.serverLogDao.insert(ServerLog(level = level.toInt(), message = msg))
}
// Log.i(AlistService.TAG, "level=${level}, msg=$msg")
// appDb.serverLogDao.insert(ServerLog(level = level.toInt(), message = msg))
}

fun setAdminPassword(pwd: String) {
if (!hasRunning) {
init()
}

Alistlib.setAdminPassword(pwd)
val log = execWithParams(
redirect = true,
params = arrayOf("admin", "set", pwd, "--data", dataPath)
).inputStream.readAllText()
appDb.serverLogDao.insert(ServerLog(level = LogLevel.INFO, message = log.removeAnsiCodes()))
}

@Suppress("DEPRECATION")
private fun notifyStatusChanged() {
LocalBroadcastManager.getInstance(context)
.sendBroadcast(Intent(ACTION_STATUS_CHANGED))
}

fun shutdown(timeout: Long = 5000L) {
runCatching {
Alistlib.shutdown(timeout)
mProcess?.destroy()
}.onFailure {
context.longToast(R.string.server_shutdown_failed, it.toString())
}
}

private var mProcess: Process? = null

private suspend fun errorLogWatcher(onNewLine: (String) -> Unit) {
mProcess?.apply {
errorStream.bufferedReader().use {
while (coroutineContext.isActive) {
val line = it.readLine() ?: break
Log.d(AlistService.TAG, "Process errorStream: $line")
onNewLine(line)
}
}
}
}

private suspend fun logWatcher(onNewLine: (String) -> Unit) {
mProcess?.apply {
inputStream.bufferedReader().use {
while (coroutineContext.isActive) {
val line = it.readLine() ?: break
Log.d(AlistService.TAG, "Process inputStream: $line")
onNewLine(line)
}
}
}
}

private val mScope = CoroutineScope(Dispatchers.IO + Job())
private fun initOutput() {
val dao = appDb.serverLogDao
mScope.launch {
runCatching {
logWatcher { msg ->
msg.removeAnsiCodes().evalLog()?.let {
dao.insert(
ServerLog(
level = it.level,
message = it.message
)
)
return@logWatcher
}

dao.insert(
ServerLog(
level = if (msg.startsWith("fail")) LogLevel.ERROR else LogLevel.INFO,
message = msg
)
)

fun startup() {
if (Alistlib.isRunning("")) {
context.longToast("服务已在运行中")
return
}
}.onFailure {
it.printStackTrace()
}
}
mScope.launch {
runCatching {
errorLogWatcher { msg ->
val log = msg.removeAnsiCodes().evalLog() ?: return@errorLogWatcher
dao.insert(
ServerLog(
level = log.level,
message = log.message,
// description = log.time + "\n" + log.code
)
)
}
}.onFailure {
it.printStackTrace()
}
}
}


@SuppressLint("SdCardPath")
fun startup(
dataFolder: String = context.getExternalFilesDir("data")?.absolutePath
?: "/data/data/${context.packageName}/files/data"
): Int {
appDb.serverLogDao.deleteAll()
mProcess =
execWithParams(params = arrayOf("server", "--data", dataFolder))
initOutput()

return mProcess!!.waitFor()
}


init()
Alistlib.start()
notifyStatusChanged()
private fun execWithParams(
redirect: Boolean = false,
vararg params: String
): Process {
val cmdline = arrayOfNulls<String>(params.size + 1)
cmdline[0] = execPath
System.arraycopy(params, 0, cmdline, 1, params.size)
return ProcessBuilder(*cmdline).redirectErrorStream(redirect).start()
?: throw IOException("Process is null!")
}
}
Loading

0 comments on commit c5fd7ab

Please sign in to comment.