mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-16 01:40:46 +08:00
Maa HTTP server DTO实现
This commit is contained in:
@@ -27,6 +27,7 @@ dependencies {
|
||||
implementation("io.ktor:ktor-server-netty-jvm:$ktor_version")
|
||||
implementation("io.ktor:ktor-server-content-negotiation:$ktor_version")
|
||||
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
|
||||
implementation("io.ktor:ktor-server-cors:$ktor_version")
|
||||
implementation("io.ktor:ktor-server-websockets:$ktor_version")
|
||||
implementation("ch.qos.logback:logback-classic:$logback_version")
|
||||
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
|
||||
|
||||
@@ -1,64 +1,42 @@
|
||||
package com.iguigui.maaj
|
||||
|
||||
import com.iguigui.maaj.dto.*
|
||||
import com.iguigui.maaj.service.MaaService
|
||||
import com.iguigui.maaj.routing.httpRouting
|
||||
import com.iguigui.maaj.routing.wsRouting
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import io.ktor.server.netty.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.plugins.cors.routing.*
|
||||
import io.ktor.server.websocket.*
|
||||
import io.ktor.websocket.*
|
||||
import java.time.Duration
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
fun main(args: Array<String>): Unit = EngineMain.main(args)
|
||||
|
||||
fun Application.module() {
|
||||
configureRouting()
|
||||
configure()
|
||||
httpRouting()
|
||||
wsRouting()
|
||||
}
|
||||
|
||||
fun Application.configureRouting() {
|
||||
fun Application.configure(){
|
||||
install(ContentNegotiation) {
|
||||
json()
|
||||
json(Json {
|
||||
encodeDefaults = true
|
||||
isLenient = true
|
||||
allowSpecialFloatingPointValues = true
|
||||
allowStructuredMapKeys = true
|
||||
prettyPrint = false
|
||||
useArrayPolymorphism = false
|
||||
})
|
||||
}
|
||||
install(CORS) {
|
||||
allowCredentials = true
|
||||
anyHost()
|
||||
}
|
||||
install(WebSockets) {
|
||||
pingPeriod = Duration.ofSeconds(15)
|
||||
timeout = Duration.ofSeconds(15)
|
||||
pingPeriod = java.time.Duration.ofSeconds(15)
|
||||
timeout = java.time.Duration.ofSeconds(15)
|
||||
maxFrameSize = Long.MAX_VALUE
|
||||
masking = false
|
||||
}
|
||||
routing {
|
||||
|
||||
post("/connect") {
|
||||
val connect = call.receive<Connect>()
|
||||
MaaService.connect(connect.adbPath, connect.host, "")
|
||||
}
|
||||
|
||||
post("/appendTask") {
|
||||
val appendTask = call.receive<AppendTask>()
|
||||
MaaService.appendTask(appendTask.host, appendTask.type, appendTask.params.toJsonString())
|
||||
}
|
||||
|
||||
post("/start") {
|
||||
val start = call.receive<Start>()
|
||||
MaaService.start(start.host)
|
||||
}
|
||||
|
||||
post("/stop") {
|
||||
val stop = call.receive<Stop>()
|
||||
MaaService.stop(stop.host)
|
||||
}
|
||||
|
||||
|
||||
webSocket("/") {
|
||||
send("You are connected!")
|
||||
for (frame in incoming) {
|
||||
frame as? Frame.Text ?: continue
|
||||
val receivedText = frame.readText()
|
||||
println("接收到信息 : $receivedText")
|
||||
send("You said: $receivedText")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import kotlinx.serialization.encodeToString
|
||||
sealed class WsRequest
|
||||
|
||||
@Serializable
|
||||
data class Connect(
|
||||
data class ConnectRequest(
|
||||
@SerialName("adbPath")
|
||||
val adbPath: String,
|
||||
@SerialName("host")
|
||||
@@ -16,7 +16,7 @@ data class Connect(
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class AppendTask(
|
||||
data class AppendTaskRequest(
|
||||
@SerialName("host")
|
||||
val host: String,
|
||||
@SerialName("type")
|
||||
@@ -30,11 +30,105 @@ sealed class Task
|
||||
|
||||
@Serializable
|
||||
data class Fight(
|
||||
@SerialName("medicine")
|
||||
val medicine: Int?,
|
||||
@SerialName("penguin_id")
|
||||
val penguinId: String?,
|
||||
@SerialName("report_to_penguin")
|
||||
val reportToPenguin: Boolean?,
|
||||
@SerialName("server")
|
||||
val server: String?,
|
||||
@SerialName("stage")
|
||||
val stage: String
|
||||
val stage: String?,
|
||||
@SerialName("stone")
|
||||
val stone: Int?,
|
||||
@SerialName("times")
|
||||
val times: Int?
|
||||
) : Task()
|
||||
|
||||
|
||||
@Serializable
|
||||
data class Recruit(
|
||||
@SerialName("confirm")
|
||||
val confirm: List<Int>,
|
||||
@SerialName("expedite")
|
||||
val expedite: Boolean?,
|
||||
@SerialName("expedite_times")
|
||||
val expediteTimes: Int?,
|
||||
@SerialName("refresh")
|
||||
val refresh: Boolean?,
|
||||
@SerialName("select")
|
||||
val select: List<Int>,
|
||||
@SerialName("set_time")
|
||||
val setTime: Boolean?,
|
||||
@SerialName("times")
|
||||
val times: Int?
|
||||
) : Task()
|
||||
|
||||
|
||||
@Serializable
|
||||
data class Infrast(
|
||||
@SerialName("drones")
|
||||
val drones: String?,
|
||||
@SerialName("facility")
|
||||
val facility: List<String>,
|
||||
@SerialName("mode")
|
||||
val mode: Int?,
|
||||
@SerialName("replenish")
|
||||
val replenish: Boolean?,
|
||||
@SerialName("threshold")
|
||||
val threshold: Double?
|
||||
) : Task()
|
||||
|
||||
|
||||
@Serializable
|
||||
class Visit : Task()
|
||||
|
||||
@Serializable
|
||||
data class Mall(
|
||||
@SerialName("blacklist")
|
||||
val blacklist: List<String>?,
|
||||
@SerialName("buy_first")
|
||||
val buyFirst: List<String>?,
|
||||
@SerialName("shopping")
|
||||
val shopping: Boolean?
|
||||
) : Task()
|
||||
|
||||
|
||||
@Serializable
|
||||
class Award : Task()
|
||||
|
||||
@Serializable
|
||||
data class Roguelike(
|
||||
@SerialName("mode")
|
||||
val mode: Int?,
|
||||
@SerialName("opers")
|
||||
val opers: List<Oper>
|
||||
) : Task()
|
||||
|
||||
|
||||
@Serializable
|
||||
data class Oper(
|
||||
@SerialName("name")
|
||||
val name: String,
|
||||
@SerialName("skill")
|
||||
val skill: Int?,
|
||||
@SerialName("skill_usage")
|
||||
val skillUsage: Int?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Copilot(
|
||||
@SerialName("filename")
|
||||
val filename: String,
|
||||
@SerialName("formation")
|
||||
val formation: Boolean,
|
||||
@SerialName("stage_name")
|
||||
val stageName: String?
|
||||
)
|
||||
|
||||
|
||||
|
||||
@Serializable
|
||||
data class Start(
|
||||
@SerialName("host")
|
||||
@@ -51,7 +145,7 @@ data class Stop(
|
||||
@Serializable
|
||||
data class ConnectWs(
|
||||
@SerialName("data")
|
||||
val `data`: Connect,
|
||||
val `data`: ConnectRequest,
|
||||
@SerialName("type")
|
||||
val type: String
|
||||
) : WsRequest()
|
||||
|
||||
74
src/Java/Maaj/src/main/java/com/iguigui/maaj/dto/response.kt
Normal file
74
src/Java/Maaj/src/main/java/com/iguigui/maaj/dto/response.kt
Normal file
@@ -0,0 +1,74 @@
|
||||
package com.iguigui.maaj.dto
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.encodeToJsonElement
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
|
||||
|
||||
@Serializable
|
||||
data class HttpResponse(
|
||||
@SerialName("version")
|
||||
val data: JsonElement = EmptyBaseData.toJsonElement(),
|
||||
@SerialName("code")
|
||||
val code: Int = 0,
|
||||
@SerialName("message")
|
||||
val message: String = "success"
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class WsResponse(
|
||||
@SerialName("version")
|
||||
val data: JsonElement,
|
||||
@SerialName("type")
|
||||
val type: String,
|
||||
@SerialName("code")
|
||||
val code: Int,
|
||||
@SerialName("message")
|
||||
val message: String
|
||||
)
|
||||
|
||||
@Serializable
|
||||
sealed class BaseData
|
||||
|
||||
@Serializable
|
||||
data class GetVersion(
|
||||
@SerialName("version")
|
||||
val version: String
|
||||
) : BaseData()
|
||||
|
||||
@Serializable
|
||||
data class ConnectResponse(
|
||||
@SerialName("version")
|
||||
val id: String
|
||||
) : BaseData()
|
||||
|
||||
|
||||
@Serializable
|
||||
data class ListInstance(
|
||||
@SerialName("version")
|
||||
val list: List<MaaInstanceInfo>
|
||||
) : BaseData()
|
||||
|
||||
@Serializable
|
||||
data class MaaInstanceInfo(
|
||||
@SerialName("id")
|
||||
val id: String,
|
||||
@SerialName("host")
|
||||
val host: String,
|
||||
@SerialName("adbPath")
|
||||
val adbPath: String,
|
||||
@SerialName("status")
|
||||
val status: Int,
|
||||
) : BaseData()
|
||||
|
||||
|
||||
object EmptyBaseData : BaseData()
|
||||
|
||||
fun BaseData.toJsonElement() =
|
||||
Json.encodeToJsonElement(Json.encodeToJsonElement(this).jsonObject.filterNot { it.key == "type" })
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.iguigui.maaj.routing
|
||||
|
||||
import com.iguigui.maaj.dto.*
|
||||
import com.iguigui.maaj.service.MaaService
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
|
||||
fun Application.httpRouting() {
|
||||
|
||||
routing {
|
||||
route("/v1") {
|
||||
get("/getVersion") {
|
||||
val version = MaaService.getVersion()
|
||||
call.respond(HttpResponse(GetVersion(version).toJsonElement()))
|
||||
}
|
||||
get("/listInstance") {
|
||||
val list = MaaService.listInstance()
|
||||
call.respond(HttpResponse(ListInstance(list).toJsonElement()))
|
||||
}
|
||||
post("/connect") {
|
||||
val connect = call.receive<ConnectRequest>()
|
||||
val id = MaaService.connect(connect.adbPath, connect.host, "")
|
||||
call.respond(HttpResponse(ConnectResponse(id).toJsonElement()))
|
||||
}
|
||||
post("/appendTask") {
|
||||
val appendTask = call.receive<AppendTaskRequest>()
|
||||
MaaService.appendTask(appendTask.host, appendTask.type, appendTask.params.toJsonString())
|
||||
call.respond(HttpResponse())
|
||||
}
|
||||
post("/start") {
|
||||
val start = call.receive<Start>()
|
||||
MaaService.start(start.host)
|
||||
call.respond(HttpResponse())
|
||||
}
|
||||
post("/stop") {
|
||||
val stop = call.receive<Stop>()
|
||||
MaaService.stop(stop.host)
|
||||
call.respond(HttpResponse())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.iguigui.maaj.routing
|
||||
|
||||
import com.iguigui.maaj.dto.*
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.plugins.contentnegotiation.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.websocket.*
|
||||
import io.ktor.websocket.*
|
||||
|
||||
|
||||
fun Application.wsRouting() {
|
||||
|
||||
routing {
|
||||
webSocket("/v1") {
|
||||
send("You are connected!")
|
||||
for (frame in incoming) {
|
||||
frame as? Frame.Text ?: continue
|
||||
val receivedText = frame.readText()
|
||||
println("接收到信息 : $receivedText")
|
||||
send("You said: $receivedText")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,10 @@ class MaaInstance(private val instance: MeoAssistant, val id: String, val adbPat
|
||||
|
||||
constructor(
|
||||
instance: MeoAssistant,
|
||||
pointer: Pointer,
|
||||
id: String, adbPath: String,
|
||||
host: String
|
||||
id: String,
|
||||
adbPath: String,
|
||||
host: String,
|
||||
pointer: Pointer
|
||||
) : this(
|
||||
instance,
|
||||
id,
|
||||
@@ -22,6 +23,8 @@ class MaaInstance(private val instance: MeoAssistant, val id: String, val adbPat
|
||||
|
||||
lateinit var pointer: Pointer
|
||||
|
||||
var status = 0
|
||||
|
||||
override fun callback(msg: Int, detail_json: String?, custom_arg: String?) {
|
||||
System.out.printf("回调msg : %s , 回调 detail_json : %s ,回调 custom_arg : %s \n", msg, detail_json, custom_arg)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package com.iguigui.maaj.service
|
||||
|
||||
import com.iguigui.maaj.dto.MaaInstanceInfo
|
||||
import com.iguigui.maaj.easySample.MeoAssistant
|
||||
import com.sun.jna.Native
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.security.MessageDigest
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
|
||||
object MaaService {
|
||||
|
||||
@@ -22,18 +23,18 @@ object MaaService {
|
||||
load
|
||||
}
|
||||
|
||||
fun connect(adbPath: String, host: String, detailJson: String): Boolean {
|
||||
fun connect(adbPath: String, host: String, detailJson: String): String {
|
||||
if (instancePool.containsKey(host)) {
|
||||
return false
|
||||
return sha1(host)
|
||||
}
|
||||
val maaInstance = MaaInstance(meoAssistant, host, adbPath, host)
|
||||
maaInstance.pointer = meoAssistant.AsstCreateEx(maaInstance, maaInstance.id)
|
||||
maaInstance.connect()
|
||||
instancePool.putIfAbsent(host, maaInstance)
|
||||
return true
|
||||
return sha1(host)
|
||||
}
|
||||
|
||||
fun appendTask(host: String,type:String, detailJson: String): Int {
|
||||
fun appendTask(host: String, type: String, detailJson: String): Int {
|
||||
val appendTask = instancePool[host]?.appendTask(type, detailJson)
|
||||
return appendTask ?: 0
|
||||
}
|
||||
@@ -42,6 +43,25 @@ object MaaService {
|
||||
|
||||
fun stop(host: String) = instancePool[host]?.stop()
|
||||
|
||||
private fun generatorId() = UUID.randomUUID().toString()
|
||||
fun getVersion() = "3.9.0"
|
||||
|
||||
private fun sha1(password: String): String {
|
||||
val messageDigest = MessageDigest.getInstance("SHA")
|
||||
val digests = messageDigest.digest(password.toByteArray())
|
||||
val stringBuilder = StringBuilder()
|
||||
for (i in digests.indices) {
|
||||
var halfbyte = digests[i].toInt() ushr 4 and 0x0F
|
||||
for (j in 0..1) {
|
||||
stringBuilder.append(
|
||||
if (0 <= halfbyte && halfbyte <= 9) ('0'.code + halfbyte).toChar() else ('a'.code + (halfbyte - 10)).toChar()
|
||||
)
|
||||
halfbyte = digests[i].toInt() and 0x0F
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString()
|
||||
}
|
||||
|
||||
fun listInstance(): List<MaaInstanceInfo> =
|
||||
instancePool.values.map { e -> MaaInstanceInfo(e.id, e.host, e.id, e.status) }.toList()
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user