Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
Mirai
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
Mirai
Commits
66f46202
Commit
66f46202
authored
Apr 22, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add `MessageSource.internalId`, support `OfflineMessageSource` building
parent
6311c39c
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
310 additions
and
78 deletions
+310
-78
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt
...n/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt
+47
-6
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/incomingSourceImpl.kt
...n/net/mamoe/mirai/qqandroid/message/incomingSourceImpl.kt
+6
-6
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/offlineSourceImpl.kt
...in/net/mamoe/mirai/qqandroid/message/offlineSourceImpl.kt
+2
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/outgoingSourceImpl.kt
...n/net/mamoe/mirai/qqandroid/message/outgoingSourceImpl.kt
+5
-5
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt
...ndroid/network/protocol/packet/chat/receive/MessageSvc.kt
+6
-6
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
+19
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/CustomMessage.kt
...Main/kotlin/net.mamoe.mirai/message/data/CustomMessage.kt
+8
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt
...commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt
+1
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
...Main/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
+5
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/OfflineMessageSource.kt
...tlin/net.mamoe.mirai/message/data/OfflineMessageSource.kt
+211
-47
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.common.kt
View file @
66f46202
...
...
@@ -35,6 +35,7 @@ import net.mamoe.mirai.event.broadcast
import
net.mamoe.mirai.event.events.MemberJoinRequestEvent
import
net.mamoe.mirai.event.events.MessageRecallEvent
import
net.mamoe.mirai.event.events.NewFriendRequestEvent
import
net.mamoe.mirai.event.internal.MiraiAtomicBoolean
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.network.LoginFailedException
...
...
@@ -45,6 +46,7 @@ import net.mamoe.mirai.qqandroid.message.*
import
net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.highway.HighwayHelper
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.LongMsg
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.*
import
net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
...
...
@@ -321,7 +323,7 @@ internal abstract class QQAndroidBotBase constructor(
bot
.
asQQAndroidBot
().
client
,
group
.
id
,
source
.
sequenceId
,
source
.
random
source
.
internalId
).
sendAndExpect
<
PbMessageSvc
.
PbMsgWithDraw
.
Response
>()
}
}
...
...
@@ -335,7 +337,7 @@ internal abstract class QQAndroidBotBase constructor(
bot
.
client
,
source
.
targetId
,
source
.
sequenceId
,
source
.
random
,
source
.
internalId
,
source
.
time
).
sendAndExpect
<
PbMessageSvc
.
PbMsgWithDraw
.
Response
>()
}
...
...
@@ -351,7 +353,7 @@ internal abstract class QQAndroidBotBase constructor(
source
.
target
.
group
.
id
,
source
.
targetId
,
source
.
sequenceId
,
source
.
random
,
source
.
internalId
,
source
.
time
).
sendAndExpect
<
PbMessageSvc
.
PbMsgWithDraw
.
Response
>()
}
...
...
@@ -365,7 +367,7 @@ internal abstract class QQAndroidBotBase constructor(
bot
.
client
,
source
.
targetId
,
source
.
sequenceId
,
source
.
random
,
source
.
internalId
,
source
.
time
).
sendAndExpect
<
PbMessageSvc
.
PbMsgWithDraw
.
Response
>()
}
...
...
@@ -378,7 +380,7 @@ internal abstract class QQAndroidBotBase constructor(
source
.
targetId
,
// groupUin
source
.
targetId
,
// memberUin
source
.
sequenceId
,
source
.
random
,
source
.
internalId
,
source
.
time
).
sendAndExpect
<
PbMessageSvc
.
PbMsgWithDraw
.
Response
>()
}
...
...
@@ -387,7 +389,7 @@ internal abstract class QQAndroidBotBase constructor(
bot
.
client
,
source
.
targetId
,
source
.
sequenceId
,
source
.
random
source
.
internalId
).
sendAndExpect
<
PbMessageSvc
.
PbMsgWithDraw
.
Response
>()
}
}
...
...
@@ -658,6 +660,43 @@ internal abstract class QQAndroidBotBase constructor(
else
->
error
(
"unsupported image class: ${image::class.simpleName}"
)
}
override
fun
constructMessageSource
(
kind
:
OfflineMessageSource
.
Kind
,
fromUin
:
Long
,
targetUin
:
Long
,
id
:
Int
,
time
:
Int
,
internalId
:
Int
,
originalMessage
:
MessageChain
):
OfflineMessageSource
{
return
object
:
OfflineMessageSource
(),
MessageSourceInternal
{
override
val
kind
:
Kind
get
()
=
kind
override
val
id
:
Int
get
()
=
id
override
val
bot
:
Bot
get
()
=
this
@QQAndroidBotBase
override
val
time
:
Int
get
()
=
time
override
val
fromId
:
Long
get
()
=
fromUin
override
val
targetId
:
Long
get
()
=
targetUin
override
val
originalMessage
:
MessageChain
get
()
=
originalMessage
override
val
sequenceId
:
Int
=
id
override
val
internalId
:
Int
=
internalId
override
var
isRecalledOrPlanned
:
MiraiAtomicBoolean
=
MiraiAtomicBoolean
(
false
)
override
fun
toJceData
():
ImMsgBody
.
SourceMsg
{
return
ImMsgBody
.
SourceMsg
(
origSeqs
=
listOf
(
sequenceId
),
senderUin
=
fromUin
,
toUin
=
0
,
flag
=
1
,
elems
=
originalMessage
.
toRichTextElems
(
forGroup
=
kind
==
Kind
.
GROUP
,
withGeneralFlags
=
false
),
type
=
0
,
time
=
time
,
pbReserve
=
EMPTY_BYTE_ARRAY
,
srcMsg
=
EMPTY_BYTE_ARRAY
)
}
}
}
@Suppress
(
"DeprecatedCallableAddReplaceWith"
)
@PlannedRemoval
(
"1.0.0"
)
@Deprecated
(
"use your own Http clients, this is going to be removed in 1.0.0"
,
level
=
DeprecationLevel
.
WARNING
)
...
...
@@ -673,6 +712,8 @@ internal abstract class QQAndroidBotBase constructor(
.
fold
(
5381
)
{
acc
:
Int
,
b
:
Byte
->
acc
+
acc
.
shl
(
5
)
+
b
.
toInt
()
}
}
internal
val
EMPTY_BYTE_ARRAY
=
ByteArray
(
0
)
@Suppress
(
"DEPRECATION"
)
@OptIn
(
MiraiInternalAPI
::
class
)
internal
expect
fun
io
.
ktor
.
utils
.
io
.
ByteReadChannel
.
toKotlinByteReadChannel
():
ByteReadChannel
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/incomingSourceImpl.kt
View file @
66f46202
...
...
@@ -27,7 +27,7 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
internal
interface
MessageSourceInternal
{
val
sequenceId
:
Int
val
random
:
Int
val
internalId
:
Int
// randomId
@Deprecated
(
"don't use this internally. Use sequenceId or random instead."
,
level
=
DeprecationLevel
.
ERROR
)
val
id
:
Int
...
...
@@ -54,12 +54,12 @@ internal class MessageSourceFromFriendImpl(
override
val
sequenceId
:
Int
get
()
=
msg
.
msgHead
.
msgSeq
override
var
isRecalledOrPlanned
:
MiraiAtomicBoolean
=
MiraiAtomicBoolean
(
false
)
override
val
id
:
Int
get
()
=
sequenceId
// msg.msgBody.richText.attr!!.random
override
val
random
:
Int
get
()
=
msg
.
msgBody
.
richText
.
attr
!!
.
random
override
val
internalId
:
Int
get
()
=
msg
.
msgBody
.
richText
.
attr
!!
.
random
override
val
time
:
Int
get
()
=
msg
.
msgHead
.
msgTime
override
val
originalMessage
:
MessageChain
by
lazy
{
msg
.
toMessageChain
(
bot
,
0
,
false
)
}
override
val
sender
:
Friend
get
()
=
bot
.
getFriend
(
msg
.
msgHead
.
fromUin
)
private
val
jceData
by
lazy
{
msg
.
toJceDataFriendOrTemp
(
random
)
}
private
val
jceData
by
lazy
{
msg
.
toJceDataFriendOrTemp
(
internalId
)
}
override
fun
toJceData
():
ImMsgBody
.
SourceMsg
=
jceData
}
...
...
@@ -105,14 +105,14 @@ internal class MessageSourceFromTempImpl(
private
val
msg
:
MsgComm
.
Msg
)
:
OnlineMessageSource
.
Incoming
.
FromTemp
(),
MessageSourceInternal
{
override
val
sequenceId
:
Int
get
()
=
msg
.
msgHead
.
msgSeq
override
val
random
:
Int
get
()
=
msg
.
msgBody
.
richText
.
attr
!!
.
random
override
val
internalId
:
Int
get
()
=
msg
.
msgBody
.
richText
.
attr
!!
.
random
override
var
isRecalledOrPlanned
:
MiraiAtomicBoolean
=
MiraiAtomicBoolean
(
false
)
override
val
id
:
Int
get
()
=
sequenceId
//
override
val
time
:
Int
get
()
=
msg
.
msgHead
.
msgTime
override
val
originalMessage
:
MessageChain
by
lazy
{
msg
.
toMessageChain
(
bot
,
0
,
false
)
}
override
val
sender
:
Member
get
()
=
with
(
msg
.
msgHead
)
{
bot
.
getGroup
(
c2cTmpMsgHead
!!
.
groupUin
)[
fromUin
]
}
private
val
jceData
by
lazy
{
msg
.
toJceDataFriendOrTemp
(
random
)
}
private
val
jceData
by
lazy
{
msg
.
toJceDataFriendOrTemp
(
internalId
)
}
override
fun
toJceData
():
ImMsgBody
.
SourceMsg
=
jceData
}
...
...
@@ -122,7 +122,7 @@ internal data class MessageSourceFromGroupImpl(
)
:
OnlineMessageSource
.
Incoming
.
FromGroup
(),
MessageSourceInternal
{
override
var
isRecalledOrPlanned
:
MiraiAtomicBoolean
=
MiraiAtomicBoolean
(
false
)
override
val
sequenceId
:
Int
get
()
=
msg
.
msgHead
.
msgSeq
override
val
random
:
Int
get
()
=
msg
.
msgBody
.
richText
.
attr
!!
.
random
override
val
internalId
:
Int
get
()
=
msg
.
msgBody
.
richText
.
attr
!!
.
random
override
val
id
:
Int
get
()
=
sequenceId
override
val
time
:
Int
get
()
=
msg
.
msgHead
.
msgTime
override
val
originalMessage
:
MessageChain
by
lazy
{
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/offlineSourceImpl.kt
View file @
66f46202
...
...
@@ -28,7 +28,7 @@ internal class OfflineMessageSourceImplByMsg(
)
:
OfflineMessageSource
(),
MessageSourceInternal
{
override
val
kind
:
Kind
=
if
(
delegate
.
msgHead
.
groupInfo
!=
null
)
Kind
.
GROUP
else
Kind
.
FRIEND
override
val
id
:
Int
get
()
=
sequenceId
override
val
random
:
Int
override
val
internalId
:
Int
get
()
=
delegate
.
msgHead
.
msgUid
.
toInt
()
override
val
time
:
Int
get
()
=
delegate
.
msgHead
.
msgTime
...
...
@@ -74,7 +74,7 @@ internal class OfflineMessageSourceImplBySourceMsg(
override
var
isRecalledOrPlanned
:
MiraiAtomicBoolean
=
MiraiAtomicBoolean
(
false
)
override
val
sequenceId
:
Int
get
()
=
delegate
.
origSeqs
?.
first
()
?:
error
(
"cannot find sequenceId"
)
override
val
random
:
Int
override
val
internalId
:
Int
get
()
=
delegate
.
pbReserve
.
loadAs
(
SourceMsg
.
ResvAttr
.
serializer
()).
origUids
?.
toInt
()
?:
0
override
val
time
:
Int
get
()
=
delegate
.
time
override
val
originalMessage
:
MessageChain
by
lazy
{
delegate
.
toMessageChain
(
bot
,
groupIdOrZero
)
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/outgoingSourceImpl.kt
View file @
66f46202
...
...
@@ -33,7 +33,7 @@ private fun <T> T.toJceDataImpl(): ImMsgBody.SourceMsg
where
T
:
MessageSourceInternal
,
T
:
MessageSource
{
val
elements
=
originalMessage
.
toRichTextElems
(
forGroup
=
false
,
withGeneralFlags
=
true
)
val
messageUid
:
Long
=
sequenceId
.
toLong
().
shl
(
32
)
or
random
.
toLong
().
and
(
0
xffFFffFF
)
val
messageUid
:
Long
=
sequenceId
.
toLong
().
shl
(
32
)
or
internalId
.
toLong
().
and
(
0
xffFFffFF
)
return
ImMsgBody
.
SourceMsg
(
origSeqs
=
listOf
(
sequenceId
),
senderUin
=
fromId
,
...
...
@@ -70,7 +70,7 @@ private fun <T> T.toJceDataImpl(): ImMsgBody.SourceMsg
internal
class
MessageSourceToFriendImpl
(
override
val
sequenceId
:
Int
,
override
val
random
:
Int
,
override
val
internalId
:
Int
,
override
val
time
:
Int
,
override
val
originalMessage
:
MessageChain
,
override
val
sender
:
Bot
,
...
...
@@ -87,7 +87,7 @@ internal class MessageSourceToFriendImpl(
internal
class
MessageSourceToTempImpl
(
override
val
sequenceId
:
Int
,
override
val
random
:
Int
,
override
val
internalId
:
Int
,
override
val
time
:
Int
,
override
val
originalMessage
:
MessageChain
,
override
val
sender
:
Bot
,
...
...
@@ -104,7 +104,7 @@ internal class MessageSourceToTempImpl(
internal
class
MessageSourceToGroupImpl
(
coroutineScope
:
CoroutineScope
,
override
val
random
:
Int
,
override
val
internalId
:
Int
,
override
val
time
:
Int
,
override
val
originalMessage
:
MessageChain
,
override
val
sender
:
Bot
,
...
...
@@ -120,7 +120,7 @@ internal class MessageSourceToGroupImpl(
coroutineScope
.
asyncFromEventOrNull
<
OnlinePush
.
PbPushGroupMsg
.
SendGroupMessageReceipt
,
Int
>(
timeoutMillis
=
3000
)
{
if
(
it
.
messageRandom
==
this
@MessageSourceToGroupImpl
.
random
)
{
if
(
it
.
messageRandom
==
this
@MessageSourceToGroupImpl
.
internalId
)
{
it
.
sequenceId
}
else
null
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt
View file @
66f46202
...
...
@@ -369,7 +369,7 @@ internal class MessageSvc {
):
OutgoingPacket
{
val
rand
=
Random
.
nextInt
().
absoluteValue
val
source
=
MessageSourceToFriendImpl
(
random
=
rand
,
internalId
=
rand
,
sender
=
client
.
bot
,
target
=
qq
,
time
=
currentTimeSeconds
.
toInt
(),
...
...
@@ -403,7 +403,7 @@ internal class MessageSvc {
)
),
msgSeq
=
source
.
sequenceId
,
msgRand
=
source
.
random
,
msgRand
=
source
.
internalId
,
syncCookie
=
SyncCookie
(
time
=
source
.
time
.
toLong
()).
toByteArray
(
SyncCookie
.
serializer
())
// msgVia = 1
)
...
...
@@ -418,7 +418,7 @@ internal class MessageSvc {
sourceCallback
:
(
MessageSourceToTempImpl
)
->
Unit
):
OutgoingPacket
{
val
source
=
MessageSourceToTempImpl
(
random
=
Random
.
nextInt
().
absoluteValue
,
internalId
=
Random
.
nextInt
().
absoluteValue
,
sender
=
client
.
bot
,
target
=
member
,
time
=
currentTimeSeconds
.
toInt
(),
...
...
@@ -451,7 +451,7 @@ internal class MessageSvc {
)
),
msgSeq
=
source
.
sequenceId
,
msgRand
=
source
.
random
,
msgRand
=
source
.
internalId
,
syncCookie
=
SyncCookie
(
time
=
source
.
time
.
toLong
()).
toByteArray
(
SyncCookie
.
serializer
())
)
)
...
...
@@ -467,7 +467,7 @@ internal class MessageSvc {
val
source
=
MessageSourceToGroupImpl
(
group
,
random
=
Random
.
nextInt
().
absoluteValue
,
internalId
=
Random
.
nextInt
().
absoluteValue
,
sender
=
client
.
bot
,
target
=
group
,
time
=
currentTimeSeconds
.
toInt
(),
...
...
@@ -503,7 +503,7 @@ internal class MessageSvc {
)
),
msgSeq
=
client
.
atomicNextMessageSequenceId
(),
msgRand
=
source
.
random
,
msgRand
=
source
.
internalId
,
syncCookie
=
EMPTY_BYTE_ARRAY
,
msgVia
=
1
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
View file @
66f46202
...
...
@@ -179,6 +179,24 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
@JvmSynthetic
abstract
suspend
fun
queryImageUrl
(
image
:
Image
):
String
/**
* 构造一个 [OfflineMessageSource]
*
* @param id 即 [MessageSource.id]
* @param internalId 即 [MessageSource.internalId]
*
* @param fromUin 为用户时为 [Friend.id], 为群时需使用 [Group.calculateGroupUinByGroupCode] 计算
* @param targetUin 为用户时为 [Friend.id], 为群时需使用 [Group.calculateGroupUinByGroupCode] 计算
*/
@MiraiExperimentalAPI
@SinceMirai
(
"0.39.0"
)
abstract
fun
constructMessageSource
(
kind
:
OfflineMessageSource
.
Kind
,
fromUin
:
Long
,
targetUin
:
Long
,
id
:
Int
,
time
:
Int
,
internalId
:
Int
,
originalMessage
:
MessageChain
):
OfflineMessageSource
/**
* 获取图片下载链接并开始下载.
*
...
...
@@ -281,6 +299,7 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI(
val
selfQQDeprecated
:
QQ
get
()
=
selfQQ
@PlannedRemoval
(
"1.0.0."
)
@JvmName
(
"getFriend"
)
@Suppress
(
"INAPPLICABLE_JVM_NAME"
,
"DEPRECATION_ERROR"
)
@Deprecated
(
"for binary compatibility"
,
level
=
DeprecationLevel
.
HIDDEN
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/CustomMessage.kt
View file @
66f46202
...
...
@@ -28,11 +28,9 @@ import net.mamoe.mirai.utils.*
*
* 目前在回复时无法通过 [originalMessage] 获取自定义类型消息
*
* **实现方法**:
*
* @sample samples.CustomMessageIdentifier 实现示例
*
* @see CustomMessageMetadata
* @see CustomMessageMetadata
自定义消息元数据
*/
@SinceMirai
(
"0.38.0"
)
@MiraiExperimentalAPI
...
...
@@ -172,6 +170,11 @@ sealed class CustomMessage : SingleMessage {
/**
* 自定义消息元数据.
*
* **实现方法**:
* 1. 实现一个类继承 [CustomMessageMetadata], 添加 `@Serializable` (来自 `kotlinx.serialization`)
* 2. 添加伴生对象, 继承 [CustomMessage.ProtoBufSerializerFactory] 或 [CustomMessage.JsonSerializerFactory], 或 [CustomMessage.Factory]
* 3. 在需要解析消息前调用一次伴生对象以注册
*
* @see CustomMessage 查看更多信息
* @see ConstrainSingle 可实现此接口以保证消息链中只存在一个元素
*/
...
...
@@ -191,8 +194,9 @@ abstract class CustomMessageMetadata : CustomMessage(), MessageMetadata {
}
@Suppress
(
"NOTHING_TO_INLINE"
)
@OptIn
(
MiraiExperimentalAPI
::
class
)
internal
fun
<
T
:
CustomMessageMetadata
>
T
.
customToStringImpl
(
factory
:
CustomMessage
.
Factory
<
*
>):
ByteArray
{
internal
inline
fun
<
T
:
CustomMessageMetadata
>
T
.
customToStringImpl
(
factory
:
CustomMessage
.
Factory
<
*
>):
ByteArray
{
@Suppress
(
"UNCHECKED_CAST"
)
return
(
factory
as
CustomMessage
.
Factory
<
T
>).
serialize
(
this
)
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Message.kt
View file @
66f46202
...
...
@@ -58,6 +58,7 @@ import kotlin.jvm.JvmSynthetic
* @see QuoteReply 一条消息的引用
* @see RichMessage 富文本消息, 如 [Xml][XmlMessage], [小程序][LightApp], [Json][JsonMessage]
* @see HummerMessage 一些特殊的消息, 如 [闪照][FlashImage], [戳一戳][PokeMessage]
* @see CustomMessage 自定义消息类型
*
* @see MessageChain 消息链(即 `List<Message>`)
* @see buildMessageChain 构造一个 [MessageChain]
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
View file @
66f46202
...
...
@@ -62,8 +62,11 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
/**
* 内部 id, 仅用于 [Bot.constructMessageSource]
* 可能为 0, 取决于服务器是否提供.
* 值没有顺序, 也可能为 0, 取决于服务器是否提供.
*
* 仅用于协议实现.
*/
@SinceMirai
(
"0.39.0"
)
abstract
val
internalId
:
Int
/**
...
...
@@ -94,7 +97,7 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
@LazyProperty
abstract
val
originalMessage
:
MessageChain
final
override
fun
toString
():
String
=
"[mirai:source:$id]"
final
override
fun
toString
():
String
=
"[mirai:source:$id
,$internalId
]"
final
override
fun
contentToString
():
String
=
""
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/OfflineMessageSource.kt
View file @
66f46202
...
...
@@ -13,13 +13,14 @@
package
net.mamoe.mirai.message.data
import
net.mamoe.mirai.BotImpl
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.ContactOrBot
import
net.mamoe.mirai.contact.Friend
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.Member
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.SinceMirai
import
net.mamoe.mirai.utils.
asSequence
import
net.mamoe.mirai.utils.
currentTimeSeconds
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmSynthetic
...
...
@@ -53,68 +54,231 @@ abstract class OfflineMessageSource : MessageSource() {
}
///////////////
//// AMEND ////
///////////////
/**
* 复制这个消息源, 并修改
* 复制这个消息源, 并以 [block] 修改
*
* @see buildMessageSource 查看更多说明
*/
@MiraiExperimentalAPI
@SinceMirai
(
"0.39.0"
)
@JvmName
(
"copySource"
)
inline
fun
MessageSource
.
copyAmend
(
block
:
MessageSourceBuilder
.()
->
Unit
):
OfflineMessageSource
{
return
constructMessageSource
()
}
fun
MessageSource
.
copyAmend
(
block
:
MessageSourceAmender
.()
->
Unit
):
OfflineMessageSource
=
toMutableOffline
().
apply
(
block
)
@MiraiExperimentalAPI
/**
* 仅于 [copyAmend] 中修改 [MessageSource]
*/
@SinceMirai
(
"0.39.0"
)
@OptIn
(
MiraiInternalAPI
::
class
)
fun
constructMessageSource
(
kind
:
OfflineMessageSource
.
Kind
,
fromUin
:
Long
,
targetUin
:
Long
,
id
:
Int
,
time
:
Int
,
internalId
:
Int
,
originalMessage
:
MessageChain
):
OfflineMessageSource
{
val
bot
=
BotImpl
.
instances
.
asSequence
().
mapNotNull
{
it
.
get
()
}.
firstOrNull
()
?:
error
(
"no Bot instance available"
)
return
bot
.
constructMessageSource
(
kind
,
fromUin
,
targetUin
,
id
,
time
,
internalId
,
originalMessage
)
interface
MessageSourceAmender
{
var
kind
:
OfflineMessageSource
.
Kind
var
fromUin
:
Long
var
targetUin
:
Long
var
id
:
Int
var
time
:
Int
var
internalId
:
Int
var
originalMessage
:
MessageChain
}
///////////////
//// BUILD ////
///////////////
/**
* 构建一个 [OfflineMessageSource]
*
* ### 参数
* 一个 [OfflineMessageSource] 须要以下参数:
* - 发送人和发送目标: 通过 [MessageSourceBuilder.sendTo] 设置
* - 消息元数据 (即 [MessageSource.id], [MessageSource.internalId], [MessageSource.time])
* 元数据用于 [撤回][MessageSource.recall], [引用回复][MessageSource.quote], 和官方客户端定位原消息.
* 可通过 [MessageSourceBuilder.id], [MessageSourceBuilder.time], [MessageSourceBuilder.internalId] 设置
* 可通过 [MessageSourceBuilder.metadata] 从另一个 [MessageSource] 复制
* - 消息内容: 通过 [MessageSourceBuilder.messages] 设置
*
* ### 性质
* - 当两个消息的元数据相同时, 他们在群中会是同一条消息. 可通过此特性决定官方客户端 "定位原消息" 的目标
* - 发送人的信息和消息内容会在官方客户端显示在引用回复中.
*/
@SinceMirai
(
"0.39.0"
)
@JvmSynthetic
@MiraiExperimentalAPI
inline
fun
buildMessageSource
(
block
:
MessageSourceBuilder
.()
->
Unit
):
MessageSource
{
val
builder
=
MessageSourceBuilder
().
apply
(
block
)
fun
Bot
.
buildMessageSource
(
block
:
MessageSourceBuilder
.()
->
Unit
):
MessageSource
{
val
builder
=
MessageSourceBuilder
Impl
().
apply
(
block
)
return
constructMessageSource
(
builder
.
kind
?:
error
(
"found "
),
block
builder
.
kind
?:
error
(
"You must call `Contact.sendTo(Contact)` when `buildMessageSource`"
),
builder
.
fromUin
,
builder
.
targetUin
,
builder
.
id
,
builder
.
time
,
builder
.
internalId
,
builder
.
originalMessages
.
build
()
)
}
@DslMarker
annotation
class
SourceBuilderDsl
class
MessageSourceBuilder
(
source
:
OfflineMessageSource
)
:
MessageChainBuilder
()
{
var
kind
:
OfflineMessageSource
.
Kind
=
source
.
kind
var
fromUin
:
Long
=
source
.
fromId
var
targetUin
:
Long
=
source
.
targetId
var
id
:
Int
=
source
.
id
var
time
:
Int
=
source
.
time
var
internalId
:
Int
=
source
.
internalId
var
originalMessage
:
MessageChain
=
source
.
originalMessage
fun
from
(
sender
:
Contact
):
MessageSourceBuilder
{
fromUin
=
if
(
sender
is
Group
)
{
Group
.
calculateGroupUinByGroupCode
(
sender
.
id
)
}
else
sender
.
id
/**
* @see buildMessageSource
*/
abstract
class
MessageSourceBuilder
{
internal
abstract
var
kind
:
OfflineMessageSource
.
Kind
?
internal
abstract
var
fromUin
:
Long
internal
abstract
var
targetUin
:
Long
internal
abstract
var
id
:
Int
internal
abstract
var
time
:
Int
internal
abstract
var
internalId
:
Int
@PublishedApi
internal
val
originalMessages
:
MessageChainBuilder
=
MessageChainBuilder
()
fun
time
(
from
:
MessageSource
):
MessageSourceBuilder
=
apply
{
this
.
time
=
from
.
time
}
val
now
:
Int
get
()
=
currentTimeSeconds
.
toInt
()
fun
time
(
value
:
Int
)
=
apply
{
this
.
time
=
value
}
fun
internalId
(
from
:
MessageSource
):
MessageSourceBuilder
=
apply
{
this
.
internalId
=
from
.
internalId
}
fun
internalId
(
value
:
Int
):
MessageSourceBuilder
=
apply
{
this
.
internalId
=
value
}
fun
id
(
from
:
MessageSource
):
MessageSourceBuilder
=
apply
{
this
.
id
=
from
.
id
}
fun
id
(
value
:
Int
):
MessageSourceBuilder
=
apply
{
this
.
id
=
value
}
/**
* 从另一个 [MessageSource] 复制 [id], [time], [internalId].
* 这三个数据决定官方客户端能 "定位" 到的原消息
*/
fun
metadata
(
from
:
MessageSource
):
MessageSourceBuilder
=
apply
{
id
(
from
)
internalId
(
from
)
time
(
from
)
}
/**
* 从另一个 [MessageSource] 复制所有信息, 包括消息内容. 不会清空已有消息.
*/
fun
allFrom
(
source
:
MessageSource
):
MessageSourceBuilder
{
this
.
kind
=
determineKind
(
source
)
this
.
id
=
source
.
id
this
.
time
=
source
.
time
this
.
fromUin
=
source
.
fromId
this
.
targetUin
=
source
.
targetId
this
.
internalId
=
source
.
internalId
this
.
originalMessages
.
addAll
(
source
.
originalMessage
)
return
this
}
fun
target
(
target
:
Contact
):
MessageSourceBuilder
{
/**
* 从另一个 [MessageSource] 复制 [消息内容][MessageSource.originalMessage]. 不会清空已有消息.
*/
fun
messagesFrom
(
source
:
MessageSource
):
MessageSourceBuilder
=
apply
{
this
.
originalMessages
.
addAll
(
source
.
originalMessage
)
}
fun
messages
(
messages
:
Iterable
<
Message
>):
MessageSourceBuilder
=
apply
{
this
.
originalMessages
.
addAll
(
messages
)
}
fun
messages
(
vararg
message
:
Message
):
MessageSourceBuilder
=
apply
{
for
(
it
in
message
)
{
this
.
originalMessages
.
add
(
it
)
}
}
@JvmSynthetic
inline
fun
messages
(
block
:
MessageChainBuilder
.()
->
Unit
):
MessageSourceBuilder
=
apply
{
this
.
originalMessages
.
apply
(
block
)
}
fun
clearMessages
():
MessageSourceBuilder
=
apply
{
this
.
originalMessages
.
clear
()
}
/**
* 设置 [发送人][this] 和 [发送目标][target], 并自动判断 [kind]
*/
@JvmSynthetic
abstract
infix
fun
ContactOrBot
.
sendTo
(
target
:
ContactOrBot
):
MessageSourceBuilder
fun
setSenderAndTarget
(
sender
:
ContactOrBot
,
target
:
ContactOrBot
)
=
sender
sendTo
target
}
//////////////////
//// INTERNAL ////
//////////////////
internal
class
MessageSourceBuilderImpl
:
MessageSourceBuilder
()
{
override
var
kind
:
OfflineMessageSource
.
Kind
?
=
null
override
var
fromUin
:
Long
=
0
override
var
targetUin
:
Long
=
0
override
var
id
:
Int
=
0
override
var
time
:
Int
=
currentTimeSeconds
.
toInt
()
override
var
internalId
:
Int
=
0
@JvmSynthetic
override
fun
ContactOrBot
.
sendTo
(
target
:
ContactOrBot
):
MessageSourceBuilder
{
fromUin
=
if
(
this
is
Group
)
{
Group
.
calculateGroupUinByGroupCode
(
this
.
id
)
}
else
this
.
id
targetUin
=
if
(
target
is
Group
)
{
Group
.
calculateGroupUinByGroupCode
(
target
.
id
)
}
else
target
.
id
return
this
check
(
this
!=
target
)
{
"sender and target mustn't be the same"
}
kind
=
when
{
this
is
Group
||
target
is
Group
->
OfflineMessageSource
.
Kind
.
GROUP
this
is
Member
||
target
is
Member
->
OfflineMessageSource
.
Kind
.
TEMP
this
is
Bot
&&
target
is
Friend
->
OfflineMessageSource
.
Kind
.
FRIEND
this
is
Friend
&&
target
is
Bot
->
OfflineMessageSource
.
Kind
.
FRIEND
else
->
throw
IllegalArgumentException
(
"Cannot determine source kind for sender $this and target $target"
)
}
return
this
@MessageSourceBuilderImpl
}
}
@JvmSynthetic
internal
fun
MessageSource
.
toMutableOffline
():
MutableOfflineMessageSourceByOnline
=
MutableOfflineMessageSourceByOnline
(
this
)
internal
class
MutableOfflineMessageSourceByOnline
(
origin
:
MessageSource
)
:
OfflineMessageSource
(),
MessageSourceAmender
{
override
var
kind
:
Kind
=
determineKind
(
origin
)
override
var
fromUin
:
Long
get
()
=
fromId
set
(
value
)
{
fromId
=
value
}
override
var
targetUin
:
Long
get
()
=
targetId
set
(
value
)
{
targetId
=
value
}
override
var
bot
:
Bot
=
origin
.
bot
override
var
id
:
Int
=
origin
.
id
override
var
internalId
:
Int
=
origin
.
internalId
override
var
time
:
Int
=
origin
.
time
override
var
fromId
:
Long
=
origin
.
fromId
override
var
targetId
:
Long
=
origin
.
targetId
override
var
originalMessage
:
MessageChain
=
origin
.
originalMessage
}
fun
private
fun
determineKind
(
source
:
MessageSource
):
OfflineMessageSource
.
Kind
{
return
when
{
source
.
isAboutGroup
()
->
OfflineMessageSource
.
Kind
.
GROUP
source
.
isAboutFriend
()
->
OfflineMessageSource
.
Kind
.
FRIEND
source
.
isAboutTemp
()
->
OfflineMessageSource
.
Kind
.
TEMP
else
->
error
(
"stub"
)
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment