From 0c58c511d0ed2d4d26e00ab034a7aa784007120c Mon Sep 17 00:00:00 2001 From: ryoii <ryoii@foxmail.com> Date: Sun, 23 Feb 2020 18:22:58 +0800 Subject: [PATCH 01/17] Http api ignore unknown message type tdo --- .../net/mamoe/mirai/api/http/data/common/MessageDTO.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt index d13a97f17..b0906898a 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt @@ -17,7 +17,9 @@ import net.mamoe.mirai.message.FriendMessage import net.mamoe.mirai.message.GroupMessage import net.mamoe.mirai.message.MessagePacket import net.mamoe.mirai.message.data.* +import net.mamoe.mirai.message.uploadImage import net.mamoe.mirai.utils.MiraiInternalAPI +import java.net.URL /* * DTO data class @@ -97,7 +99,7 @@ fun MessageChain.toDTOChain() = mutableListOf(this[MessageSource].toDTO()).apply } fun MessageChainDTO.toMessageChain(contact: Contact) = - buildMessageChain { this@toMessageChain.forEach { add(it.toMessage(contact)) } } + buildMessageChain { this@toMessageChain.forEach { it.toMessage(contact)?.let(::add) } } @UseExperimental(ExperimentalUnsignedTypes::class) fun Message.toDTO() = when (this) { @@ -119,6 +121,6 @@ fun MessageDTO.toMessage(contact: Contact) = when (this) { is PlainDTO -> PlainText(text) is ImageDTO -> Image(imageId) is XmlDTO -> XMLMessage(xml) - is MessageSourceDTO, is UnknownMessageDTO -> PlainText("assert cannot reach") + is MessageSourceDTO, is UnknownMessageDTO -> null } From 94d859a4e6cf410d3e79d63f97ffa11a54771bbe Mon Sep 17 00:00:00 2001 From: ryoii <ryoii@foxmail.com> Date: Sun, 23 Feb 2020 19:18:14 +0800 Subject: [PATCH 02/17] Http api better image with url --- .../mirai/api/http/data/common/BotEventDTO.kt | 2 +- .../mirai/api/http/data/common/MessageDTO.kt | 42 +++++++++++-------- .../mirai/api/http/queue/MessageQueue.kt | 2 +- .../api/http/route/MessageRouteModule.kt | 2 + 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/BotEventDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/BotEventDTO.kt index e94a0c5e4..28630c173 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/BotEventDTO.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/BotEventDTO.kt @@ -12,7 +12,7 @@ import net.mamoe.mirai.utils.MiraiExperimentalAPI sealed class BotEventDTO : EventDTO() @UseExperimental(MiraiExperimentalAPI::class) -fun BotEvent.toDTO() = when(this) { +suspend fun BotEvent.toDTO() = when(this) { is MessagePacket<*, *> -> toDTO() else -> when(this) { is BotOnlineEvent -> BotOnlineEventDTO(bot.uin) diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt index b0906898a..187c49a0e 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/MessageDTO.kt @@ -58,7 +58,7 @@ data class PlainDTO(val text: String) : MessageDTO() @Serializable @SerialName("Image") -data class ImageDTO(val imageId: String) : MessageDTO() +data class ImageDTO(val imageId: String? = null, val url: String? = null) : MessageDTO() @Serializable @SerialName("Xml") @@ -85,41 +85,47 @@ sealed class MessageDTO : DTO /* Extend function */ -fun MessagePacket<*, *>.toDTO() = when (this) { +suspend fun MessagePacket<*, *>.toDTO() = when (this) { is FriendMessage -> FriendMessagePacketDTO(QQDTO(sender)) is GroupMessage -> GroupMessagePacketDTO(MemberDTO(sender)) else -> IgnoreEventDTO }.apply { - if (this is MessagePacketDTO) { messageChain = message.toDTOChain() } - // else: `this` is bot event + if (this is MessagePacketDTO) { + // 将MessagePacket中的所有Message转为DTO对象,并添加到messageChain + // foreachContent会忽略MessageSource,一次主动获取 + messageChain = mutableListOf(messageDTO(message[MessageSource])).apply { + message.foreachContent { content -> messageDTO(content).takeUnless { it == UnknownMessageDTO }?.let(::add) } + } + // else: `this` is bot event + } } -fun MessageChain.toDTOChain() = mutableListOf(this[MessageSource].toDTO()).apply { - foreachContent { content -> content.toDTO().takeUnless { it == UnknownMessageDTO }?.let(::add) } -} - -fun MessageChainDTO.toMessageChain(contact: Contact) = +suspend fun MessageChainDTO.toMessageChain(contact: Contact) = buildMessageChain { this@toMessageChain.forEach { it.toMessage(contact)?.let(::add) } } @UseExperimental(ExperimentalUnsignedTypes::class) -fun Message.toDTO() = when (this) { - is MessageSource -> MessageSourceDTO(id) - is At -> AtDTO(target, display) +suspend fun MessagePacket<*, *>.messageDTO(message: Message) = when (message) { + is MessageSource -> MessageSourceDTO(message.id) + is At -> AtDTO(message.target, message.display) is AtAll -> AtAllDTO(0L) - is Face -> FaceDTO(id) - is PlainText -> PlainDTO(stringValue) - is Image -> ImageDTO(imageId) - is XMLMessage -> XmlDTO(stringValue) + is Face -> FaceDTO(message.id) + is PlainText -> PlainDTO(message.stringValue) + is Image -> ImageDTO(message.imageId, message.url()) + is XMLMessage -> XmlDTO(message.stringValue) else -> UnknownMessageDTO } @UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class) -fun MessageDTO.toMessage(contact: Contact) = when (this) { +suspend fun MessageDTO.toMessage(contact: Contact) = when (this) { is AtDTO -> At((contact as Group)[target]) is AtAllDTO -> AtAll is FaceDTO -> Face(faceId) is PlainDTO -> PlainText(text) - is ImageDTO -> Image(imageId) + is ImageDTO -> when { + !imageId.isNullOrBlank() -> Image(imageId) + !url.isNullOrBlank() -> contact.uploadImage(URL(url)) + else -> null + } is XmlDTO -> XMLMessage(xml) is MessageSourceDTO, is UnknownMessageDTO -> null } diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt index e497d56e6..1cb1a54cb 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt @@ -23,7 +23,7 @@ class MessageQueue : ConcurrentLinkedDeque<BotEvent>() { val quoteCacheSize = 4096 val quoteCache = LinkedHashMap<Long, GroupMessage>() - fun fetch(size: Int): List<EventDTO> { + suspend fun fetch(size: Int): List<EventDTO> { var count = size val ret = ArrayList<EventDTO>(count) diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt index 04631b2d1..e5b7b0bb7 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt @@ -46,12 +46,14 @@ fun Application.messageModule() { it.session.bot.getFriend(it.target).apply { sendMessage(it.messageChain.toMessageChain(this)) // this aka QQ } + call.respondStateCode(StateCode.Success) } miraiVerify<SendDTO>("/sendGroupMessage") { it.session.bot.getGroup(it.target).apply { sendMessage(it.messageChain.toMessageChain(this)) // this aka Group } + call.respondStateCode(StateCode.Success) } miraiVerify<SendDTO>("/sendQuoteMessage") { From 0e5e2336ff9af79265dfe5b7b72acf0eb3704e74 Mon Sep 17 00:00:00 2001 From: ryoii <ryoii@foxmail.com> Date: Sun, 23 Feb 2020 20:33:03 +0800 Subject: [PATCH 03/17] Http api return messageId after send a message --- mirai-api-http/README_CH.md | 20 ++++++++++------ .../api/http/route/MessageRouteModule.kt | 24 +++++++++++-------- .../net.mamoe.mirai/message/MessageReceipt.kt | 2 +- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/mirai-api-http/README_CH.md b/mirai-api-http/README_CH.md index 274d7cd84..7019abd7d 100644 --- a/mirai-api-http/README_CH.md +++ b/mirai-api-http/README_CH.md @@ -175,12 +175,13 @@ fun main() { | target | Long | false | 987654321 | 发送消息目标好友的QQ号 | | messageChain | Array | false | [] | 消息链,是一个消息对象构成的数组 | -#### 响应: 返回统一状态码 +#### 响应: 返回统一状态码(并携带messageId) ```json5 { "code": 0, - "msg": "success" + "msg": "success", + "messageId": 1234567890 // 一个Long类型属性,标识本条消息,用于撤回和引用回复 } ``` @@ -213,12 +214,13 @@ fun main() { | target | Long | false | 987654321 | 发送消息目标群的群号 | | messageChain | Array | false | [] | 消息链,是一个消息对象构成的数组 | -#### 响应: 返回统一状态码 +#### 响应: 返回统一状态码(并携带messageId) ```json5 { "code": 0, - "msg": "success" + "msg": "success", + "messageId": 1234567890 // 一个Long类型属性,标识本条消息,用于撤回和引用回复 } ``` @@ -251,12 +253,13 @@ fun main() { | target | Long | false | 987654321 | 引用消息的Message Source的Uid | | messageChain | Array | false | [] | 消息链,是一个消息对象构成的数组 | -#### 响应: 返回统一状态码 +#### 响应: 返回统一状态码(并携带messageId) ```json5 { "code": 0, - "msg": "success" + "msg": "success", + "messageId": 1234567890 // 一个Long类型属性,标识本条消息,用于撤回和引用回复 } ``` @@ -370,7 +373,10 @@ Content-Type:multipart/form-data } },{ "type": "FriendMessage", // 消息类型:GroupMessage或FriendMessage或各类Event - "messageChain": [{ // 消息链,是一个消息对象构成的数组 + "messageChain": [{ // 消息链,是一个消息对象构成的数组 + "type": "Source", + "uid": 123456 + },{ "type": "Plain", "text": "Miral牛逼" }], diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt index e5b7b0bb7..872d40497 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt @@ -20,10 +20,10 @@ import io.ktor.response.respondText import io.ktor.routing.post import io.ktor.routing.routing import kotlinx.serialization.Serializable -import kotlinx.serialization.Transient 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.DTO 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.toMessageChain @@ -44,23 +44,26 @@ fun Application.messageModule() { miraiVerify<SendDTO>("/sendFriendMessage") { it.session.bot.getFriend(it.target).apply { - sendMessage(it.messageChain.toMessageChain(this)) // this aka QQ + val receipt = sendMessage(it.messageChain.toMessageChain(this)) // this aka QQ + receipt.source.ensureSequenceIdAvailable() + call.respondDTO(SendRetDTO(messageId = receipt.source.id)) } - call.respondStateCode(StateCode.Success) } miraiVerify<SendDTO>("/sendGroupMessage") { it.session.bot.getGroup(it.target).apply { - sendMessage(it.messageChain.toMessageChain(this)) // this aka Group + val receipt = sendMessage(it.messageChain.toMessageChain(this)) // this aka Group + receipt.source.ensureSequenceIdAvailable() + call.respondDTO(SendRetDTO(messageId = receipt.source.id)) } - call.respondStateCode(StateCode.Success) } miraiVerify<SendDTO>("/sendQuoteMessage") { it.session.messageQueue.quoteCache[it.target]?.apply { - quoteReply(it.messageChain.toMessageChain(group)) + val receipt = quoteReply(it.messageChain.toMessageChain(group)) + receipt.source.ensureSequenceIdAvailable() + call.respondDTO(SendRetDTO(messageId = receipt.source.id)) } ?: throw NoSuchElementException() - call.respondStateCode(StateCode.Success) } miraiVerify<SendImageDTO>("sendImageMessage") { @@ -127,9 +130,10 @@ private data class SendImageDTO( @Serializable private class SendRetDTO( - val messageId: Long, - @Transient val stateCode: StateCode = Success -) : StateCode(stateCode.code, stateCode.msg) + val code: Int = 0, + val msg: String = "success", + val messageId: Long +) : DTO @Serializable private data class RecallDTO( diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt index 7d5c37657..31482e393 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt @@ -31,7 +31,7 @@ import net.mamoe.mirai.utils.unsafeWeakRef * @see QQ.sendMessage 发送群消息, 返回回执(此对象) */ open class MessageReceipt<C : Contact>( - private val source: MessageSource, + val source: MessageSource, target: C ) { init { From a52655e2abe32d6b31dd34eb153e754de852e1aa Mon Sep 17 00:00:00 2001 From: ryoii <ryoii@foxmail.com> Date: Sun, 23 Feb 2020 22:57:06 +0800 Subject: [PATCH 04/17] Fix error in LockFreeLinkedListTest --- .../kotlin/net/mamoe/mirai/utils/LockFreeLinkedListTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mirai-core/src/jvmTest/kotlin/net/mamoe/mirai/utils/LockFreeLinkedListTest.kt b/mirai-core/src/jvmTest/kotlin/net/mamoe/mirai/utils/LockFreeLinkedListTest.kt index de4c3b195..6af63aa89 100644 --- a/mirai-core/src/jvmTest/kotlin/net/mamoe/mirai/utils/LockFreeLinkedListTest.kt +++ b/mirai-core/src/jvmTest/kotlin/net/mamoe/mirai/utils/LockFreeLinkedListTest.kt @@ -161,7 +161,7 @@ internal class LockFreeLinkedListTest { println("Check value") value shouldBeEqualTo 6 println("Check size") - println(list.getLinkStructure()) +// println(list.getLinkStructure()) list.size shouldBeEqualTo 6 } @@ -174,7 +174,7 @@ internal class LockFreeLinkedListTest { println("Check value") value shouldBeEqualTo 2 println("Check size") - println(list.getLinkStructure()) +// println(list.getLinkStructure()) list.size shouldBeEqualTo 5 } @@ -198,7 +198,7 @@ internal class LockFreeLinkedListTest { println("Check value") value shouldBeEqualTo 2 println("Check size") - println(list.getLinkStructure()) +// println(list.getLinkStructure()) list.size shouldBeEqualTo 1 } /* From cd73d7f53467407cc3c9b277a39decf391f02e45 Mon Sep 17 00:00:00 2001 From: ryoii <ryoii@foxmail.com> Date: Sun, 23 Feb 2020 22:58:24 +0800 Subject: [PATCH 05/17] Http api friendly quote --- .../mirai/api/http/queue/MessageQueue.kt | 11 +++-- .../api/http/route/MessageRouteModule.kt | 40 ++++++++++++++----- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt index 1cb1a54cb..83250127a 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt @@ -14,6 +14,7 @@ import net.mamoe.mirai.api.http.data.common.IgnoreEventDTO import net.mamoe.mirai.api.http.data.common.toDTO import net.mamoe.mirai.event.events.BotEvent import net.mamoe.mirai.message.GroupMessage +import net.mamoe.mirai.message.MessagePacket import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.utils.firstKey import java.util.concurrent.ConcurrentLinkedDeque @@ -21,7 +22,7 @@ import java.util.concurrent.ConcurrentLinkedDeque class MessageQueue : ConcurrentLinkedDeque<BotEvent>() { val quoteCacheSize = 4096 - val quoteCache = LinkedHashMap<Long, GroupMessage>() + val quoteCache = LinkedHashMap<Long, MessagePacket<*, *>>() suspend fun fetch(size: Int): List<EventDTO> { var count = size @@ -37,15 +38,17 @@ class MessageQueue : ConcurrentLinkedDeque<BotEvent>() { } } - // TODO: 等FriendMessage支持quote - if (event is GroupMessage) { + if (event is MessagePacket<*, *>) { addQuoteCache(event) } } return ret } - private fun addQuoteCache(msg: GroupMessage) { + fun cacheQuote(messageId: Long) = + quoteCache[messageId] ?: throw NoSuchElementException() + + private fun addQuoteCache(msg: MessagePacket<*, *>) { quoteCache[msg.message[MessageSource].id] = msg if (quoteCache.size > quoteCacheSize) { quoteCache.remove(quoteCache.firstKey()) diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt index 872d40497..7e59e6e43 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt @@ -28,7 +28,9 @@ 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.toMessageChain import net.mamoe.mirai.api.http.util.toJson -import net.mamoe.mirai.message.data.MessageChain +import net.mamoe.mirai.contact.Contact +import net.mamoe.mirai.message.MessageReceipt +import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.uploadImage import java.net.URL @@ -42,30 +44,45 @@ fun Application.messageModule() { call.respondJson(fetch.toJson()) } + suspend fun <C : Contact> sendMessage( + quote: QuoteReplyToSend?, + messageChain: MessageChain, + target: C + ): MessageReceipt<out Contact> { + val send = if (quote == null) { + messageChain + } else { + (quote + messageChain).toChain() + } + return target.sendMessage(send) + } + miraiVerify<SendDTO>("/sendFriendMessage") { + val quote = it.quote?.let { q -> + it.session.messageQueue.cacheQuote(q).run { + this[MessageSource].quote(sender) + }} + it.session.bot.getFriend(it.target).apply { - val receipt = sendMessage(it.messageChain.toMessageChain(this)) // this aka QQ + val receipt = sendMessage(quote, it.messageChain.toMessageChain(this), this) receipt.source.ensureSequenceIdAvailable() call.respondDTO(SendRetDTO(messageId = receipt.source.id)) } } miraiVerify<SendDTO>("/sendGroupMessage") { + val quote = it.quote?.let { q -> + it.session.messageQueue.cacheQuote(q).run { + this[MessageSource].quote(sender) + }} + it.session.bot.getGroup(it.target).apply { - val receipt = sendMessage(it.messageChain.toMessageChain(this)) // this aka Group + val receipt = sendMessage(quote, it.messageChain.toMessageChain(this), this) receipt.source.ensureSequenceIdAvailable() call.respondDTO(SendRetDTO(messageId = receipt.source.id)) } } - miraiVerify<SendDTO>("/sendQuoteMessage") { - it.session.messageQueue.quoteCache[it.target]?.apply { - val receipt = quoteReply(it.messageChain.toMessageChain(group)) - receipt.source.ensureSequenceIdAvailable() - call.respondDTO(SendRetDTO(messageId = receipt.source.id)) - } ?: throw NoSuchElementException() - } - miraiVerify<SendImageDTO>("sendImageMessage") { val bot = it.session.bot val contact = when { @@ -115,6 +132,7 @@ fun Application.messageModule() { @Serializable private data class SendDTO( override val sessionKey: String, + val quote: Long? = null, val target: Long, val messageChain: MessageChainDTO ) : VerifyDTO() From 0d7af4a111f8ce521a1d82c2fce660999c6b8e2b Mon Sep 17 00:00:00 2001 From: ryoii <ryoii@foxmail.com> Date: Sun, 23 Feb 2020 23:01:41 +0800 Subject: [PATCH 06/17] Http api update README_CH.md --- mirai-api-http/README_CH.md | 41 ++----------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/mirai-api-http/README_CH.md b/mirai-api-http/README_CH.md index 7019abd7d..30f52fce4 100644 --- a/mirai-api-http/README_CH.md +++ b/mirai-api-http/README_CH.md @@ -173,6 +173,7 @@ fun main() { | ------------ | ------ | ----- | ----------- | -------------------------------- | | sessionKey | String | false | YourSession | 已经激活的Session | | target | Long | false | 987654321 | 发送消息目标好友的QQ号 | +| quote | Long | true | 135798642 | 引用一条消息的messageId进行回复 | | messageChain | Array | false | [] | 消息链,是一个消息对象构成的数组 | #### 响应: 返回统一状态码(并携带messageId) @@ -212,45 +213,7 @@ fun main() { | ------------ | ------ | ----- | ----------- | -------------------------------- | | sessionKey | String | false | YourSession | 已经激活的Session | | target | Long | false | 987654321 | 发送消息目标群的群号 | -| messageChain | Array | false | [] | 消息链,是一个消息对象构成的数组 | - -#### 响应: 返回统一状态码(并携带messageId) - -```json5 -{ - "code": 0, - "msg": "success", - "messageId": 1234567890 // 一个Long类型属性,标识本条消息,用于撤回和引用回复 -} -``` - - - -### 发送引用回复消息(仅支持群消息) - -``` -[POST] /sendQuoteMessage -``` - -使用此方法向指定的消息进行引用回复 - -#### 请求 - -```json5 -{ - "sessionKey": "YourSession", - "target": 987654321, - "messageChain": [ - { "type": "Plain", "text":"hello\n" }, - { "type": "Plain", "text":"world" } - ] -} -``` - -| 名字 | 类型 | 可选 | 举例 | 说明 | -| ------------ | ------ | ----- | ----------- | -------------------------------- | -| sessionKey | String | false | YourSession | 已经激活的Session | -| target | Long | false | 987654321 | 引用消息的Message Source的Uid | +| quote | Long | true | 135798642 | 引用一条消息的messageId进行回复 | | messageChain | Array | false | [] | 消息链,是一个消息对象构成的数组 | #### 响应: 返回统一状态码(并携带messageId) From f4020e4a03a6868ac358dc665bbbf4e4beb3703d Mon Sep 17 00:00:00 2001 From: ryoii <ryoii@foxmail.com> Date: Sun, 23 Feb 2020 23:58:01 +0800 Subject: [PATCH 07/17] Http api support recall --- mirai-api-http/README_CH.md | 33 +++++++++++++++++++ .../mirai/api/http/queue/MessageQueue.kt | 17 +++++----- .../api/http/route/MessageRouteModule.kt | 19 +++++++---- 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/mirai-api-http/README_CH.md b/mirai-api-http/README_CH.md index 30f52fce4..ff595681d 100644 --- a/mirai-api-http/README_CH.md +++ b/mirai-api-http/README_CH.md @@ -297,6 +297,39 @@ Content-Type:multipart/form-data +### 撤回消息 + +``` +[POST] /recall +``` + +使用此方法撤回指定消息。对于bot发送的消息,又2分钟时间限制。对于撤回群聊中群员的消息,需要有相应权限 + +#### 请求 + +```json5 +{ + "sessionKey": "YourSession", + "target": 987654321 +} +``` + +| 名字 | 类型 | 可选 | 举例 | 说明 | +| ------------ | ------ | ----- | ----------- | -------------------------------- | +| sessionKey | String | false | YourSession | 已经激活的Session | +| target | Long | false | 987654321 | 需要撤回的消息的messageId | + +#### 响应: 返回统一状态码 + +```json5 +{ + "code": 0, + "msg": "success" +} +``` + + + ### 获取Bot收到的消息和事件 ``` diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt index 83250127a..f39a3e8e8 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/queue/MessageQueue.kt @@ -13,7 +13,6 @@ import net.mamoe.mirai.api.http.data.common.EventDTO import net.mamoe.mirai.api.http.data.common.IgnoreEventDTO import net.mamoe.mirai.api.http.data.common.toDTO import net.mamoe.mirai.event.events.BotEvent -import net.mamoe.mirai.message.GroupMessage import net.mamoe.mirai.message.MessagePacket import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.utils.firstKey @@ -21,8 +20,8 @@ import java.util.concurrent.ConcurrentLinkedDeque class MessageQueue : ConcurrentLinkedDeque<BotEvent>() { - val quoteCacheSize = 4096 - val quoteCache = LinkedHashMap<Long, MessagePacket<*, *>>() + val cacheSize = 4096 + val cache = LinkedHashMap<Long, MessagePacket<*, *>>() suspend fun fetch(size: Int): List<EventDTO> { var count = size @@ -45,13 +44,13 @@ class MessageQueue : ConcurrentLinkedDeque<BotEvent>() { return ret } - fun cacheQuote(messageId: Long) = - quoteCache[messageId] ?: throw NoSuchElementException() + fun cache(messageId: Long) = + cache[messageId] ?: throw NoSuchElementException() - private fun addQuoteCache(msg: MessagePacket<*, *>) { - quoteCache[msg.message[MessageSource].id] = msg - if (quoteCache.size > quoteCacheSize) { - quoteCache.remove(quoteCache.firstKey()) + fun addQuoteCache(msg: MessagePacket<*, *>) { + cache[msg.message[MessageSource].id] = msg + if (cache.size > cacheSize) { + cache.remove(cache.firstKey()) } } } \ No newline at end of file diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt index 7e59e6e43..46a555a99 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/MessageRouteModule.kt @@ -29,6 +29,8 @@ import net.mamoe.mirai.api.http.data.common.VerifyDTO import net.mamoe.mirai.api.http.data.common.toMessageChain import net.mamoe.mirai.api.http.util.toJson import net.mamoe.mirai.contact.Contact +import net.mamoe.mirai.message.FriendMessage +import net.mamoe.mirai.message.GroupMessage import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.uploadImage @@ -59,26 +61,30 @@ fun Application.messageModule() { miraiVerify<SendDTO>("/sendFriendMessage") { val quote = it.quote?.let { q -> - it.session.messageQueue.cacheQuote(q).run { + it.session.messageQueue.cache(q).run { this[MessageSource].quote(sender) }} it.session.bot.getFriend(it.target).apply { val receipt = sendMessage(quote, it.messageChain.toMessageChain(this), this) receipt.source.ensureSequenceIdAvailable() + + it.session.messageQueue.addQuoteCache(FriendMessage(bot.selfQQ, receipt.source.toChain())) call.respondDTO(SendRetDTO(messageId = receipt.source.id)) } } miraiVerify<SendDTO>("/sendGroupMessage") { val quote = it.quote?.let { q -> - it.session.messageQueue.cacheQuote(q).run { + it.session.messageQueue.cache(q).run { this[MessageSource].quote(sender) }} it.session.bot.getGroup(it.target).apply { val receipt = sendMessage(quote, it.messageChain.toMessageChain(this), this) receipt.source.ensureSequenceIdAvailable() + + it.session.messageQueue.addQuoteCache(GroupMessage("", botPermission, botAsMember, receipt.source.toChain())) call.respondDTO(SendRetDTO(messageId = receipt.source.id)) } } @@ -123,8 +129,10 @@ fun Application.messageModule() { } miraiVerify<RecallDTO>("recall") { - // TODO - call.respond(HttpStatusCode.NotFound, "未完成") + it.session.messageQueue.cache(it.target).apply { + it.session.bot.recall(get(MessageSource)) + } + call.respondStateCode(StateCode.Success) } } } @@ -156,6 +164,5 @@ private class SendRetDTO( @Serializable private data class RecallDTO( override val sessionKey: String, - val target: Long, - val sender: Long + val target: Long ) : VerifyDTO() From 6cbc69cd685a557e4325ff1dfd04f080f1965428 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 10:26:27 +0800 Subject: [PATCH 08/17] Fix sequenceId for FriendMessage --- .../net/mamoe/mirai/qqandroid/ContactImpl.kt | 2 +- .../net/mamoe/mirai/qqandroid/QQAndroidBot.kt | 8 +++- .../protocol/packet/chat/PbMessageSvc.kt | 29 +++++++++++++ .../packet/chat/receive/MessageSvc.kt | 43 ++++++++++++++----- .../net.mamoe.mirai/message/MessageReceipt.kt | 10 ++--- 5 files changed, 72 insertions(+), 20 deletions(-) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt index 614d5873c..a7c26c452 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt @@ -542,7 +542,7 @@ internal class GroupImpl( if (event.isCancelled) { throw EventCancelledException("cancelled by FriendMessageSendEvent") } - lateinit var source: MessageSvc.PbSendMsg.MessageSourceFromSend + lateinit var source: MessageSvc.PbSendMsg.MessageSourceFromSendGroup bot.network.run { val response: MessageSvc.PbSendMsg.Response = MessageSvc.PbSendMsg.ToGroup( bot.client, diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt index 5b400fca4..c6e697b35 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -129,9 +129,15 @@ internal abstract class QQAndroidBotBase constructor( source.ensureSequenceIdAvailable() network.run { - val response: PbMessageSvc.PbMsgWithDraw.Response = + val response: PbMessageSvc.PbMsgWithDraw.Response = if (source.groupId == 0L) { + PbMessageSvc.PbMsgWithDraw.Friend(bot.client, source.senderId, source.sequenceId, source.messageRandom, source.time) + .sendAndExpect() + } else { + PbMessageSvc.PbMsgWithDraw.Group(bot.client, source.groupId, source.sequenceId, source.messageRandom) .sendAndExpect() + } + check(response is PbMessageSvc.PbMsgWithDraw.Response.Success) { "Failed to recall message #${source.sequenceId}: $response" } } } diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt index eab98c991..88dd705db 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt @@ -71,6 +71,35 @@ internal class PbMessageSvc { ) } + fun Friend( + client: QQAndroidClient, + toUin: Long, + messageSequenceId: Int, // 56639 + messageRandom: Int, // 921878719 + time: Long, + messageType: Int = 0 + ): OutgoingPacket = buildOutgoingUniPacket(client) { + writeProtoBuf( + MsgSvc.PbMsgWithDrawReq.serializer(), + MsgSvc.PbMsgWithDrawReq( + c2cWithDraw = listOf( + MsgSvc.PbC2CMsgWithDrawReq( + subCmd = 1, + msgInfo = listOf( + MsgSvc.PbC2CMsgWithDrawReq.MsgInfo( + fromUin = client.bot.uin, + toUin = toUin, + msgSeq = messageSequenceId, + msgUid = messageRandom.toLong() and 0xffffffff, + msgTime = time and 0xffffffff + ) + ) + ) + ) + ) + ) + } + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response { val resp = readProtoBuf(MsgSvc.PbMsgWithDrawResp.serializer()) resp.groupWithDraw?.firstOrNull()?.let { diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt index 7207413db..41aa13650 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt @@ -269,7 +269,28 @@ internal class MessageSvc { } } - internal class MessageSourceFromSend( + internal class MessageSourceFromSendFriend( + val messageRandom: Int, + override val time: Long, + override val senderId: Long, + override val groupId: Long, + val sequenceId: Int + ) : MessageSource { + @UseExperimental(ExperimentalCoroutinesApi::class) + override val id: Long + get() = sequenceId.toLong().shl(32) or + messageRandom.toLong().and(0xFFFFFFFF) + + override suspend fun ensureSequenceIdAvailable() { + // nothing to do + } + + override fun toString(): String { + return "" + } + } + + internal class MessageSourceFromSendGroup( val messageRandom: Int, override val time: Long, override val senderId: Long, @@ -286,7 +307,7 @@ internal class MessageSvc { @UseExperimental(MiraiExperimentalAPI::class) fun startWaitingSequenceId(contact: Contact) { sequenceIdDeferred = contact.subscribingGetAsync<OnlinePush.PbPushGroupMsg.SendGroupMessageReceipt, Int>(timeoutMillis = 3000) { - if (it.messageRandom == this@MessageSourceFromSend.messageRandom) { + if (it.messageRandom == this@MessageSourceFromSendGroup.messageRandom) { it.sequenceId } else null } @@ -305,14 +326,14 @@ internal class MessageSvc { client: QQAndroidClient, toUin: Long, message: MessageChain, - crossinline sourceCallback: (MessageSource) -> Unit + crossinline sourceCallback: (MessageSourceFromSendFriend) -> Unit ): OutgoingPacket { - val source = MessageSourceFromSend( + val source = MessageSourceFromSendFriend( messageRandom = Random.nextInt().absoluteValue, senderId = client.uin, time = currentTimeSeconds + client.timeDifference, - groupId = 0// - // sourceMessage = message + groupId = 0, + sequenceId = client.atomicNextMessageSequenceId() ) sourceCallback(source) return ToFriend(client, toUin, message, source) @@ -326,7 +347,7 @@ internal class MessageSvc { client: QQAndroidClient, toUin: Long, message: MessageChain, - source: MessageSourceFromSend + source: MessageSourceFromSendFriend ): OutgoingPacket = buildOutgoingUniPacket(client) { ///writeFully("0A 08 0A 06 08 89 FC A6 8C 0B 12 06 08 01 10 00 18 00 1A 1F 0A 1D 12 08 0A 06 0A 04 F0 9F 92 A9 12 11 AA 02 0E 88 01 00 9A 01 08 78 00 F8 01 00 C8 02 00 20 9B 7A 28 F4 CA 9B B8 03 32 34 08 92 C2 C4 F1 05 10 92 C2 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 89 84 F9 A2 06 48 DE 8C EA E5 0E 58 D9 BD BB A0 09 60 1D 68 92 C2 C4 F1 05 70 00 40 01".hexToBytes()) @@ -340,7 +361,7 @@ internal class MessageSvc { elems = message.toRichTextElems(false) ) ), - msgSeq = client.atomicNextMessageSequenceId(), + msgSeq = source.sequenceId, msgRand = source.messageRandom, syncCookie = SyncCookie(time = source.time).toByteArray(SyncCookie.serializer()) // msgVia = 1 @@ -353,10 +374,10 @@ internal class MessageSvc { client: QQAndroidClient, groupCode: Long, message: MessageChain, - sourceCallback: (MessageSourceFromSend) -> Unit + sourceCallback: (MessageSourceFromSendGroup) -> Unit ): OutgoingPacket { - val source = MessageSourceFromSend( + val source = MessageSourceFromSendGroup( messageRandom = Random.nextInt().absoluteValue, senderId = client.uin, time = currentTimeSeconds + client.timeDifference, @@ -375,7 +396,7 @@ internal class MessageSvc { client: QQAndroidClient, groupCode: Long, message: MessageChain, - source: MessageSourceFromSend + source: MessageSourceFromSendGroup ): OutgoingPacket = buildOutgoingUniPacket(client) { ///writeFully("0A 08 0A 06 08 89 FC A6 8C 0B 12 06 08 01 10 00 18 00 1A 1F 0A 1D 12 08 0A 06 0A 04 F0 9F 92 A9 12 11 AA 02 0E 88 01 00 9A 01 08 78 00 F8 01 00 C8 02 00 20 9B 7A 28 F4 CA 9B B8 03 32 34 08 92 C2 C4 F1 05 10 92 C2 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 89 84 F9 A2 06 48 DE 8C EA E5 0E 58 D9 BD BB A0 09 60 1D 68 92 C2 C4 F1 05 70 00 40 01".hexToBytes()) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt index 7d5c37657..37e6148db 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt @@ -78,13 +78,9 @@ open class MessageReceipt<C : Contact>( fun recallIn(millis: Long): Job { @Suppress("BooleanLiteralArgument") if (_isRecalled.compareAndSet(false, true)) { - when (val contact = target) { - is Group -> { - return contact.bot.recallIn(source, millis) - } - is QQ -> { - TODO() - } + return when (val contact = target) { + is QQ, + is Group -> contact.bot.recallIn(source, millis) else -> error("Unknown contact type") } } else error("message is already or planned to be recalled") From a6f359ec962fcf8d18fd5ba2d0f2dd404586b78f Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 10:33:09 +0800 Subject: [PATCH 09/17] Add consoleversion --- gradle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle.properties b/gradle.properties index 370fdbd0c..ab40596ca 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,7 @@ kotlin.code.style=official # config mirai_version=0.21.0 mirai_japt_version=1.1.0 +mirai_console_version=0.1.0 kotlin.incremental.multiplatform=true kotlin.parallel.tasks.in.project=true # kotlin From 693b8ee1de5acdd194eb0fa094edd8e35e613fac Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 11:13:22 +0800 Subject: [PATCH 10/17] Remove mirai-api-http dependency --- mirai-console/build.gradle.kts | 2 +- .../net/mamoe/mirai/console/MiraiConsole.kt | 26 ++++++++----------- .../kotlin/net/mamoe/mirai/console/Setu.kt | 2 -- 3 files changed, 12 insertions(+), 18 deletions(-) delete mode 100644 mirai-console/src/main/kotlin/net/mamoe/mirai/console/Setu.kt diff --git a/mirai-console/build.gradle.kts b/mirai-console/build.gradle.kts index 6937c46ee..ce59efa26 100644 --- a/mirai-console/build.gradle.kts +++ b/mirai-console/build.gradle.kts @@ -32,7 +32,7 @@ tasks.withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>() { dependencies { api(project(":mirai-core")) api(project(":mirai-core-qqandroid")) - api(project(":mirai-api-http")) + // api(project(":mirai-api-http")) runtimeOnly(files("../mirai-core-qqandroid/build/classes/kotlin/jvm/main")) runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) api(kotlin("serialization")) diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt index 19dc0335b..5ee1b1b5b 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt @@ -12,32 +12,26 @@ package net.mamoe.mirai.console import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import net.mamoe.mirai.Bot -import net.mamoe.mirai.api.http.MiraiHttpAPIServer -import net.mamoe.mirai.api.http.generateSessionKey import net.mamoe.mirai.console.MiraiConsole.CommandProcessor.processNextCommandLine -import net.mamoe.mirai.console.command.* +import net.mamoe.mirai.console.command.CommandManager +import net.mamoe.mirai.console.command.CommandSender +import net.mamoe.mirai.console.command.ConsoleCommandSender +import net.mamoe.mirai.console.command.DefaultCommands import net.mamoe.mirai.console.plugins.PluginManager import net.mamoe.mirai.console.plugins.loadAsConfig import net.mamoe.mirai.console.plugins.withDefaultWrite -import net.mamoe.mirai.console.plugins.withDefaultWriteSave import net.mamoe.mirai.console.utils.MiraiConsoleUI -import net.mamoe.mirai.console.utils.checkManager -import net.mamoe.mirai.contact.sendMessage -import net.mamoe.mirai.event.subscribeMessages -import net.mamoe.mirai.utils.SimpleLogger import net.mamoe.mirai.utils.cryptor.ECDH import java.io.File -import java.security.Security -import java.util.* object MiraiConsole { /** * 发布的版本号 统一修改位置 */ - val version = "v0.01" - var coreVersion = "v0.18.0" - val build = "Alpha" + const val version = "0.1.0" + const val coreVersion = "v0.18.0" + const val build = "Alpha" /** @@ -194,13 +188,15 @@ object MiraiProperties { var HTTP_API_ENABLE: Boolean by config.withDefaultWrite { true } var HTTP_API_PORT: Int by config.withDefaultWrite { 8080 } + /* var HTTP_API_AUTH_KEY: String by config.withDefaultWriteSave { "InitKey" + generateSessionKey() - } + }*/ } object HTTPAPIAdaptar { operator fun invoke() { + /* if (MiraiProperties.HTTP_API_ENABLE) { if (MiraiProperties.HTTP_API_AUTH_KEY.startsWith("InitKey")) { MiraiConsole.logger("请尽快更改初始生成的HTTP API AUTHKEY") @@ -214,7 +210,7 @@ object HTTPAPIAdaptar { MiraiProperties.HTTP_API_AUTH_KEY ) MiraiConsole.logger("HTTPAPI启动完成; 端口= " + MiraiProperties.HTTP_API_PORT) - } + }*/ } } diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/Setu.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/Setu.kt deleted file mode 100644 index 03dac5a40..000000000 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/Setu.kt +++ /dev/null @@ -1,2 +0,0 @@ -package net.mamoe.mirai.console - From df2a4a1b919562048dfc5ffa4dfbd1e267be37c5 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 11:13:50 +0800 Subject: [PATCH 11/17] mirai-console 0.1.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index ab40596ca..9847d50b8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ kotlin.code.style=official # config mirai_version=0.21.0 mirai_japt_version=1.1.0 -mirai_console_version=0.1.0 +mirai_console_version=0.1.1 kotlin.incremental.multiplatform=true kotlin.parallel.tasks.in.project=true # kotlin From 227a0a5e1ecf39343911d7b6a3a6159241fd026d Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 11:34:32 +0800 Subject: [PATCH 12/17] Support for kotlin object `PluginBase` --- .../main/kotlin/net/mamoe/mirai/console/plugins/PluginBase.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginBase.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginBase.kt index 4d1bd6f07..f43aa1685 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginBase.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/PluginBase.kt @@ -9,9 +9,9 @@ package net.mamoe.mirai.console.plugins -import net.mamoe.mirai.console.command.Command import kotlinx.coroutines.* import net.mamoe.mirai.console.MiraiConsole +import net.mamoe.mirai.console.command.Command import net.mamoe.mirai.utils.DefaultLogger import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.SimpleLogger @@ -294,7 +294,7 @@ object PluginManager { } return try { val subClass = pluginClass.asSubclass(PluginBase::class.java) - val plugin: PluginBase = subClass.getDeclaredConstructor().newInstance() + val plugin: PluginBase = subClass.kotlin.objectInstance ?: subClass.getDeclaredConstructor().newInstance() description.loaded = true logger.info("successfully loaded plugin " + description.name + " version " + description.version + " by " + description.author) logger.info(description.info) From 583c99392dac3ffe99938d00f68940cca55680dd Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 11:54:53 +0800 Subject: [PATCH 13/17] Update docs and references --- .../kotlin/net.mamoe.mirai/message/MessageReceipt.kt | 2 +- .../kotlin/net.mamoe.mirai/message/data/MessageSource.kt | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt index a854b8ded..a2a85d368 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt @@ -48,7 +48,7 @@ open class MessageReceipt<C : Contact>( /** * 撤回这条消息. [recall] 或 [recallIn] 只能被调用一次. * - * @see Group.recall + * @see Bot.recall * @throws IllegalStateException 当此消息已经被撤回或正计划撤回时 */ @UseExperimental(MiraiExperimentalAPI::class) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt index 992129835..0d5c0c187 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt @@ -12,15 +12,18 @@ package net.mamoe.mirai.message.data +import net.mamoe.mirai.Bot import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName /** - * 消息源, 用于被引用. 它将由协议模块实现. - * 消息源只用于 [QuoteReply] + * 消息源, 它存在于 [MessageChain] 中, 用于表示这个消息的来源. + * + * 消息源只用于 [引用回复][QuoteReply] 或 [撤回][Bot.recall]. * * `mirai-core-qqandroid`: `net.mamoe.mirai.qqandroid.message.MessageSourceFromMsg` * + * @see Bot.recall 撤回一条消息 * @see MessageSource.quote 引用这条消息, 创建 [MessageChain] */ interface MessageSource : Message, MessageMetadata { From 0a55733cb803393fb3f4bceca634ba54f3c064cf Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 11:56:07 +0800 Subject: [PATCH 14/17] Rename `instanceWhose` to `getInstance` --- .../kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt | 2 +- mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt index 45adcf2b3..aa229181d 100644 --- a/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt +++ b/mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/route/AuthRouteModule.kt @@ -63,7 +63,7 @@ private data class AuthRetDTO(val code: Int, val session: String) : DTO private data class BindDTO(override val sessionKey: String, val qq: Long) : VerifyDTO() private fun getBotOrThrow(qq: Long) = try { - Bot.instanceWhose(qq) + Bot.getInstance(qq) } catch (e: NoSuchElementException) { throw NoSuchBotException } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt index 248ac05f1..5a001c115 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -59,7 +59,7 @@ abstract class Bot : CoroutineScope { * 获取一个 [Bot] 实例, 找不到则 [NoSuchElementException] */ @JvmStatic - fun instanceWhose(qq: Long): Bot = BotImpl.instanceWhose(qq = qq) + fun getInstance(qq: Long): Bot = BotImpl.instanceWhose(qq = qq) } /** From 559e24b4ce4b18b50edbf1f52bf9e12ee3bc12e0 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 12:06:40 +0800 Subject: [PATCH 15/17] Rename `instanceWhose` to `getInstance` --- mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt | 2 +- mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt index 5a001c115..35c454f92 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -59,7 +59,7 @@ abstract class Bot : CoroutineScope { * 获取一个 [Bot] 实例, 找不到则 [NoSuchElementException] */ @JvmStatic - fun getInstance(qq: Long): Bot = BotImpl.instanceWhose(qq = qq) + fun getInstance(qq: Long): Bot = BotImpl.getInstance(qq = qq) } /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt index 7ee7f84b3..79ef2ae49 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt @@ -60,7 +60,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor( it.get()?.let(block) } - fun instanceWhose(qq: Long): Bot { + fun getInstance(qq: Long): Bot { instances.forEach { it.get()?.let { bot -> if (bot.uin == qq) { From b0bd3d2202e44d9d31a040c4d86fc74743eda953 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 12:13:40 +0800 Subject: [PATCH 16/17] mirai-core 0.22.0 --- CHANGELOG.md | 9 +++++++++ gradle.properties | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93eab3aa7..00f4cc774 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ 开发版本. 频繁更新, 不保证高稳定性 +## `0.22.0` 2020/2/24 +### mirai-core +- 重构 `MessageChain`, 引入 `CombinedMessage`. (兼容大部分原 API) +- 新增 `MessageChainBuilder`, `buildMessageChain` +- `ExternalImage` 现在接收多种输入参数 + +### mirai-core-qqandroid +- 修复访问好友消息回执 `.sequenceId` 时抛出异常的问题 + ## `0.21.0` 2020/2/23 - 支持好友消息的引用回复 - 更加结构化的 `QuoteReply` 架构, 支持引用任意群/好友消息回复给任意群/好友. diff --git a/gradle.properties b/gradle.properties index 9847d50b8..55dba9b74 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # style guide kotlin.code.style=official # config -mirai_version=0.21.0 +mirai_version=0.22.0 mirai_japt_version=1.1.0 mirai_console_version=0.1.1 kotlin.incremental.multiplatform=true From 8b9cef05d762eedd2dc6d3752d67c9bcc6416f0f Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Mon, 24 Feb 2020 17:09:08 +0800 Subject: [PATCH 17/17] Specify `OverFileSizeMaxException` throws --- .../commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt | 1 + .../src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt index a7c26c452..fec23b029 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt @@ -579,6 +579,7 @@ internal class GroupImpl( when (response) { is ImgStore.GroupPicUp.Response.Failed -> { ImageUploadEvent.Failed(this@GroupImpl, image, response.resultCode, response.message).broadcast() + if (response.message == "over file size max") throw OverFileSizeMaxException() error("upload group image failed with reason ${response.message}") } is ImgStore.GroupPicUp.Response.FileExists -> { diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt index 678af1d00..ca1f94607 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt @@ -25,6 +25,7 @@ import net.mamoe.mirai.recall import net.mamoe.mirai.recallIn import net.mamoe.mirai.utils.ExternalImage import net.mamoe.mirai.utils.MiraiExperimentalAPI +import net.mamoe.mirai.utils.OverFileSizeMaxException import net.mamoe.mirai.utils.WeakRefProperty import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext @@ -74,6 +75,7 @@ interface Contact : CoroutineScope { * @see ImageUploadEvent 图片发送完成事件 * * @throws EventCancelledException 当发送消息事件被取消 + * @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时. (最大大小约为 20 MB) */ suspend fun uploadImage(image: ExternalImage): Image