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.MD5
import moe.fuqiuluo.symbols.OneBotHandler
import java.io.File
@OneBotHandler("download_file")
internal object DownloadFile: IActionHandler() {
@ -19,6 +20,7 @@ internal object DownloadFile: IActionHandler() {
val url = session.getStringOrNull("url")
val name = session.getStringOrNull("name")
val b64 = session.getStringOrNull("base64")
val rootDir = session.getStringOrNull("root")
val threadCnt = session.getIntOrNull("thread_cnt") ?: 3
val headers = if (session.has("headers")) (if (session.isArray("headers")) {
session.getArray("headers").map {
@ -27,7 +29,7 @@ internal object DownloadFile: IActionHandler() {
} else {
session.getString("headers").split("\r\n")
}) 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(
@ -36,6 +38,7 @@ internal object DownloadFile: IActionHandler() {
threadCnt: Int,
headers: List<String>,
name: String?,
root: String?,
echo: JsonElement = EmptyJsonString
): String {
if (url != null) {
@ -49,9 +52,9 @@ internal object DownloadFile: IActionHandler() {
headerMap[k] = v
}
}
return invoke(url, threadCnt, headerMap, name, echo)
return invoke(url, threadCnt, headerMap, name, root, echo)
} else if (base64 != null) {
return invoke(base64, name, echo)
return invoke(base64, name, root, echo)
} else {
return noParam("url/base64", echo)
}
@ -60,6 +63,7 @@ internal object DownloadFile: IActionHandler() {
operator fun invoke(
base64: String,
name: String?,
root: String?,
echo: JsonElement
): String {
kotlin.runCatching {
@ -68,12 +72,17 @@ internal object DownloadFile: IActionHandler() {
it.writeBytes(bytes)
}
}.onSuccess {
val tmp = if (name == null)
var tmp = if (name == null)
FileUtils.renameByMd5(it)
else it.parentFile!!.resolve(name).also { target ->
it.renameTo(target)
it.delete()
}
if (root != null) {
tmp = File(root).resolve(name ?: tmp.name).also {
tmp.renameTo(it)
}
}
return ok(data = DownloadResult(
file = tmp.absolutePath,
md5 = MD5.genFileMd5Hex(tmp.absolutePath)
@ -89,6 +98,7 @@ internal object DownloadFile: IActionHandler() {
threadCnt: Int,
headers: Map<String, String>,
name: String?,
root: String?,
echo: JsonElement = EmptyJsonString
): String {
return kotlin.runCatching {
@ -108,6 +118,11 @@ internal object DownloadFile: IActionHandler() {
tmp.renameTo(newFile)
newFile
}
if (root != null) {
tmp = File(root).resolve(name ?: tmp.name).also {
tmp.renameTo(it)
}
}
ok(data = DownloadResult(
file = 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.MsgRecord
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
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.remote.action.ActionSession
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.asInt
import moe.fuqiuluo.shamrock.tools.asIntOrNull
import moe.fuqiuluo.shamrock.tools.asJsonObject
import moe.fuqiuluo.shamrock.tools.asLong
import moe.fuqiuluo.shamrock.tools.asString
import moe.fuqiuluo.shamrock.tools.json
import moe.fuqiuluo.shamrock.tools.jsonArray
import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler(".handle_quick_operation_async")
internal object QuickOperation: IActionHandler() {
internal object QuickOperation : IActionHandler() {
val actionMsgTypes = arrayOf(
"record", "voice", "video", "markdown"
)
@ -51,36 +51,27 @@ internal object QuickOperation: IActionHandler() {
if (operation.containsKey("reply")) {
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 autoReply = operation["auto_reply"].asBooleanOrNull ?: true
val message = operation["reply"]
if (message is JsonPrimitive) {
if (autoEscape) {
val msgList = mutableSetOf<JsonElement>()
msgList.add(mapOf(
"type" to "text",
"data" to mapOf(
"text" to message.asString
)
).json)
quicklyReply(
record,
msgList.jsonArray,
msgHash,
atSender,
autoReply
)
} else {
val messageArray = MessageHelper.decodeCQCode(message.asString)
quicklyReply(
record,
messageArray,
msgHash,
atSender,
autoReply
)
}
quicklyReply(
record,
if (autoEscape == true)
listOf(
mapOf(
"type" to "text",
"data" to mapOf(
"text" to message.asString
)
)
).json
else MessageHelper.decodeCQCode(message.asString),
msgHash,
atSender,
autoReply
)
} else if (message is JsonArray) {
quicklyReply(
record,
@ -92,18 +83,29 @@ internal object QuickOperation: IActionHandler() {
}
}
if (MsgConstant.KCHATTYPEGROUP == record.chatType && operation.containsKey("delete") && operation["delete"].asBoolean) {
MsgSvc.recallMsg(msgHash)
}
if (MsgConstant.KCHATTYPEGROUP == record.chatType && operation.containsKey("kick") && operation["kick"].asBoolean) {
GroupSvc.kickMember(record.peerUin, false, "", record.senderUin)
}
if (MsgConstant.KCHATTYPEGROUP == record.chatType && operation.containsKey("ban") && operation["ban"].asBoolean) {
val banTime = operation["ban_duration"].asIntOrNull ?: (30 * 60)
if (banTime <= 0) return logic("禁言时间必须大于0", session.echo)
GroupSvc.banMember(record.peerUin, record.senderUin, banTime)
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)
}
} else {
MsgSvc.recallMsg(msgHash)
}
}
if (operation["kick"].asBooleanOrNull == true) {
GroupSvc.kickMember(record.peerUin, false, "", record.senderUin)
}
if (operation["ban"].asBooleanOrNull == true) {
val banTime = operation["ban_duration"].asIntOrNull ?: (30 * 60)
if (banTime <= 0) return logic("禁言时间必须大于0", session.echo)
GroupSvc.banMember(record.peerUin, record.senderUin, banTime)
}
}
return logic("操作成功", session.echo)
}
@ -128,19 +130,23 @@ internal object QuickOperation: IActionHandler() {
}
}
if (autoReply) messageList.add(mapOf(
"type" to "reply",
"data" to mapOf(
"id" to msgHash
)
).json) // 添加回复
if (MsgConstant.KCHATTYPEGROUP == record.chatType && atSender) {
messageList.add(mapOf(
"type" to "at",
if (autoReply) messageList.add(
mapOf(
"type" to "reply",
"data" to mapOf(
"qq" to record.senderUin
"id" to msgHash
)
).json) // 添加@发送者
).json
) // 添加回复
if (MsgConstant.KCHATTYPEGROUP == record.chatType && atSender) {
messageList.add(
mapOf(
"type" to "at",
"data" to mapOf(
"qq" to record.senderUin
)
).json
) // 添加@发送者
}
messageList.addAll(message)
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 b64 = fetchOrNull("base64")
val name = fetchOrNull("name")
val root = fetchOrNull("root")
val threadCnt = fetchOrNull("thread_cnt")?.toInt() ?: 0
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") {

View File

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

View File

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