6 Commits

Author SHA1 Message Date
a9a2e9a3dd Shamrock: fix #258
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-26 20:59:29 +08:00
964c55de31 Shamrock: fix #256
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-26 20:51:45 +08:00
befb4a2bef Merge pull request #257 from huankong233/master
add `delete_delay` option in QuickOperation
2024-02-26 20:50:04 +08:00
210609bd7b use coroutines 2024-02-26 18:51:05 +08:00
3e03d4782d fix 2024-02-26 18:31:10 +08:00
a78b5cab23 add delete_delay option in QuickOperation 2024-02-26 15:05:13 +08:00
5 changed files with 81 additions and 57 deletions

View File

@ -12,6 +12,7 @@ import moe.fuqiuluo.shamrock.utils.DownloadUtils
import moe.fuqiuluo.shamrock.utils.FileUtils import moe.fuqiuluo.shamrock.utils.FileUtils
import moe.fuqiuluo.shamrock.utils.MD5 import moe.fuqiuluo.shamrock.utils.MD5
import moe.fuqiuluo.symbols.OneBotHandler import moe.fuqiuluo.symbols.OneBotHandler
import java.io.File
@OneBotHandler("download_file") @OneBotHandler("download_file")
internal object DownloadFile: IActionHandler() { internal object DownloadFile: IActionHandler() {
@ -19,6 +20,7 @@ internal object DownloadFile: IActionHandler() {
val url = session.getStringOrNull("url") val url = session.getStringOrNull("url")
val name = session.getStringOrNull("name") val name = session.getStringOrNull("name")
val b64 = session.getStringOrNull("base64") val b64 = session.getStringOrNull("base64")
val rootDir = session.getStringOrNull("root")
val threadCnt = session.getIntOrNull("thread_cnt") ?: 3 val threadCnt = session.getIntOrNull("thread_cnt") ?: 3
val headers = if (session.has("headers")) (if (session.isArray("headers")) { val headers = if (session.has("headers")) (if (session.isArray("headers")) {
session.getArray("headers").map { session.getArray("headers").map {
@ -27,7 +29,7 @@ internal object DownloadFile: IActionHandler() {
} else { } else {
session.getString("headers").split("\r\n") session.getString("headers").split("\r\n")
}) else emptyList() }) else emptyList()
return invoke(url, b64, threadCnt, headers, name, session.echo) return invoke(url, b64, threadCnt, headers, name, rootDir, session.echo)
} }
suspend operator fun invoke( suspend operator fun invoke(
@ -36,6 +38,7 @@ internal object DownloadFile: IActionHandler() {
threadCnt: Int, threadCnt: Int,
headers: List<String>, headers: List<String>,
name: String?, name: String?,
root: String?,
echo: JsonElement = EmptyJsonString echo: JsonElement = EmptyJsonString
): String { ): String {
if (url != null) { if (url != null) {
@ -49,9 +52,9 @@ internal object DownloadFile: IActionHandler() {
headerMap[k] = v headerMap[k] = v
} }
} }
return invoke(url, threadCnt, headerMap, name, echo) return invoke(url, threadCnt, headerMap, name, root, echo)
} else if (base64 != null) { } else if (base64 != null) {
return invoke(base64, name, echo) return invoke(base64, name, root, echo)
} else { } else {
return noParam("url/base64", echo) return noParam("url/base64", echo)
} }
@ -60,6 +63,7 @@ internal object DownloadFile: IActionHandler() {
operator fun invoke( operator fun invoke(
base64: String, base64: String,
name: String?, name: String?,
root: String?,
echo: JsonElement echo: JsonElement
): String { ): String {
kotlin.runCatching { kotlin.runCatching {
@ -68,12 +72,17 @@ internal object DownloadFile: IActionHandler() {
it.writeBytes(bytes) it.writeBytes(bytes)
} }
}.onSuccess { }.onSuccess {
val tmp = if (name == null) var tmp = if (name == null)
FileUtils.renameByMd5(it) FileUtils.renameByMd5(it)
else it.parentFile!!.resolve(name).also { target -> else it.parentFile!!.resolve(name).also { target ->
it.renameTo(target) it.renameTo(target)
it.delete() it.delete()
} }
if (root != null) {
tmp = File(root).resolve(name ?: tmp.name).also {
tmp.renameTo(it)
}
}
return ok(data = DownloadResult( return ok(data = DownloadResult(
file = tmp.absolutePath, file = tmp.absolutePath,
md5 = MD5.genFileMd5Hex(tmp.absolutePath) md5 = MD5.genFileMd5Hex(tmp.absolutePath)
@ -89,6 +98,7 @@ internal object DownloadFile: IActionHandler() {
threadCnt: Int, threadCnt: Int,
headers: Map<String, String>, headers: Map<String, String>,
name: String?, name: String?,
root: String?,
echo: JsonElement = EmptyJsonString echo: JsonElement = EmptyJsonString
): String { ): String {
return kotlin.runCatching { return kotlin.runCatching {
@ -108,6 +118,11 @@ internal object DownloadFile: IActionHandler() {
tmp.renameTo(newFile) tmp.renameTo(newFile)
newFile newFile
} }
if (root != null) {
tmp = File(root).resolve(name ?: tmp.name).also {
tmp.renameTo(it)
}
}
ok(data = DownloadResult( ok(data = DownloadResult(
file = tmp.absolutePath, file = tmp.absolutePath,
md5 = MD5.genFileMd5Hex(tmp.absolutePath) md5 = MD5.genFileMd5Hex(tmp.absolutePath)

View File

@ -2,6 +2,9 @@ package moe.fuqiuluo.shamrock.remote.action.handlers
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive import kotlinx.serialization.json.JsonPrimitive
@ -13,20 +16,17 @@ import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.helper.MessageHelper import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.remote.action.ActionSession import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.remote.service.HttpService
import moe.fuqiuluo.shamrock.tools.asBoolean
import moe.fuqiuluo.shamrock.tools.asBooleanOrNull import moe.fuqiuluo.shamrock.tools.asBooleanOrNull
import moe.fuqiuluo.shamrock.tools.asInt import moe.fuqiuluo.shamrock.tools.asInt
import moe.fuqiuluo.shamrock.tools.asIntOrNull import moe.fuqiuluo.shamrock.tools.asIntOrNull
import moe.fuqiuluo.shamrock.tools.asJsonObject import moe.fuqiuluo.shamrock.tools.asJsonObject
import moe.fuqiuluo.shamrock.tools.asLong
import moe.fuqiuluo.shamrock.tools.asString import moe.fuqiuluo.shamrock.tools.asString
import moe.fuqiuluo.shamrock.tools.json import moe.fuqiuluo.shamrock.tools.json
import moe.fuqiuluo.shamrock.tools.jsonArray import moe.fuqiuluo.shamrock.tools.jsonArray
import moe.fuqiuluo.symbols.OneBotHandler import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler(".handle_quick_operation_async") @OneBotHandler(".handle_quick_operation_async")
internal object QuickOperation: IActionHandler() { internal object QuickOperation : IActionHandler() {
val actionMsgTypes = arrayOf( val actionMsgTypes = arrayOf(
"record", "voice", "video", "markdown" "record", "voice", "video", "markdown"
) )
@ -51,36 +51,27 @@ internal object QuickOperation: IActionHandler() {
if (operation.containsKey("reply")) { if (operation.containsKey("reply")) {
LogCenter.log({ "websocket quickly reply successfully" }, Level.DEBUG) LogCenter.log({ "websocket quickly reply successfully" }, Level.DEBUG)
val autoEscape = operation["auto_escape"].asBooleanOrNull ?: false val autoEscape = operation["auto_escape"].asBooleanOrNull
val atSender = operation["at_sender"].asBooleanOrNull ?: false val atSender = operation["at_sender"].asBooleanOrNull ?: false
val autoReply = operation["auto_reply"].asBooleanOrNull ?: true val autoReply = operation["auto_reply"].asBooleanOrNull ?: true
val message = operation["reply"] val message = operation["reply"]
if (message is JsonPrimitive) { if (message is JsonPrimitive) {
if (autoEscape) { quicklyReply(
val msgList = mutableSetOf<JsonElement>() record,
msgList.add(mapOf( if (autoEscape == true)
listOf(
mapOf(
"type" to "text", "type" to "text",
"data" to mapOf( "data" to mapOf(
"text" to message.asString "text" to message.asString
) )
).json) )
quicklyReply( ).json
record, else MessageHelper.decodeCQCode(message.asString),
msgList.jsonArray,
msgHash, msgHash,
atSender, atSender,
autoReply autoReply
) )
} else {
val messageArray = MessageHelper.decodeCQCode(message.asString)
quicklyReply(
record,
messageArray,
msgHash,
atSender,
autoReply
)
}
} else if (message is JsonArray) { } else if (message is JsonArray) {
quicklyReply( quicklyReply(
record, record,
@ -92,17 +83,28 @@ internal object QuickOperation: IActionHandler() {
} }
} }
if (MsgConstant.KCHATTYPEGROUP == record.chatType && operation.containsKey("delete") && operation["delete"].asBoolean) { if (MsgConstant.KCHATTYPEGROUP == record.chatType) {
if (operation["delete"].asBooleanOrNull == true) {
val duration = operation["delay"].asIntOrNull
if (duration != null) {
GlobalScope.launch {
delay(duration.toLong())
MsgSvc.recallMsg(msgHash) MsgSvc.recallMsg(msgHash)
} }
if (MsgConstant.KCHATTYPEGROUP == record.chatType && operation.containsKey("kick") && operation["kick"].asBoolean) { } else {
MsgSvc.recallMsg(msgHash)
}
}
if (operation["kick"].asBooleanOrNull == true) {
GroupSvc.kickMember(record.peerUin, false, "", record.senderUin) GroupSvc.kickMember(record.peerUin, false, "", record.senderUin)
} }
if (MsgConstant.KCHATTYPEGROUP == record.chatType && operation.containsKey("ban") && operation["ban"].asBoolean) { if (operation["ban"].asBooleanOrNull == true) {
val banTime = operation["ban_duration"].asIntOrNull ?: (30 * 60) val banTime = operation["ban_duration"].asIntOrNull ?: (30 * 60)
if (banTime <= 0) return logic("禁言时间必须大于0", session.echo) if (banTime <= 0) return logic("禁言时间必须大于0", session.echo)
GroupSvc.banMember(record.peerUin, record.senderUin, banTime) GroupSvc.banMember(record.peerUin, record.senderUin, banTime)
} }
}
return logic("操作成功", session.echo) return logic("操作成功", session.echo)
} }
@ -128,19 +130,23 @@ internal object QuickOperation: IActionHandler() {
} }
} }
if (autoReply) messageList.add(mapOf( if (autoReply) messageList.add(
mapOf(
"type" to "reply", "type" to "reply",
"data" to mapOf( "data" to mapOf(
"id" to msgHash "id" to msgHash
) )
).json) // 添加回复 ).json
) // 添加回复
if (MsgConstant.KCHATTYPEGROUP == record.chatType && atSender) { if (MsgConstant.KCHATTYPEGROUP == record.chatType && atSender) {
messageList.add(mapOf( messageList.add(
mapOf(
"type" to "at", "type" to "at",
"data" to mapOf( "data" to mapOf(
"qq" to record.senderUin "qq" to record.senderUin
) )
).json) // 添加@发送者 ).json
) // 添加@发送者
} }
messageList.addAll(message) messageList.addAll(message)
MsgSvc.sendToAio(record.chatType, record.peerUin.toString(), JsonArray(messageList), retryCnt = 3) MsgSvc.sendToAio(record.chatType, record.peerUin.toString(), JsonArray(messageList), retryCnt = 3)

View File

@ -92,9 +92,10 @@ fun Routing.otherAction() {
val url = fetchOrNull("url") val url = fetchOrNull("url")
val b64 = fetchOrNull("base64") val b64 = fetchOrNull("base64")
val name = fetchOrNull("name") val name = fetchOrNull("name")
val root = fetchOrNull("root")
val threadCnt = fetchOrNull("thread_cnt")?.toInt() ?: 0 val threadCnt = fetchOrNull("thread_cnt")?.toInt() ?: 0
val headers = fetchOrNull("headers") ?: "" val headers = fetchOrNull("headers") ?: ""
call.respondText(DownloadFile(url, b64, threadCnt, headers.split("\r\n"), name), ContentType.Application.Json) call.respondText(DownloadFile(url, b64, threadCnt, headers.split("\r\n"), name, root), ContentType.Application.Json)
} }
post("/upload_file") { post("/upload_file") {

View File

@ -357,6 +357,8 @@ internal object GlobalEventTransmitter: BaseSvc() {
type = NoticeType.GroupAdminChange, type = NoticeType.GroupAdminChange,
subType = if (setAdmin) NoticeSubType.Set else NoticeSubType.UnSet, subType = if (setAdmin) NoticeSubType.Set else NoticeSubType.UnSet,
operatorId = 0, operatorId = 0,
userId = target,
userUid = targetUid,
target = target, target = target,
targetUid = targetUid, targetUid = targetUid,
groupId = groupCode groupId = groupCode

View File

@ -32,7 +32,7 @@ internal enum class NoticeSubType {
@SerialName("lift_ban") LiftBan, @SerialName("lift_ban") LiftBan,
@SerialName("set") Set, @SerialName("set") Set,
@SerialName("un_set") UnSet, @SerialName("unset") UnSet,
@SerialName("add") Add, @SerialName("add") Add,
@SerialName("invite") Invite, @SerialName("invite") Invite,