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
3748963a
Commit
3748963a
authored
Mar 01, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support `MessageReceipt.quoteReply` for group
parent
f57d0242
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
456 additions
and
156 deletions
+456
-156
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
...ommonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
+21
-9
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
...mmonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
+16
-6
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/MessageSourceImpl.kt
...in/net/mamoe/mirai/qqandroid/message/MessageSourceImpl.kt
+295
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt
...Main/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt
+4
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
...moe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+6
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt
...ai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt
+2
-1
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
+29
-71
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
+2
-24
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/GroupInfo.kt
...e/src/commonMain/kotlin/net.mamoe.mirai/data/GroupInfo.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/lowLevelApi.kt
...core/src/commonMain/kotlin/net.mamoe.mirai/lowLevelApi.kt
+29
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt
...mmonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt
+26
-23
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
...Main/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
+10
-10
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
...monMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
+15
-9
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
View file @
3748963a
...
...
@@ -20,6 +20,7 @@ import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import
net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.qqandroid.message.MessageSourceFromSendGroup
import
net.mamoe.mirai.qqandroid.network.highway.HighwayHelper
import
net.mamoe.mirai.qqandroid.network.highway.postImage
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.StTroopMemberInfo
...
...
@@ -79,10 +80,12 @@ internal class QQImpl(
bot
.
client
,
id
,
event
.
message
)
{
source
=
it
}.
sendAndExpect
<
MessageSvc
.
PbSendMsg
.
Response
>()
is
MessageSvc
.
PbSendMsg
.
Response
.
SUCCESS
)
{
source
=
it
}.
sendAndExpect
<
MessageSvc
.
PbSendMsg
.
Response
>()
is
MessageSvc
.
PbSendMsg
.
Response
.
SUCCESS
)
{
"send message failed"
}
}
return
MessageReceipt
(
source
,
this
)
return
MessageReceipt
(
source
,
this
,
null
)
}
override
suspend
fun
uploadImage
(
image
:
ExternalImage
):
Image
=
try
{
...
...
@@ -117,7 +120,14 @@ internal class QQImpl(
ImageUploadEvent
.
Succeed
(
this
@QQImpl
,
image
,
it
).
broadcast
()
}
is
LongConn
.
OffPicUp
.
Response
.
RequireUpload
->
{
Http
.
postImage
(
"0x6ff0070"
,
bot
.
uin
,
null
,
imageInput
=
image
.
input
,
inputSize
=
image
.
inputSize
,
uKeyHex
=
response
.
uKey
.
toUHexString
(
""
))
Http
.
postImage
(
"0x6ff0070"
,
bot
.
uin
,
null
,
imageInput
=
image
.
input
,
inputSize
=
image
.
inputSize
,
uKeyHex
=
response
.
uKey
.
toUHexString
(
""
)
)
//HighwayHelper.uploadImage(
// client = bot.client,
// serverIp = response.serverIp[0].toIpV4AddressString(),
...
...
@@ -527,7 +537,8 @@ internal class GroupImpl(
override
operator
fun
get
(
id
:
Long
):
Member
{
return
members
.
delegate
.
filteringGetOrNull
{
it
.
id
==
id
}
?:
throw
NoSuchElementException
(
"member $id not found in group $uin"
)
return
members
.
delegate
.
filteringGetOrNull
{
it
.
id
==
id
}
?:
throw
NoSuchElementException
(
"member $id not found in group $uin"
)
}
override
fun
contains
(
id
:
Long
):
Boolean
{
...
...
@@ -544,21 +555,22 @@ internal class GroupImpl(
if
(
event
.
isCancelled
)
{
throw
EventCancelledException
(
"cancelled by FriendMessageSendEvent"
)
}
lateinit
var
source
:
MessageS
vc
.
PbSendMsg
.
MessageS
ourceFromSendGroup
lateinit
var
source
:
MessageSourceFromSendGroup
bot
.
network
.
run
{
val
response
:
MessageSvc
.
PbSendMsg
.
Response
=
MessageSvc
.
PbSendMsg
.
ToGroup
(
bot
.
client
,
id
,
event
.
message
)
{
source
=
it
}.
sendAndExpect
()
)
{
source
=
it
source
.
startWaitingSequenceId
(
this
)
}.
sendAndExpect
()
check
(
response
is
MessageSvc
.
PbSendMsg
.
Response
.
SUCCESS
)
{
"send message failed: $response"
}
}
source
.
startWaitingSequenceId
(
this
)
return
MessageReceipt
(
source
,
this
)
return
MessageReceipt
(
source
,
this
,
botAsMember
)
}
override
suspend
fun
uploadImage
(
image
:
ExternalImage
):
Image
=
try
{
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
View file @
3748963a
...
...
@@ -14,6 +14,7 @@ import io.ktor.client.statement.HttpResponse
import
io.ktor.utils.io.ByteReadChannel
import
net.mamoe.mirai.BotAccount
import
net.mamoe.mirai.BotImpl
import
net.mamoe.mirai.LowLevelAPI
import
net.mamoe.mirai.contact.*
import
net.mamoe.mirai.data.AddFriendResult
import
net.mamoe.mirai.data.FriendInfo
...
...
@@ -84,21 +85,28 @@ internal abstract class QQAndroidBotBase constructor(
return
groups
.
delegate
.
getOrNull
(
uin
)
}
override
suspend
fun
queryGroupList
():
Sequence
<
Long
>
{
@UseExperimental
(
LowLevelAPI
::
class
)
override
suspend
fun
_lowLevelQueryGroupList
():
Sequence
<
Long
>
{
return
network
.
run
{
FriendList
.
GetTroopListSimplify
(
bot
.
client
)
.
sendAndExpect
<
FriendList
.
GetTroopListSimplify
.
Response
>(
retry
=
2
)
}.
groups
.
asSequence
().
map
{
it
.
groupUin
.
shl
(
32
)
and
it
.
groupCode
}
}
override
suspend
fun
queryGroupInfo
(
groupCode
:
Long
):
GroupInfo
=
network
.
run
{
@UseExperimental
(
LowLevelAPI
::
class
)
override
suspend
fun
_lowLevelQueryGroupInfo
(
groupCode
:
Long
):
GroupInfo
=
network
.
run
{
TroopManagement
.
GetGroupInfo
(
client
=
bot
.
client
,
groupCode
=
groupCode
).
sendAndExpect
<
GroupInfoImpl
>(
retry
=
2
)
}
override
suspend
fun
queryGroupMemberList
(
groupUin
:
Long
,
groupCode
:
Long
,
ownerId
:
Long
):
Sequence
<
MemberInfo
>
=
@UseExperimental
(
LowLevelAPI
::
class
)
override
suspend
fun
_lowLevelQueryGroupMemberList
(
groupUin
:
Long
,
groupCode
:
Long
,
ownerId
:
Long
):
Sequence
<
MemberInfo
>
=
network
.
run
{
var
nextUin
=
0L
var
sequence
=
sequenceOf
<
MemberInfoImpl
>()
...
...
@@ -125,7 +133,7 @@ internal abstract class QQAndroidBotBase constructor(
}
override
suspend
fun
recall
(
source
:
MessageSource
)
{
if
(
source
.
qq
Id
!=
uin
&&
source
.
groupId
!=
0L
)
{
if
(
source
.
sender
Id
!=
uin
&&
source
.
groupId
!=
0L
)
{
getGroup
(
source
.
groupId
).
checkBotPermissionOperator
()
}
...
...
@@ -136,7 +144,7 @@ internal abstract class QQAndroidBotBase constructor(
if
(
source
.
groupId
==
0L
)
{
PbMessageSvc
.
PbMsgWithDraw
.
Friend
(
bot
.
client
,
source
.
qq
Id
,
source
.
sender
Id
,
source
.
sequenceId
,
source
.
messageRandom
,
source
.
time
...
...
@@ -144,7 +152,7 @@ internal abstract class QQAndroidBotBase constructor(
}
else
{
MessageRecallEvent
.
GroupRecall
(
bot
,
source
.
qq
Id
,
source
.
sender
Id
,
source
.
id
,
source
.
time
.
toInt
(),
null
,
...
...
@@ -162,6 +170,7 @@ internal abstract class QQAndroidBotBase constructor(
}
}
@UseExperimental
(
LowLevelAPI
::
class
)
override
suspend
fun
_lowLevelRecallFriendMessage
(
friendId
:
Long
,
messageId
:
Long
,
time
:
Long
)
{
network
.
run
{
val
response
:
PbMessageSvc
.
PbMsgWithDraw
.
Response
=
...
...
@@ -172,6 +181,7 @@ internal abstract class QQAndroidBotBase constructor(
}
}
@UseExperimental
(
LowLevelAPI
::
class
)
override
suspend
fun
_lowLevelRecallGroupMessage
(
groupId
:
Long
,
messageId
:
Long
)
{
network
.
run
{
val
response
:
PbMessageSvc
.
PbMsgWithDraw
.
Response
=
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/MessageSource
FromMsg
.kt
→
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/MessageSource
Impl
.kt
View file @
3748963a
...
...
@@ -9,14 +9,22 @@
package
net.mamoe.mirai.qqandroid.message
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Deferred
import
kotlinx.coroutines.ExperimentalCoroutinesApi
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.event.subscribingGetAsync
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.message.data.MessageSource
import
net.mamoe.mirai.message.data.messageRandom
import
net.mamoe.mirai.message.data.sequenceId
import
net.mamoe.mirai.qqandroid.io.serialization.loadAs
import
net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.SourceMsg
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.OnlinePush
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
internal
inline
class
MessageSourceFromServer
(
val
delegate
:
ImMsgBody
.
SourceMsg
...
...
@@ -24,16 +32,18 @@ internal inline class MessageSourceFromServer(
override
val
time
:
Long
get
()
=
delegate
.
time
.
toLong
()
and
0
xFFFFFFFF
override
val
id
:
Long
get
()
=
(
delegate
.
origSeqs
?.
firstOrNull
()
?:
error
(
"cannot find sequenceId from ImMsgBody.SourceMsg"
)).
toLong
().
shl
(
32
)
or
get
()
=
(
delegate
.
origSeqs
?.
firstOrNull
()
?:
error
(
"cannot find sequenceId from ImMsgBody.SourceMsg"
)).
toLong
().
shl
(
32
)
or
(
delegate
.
pbReserve
.
loadAs
(
SourceMsg
.
ResvAttr
.
serializer
()).
origUids
!!
.
toInt
()).
toLong
().
and
(
0
xFFFFFFFF
)
override
val
toUin
:
Long
get
()
=
delegate
.
toUin
override
suspend
fun
ensureSequenceIdAvailable
()
{
// nothing to do
}
// override val sourceMessage: MessageChain get() = delegate.toMessageChain()
override
val
qq
Id
:
Long
get
()
=
delegate
.
senderUin
override
val
sender
Id
:
Long
get
()
=
delegate
.
senderUin
override
val
groupId
:
Long
get
()
=
Group
.
calculateGroupCodeByGroupUin
(
delegate
.
toUin
)
override
fun
toString
():
String
=
""
...
...
@@ -51,8 +61,8 @@ internal inline class MessageSourceFromMsg(
// nothing to do
}
// override val sourceMessage: MessageChain get() = delegate.toMessageChain()
override
val
qq
Id
:
Long
get
()
=
delegate
.
msgHead
.
fromUin
override
val
toUin
:
Long
get
()
=
delegate
.
msgHead
.
toUin
override
val
sender
Id
:
Long
get
()
=
delegate
.
msgHead
.
fromUin
override
val
groupId
:
Long
get
()
=
delegate
.
msgHead
.
groupInfo
?.
groupCode
?:
0
fun
toJceData
():
ImMsgBody
.
SourceMsg
{
...
...
@@ -136,3 +146,150 @@ internal inline class MessageSourceFromMsg(
override
fun
toString
():
String
=
""
}
internal
abstract
class
MessageSourceFromSend
:
MessageSource
{
abstract
val
sourceMessage
:
MessageChain
fun
toJceData
():
ImMsgBody
.
SourceMsg
{
return
if
(
groupId
==
0L
)
{
toJceDataImplForFriend
()
}
else
toJceDataImplForGroup
()
}
private
val
elems
by
lazy
{
sourceMessage
.
toRichTextElems
(
groupId
!=
0L
)
}
private
fun
toJceDataImplForFriend
():
ImMsgBody
.
SourceMsg
{
val
messageUid
:
Long
=
262144L
.
shl
(
32
)
or
messageRandom
.
toLong
().
and
(
0
xffFFffFF
)
return
ImMsgBody
.
SourceMsg
(
origSeqs
=
listOf
(
sequenceId
),
senderUin
=
senderId
,
toUin
=
toUin
,
flag
=
1
,
elems
=
elems
,
type
=
0
,
time
=
time
.
toInt
(),
pbReserve
=
SourceMsg
.
ResvAttr
(
origUids
=
messageUid
).
toByteArray
(
SourceMsg
.
ResvAttr
.
serializer
()),
srcMsg
=
MsgComm
.
Msg
(
msgHead
=
MsgComm
.
MsgHead
(
fromUin
=
senderId
,
// qq
toUin
=
toUin
,
// group
msgType
=
9
,
// 82?
c2cCmd
=
11
,
msgSeq
=
sequenceId
,
msgTime
=
time
.
toInt
(),
msgUid
=
messageUid
,
// ok
// groupInfo = MsgComm.GroupInfo(groupCode = delegate.msgHead.groupInfo.groupCode),
isSrcMsg
=
true
),
msgBody
=
ImMsgBody
.
MsgBody
(
richText
=
ImMsgBody
.
RichText
(
elems
=
elems
.
toMutableList
().
also
{
if
(
it
.
last
().
elemFlags2
==
null
)
it
.
add
(
ImMsgBody
.
Elem
(
elemFlags2
=
ImMsgBody
.
ElemFlags2
()))
}
)
)
).
toByteArray
(
MsgComm
.
Msg
.
serializer
())
)
}
private
fun
toJceDataImplForGroup
():
ImMsgBody
.
SourceMsg
{
return
ImMsgBody
.
SourceMsg
(
origSeqs
=
listOf
(
sequenceId
),
senderUin
=
senderId
,
toUin
=
toUin
,
flag
=
1
,
elems
=
elems
,
type
=
0
,
time
=
time
.
toInt
(),
pbReserve
=
SourceMsg
.
ResvAttr
(
origUids
=
messageRandom
.
toLong
()
and
0
xffFFffFF
).
toByteArray
(
SourceMsg
.
ResvAttr
.
serializer
()),
srcMsg
=
MsgComm
.
Msg
(
msgHead
=
MsgComm
.
MsgHead
(
fromUin
=
senderId
,
// qq
toUin
=
toUin
,
// group
msgType
=
82
,
// 82?
c2cCmd
=
1
,
msgSeq
=
sequenceId
,
msgTime
=
time
.
toInt
(),
msgUid
=
messageRandom
.
toLong
()
and
0
xffFFffFF
,
// ok
groupInfo
=
MsgComm
.
GroupInfo
(
groupCode
=
groupId
),
isSrcMsg
=
true
),
msgBody
=
ImMsgBody
.
MsgBody
(
richText
=
ImMsgBody
.
RichText
(
elems
=
elems
.
toMutableList
().
also
{
if
(
it
.
last
().
elemFlags2
==
null
)
it
.
add
(
ImMsgBody
.
Elem
(
elemFlags2
=
ImMsgBody
.
ElemFlags2
()))
}
)
)
).
toByteArray
(
MsgComm
.
Msg
.
serializer
())
)
}
}
internal
class
MessageSourceFromSendFriend
(
val
messageRandom
:
Int
,
override
val
time
:
Long
,
override
val
senderId
:
Long
,
override
val
toUin
:
Long
,
override
val
groupId
:
Long
,
val
sequenceId
:
Int
,
override
val
sourceMessage
:
MessageChain
)
:
MessageSourceFromSend
()
{
@UseExperimental
(
ExperimentalCoroutinesApi
::
class
)
override
val
id
:
Long
get
()
=
sequenceId
.
toLong
().
shl
(
32
)
or
messageRandom
.
toLong
().
and
(
0
xFFFFFFFF
)
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
,
override
val
toUin
:
Long
,
override
val
groupId
:
Long
,
override
val
sourceMessage
:
MessageChain
)
:
MessageSourceFromSend
()
{
private
lateinit
var
sequenceIdDeferred
:
Deferred
<
Int
>
@UseExperimental
(
ExperimentalCoroutinesApi
::
class
)
override
val
id
:
Long
get
()
=
sequenceIdDeferred
.
getCompleted
().
toLong
().
shl
(
32
)
or
messageRandom
.
toLong
().
and
(
0
xFFFFFFFF
)
@UseExperimental
(
MiraiExperimentalAPI
::
class
)
internal
fun
startWaitingSequenceId
(
coroutineScope
:
CoroutineScope
)
{
sequenceIdDeferred
=
coroutineScope
.
subscribingGetAsync
<
OnlinePush
.
PbPushGroupMsg
.
SendGroupMessageReceipt
,
Int
>(
timeoutMillis
=
3000
)
{
if
(
it
.
messageRandom
==
this
@MessageSourceFromSendGroup
.
messageRandom
)
{
it
.
sequenceId
}
else
null
}
}
override
suspend
fun
ensureSequenceIdAvailable
()
{
sequenceIdDeferred
.
join
()
}
override
fun
toString
():
String
{
return
""
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt
View file @
3748963a
...
...
@@ -226,6 +226,7 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgB
when
(
val
source
=
this
[
QuoteReply
].
source
)
{
is
MessageSourceFromServer
->
elements
.
add
(
ImMsgBody
.
Elem
(
srcMsg
=
source
.
delegate
))
is
MessageSourceFromMsg
->
elements
.
add
(
ImMsgBody
.
Elem
(
srcMsg
=
source
.
toJceData
()))
is
MessageSourceFromSend
->
elements
.
add
(
ImMsgBody
.
Elem
(
srcMsg
=
source
.
toJceData
()))
else
->
error
(
"unsupported MessageSource implementation: ${source::class.simpleName}"
)
}
}
...
...
@@ -243,6 +244,9 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgB
is
Face
->
elements
.
add
(
ImMsgBody
.
Elem
(
face
=
it
.
toJceData
()))
is
QuoteReplyToSend
->
{
if
(
forGroup
)
{
check
(
it
is
QuoteReplyToSend
.
ToGroup
)
{
"sending a quote to group suing QuoteReplyToSend.ToFriend"
}
if
(
it
.
sender
is
Member
)
{
transformOneMessage
(
it
.
createAt
())
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
View file @
3748963a
...
...
@@ -245,7 +245,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
bot
=
bot
,
coroutineContext
=
bot
.
coroutineContext
,
id
=
troopNum
.
groupCode
,
groupInfo
=
bot
.
q
ueryGroupInfo
(
troopNum
.
groupCode
).
apply
{
groupInfo
=
bot
.
_lowLevelQ
ueryGroupInfo
(
troopNum
.
groupCode
).
apply
{
this
as
GroupInfoImpl
if
(
this
.
delegate
.
groupName
==
null
)
{
...
...
@@ -262,7 +262,11 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
this
.
delegate
.
groupCode
=
troopNum
.
groupCode
},
members
=
bot
.
queryGroupMemberList
(
troopNum
.
groupUin
,
troopNum
.
groupCode
,
troopNum
.
dwGroupOwnerUin
)
members
=
bot
.
_lowLevelQueryGroupMemberList
(
troopNum
.
groupUin
,
troopNum
.
groupCode
,
troopNum
.
dwGroupOwnerUin
)
))
)
}
?.
let
{
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/PbMessageSvc.kt
View file @
3748963a
...
...
@@ -78,6 +78,7 @@ internal class PbMessageSvc {
messageRandom
:
Int
,
// 921878719
time
:
Long
):
OutgoingPacket
=
buildOutgoingUniPacket
(
client
)
{
val
messageUid
:
Long
=
262144L
.
shl
(
32
)
or
messageRandom
.
toLong
().
and
(
0
xffFFffFF
)
writeProtoBuf
(
MsgSvc
.
PbMsgWithDrawReq
.
serializer
(),
MsgSvc
.
PbMsgWithDrawReq
(
...
...
@@ -89,7 +90,7 @@ internal class PbMessageSvc {
fromUin
=
client
.
bot
.
uin
,
toUin
=
toUin
,
msgSeq
=
messageSequenceId
,
msgUid
=
message
Random
.
toLong
()
and
0
xffffffff
,
msgUid
=
message
Uid
,
msgTime
=
time
and
0
xffffffff
,
routingHead
=
MsgSvc
.
RoutingHead
(
c2c
=
MsgSvc
.
C2C
(
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt
View file @
3748963a
...
...
@@ -10,9 +10,6 @@
package
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import
io.ktor.utils.io.core.ByteReadPacket
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Deferred
import
kotlinx.coroutines.ExperimentalCoroutinesApi
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.MemberPermission
import
net.mamoe.mirai.data.MemberInfo
...
...
@@ -21,16 +18,16 @@ import net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.event.events.BotJoinGroupEvent
import
net.mamoe.mirai.event.events.BotOfflineEvent
import
net.mamoe.mirai.event.events.MemberJoinEvent
import
net.mamoe.mirai.event.subscribingGetAsync
import
net.mamoe.mirai.message.FriendMessage
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.message.data.MessageSource
import
net.mamoe.mirai.qqandroid.GroupImpl
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket
import
net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
import
net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import
net.mamoe.mirai.qqandroid.io.serialization.writeProtoBuf
import
net.mamoe.mirai.qqandroid.message.MessageSourceFromSendFriend
import
net.mamoe.mirai.qqandroid.message.MessageSourceFromSendGroup
import
net.mamoe.mirai.qqandroid.message.toMessageChain
import
net.mamoe.mirai.qqandroid.message.toRichTextElems
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
...
...
@@ -45,6 +42,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.GroupInfoImpl
import
net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils._miraiContentToString
import
net.mamoe.mirai.utils.currentTimeSeconds
import
kotlin.math.absoluteValue
import
kotlin.random.Random
...
...
@@ -97,7 +95,7 @@ internal class MessageSvc {
syncFlag
=
syncFlag
,
// serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY,
syncCookie
=
client
.
c2cMessageSync
.
syncCookie
?:
SyncCookie
(
time
=
msgTime
+
client
.
timeDifference
).
toByteArray
(
SyncCookie
.
serializer
())
//.also { client.c2cMessageSync.syncCookie = it },
?:
SyncCookie
(
time
=
msgTime
).
toByteArray
(
SyncCookie
.
serializer
())
//.also { client.c2cMessageSync.syncCookie = it },
// syncFlag = client.c2cMessageSync.syncFlag,
//msgCtrlBuf = client.c2cMessageSync.msgCtrlBuf,
//pubaccountCookie = client.c2cMessageSync.pubAccountCookie
...
...
@@ -165,7 +163,7 @@ internal class MessageSvc {
bot
=
bot
,
coroutineContext
=
bot
.
coroutineContext
,
id
=
Group
.
calculateGroupCodeByGroupUin
(
msg
.
msgHead
.
fromUin
),
groupInfo
=
bot
.
q
ueryGroupInfo
(
troopNum
.
groupCode
).
apply
{
groupInfo
=
bot
.
_lowLevelQ
ueryGroupInfo
(
troopNum
.
groupCode
).
apply
{
this
as
GroupInfoImpl
...
...
@@ -183,7 +181,11 @@ internal class MessageSvc {
this
.
delegate
.
groupCode
=
troopNum
.
groupCode
},
members
=
bot
.
queryGroupMemberList
(
troopNum
.
groupUin
,
troopNum
.
groupCode
,
troopNum
.
dwGroupOwnerUin
)
members
=
bot
.
_lowLevelQueryGroupMemberList
(
troopNum
.
groupUin
,
troopNum
.
groupCode
,
troopNum
.
dwGroupOwnerUin
)
)
bot
.
groups
.
delegate
.
addLast
(
newGroup
)
return
@
mapNotNull
BotJoinGroupEvent
(
newGroup
)
...
...
@@ -198,12 +200,15 @@ internal class MessageSvc {
override
val
specialTitle
:
String
get
()
=
""
override
val
muteTimestamp
:
Int
get
()
=
0
override
val
uin
:
Long
get
()
=
msg
.
msgHead
.
authUin
override
val
nick
:
String
get
()
=
msg
.
msgHead
.
authNick
.
takeIf
{
it
.
isNotEmpty
()
}
?:
msg
.
msgHead
.
fromNick
override
val
nick
:
String
get
()
=
msg
.
msgHead
.
authNick
.
takeIf
{
it
.
isNotEmpty
()
}
?:
msg
.
msgHead
.
fromNick
}).
also
{
group
.
members
.
delegate
.
addLast
(
it
)
})
}
}
}
166
->
{
println
(
msg
.
_miraiContentToString
())
return
@
mapNotNull
when
{
msg
.
msgHead
.
fromUin
==
bot
.
uin
->
null
!
bot
.
firstLoginSucceed
->
null
...
...
@@ -227,8 +232,13 @@ internal class MessageSvc {
override
suspend
fun
QQAndroidBot
.
handle
(
packet
:
Response
)
{
when
(
packet
.
syncFlagFromServer
)
{
MsgSvc
.
SyncFlag
.
STOP
,
MsgSvc
.
SyncFlag
.
START
->
return
MsgSvc
.
SyncFlag
.
STOP
->
return
MsgSvc
.
SyncFlag
.
START
->
{
network
.
run
{
PbGetMsg
(
client
,
MsgSvc
.
SyncFlag
.
CONTINUE
,
currentTimeSeconds
).
sendWithoutExpect
()
}
return
}
MsgSvc
.
SyncFlag
.
CONTINUE
->
{
network
.
run
{
...
...
@@ -266,62 +276,6 @@ internal class MessageSvc {
}
}
internal
class
MessageSourceFromSendFriend
(
val
messageRandom
:
Int
,
override
val
time
:
Long
,
override
val
qqId
:
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
(
0
xFFFFFFFF
)
override
suspend
fun
ensureSequenceIdAvailable
()
{
// nothing to do
}
override
fun
toString
():
String
{
return
""
}
}
internal
class
MessageSourceFromSendGroup
(
val
messageRandom
:
Int
,
override
val
time
:
Long
,
override
val
qqId
:
Long
,
override
val
groupId
:
Long
// ,
// override val sourceMessage: MessageChain
)
:
MessageSource
{
private
lateinit
var
sequenceIdDeferred
:
Deferred
<
Int
>
@UseExperimental
(
ExperimentalCoroutinesApi
::
class
)
override
val
id
:
Long
get
()
=
sequenceIdDeferred
.
getCompleted
().
toLong
().
shl
(
32
)
or
messageRandom
.
toLong
().
and
(
0
xFFFFFFFF
)
@UseExperimental
(
MiraiExperimentalAPI
::
class
)
fun
startWaitingSequenceId
(
coroutineScope
:
CoroutineScope
)
{
sequenceIdDeferred
=
coroutineScope
.
subscribingGetAsync
<
OnlinePush
.
PbPushGroupMsg
.
SendGroupMessageReceipt
,
Int
>(
timeoutMillis
=
3000
)
{
if
(
it
.
messageRandom
==
this
@MessageSourceFromSendGroup
.
messageRandom
)
{
it
.
sequenceId
}
else
null
}
}
override
suspend
fun
ensureSequenceIdAvailable
()
{
sequenceIdDeferred
.
join
()
}
override
fun
toString
():
String
{
return
""
}
}
inline
fun
ToFriend
(
client
:
QQAndroidClient
,
toUin
:
Long
,
...
...
@@ -330,10 +284,12 @@ internal class MessageSvc {
):
OutgoingPacket
{
val
source
=
MessageSourceFromSendFriend
(
messageRandom
=
Random
.
nextInt
().
absoluteValue
,
qqId
=
toUin
,
senderId
=
client
.
uin
,
toUin
=
toUin
,
time
=
currentTimeSeconds
+
client
.
timeDifference
,
groupId
=
0
,
sequenceId
=
client
.
atomicNextMessageSequenceId
()
sequenceId
=
client
.
atomicNextMessageSequenceId
(),
sourceMessage
=
message
)
sourceCallback
(
source
)
return
ToFriend
(
client
,
toUin
,
message
,
source
)
...
...
@@ -379,9 +335,11 @@ internal class MessageSvc {
val
source
=
MessageSourceFromSendGroup
(
messageRandom
=
Random
.
nextInt
().
absoluteValue
,
qqId
=
client
.
uin
,
senderId
=
client
.
uin
,
toUin
=
Group
.
calculateGroupUinByGroupCode
(
groupCode
),
time
=
currentTimeSeconds
+
client
.
timeDifference
,
groupId
=
groupCode
//,
groupId
=
groupCode
,
sourceMessage
=
message
//,
// sourceMessage = message
)
sourceCallback
(
source
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
View file @
3748963a
...
...
@@ -19,8 +19,6 @@ import kotlinx.coroutines.launch
import
net.mamoe.mirai.contact.*
import
net.mamoe.mirai.data.AddFriendResult
import
net.mamoe.mirai.data.FriendInfo
import
net.mamoe.mirai.data.GroupInfo
import
net.mamoe.mirai.data.MemberInfo
import
net.mamoe.mirai.message.MessageReceipt
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.MessageChain
...
...
@@ -41,7 +39,7 @@ import kotlin.jvm.JvmStatic
* @see Contact 联系人
* @see kotlinx.coroutines.isActive 判断 [Bot] 是否正常运行中. (在线, 且没有被 [close])
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
@UseExperimental
(
MiraiInternalAPI
::
class
,
LowLevelAPI
::
class
)
abstract
class
Bot
:
CoroutineScope
,
LowLevelBotAPIAccessor
{
companion
object
{
/**
...
...
@@ -151,27 +149,6 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor {
?:
throw
NoSuchElementException
(
"No such group $id for bot ${this.uin}"
)
}
/**
* 向服务器查询群列表. 返回值前 32 bits 为 uin, 后 32 bits 为 groupCode
*/
abstract
suspend
fun
queryGroupList
():
Sequence
<
Long
>
/**
* 向服务器查询群资料. 获得的仅为当前时刻的资料.
* 请优先使用 [getGroup] 然后查看群资料.
*/
abstract
suspend
fun
queryGroupInfo
(
groupCode
:
Long
):
GroupInfo
/**
* 向服务器查询群成员列表.
* 请优先使用 [getGroup], [Group.members] 查看群成员.
*
* 这个函数很慢. 请不要频繁使用.
*
* @see Group.calculateGroupUinByGroupCode 使用 groupCode 计算 groupUin
*/
abstract
suspend
fun
queryGroupMemberList
(
groupUin
:
Long
,
groupCode
:
Long
,
ownerId
:
Long
):
Sequence
<
MemberInfo
>
// endregion
// region network
...
...
@@ -263,6 +240,7 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor {
*/
abstract
fun
close
(
cause
:
Throwable
?
=
null
)
@UseExperimental
(
LowLevelAPI
::
class
)
final
override
fun
toString
():
String
=
"Bot(${uin})"
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/GroupInfo.kt
View file @
3748963a
...
...
@@ -5,7 +5,7 @@ import net.mamoe.mirai.Bot
/**
* 群资料.
*
* 通过 [Bot.
q
ueryGroupInfo] 得到
* 通过 [Bot.
_lowLevelQ
ueryGroupInfo] 得到
*/
interface
GroupInfo
{
/**
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/lowLevelApi.kt
View file @
3748963a
...
...
@@ -9,6 +9,9 @@
package
net.mamoe.mirai
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.data.GroupInfo
import
net.mamoe.mirai.data.MemberInfo
import
net.mamoe.mirai.message.data.MessageSource
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
...
...
@@ -18,6 +21,7 @@ import net.mamoe.mirai.utils.MiraiExperimentalAPI
* 使用低级的 API 无法带来任何安全和便捷保障.
* 仅在某些使用结构化 API 可能影响性能的情况下使用这些低级 API.
*/
@Experimental
@Retention
(
AnnotationRetention
.
BINARY
)
@Target
(
AnnotationTarget
.
CLASS
,
AnnotationTarget
.
TYPE
,
AnnotationTarget
.
FUNCTION
,
AnnotationTarget
.
PROPERTY
)
annotation
class
LowLevelAPI
...
...
@@ -29,6 +33,31 @@ annotation class LowLevelAPI
@Suppress
(
"FunctionName"
,
"unused"
)
@LowLevelAPI
interface
LowLevelBotAPIAccessor
{
/**
* 向服务器查询群列表. 返回值前 32 bits 为 uin, 后 32 bits 为 groupCode
*/
@LowLevelAPI
suspend
fun
_lowLevelQueryGroupList
():
Sequence
<
Long
>
/**
* 向服务器查询群资料. 获得的仅为当前时刻的资料.
* 请优先使用 [Bot.getGroup] 然后查看群资料.
*/
@LowLevelAPI
suspend
fun
_lowLevelQueryGroupInfo
(
groupCode
:
Long
):
GroupInfo
/**
* 向服务器查询群成员列表.
* 请优先使用 [Bot.getGroup], [Group.members] 查看群成员.
*
* 这个函数很慢. 请不要频繁使用.
*
* @see Group.calculateGroupUinByGroupCode 使用 groupCode 计算 groupUin
*/
@LowLevelAPI
suspend
fun
_lowLevelQueryGroupMemberList
(
groupUin
:
Long
,
groupCode
:
Long
,
ownerId
:
Long
):
Sequence
<
MemberInfo
>
/**
* 撤回一条由机器人发送给好友的消息
* @param messageId [MessageSource.id]
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt
View file @
3748963a
...
...
@@ -12,13 +12,10 @@ package net.mamoe.mirai.message
import
kotlinx.atomicfu.atomic
import
kotlinx.coroutines.Job
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.contact.sendMessage
import
net.mamoe.mirai.LowLevelAPI
import
net.mamoe.mirai.contact.*
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.recallIn
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.getValue
import
net.mamoe.mirai.utils.unsafeWeakRef
...
...
@@ -36,7 +33,8 @@ import net.mamoe.mirai.utils.unsafeWeakRef
*/
open
class
MessageReceipt
<
C
:
Contact
>(
val
source
:
MessageSource
,
target
:
C
target
:
C
,
private
val
botAsMember
:
Member
?
)
{
init
{
require
(
target
is
Group
||
target
is
QQ
)
{
"target must be either Group or QQ"
}
...
...
@@ -47,6 +45,11 @@ open class MessageReceipt<C : Contact>(
*/
val
target
:
C
by
target
.
unsafeWeakRef
()
/**
* 是否为发送给群的消息的回执
*/
val
isToGroup
:
Boolean
=
botAsMember
!=
null
private
val
_isRecalled
=
atomic
(
false
)
/**
...
...
@@ -55,7 +58,6 @@ open class MessageReceipt<C : Contact>(
* @see Bot.recall
* @throws IllegalStateException 当此消息已经被撤回或正计划撤回时
*/
@UseExperimental
(
MiraiExperimentalAPI
::
class
)
suspend
fun
recall
()
{
@Suppress
(
"BooleanLiteralArgument"
)
if
(
_isRecalled
.
compareAndSet
(
false
,
true
))
{
...
...
@@ -75,10 +77,8 @@ open class MessageReceipt<C : Contact>(
* 在一段时间后撤回这条消息.. [recall] 或 [recallIn] 只能被调用一次.
*
* @param millis 延迟时间, 单位为毫秒
*
* @throws IllegalStateException 当此消息已经被撤回或正计划撤回时
*/
@UseExperimental
(
MiraiExperimentalAPI
::
class
)
fun
recallIn
(
millis
:
Long
):
Job
{
@Suppress
(
"BooleanLiteralArgument"
)
if
(
_isRecalled
.
compareAndSet
(
false
,
true
))
{
...
...
@@ -91,27 +91,32 @@ open class MessageReceipt<C : Contact>(
}
/**
* 引用这条消息.
*
* [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable] 然后引用这条消息.
* @see MessageChain.quote 引用一条消息
*/
open
suspend
fun
quote
():
QuoteReplyToSend
{
this
.
source
.
ensureSequenceIdAvailable
()
@UseExperimental
(
LowLevelAPI
::
class
)
return
_unsafeQuote
()
}
/**
* 引用这条消息, 但不会 [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable].
* 在 sequenceId 可用前就发送这条消息则会导致一个异常.
* 当且仅当用于存储而不用于发送时使用这个方法.
*
* @
throws IllegalStateException 当此消息不是群消息时
* @
see MessageChain.quote 引用一条消息
*/
@MiraiExperimentalAPI
(
"unstable"
)
open
fun
quote
():
QuoteReplyToSend
{
val
target
=
target
check
(
target
is
Group
)
{
"quote is only available for GroupMessage"
}
return
this
.
source
.
quote
(
target
.
botAsMember
)
@LowLevelAPI
@Suppress
(
"FunctionName"
)
fun
_unsafeQuote
():
QuoteReplyToSend
{
return
this
.
source
.
quote
(
botAsMember
as
?
QQ
)
}
/**
* 引用这条消息并回复.
*
* @see MessageChain.quote 引用一条消息
*
* @throws IllegalStateException 当此消息不是群消息时
*/
@MiraiExperimentalAPI
(
"unstable"
)
suspend
fun
quoteReply
(
message
:
MessageChain
)
{
target
.
sendMessage
(
this
.
quote
()
+
message
)
}
...
...
@@ -138,12 +143,10 @@ inline val MessageReceipt<*>.sourceSequenceId: Int get() = this.source.sequenceI
*/
inline
val
MessageReceipt
<*>.
sourceTime
:
Long
get
()
=
this
.
source
.
time
@MiraiExperimentalAPI
(
"unstable"
)
suspend
inline
fun
MessageReceipt
<
out
Contact
>.
quoteReply
(
message
:
Message
)
{
return
this
.
quoteReply
(
message
.
toChain
())
}
@MiraiExperimentalAPI
(
"unstable"
)
suspend
inline
fun
MessageReceipt
<
out
Contact
>.
quoteReply
(
message
:
String
)
{
return
this
.
quoteReply
(
message
.
toMessage
().
toChain
())
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
View file @
3748963a
...
...
@@ -13,7 +13,7 @@
package
net.mamoe.mirai.message.data
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.
QQ
import
net.mamoe.mirai.contact.
Group
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
...
...
@@ -50,19 +50,17 @@ interface MessageSource : Message, MessageMetadata {
val
time
:
Long
/**
* 与这个消息相关的 [QQ] 的 [QQ.id]
*
* 群消息时为发送人的 id (可能为 bot 自己). 好友消息时为消息发送目标好友的 id (不可能为 bot 自己)
* 发送人. 可以为机器人自己
*/
val
qqId
:
Long
@Suppress
(
"unused"
)
@Deprecated
(
"使用 qqId. 此 API 将在不久后删除"
,
level
=
DeprecationLevel
.
ERROR
,
replaceWith
=
ReplaceWith
(
"this.qqId"
))
val
senderId
:
Long
get
()
=
qqId
/**
* 群号码, 为 0 时则来自好友消息
* 消息发送对象, 可以为一个群的 `uin` (非 `id`)或一个好友, 或机器人自己
*/
val
toUin
:
Long
/**
* 当群消息时为群 id, [Group.id], 好友消息时为 0
*/
val
groupId
:
Long
...
...
@@ -72,6 +70,8 @@ interface MessageSource : Message, MessageMetadata {
override
fun
toString
():
String
}
interface
GroupMessageSource
:
MessageSource
/**
* 序列号. 若是机器人发出去的消息, 请先 [确保 sequenceId 可用][MessageSource.ensureSequenceIdAvailable]
* @see MessageSource.id
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
View file @
3748963a
...
...
@@ -40,16 +40,21 @@ open class QuoteReply
* 总是使用 [quote] 来构造实例.
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
class
QuoteReplyToSend
@MiraiInternalAPI
constructor
(
source
:
MessageSource
,
val
sender
:
QQ
)
:
QuoteReply
(
source
)
{
sealed
class
QuoteReplyToSend
@MiraiInternalAPI
constructor
(
source
:
MessageSource
)
:
QuoteReply
(
source
)
{
class
ToGroup
(
source
:
MessageSource
,
val
sender
:
QQ
)
:
QuoteReplyToSend
(
source
)
{
fun
createAt
():
At
=
At
(
sender
as
Member
)
}
class
ToFriend
(
source
:
MessageSource
)
:
QuoteReplyToSend
(
source
)
}
/**
* 引用这条消息.
* @see sender 消息发送人.
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
fun
MessageChain
.
quote
(
sender
:
QQ
):
QuoteReplyToSend
{
fun
MessageChain
.
quote
(
sender
:
QQ
?
):
QuoteReplyToSend
{
this
.
firstOrNull
<
MessageSource
>()
?.
let
{
return
it
.
quote
(
sender
)
}
...
...
@@ -58,11 +63,12 @@ fun MessageChain.quote(sender: QQ): QuoteReplyToSend {
/**
* 引用这条消息.
* @see from 消息来源. 若是好友发送
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
fun
MessageSource
.
quote
(
sender
:
QQ
):
QuoteReplyToSend
{
if
(
this
.
groupId
!=
0L
)
{
check
(
sender
is
Member
)
{
"sender must be Member to quote a GroupMessage"
}
}
return
QuoteReplyToSend
(
this
,
sender
)
fun
MessageSource
.
quote
(
from
:
QQ
?
):
QuoteReplyToSend
{
return
if
(
this
.
groupId
!=
0L
)
{
check
(
from
is
Member
)
{
"sender must be Member to quote a GroupMessage"
}
QuoteReplyToSend
.
ToGroup
(
this
,
from
)
}
else
QuoteReplyToSend
.
ToFriend
(
this
)
}
\ 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