mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-12 14:00:12 +08:00
Merge remote-tracking branch 'origin/master'
# Conflicts: # mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt
This commit is contained in:
commit
94570ec447
@ -220,6 +220,75 @@ fun main() {
|
||||
|
||||
|
||||
|
||||
### 发送图片消息(通过URL)
|
||||
|
||||
```
|
||||
[POST] /sendGroupMessage
|
||||
```
|
||||
|
||||
使用此方法向指定群发送消息
|
||||
|
||||
#### 请求
|
||||
|
||||
```json5
|
||||
{
|
||||
"sessionKey": "YourSession",
|
||||
"target": 987654321,
|
||||
"qq": 1234567890,
|
||||
"group": 987654321,
|
||||
"urls": [
|
||||
"https://xxx.yyy.zzz/",
|
||||
"https://aaa.bbb.ccc/"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| 名字 | 类型 | 可选 | 举例 | 说明 |
|
||||
| ------------ | ------ | ----- | ----------- | ---------------------------------- |
|
||||
| sessionKey | String | false | YourSession | 已经激活的Session |
|
||||
| target | Long | true | 987654321 | 发送对象的QQ号或群号,可能存在歧义 |
|
||||
| qq | Long | true | 123456789 | 发送对象的QQ号 |
|
||||
| group | Long | true | 987654321 | 发送对象的群号 |
|
||||
| urls | Array | false | [] | 是一个url字符串构成的数组 |
|
||||
|
||||
#### 响应: 图片的imageId数组
|
||||
|
||||
```json5
|
||||
[
|
||||
"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}.jpg",
|
||||
"{YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY}.jpg"
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 图片文件上传
|
||||
|
||||
```
|
||||
[POST] /sendGroupMessage
|
||||
```
|
||||
|
||||
使用此方法上传图片文件至服务器并返回ImageId
|
||||
|
||||
#### 请求
|
||||
|
||||
Content-Type:multipart/form-data
|
||||
|
||||
| 名字 | 类型 | 可选 | 举例 | 说明 |
|
||||
| ------------ | ------ | ----- | ----------- | ---------------------------------- |
|
||||
| sessionKey | String | false | YourSession | 已经激活的Session |
|
||||
| type | String | false | "friend " | "friend" 或 "group" |
|
||||
| img | File | false | - | 图片文件 |
|
||||
|
||||
|
||||
#### 响应: 图片的imageId(好友图片与群聊图片Id不同)
|
||||
|
||||
```
|
||||
{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}.jpg
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 获取Bot收到的消息
|
||||
|
||||
```
|
||||
|
@ -18,6 +18,7 @@ import io.ktor.features.DefaultHeaders
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.content.PartData
|
||||
import io.ktor.request.receive
|
||||
import io.ktor.response.defaultTextContentType
|
||||
import io.ktor.response.respondText
|
||||
@ -182,3 +183,20 @@ internal inline fun <reified R> PipelineContext<Unit, ApplicationCall>.paramOrNu
|
||||
|
||||
else -> error(name::class.simpleName + " is not supported")
|
||||
} as R ?: illegalParam(R::class.simpleName, name)
|
||||
|
||||
/**
|
||||
* multi part
|
||||
*/
|
||||
internal fun List<PartData>.value(name: String) =
|
||||
try {
|
||||
(filter { it.name == name }[0] as PartData.FormItem).value
|
||||
} catch (e: Exception) {
|
||||
throw IllegalParamException("参数格式错误")
|
||||
}
|
||||
|
||||
internal fun List<PartData>.file(name: String) =
|
||||
try {
|
||||
filter { it.name == name }[0] as? PartData.FileItem
|
||||
} catch (e: Exception) {
|
||||
throw IllegalParamException("参数格式错误")
|
||||
}
|
@ -11,14 +11,25 @@ package net.mamoe.mirai.api.http.route
|
||||
|
||||
import io.ktor.application.Application
|
||||
import io.ktor.application.call
|
||||
import io.ktor.http.content.readAllParts
|
||||
import io.ktor.http.content.streamProvider
|
||||
import io.ktor.request.receiveMultipart
|
||||
import io.ktor.response.respondText
|
||||
import io.ktor.routing.post
|
||||
import io.ktor.routing.routing
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.api.http.data.StateCode
|
||||
import net.mamoe.mirai.api.http.AuthedSession
|
||||
import net.mamoe.mirai.api.http.SessionManager
|
||||
import net.mamoe.mirai.api.http.data.*
|
||||
import net.mamoe.mirai.api.http.data.common.MessageChainDTO
|
||||
import net.mamoe.mirai.api.http.data.common.VerifyDTO
|
||||
import net.mamoe.mirai.api.http.data.common.toDTO
|
||||
import net.mamoe.mirai.api.http.data.common.toMessageChain
|
||||
import net.mamoe.mirai.api.http.util.toJson
|
||||
import net.mamoe.mirai.contact.toList
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.uploadImage
|
||||
import java.net.URL
|
||||
|
||||
fun Application.messageModule() {
|
||||
routing {
|
||||
@ -41,6 +52,42 @@ fun Application.messageModule() {
|
||||
call.respondStateCode(StateCode.Success)
|
||||
}
|
||||
|
||||
miraiVerify<SendImageDTO>("sendImageMessage") {
|
||||
val bot = it.session.bot
|
||||
val contact = when {
|
||||
it.target != null -> bot[it.target]
|
||||
it.qq != null -> bot.getFriend(it.qq)
|
||||
it.group != null -> bot.getGroup(it.group)
|
||||
else -> throw IllegalParamException("target、qq、group不可全为null")
|
||||
}
|
||||
val ls = it.urls.map { url -> contact.uploadImage(URL(url)) }
|
||||
contact.sendMessage(MessageChain(ls))
|
||||
call.respondJson(ls.map { image -> image.imageId }.toJson())
|
||||
}
|
||||
|
||||
// TODO: 重构
|
||||
post("uploadImage") {
|
||||
val parts = call.receiveMultipart().readAllParts()
|
||||
val sessionKey = parts.value("sessionKey")
|
||||
if (!SessionManager.containSession(sessionKey)) throw IllegalSessionException
|
||||
val session = try {
|
||||
SessionManager[sessionKey] as AuthedSession
|
||||
} catch (e: TypeCastException) { throw NotVerifiedSessionException }
|
||||
|
||||
val type = parts.value("type")
|
||||
parts.file("img")?.apply {
|
||||
val image = streamProvider().use {
|
||||
when(type) {
|
||||
"group" -> session.bot.groups.toList().random().uploadImage(it)
|
||||
"friend" -> session.bot.qqs.toList().random().uploadImage(it)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
image?.apply {
|
||||
call.respondText(imageId)
|
||||
} ?: throw IllegalAccessException("图片上传错误")
|
||||
} ?: throw IllegalAccessException("未知错误")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,4 +96,14 @@ private data class SendDTO(
|
||||
override val sessionKey: String,
|
||||
val target: Long,
|
||||
val messageChain: MessageChainDTO
|
||||
) : VerifyDTO()
|
||||
) : VerifyDTO()
|
||||
|
||||
@Serializable
|
||||
private data class SendImageDTO(
|
||||
override val sessionKey: String,
|
||||
val target: Long? = null,
|
||||
val qq: Long? = null,
|
||||
val group: Long? = null,
|
||||
val urls: List<String>
|
||||
) : VerifyDTO()
|
||||
|
||||
|
@ -32,7 +32,11 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgSvc
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.SyncCookie
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.*
|
||||
import net.mamoe.mirai.qqandroid.message.toMessageChain
|
||||
import net.mamoe.mirai.qqandroid.message.toRichTextElems
|
||||
import net.mamoe.mirai.utils.MiraiDebugAPI
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.cryptor.contentToString
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.random.Random
|
||||
@ -44,13 +48,16 @@ internal class MessageSvc {
|
||||
internal object PushNotify : IncomingPacketFactory<RequestPushNotify>("MessageSvc.PushNotify") {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): RequestPushNotify {
|
||||
discardExact(4) // don't remove
|
||||
|
||||
return decodeUniPacket(RequestPushNotify.serializer())
|
||||
}
|
||||
|
||||
override suspend fun QQAndroidBot.handle(packet: RequestPushNotify, sequenceId: Int): OutgoingPacket? {
|
||||
network.run {
|
||||
return PbGetMsg(client, MsgSvc.SyncFlag.START, packet.stMsgInfo?.uMsgTime ?: currentTimeSeconds)
|
||||
return PbGetMsg(
|
||||
client,
|
||||
MsgSvc.SyncFlag.START,
|
||||
packet.stMsgInfo?.uMsgTime ?: currentTimeSeconds
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,6 +136,10 @@ internal class MessageSvc {
|
||||
|
||||
val messages = resp.uinPairMsgs.asSequence().filterNot { it.msg == null }.flatMap { it.msg!!.asSequence() }.mapNotNull {
|
||||
when (it.msgHead.msgType) {
|
||||
33 -> {
|
||||
println("GroupUin" + it.msgHead.fromUin + "新群员" + it.msgHead.authUin + " 出现了[" + it.msgHead.authNick + "] 添加刷新")
|
||||
null
|
||||
}
|
||||
166 -> {
|
||||
when {
|
||||
it.msgHead.fromUin == bot.uin -> null
|
||||
|
@ -111,9 +111,9 @@ internal class OnlinePush {
|
||||
val groupUin = content.fromUin
|
||||
val target = var7
|
||||
if (this.readByte().toInt() == 1) {
|
||||
println("群" + groupUin + "新增管理员" + target)
|
||||
println("群uin" + groupUin + "新增管理员" + target)
|
||||
} else {
|
||||
println("群" + groupUin + "减少管理员" + target)
|
||||
println("群uin" + groupUin + "减少管理员" + target)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,8 +122,9 @@ internal class OnlinePush {
|
||||
if (readByte().toInt() == 1) {
|
||||
val target = readUInt().toLong()
|
||||
val groupUin = content.fromUin
|
||||
println("群" + groupUin + "t掉了" + target)
|
||||
println("群uin" + groupUin + "t掉了" + target)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,6 +201,10 @@ internal class OnlinePush {
|
||||
}
|
||||
}
|
||||
}
|
||||
4352 -> {
|
||||
println(msgInfo.contentToString())
|
||||
println(msgInfo.vMsg.toUHexString())
|
||||
}
|
||||
else -> {
|
||||
println("unknown group internal type $internalType , data: " + this.readBytes().toUHexString() + " ")
|
||||
}
|
||||
@ -207,8 +212,6 @@ internal class OnlinePush {
|
||||
} else if (msgInfo.shMsgType.toInt() == 528) {
|
||||
val content = msgInfo.vMsg.loadAs(OnlinePushPack.MsgType0x210.serializer())
|
||||
println(content.contentToString())
|
||||
} else if (msgInfo.shMsgType.toInt() == 4352) {
|
||||
println("4352")
|
||||
} else {
|
||||
println("unknown shtype ${msgInfo.shMsgType.toInt()}")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user