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
23adcf6d
Commit
23adcf6d
authored
Feb 09, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Quote reply support
parent
33867d04
Changes
25
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
273 additions
and
305 deletions
+273
-305
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/ContactDTO.kt
...kotlin/net/mamoe/mirai/api/http/data/common/ContactDTO.kt
+5
-6
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
...ommonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
+29
-24
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
...mmonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
+3
-5
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/ProtoBufWithNullableSupport.kt
...qqandroid/io/serialization/ProtoBufWithNullableSupport.kt
+4
-10
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/SerializationUtils.kt
...oe/mirai/qqandroid/io/serialization/SerializationUtils.kt
+1
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/MessageQQA.kt
...in/kotlin/net/mamoe/mirai/qqandroid/message/MessageQQA.kt
+14
-13
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/MessageSourceFromMsg.kt
...net/mamoe/mirai/qqandroid/message/MessageSourceFromMsg.kt
+21
-30
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/QuoteReplyImpl.kt
...otlin/net/mamoe/mirai/qqandroid/message/QuoteReplyImpl.kt
+0
-17
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
...moe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+74
-122
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
...tlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
+3
-4
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/Codec.kt
...kotlin/net/mamoe/mirai/qqandroid/network/highway/Codec.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Msg.kt
.../mamoe/mirai/qqandroid/network/protocol/data/proto/Msg.kt
+13
-13
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
+8
-13
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/Guid.kt
...commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/Guid.kt
+1
-6
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
...re/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
+22
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
...e/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
+18
-10
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Permission.kt
...c/commonMain/kotlin/net.mamoe.mirai/contact/Permission.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
...-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
+5
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/Packet.kt
...core/src/commonMain/kotlin/net.mamoe.mirai/data/Packet.kt
+5
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessagePacket.kt
...ommonMain/kotlin/net.mamoe.mirai/message/MessagePacket.kt
+9
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/At.kt
.../src/commonMain/kotlin/net.mamoe.mirai/message/data/At.kt
+2
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
...nMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
+3
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
...Main/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
+6
-20
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
...monMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
+20
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
+5
-1
No files found.
mirai-api-http/src/main/kotlin/net/mamoe/mirai/api/http/data/common/ContactDTO.kt
View file @
23adcf6d
...
...
@@ -10,10 +10,8 @@
package
net.mamoe.mirai.api.http.data.common
import
kotlinx.serialization.Serializable
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.Member
import
net.mamoe.mirai.contact.MemberPermission
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.contact.*
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
@Serializable
abstract
class
ContactDTO
:
DTO
{
...
...
@@ -38,8 +36,8 @@ data class MemberDTO(
val
permission
:
MemberPermission
,
val
group
:
GroupDTO
)
:
ContactDTO
()
{
constructor
(
member
:
Member
)
:
this
(
member
.
id
,
member
.
groupCard
,
member
.
permission
,
constructor
(
member
:
Member
)
:
this
(
member
.
id
,
member
.
groupCard
OrNick
,
member
.
permission
,
GroupDTO
(
member
.
group
)
)
}
...
...
@@ -50,5 +48,6 @@ data class GroupDTO(
val
name
:
String
,
val
permission
:
MemberPermission
)
:
ContactDTO
()
{
@UseExperimental
(
MiraiExperimentalAPI
::
class
)
constructor
(
group
:
Group
)
:
this
(
group
.
id
,
group
.
name
,
group
.
botPermission
)
}
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
View file @
23adcf6d
...
...
@@ -48,6 +48,8 @@ internal abstract class ContactImpl : Contact {
internal class
QQImpl
(
bot
:
QQAndroidBot
,
override
val
coroutineContext
:
CoroutineContext
,
override
val
id
:
Long
)
:
ContactImpl
(),
QQ
{
override
val
bot
:
QQAndroidBot
by
bot
.
unsafeWeakRef
()
override
lateinit
var
nick
:
String
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
{
bot
.
network
.
run
{
check
(
...
...
@@ -186,20 +188,10 @@ internal class MemberImpl(
override
val
bot
:
QQAndroidBot
get
()
=
qq
.
bot
override
suspend
fun
mute
(
durationSeconds
:
Int
):
Boolean
{
if
(
bot
.
uin
==
this
.
qq
.
id
)
{
return
false
}
//判断有无禁言权限
val
myPermission
=
group
.
botPermission
val
targetPermission
=
this
.
permission
if
(
myPermission
!=
MemberPermission
.
OWNER
)
{
if
(
targetPermission
==
MemberPermission
.
OWNER
||
targetPermission
==
MemberPermission
.
ADMINISTRATOR
)
{
return
false
}
}
else
if
(
myPermission
==
MemberPermission
.
MEMBER
)
{
if
(
group
.
botPermission
!=
MemberPermission
.
OWNER
&&
(!
group
.
botPermission
.
isOperator
()
||
this
.
isOperator
()))
{
return
false
}
return
try
{
bot
.
network
.
run
{
TroopManagement
.
Mute
(
client
=
bot
.
client
,
...
...
@@ -208,17 +200,30 @@ internal class MemberImpl(
timeInSecond
=
durationSeconds
).
sendAndExpect
<
TroopManagement
.
Mute
.
Response
>()
}
true
}
catch
(
e
:
Exception
)
{
false
}
return
true
}
override
suspend
fun
unmute
():
Boolean
{
return
mute
(
0
)
if
(
group
.
botPermission
!=
MemberPermission
.
OWNER
&&
(!
group
.
botPermission
.
isOperator
()
||
this
.
isOperator
()))
{
return
false
}
bot
.
network
.
run
{
TroopManagement
.
Mute
(
client
=
bot
.
client
,
groupCode
=
group
.
id
,
memberUin
=
this
@MemberImpl
.
id
,
timeInSecond
=
0
).
sendAndExpect
<
TroopManagement
.
Mute
.
Response
>()
}
return
true
}
override
suspend
fun
kick
(
message
:
String
):
Boolean
{
if
(
group
.
botPermission
!=
MemberPermission
.
OWNER
&&
(!
group
.
botPermission
.
isOperator
()
||
this
.
isOperator
()))
{
return
false
}
bot
.
network
.
run
{
return
TroopManagement
.
Kick
(
client
=
bot
.
client
,
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
View file @
23adcf6d
...
...
@@ -18,10 +18,7 @@ import net.mamoe.mirai.event.events.BotEvent
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.utils.BotConfiguration
import
net.mamoe.mirai.utils.Context
import
net.mamoe.mirai.utils.LockFreeLinkedList
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.*
import
kotlin.coroutines.CoroutineContext
@UseExperimental
(
MiraiInternalAPI
::
class
)
...
...
@@ -37,7 +34,8 @@ internal abstract class QQAndroidBotBase constructor(
account
:
BotAccount
,
configuration
:
BotConfiguration
)
:
BotImpl
<
QQAndroidBotNetworkHandler
>(
account
,
configuration
)
{
val
client
:
QQAndroidClient
=
QQAndroidClient
(
context
,
account
,
bot
=
@Suppress
(
"LeakingThis"
)
this
as
QQAndroidBot
)
val
client
:
QQAndroidClient
=
QQAndroidClient
(
context
,
account
,
bot
=
@Suppress
(
"LeakingThis"
)
this
as
QQAndroidBot
,
device
=
configuration
.
deviceInfo
?.
invoke
(
context
)
?:
SystemDeviceInfo
(
context
))
internal
var
firstLoginSucceed
:
Boolean
=
false
override
val
uin
:
Long
get
()
=
client
.
uin
override
val
qqs
:
ContactList
<
QQ
>
=
ContactList
(
LockFreeLinkedList
())
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/ProtoBufWithNullableSupport.kt
View file @
23adcf6d
/*
* Copyright 2020 Mamoe Technologies and contributors.
* Copyright 2017-2019 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 license.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
/*
* Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
* Some code changed by Mamoe is annotated around "MIRAI MODIFY START" and "MIRAI MODIFY END"
*/
package
net.mamoe.mirai.qqandroid.io.serialization
...
...
@@ -73,7 +67,7 @@ class ProtoBufWithNullableSupport(context: SerialModule = EmptyModule) : Abstrac
override
fun
SerialDescriptor
.
getTag
(
index
:
Int
)
=
this
.
getProtoDesc
(
index
)
// MIRAI MODIFY START
:
// MIRAI MODIFY START
override
fun
encodeTaggedNull
(
tag
:
ProtoDesc
)
{
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/io/serialization/SerializationUtils.kt
View file @
23adcf6d
...
...
@@ -20,6 +20,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestDataVersion3
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPacket
import
net.mamoe.mirai.utils.firstValue
import
net.mamoe.mirai.utils.io.read
import
net.mamoe.mirai.utils.io.toUHexString
fun
<
T
:
JceStruct
>
ByteArray
.
loadAs
(
deserializer
:
DeserializationStrategy
<
T
>,
c
:
JceCharset
=
JceCharset
.
UTF8
):
T
{
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/MessageQQA.kt
View file @
23adcf6d
...
...
@@ -189,10 +189,8 @@ internal fun MessageChain.toRichTextElems(): MutableList<ImMsgBody.Elem> {
if
(
this
.
any
<
QuoteReply
>())
{
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
MessageSourceFromServer
->
elements
.
add
(
ImMsgBody
.
Elem
(
srcMsg
=
source
.
delegate
))
is
MessageSourceFromMsg
->
elements
.
add
(
ImMsgBody
.
Elem
(
srcMsg
=
source
.
toJceData
()))
else
->
error
(
"unsupported MessageSource implementation: ${source::class.simpleName}"
)
}
}
...
...
@@ -204,16 +202,19 @@ internal fun MessageChain.toRichTextElems(): MutableList<ImMsgBody.Elem> {
is
CustomFaceFromFile
->
elements
.
add
(
ImMsgBody
.
Elem
(
customFace
=
it
.
toJceData
()))
is
CustomFaceFromServer
->
elements
.
add
(
ImMsgBody
.
Elem
(
customFace
=
it
.
delegate
))
is
NotOnlineImageFromServer
->
elements
.
add
(
ImMsgBody
.
Elem
(
notOnlineImage
=
it
.
delegate
))
is
NotOnlineImageFromFile
->
elements
.
add
(
ImMsgBody
.
Elem
(
notOnlineImage
=
it
.
toJceData
(),
generalFlags
=
ImMsgBody
.
GeneralFlags
(
pbReserve
=
"78 00 F8 01 00 C8 02 00"
.
hexToBytes
()
)
)
)
is
NotOnlineImageFromFile
->
elements
.
add
(
ImMsgBody
.
Elem
(
notOnlineImage
=
it
.
toJceData
()))
is
QuoteReply
,
is
MessageSource
->
{
}
else
->
error
(
"unsupported message type: ${it::class.simpleName}"
)
}
}
// if(this.any<QuoteReply>()){
elements
.
add
(
ImMsgBody
.
Elem
(
generalFlags
=
ImMsgBody
.
GeneralFlags
(
pbReserve
=
"78 00 F8 01 00 C8 02 00"
.
hexToBytes
())))
// }
return
elements
}
...
...
@@ -275,12 +276,12 @@ internal class NotOnlineImageFromServer(
internal
fun
MsgComm
.
Msg
.
toMessageChain
():
MessageChain
{
val
elems
=
this
.
msgBody
.
richText
.
elems
val
message
=
MessageChain
(
initialCapacity
=
elems
.
size
)
val
message
=
MessageChain
(
initialCapacity
=
elems
.
size
+
1
)
message
.
add
(
MessageSourceFromMsg
(
delegate
=
this
))
elems
.
forEach
{
when
{
it
.
srcMsg
!=
null
->
message
.
add
(
QuoteReply
Impl
(
MessageSourceFromServer
(
it
.
srcMsg
)))
it
.
srcMsg
!=
null
->
message
.
add
(
QuoteReply
(
MessageSourceFromServer
(
it
.
srcMsg
)))
it
.
notOnlineImage
!=
null
->
message
.
add
(
NotOnlineImageFromServer
(
it
.
notOnlineImage
))
it
.
customFace
!=
null
->
message
.
add
(
CustomFaceFromServer
(
it
.
customFace
))
it
.
text
!=
null
->
{
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/MessageSourceFromMsg.kt
View file @
23adcf6d
...
...
@@ -9,22 +9,19 @@
package
net.mamoe.mirai.qqandroid.message
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.message.data.MessageSource
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.utils.cryptor.contentToString
import
net.mamoe.mirai.utils.io.toUHexString
import
kotlin.jvm.JvmStatic
internal
inline
class
MessageSourceFromServer
(
val
delegate
:
ImMsgBody
.
SourceMsg
)
:
MessageSource
{
override
val
originalSeq
:
Int
get
()
=
delegate
.
origSeqs
!!
.
first
()
override
val
senderId
:
Long
get
()
=
delegate
.
senderUin
override
val
groupId
:
Long
get
()
=
delegate
.
toUin
override
val
time
:
Int
get
()
=
delegate
.
time
override
val
messageUid
:
Long
get
()
=
delegate
.
pbReserve
.
loadAs
(
SourceMsg
.
ResvAttr
.
serializer
()).
origUids
!!
override
fun
toString
():
String
=
""
}
...
...
@@ -32,52 +29,46 @@ internal inline class MessageSourceFromServer(
internal
inline
class
MessageSourceFromMsg
(
val
delegate
:
MsgComm
.
Msg
)
:
MessageSource
{
override
val
originalSeq
:
Int
get
()
=
delegate
.
msgHead
.
msgSeq
override
val
senderId
:
Long
get
()
=
delegate
.
msgHead
.
fromUin
override
val
groupId
:
Long
get
()
=
delegate
.
msgHead
.
toUin
override
val
time
:
Int
get
()
=
delegate
.
msgHead
.
msgTime
override
val
messageUid
:
Long
get
()
=
delegate
.
msgBody
.
richText
.
attr
!!
.
random
.
toLong
()
fun
toJceData
():
ImMsgBody
.
SourceMsg
{
val
groupUin
=
Group
.
calculateGroupIdByGroupCode
(
delegate
.
msgHead
.
groupInfo
!!
.
groupCode
)
return
ImMsgBody
.
SourceMsg
(
origSeqs
=
listOf
(
delegate
.
msgHead
.
msgSeq
),
senderUin
=
delegate
.
msgHead
.
fromUin
,
toUin
=
delegate
.
msgHead
.
groupInfo
!!
.
groupCode
,
toUin
=
groupUin
,
flag
=
1
,
elems
=
delegate
.
toMessageChain
().
toRichTextElems
()
,
elems
=
delegate
.
msgBody
.
richText
.
elems
,
type
=
0
,
time
=
delegate
.
msgHead
.
msgTime
,
pbReserve
=
SourceMsg
.
ResvAttr
(
origUids
=
delegate
.
msgBody
.
richText
.
attr
!!
.
random
.
toLong
()
//,
//oriMsgtype = delegate.msgHead.msgType
).
toByteArray
(
SourceMsg
.
ResvAttr
.
serializer
()).
also
{
println
(
"pbReserve="
+
it
.
toUHexString
())
},
// PbReserve(delegate.msgBody.richText.attr!!.random.toLong()).toByteArray(PbReserve.serializer()).also { println("pbReserve=" + it.toUHexString()) },
origUids
=
messageUid
).
toByteArray
(
SourceMsg
.
ResvAttr
.
serializer
()),
srcMsg
=
MsgComm
.
Msg
(
msgHead
=
MsgComm
.
MsgHead
(
fromUin
=
delegate
.
msgHead
.
fromUin
,
// qq
toUin
=
delegate
.
msgHead
.
groupInfo
.
groupCode
,
// group
msgType
=
delegate
.
msgHead
.
msgType
.
also
{
println
(
"msgType=$it"
)
}
,
// 82?
toUin
=
groupUin
,
// group
msgType
=
delegate
.
msgHead
.
msgType
,
// 82?
c2cCmd
=
delegate
.
msgHead
.
c2cCmd
,
msgSeq
=
delegate
.
msgHead
.
msgSeq
,
msgTime
=
delegate
.
msgHead
.
msgTime
,
msgUid
=
delegate
.
msgBody
.
richText
.
attr
.
random
.
toLong
()
,
// ok
msgUid
=
messageUid
,
// ok
groupInfo
=
MsgComm
.
GroupInfo
(
groupCode
=
delegate
.
msgHead
.
groupInfo
.
groupCode
),
isSrcMsg
=
true
),
msgBody
=
ImMsgBody
.
MsgBody
(
richText
=
ImMsgBody
.
RichText
(
elems
=
delegate
.
toMessageChain
().
toRichTextElems
().
apply
{
add
(
ImMsgBody
.
Elem
(
elemFlags2
=
ImMsgBody
.
ElemFlags2
()))
}
elems
=
delegate
.
msgBody
.
richText
.
elems
.
also
{
if
(
it
.
last
().
elemFlags2
==
null
)
it
.
add
(
ImMsgBody
.
Elem
(
elemFlags2
=
ImMsgBody
.
ElemFlags2
()))
}
)
)
).
toByteArray
(
MsgComm
.
Msg
.
serializer
())
)
).
toByteArray
(
MsgComm
.
Msg
.
serializer
()).
also
{
println
(
"srcMsg="
+
it
.
toUHexString
())
}
// fucking slow
).
also
{
println
(
it
.
contentToString
())
}
}
override
fun
toString
():
String
=
""
companion
object
{
@JvmStatic
val
PB_RESERVE_HEAD
=
byteArrayOf
(
0
x18
)
@JvmStatic
val
PB_RESERVE_TAIL
=
byteArrayOf
(
1
)
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/QuoteReplyImpl.kt
deleted
100644 → 0
View file @
33867d04
/*
* Copyright 2020 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package
net.mamoe.mirai.qqandroid.message
import
net.mamoe.mirai.message.data.MessageSource
import
net.mamoe.mirai.message.data.QuoteReply
class
QuoteReplyImpl
(
override
val
source
:
MessageSource
)
:
QuoteReply
{
override
fun
toString
():
kotlin
.
String
=
""
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
View file @
23adcf6d
...
...
@@ -43,7 +43,6 @@ import net.mamoe.mirai.utils.io.*
import
kotlin.coroutines.CoroutineContext
import
kotlin.jvm.Volatile
import
kotlin.time.ExperimentalTime
import
kotlin.time.measureTime
@Suppress
(
"MemberVisibilityCanBePrivate"
)
@UseExperimental
(
MiraiInternalAPI
::
class
)
...
...
@@ -131,8 +130,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
bot
.
qqs
.
delegate
.
clear
()
bot
.
groups
.
delegate
.
clear
()
val
friendListLoadTime
=
async
{
measureTime
{
val
friendListJob
=
launch
{
try
{
bot
.
logger
.
info
(
"开始加载好友信息"
)
var
currentFriendCount
=
0
...
...
@@ -164,34 +162,21 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
bot
.
logger
.
error
(
"加载好友列表失败|一般这是由于加载过于频繁导致/将以热加载方式加载好友列表"
)
}
}
}
val
groupInfo
=
mutableMapOf
<
Long
,
Int
>()
val
groupTime
=
async
{
measureTime
{
val
groupJob
=
launch
{
try
{
bot
.
logger
.
info
(
"开始加载群组列表与群成员列表"
)
val
troopListData
=
FriendList
.
GetTroopListSimplify
(
bot
.
client
)
.
sendAndExpect
<
FriendList
.
GetTroopListSimplify
.
Response
>(
timeoutMillis
=
5000
,
retry
=
2
)
// println("获取到群数量" + troopData.groups.size)
val
toGet
:
MutableMap
<
GroupImpl
,
ContactList
<
Member
>>
=
mutableMapOf
()
.
sendAndExpect
<
FriendList
.
GetTroopListSimplify
.
Response
>(
retry
=
2
)
troopListData
.
groups
.
forEach
{
troopNum
->
val
contactList
=
ContactList
(
LockFreeLinkedList
<
Member
>())
val
groupInfoResponse
=
try
{
val
groupInfoResponse
=
TroopManagement
.
GetGroupOperationInfo
(
client
=
bot
.
client
,
groupCode
=
troopNum
.
groupCode
).
sendAndExpect
<
TroopManagement
.
GetGroupOperationInfo
.
Response
>()
}
catch
(
e
:
Exception
)
{
bot
.
logger
.
info
(
"获取"
+
troopNum
.
groupCode
+
"的群设置失败"
)
TroopManagement
.
GetGroupOperationInfo
.
Response
(
allowAnonymousChat
=
false
,
allowMemberInvite
=
false
,
autoApprove
=
false
,
confessTalk
=
false
)
}
val
group
=
GroupImpl
(
bot
=
bot
,
...
...
@@ -207,15 +192,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
_anonymousChat
=
groupInfoResponse
.
allowAnonymousChat
,
members
=
contactList
)
toGet
[
group
]
=
contactList
bot
.
groups
.
delegate
.
addLast
(
group
)
launch
{
try
{
fillTroopMemberList
(
group
,
contactList
,
troopNum
.
dwGroupOwnerUin
)
groupInfo
[
troopNum
.
groupCode
]
=
contactList
.
size
}
catch
(
e
:
Exception
)
{
groupInfo
[
troopNum
.
groupCode
]
=
-
1
bot
.
logger
.
warning
(
"群${troopNum.groupCode}的列表拉取失败, 将采用动态加入"
)
bot
.
logger
.
error
(
"群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试"
)
bot
.
logger
.
error
(
e
)
}
}
...
...
@@ -226,38 +208,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
bot
.
logger
.
error
(
e
)
}
}
}
//===log===//
fun
fillUntil
(
long
:
Number
,
size
:
Int
):
String
{
val
x
=
long
.
toString
()
return
x
+
" "
.
repeat
(
if
(
size
-
x
.
length
>
0
)
{
size
-
x
.
length
}
else
{
0
}
)
}
joinAll
(
friendListLoadTime
,
groupTime
)
bot
.
logger
.
info
(
"====================Mirai Bot List初始化完毕===================="
)
bot
.
logger
.
info
(
"好友数量: ${fillUntil(bot.qqs.size, 9)}\t\t\t 加载时间: ${friendListLoadTime.await().inMilliseconds}ms"
)
bot
.
logger
.
info
(
"加入群组: ${fillUntil(bot.groups.size, 9)}\t\t\t 加载时间: ${groupTime.await().inMilliseconds}ms"
)
groupInfo
.
forEach
{
if
(
it
.
value
==
-
1
)
{
bot
.
logger
.
error
(
"群组号码: ${fillUntil(it.key, 9)}\t 成员数量加载失败"
)
}
else
{
bot
.
logger
.
info
(
"群组号码: ${fillUntil(it.key, 9)}\t 成员数量: ${fillUntil(
it
.
value
,
4
)}
\
t
BOT
权限
:
" + bot.groups[it.key].botPermission.toString() + ""
)
}
}
bot
.
logger
.
info
(
"====================Mirai Bot List初始化完毕===================="
)
joinAll
(
friendListJob
,
groupJob
)
this
@QQAndroidBotNetworkHandler
.
launch
(
CoroutineName
(
"Heartbeat"
))
{
while
(
this
.
isActive
)
{
...
...
@@ -302,23 +254,23 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
targetGroupCode
=
group
.
id
,
nextUin
=
nextUin
).
sendAndExpect
<
FriendList
.
GetTroopMemberList
.
Response
>(
timeoutMillis
=
3000
)
data
.
members
.
forEach
{
data
.
members
.
forEach
{
troopMemberInfo
->
val
member
=
MemberImpl
(
qq
=
bot
.
QQ
(
it
.
memberUin
)
as
QQImpl
,
_groupCard
=
it
.
autoRemark
?:
it
.
nick
,
_specialTitle
=
it
.
sSpecialTitle
?:
""
,
qq
=
(
bot
.
QQ
(
troopMemberInfo
.
memberUin
)
as
QQImpl
).
also
{
it
.
nick
=
troopMemberInfo
.
nick
}
,
_groupCard
=
troopMemberInfo
.
sName
?:
""
,
_specialTitle
=
troopMemberInfo
.
sSpecialTitle
?:
""
,
group
=
group
,
coroutineContext
=
group
.
coroutineContext
,
permission
=
when
{
it
.
memberUin
==
owner
->
MemberPermission
.
OWNER
it
.
dwFlag
==
1L
->
MemberPermission
.
ADMINISTRATOR
troopMemberInfo
.
memberUin
==
owner
->
MemberPermission
.
OWNER
troopMemberInfo
.
dwFlag
==
1L
->
MemberPermission
.
ADMINISTRATOR
else
->
MemberPermission
.
MEMBER
}
)
if
(
member
.
permission
==
MemberPermission
.
OWNER
)
{
group
.
owner
=
member
}
if
(
it
.
memberUin
!=
bot
.
uin
)
{
if
(
troopMemberInfo
.
memberUin
!=
bot
.
uin
)
{
list
.
delegate
.
addLast
(
member
)
}
else
{
group
.
botPermission
=
member
.
permission
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
View file @
23adcf6d
...
...
@@ -20,12 +20,11 @@ import net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import
net.mamoe.mirai.qqandroid.network.protocol.packet.PacketLogger
import
net.mamoe.mirai.qqandroid.network.protocol.packet.Tlv
import
net.mamoe.mirai.
qqandroid.
utils.DeviceInfo
import
net.mamoe.mirai.utils.DeviceInfo
import
net.mamoe.mirai.qqandroid.utils.NetworkType
import
net.mamoe.mirai.
qqandroid.
utils.SystemDeviceInfo
import
net.mamoe.mirai.utils.SystemDeviceInfo
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.cryptor.ECDH
import
net.mamoe.mirai.utils.cryptor.contentToString
import
net.mamoe.mirai.utils.cryptor.decryptBy
import
net.mamoe.mirai.utils.io.*
...
...
@@ -105,7 +104,7 @@ internal open class QQAndroidClient(
val
apkVersionName
:
ByteArray
get
()
=
"8.2.0"
.
toByteArray
()
val
buildVer
:
String
get
()
=
"8.2.0.1296"
private
val
messageSequenceId
:
AtomicInt
=
atomic
(
0
)
private
val
messageSequenceId
:
AtomicInt
=
atomic
(
22911
)
internal
fun
atomicNextMessageSequenceId
():
Int
=
messageSequenceId
.
getAndAdd
(
2
)
private
val
requestPacketRequestId
:
AtomicInt
=
atomic
(
1921334513
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/Codec.kt
View file @
23adcf6d
...
...
@@ -80,7 +80,7 @@ object Highway {
writeFully
(
head
)
check
(
body
.
copyTo
(
this
).
toInt
()
==
bodySize
)
{
"bad body size"
}
writeByte
(
41
)
}
.
also
{
println
(
it
.
remaining
)
}
}
}
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Msg.kt
View file @
23adcf6d
...
...
@@ -356,7 +356,7 @@ internal class ImMsgBody : ProtoBuf {
@SerialId
(
26
)
val
conferenceTipsInfo
:
ConferenceTipsInfo
?
=
null
,
@SerialId
(
27
)
val
redbagInfo
:
RedBagInfo
?
=
null
,
@SerialId
(
28
)
val
lowVersionTips
:
LowVersionTips
?
=
null
,
@SerialId
(
29
)
val
bankcodeCtrlInfo
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@SerialId
(
29
)
val
bankcodeCtrlInfo
:
ByteArray
?
=
null
,
@SerialId
(
30
)
val
nearByMsg
:
NearByMessageType
?
=
null
,
@SerialId
(
31
)
val
customElem
:
CustomElem
?
=
null
,
@SerialId
(
32
)
val
locationInfo
:
LocationInfo
?
=
null
,
...
...
@@ -1142,7 +1142,7 @@ internal class ImReceipt : ProtoBuf {
)
:
ProtoBuf
@Serializable
data
internal
class
ReceiptResp
(
internal
data
class
ReceiptResp
(
@SerialId
(
1
)
val
command
:
Int
/* enum */
=
1
,
@SerialId
(
2
)
val
receiptInfo
:
ReceiptInfo
?
=
null
)
:
ProtoBuf
...
...
@@ -1194,10 +1194,10 @@ internal class Submsgtype0xc7 : ProtoBuf {
@SerialId
(
2
)
val
srcUin
:
Long
=
0L
,
@SerialId
(
3
)
val
dstUin
:
Long
=
0L
,
@SerialId
(
4
)
val
changeType
:
Int
/* enum */
=
1
,
@SerialId
(
5
)
val
msgRelationalChainInfoOld
:
Submsgtype0xc7
.
RelationalChainInfo
?
=
null
,
@SerialId
(
6
)
val
msgRelationalChainInfoNew
:
Submsgtype0xc7
.
RelationalChainInfo
?
=
null
,
@SerialId
(
7
)
val
msgToDegradeInfo
:
Submsgtype0xc7
.
ToDegradeInfo
?
=
null
,
@SerialId
(
20
)
val
relationalChainInfos
:
List
<
Submsgtype0xc7
.
RelationalChainInfos
>?
=
null
,
@SerialId
(
5
)
val
msgRelationalChainInfoOld
:
RelationalChainInfo
?
=
null
,
@SerialId
(
6
)
val
msgRelationalChainInfoNew
:
RelationalChainInfo
?
=
null
,
@SerialId
(
7
)
val
msgToDegradeInfo
:
ToDegradeInfo
?
=
null
,
@SerialId
(
20
)
val
relationalChainInfos
:
List
<
RelationalChainInfos
>?
=
null
,
@SerialId
(
100
)
val
uint32FeatureId
:
List
<
Int
>?
=
null
)
:
ProtoBuf
...
...
@@ -1235,8 +1235,8 @@ internal class Submsgtype0xc7 : ProtoBuf {
internal
class
ForwardBody
(
@SerialId
(
1
)
val
notifyType
:
Int
=
0
,
@SerialId
(
2
)
val
opType
:
Int
=
0
,
@SerialId
(
3000
)
val
msgHotFriendNotify
:
Submsgtype0xc7
.
HotFriendNotify
?
=
null
,
@SerialId
(
4000
)
val
msgRelationalChainChange
:
Submsgtype0xc7
.
RelationalChainChange
?
=
null
@SerialId
(
3000
)
val
msgHotFriendNotify
:
HotFriendNotify
?
=
null
,
@SerialId
(
4000
)
val
msgRelationalChainChange
:
RelationalChainChange
?
=
null
)
:
ProtoBuf
@Serializable
...
...
@@ -1277,24 +1277,24 @@ internal class Submsgtype0xc7 : ProtoBuf {
@SerialId
(
303
)
val
lastBoatTime
:
Int
=
0
,
@SerialId
(
304
)
val
boatWording
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@SerialId
(
400
)
val
notifyType
:
Int
=
0
,
@SerialId
(
401
)
val
msgFriendshipFlagNotify
:
Submsgtype0xc7
.
FriendShipFlagNotify
?
=
null
@SerialId
(
401
)
val
msgFriendshipFlagNotify
:
FriendShipFlagNotify
?
=
null
)
:
ProtoBuf
@Serializable
internal
class
RelationalChainInfos
(
@SerialId
(
1
)
val
msgRelationalChainInfoOld
:
Submsgtype0xc7
.
RelationalChainInfo
?
=
null
,
@SerialId
(
2
)
val
msgRelationalChainInfoNew
:
Submsgtype0xc7
.
RelationalChainInfo
?
=
null
@SerialId
(
1
)
val
msgRelationalChainInfoOld
:
RelationalChainInfo
?
=
null
,
@SerialId
(
2
)
val
msgRelationalChainInfoNew
:
RelationalChainInfo
?
=
null
)
:
ProtoBuf
@Serializable
internal
class
ToDegradeInfo
(
@SerialId
(
1
)
val
toDegradeItem
:
List
<
Submsgtype0xc7
.
ToDegradeItem
>?
=
null
,
@SerialId
(
1
)
val
toDegradeItem
:
List
<
ToDegradeItem
>?
=
null
,
@SerialId
(
2
)
val
nick
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@SerialId
(
3
)
val
notifyTime
:
Long
=
0L
)
:
ProtoBuf
@Serializable
internal
class
MsgBody
(
@SerialId
(
1
)
val
msgModInfos
:
List
<
Submsgtype0xc7
.
ForwardBody
>?
=
null
@SerialId
(
1
)
val
msgModInfos
:
List
<
ForwardBody
>?
=
null
)
:
ProtoBuf
}
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.kt
View file @
23adcf6d
...
...
@@ -22,6 +22,8 @@ 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.toMessageChain
import
net.mamoe.mirai.qqandroid.message.toRichTextElems
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPushForceOffline
import
net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPushNotify
...
...
@@ -30,8 +32,6 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgSvc
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.SyncCookie
import
net.mamoe.mirai.qqandroid.network.protocol.packet.*
import
net.mamoe.mirai.qqandroid.message.toMessageChain
import
net.mamoe.mirai.qqandroid.message.toRichTextElems
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.currentTimeSeconds
import
kotlin.math.absoluteValue
...
...
@@ -184,8 +184,8 @@ internal class MessageSvc {
override
fun
toString
():
String
=
"MessageSvc.PbSendMsg.Response.SUCCESS"
}
data class
Failed
(
val
errorCode
:
Int
,
val
errorMessage
:
String
)
:
Response
()
{
override
fun
toString
():
String
=
"MessageSvc.PbSendMsg.Response.Failed(errorCode=$errorCode, errorMessage=$errorMessage)"
data class
Failed
(
val
resultType
:
Int
,
val
errorCode
:
Int
,
val
errorMessage
:
String
)
:
Response
()
{
override
fun
toString
():
String
=
"MessageSvc.PbSendMsg.Response.Failed(
resultType=$resultType,
errorCode=$errorCode, errorMessage=$errorMessage)"
}
}
...
...
@@ -236,21 +236,16 @@ internal class MessageSvc {
writeProtoBuf
(
MsgSvc
.
PbSendMsgReq
.
serializer
(),
MsgSvc
.
PbSendMsgReq
(
routingHead
=
MsgSvc
.
RoutingHead
(
grp
=
MsgSvc
.
Grp
(
groupCode
=
groupCode
)),
contentHead
=
MsgComm
.
ContentHead
(
pkgNum
=
1
,
divSeq
=
seq
),
contentHead
=
MsgComm
.
ContentHead
(
pkgNum
=
1
),
msgBody
=
ImMsgBody
.
MsgBody
(
richText
=
ImMsgBody
.
RichText
(
elems
=
message
.
toRichTextElems
()
)
),
//
//
//
msgSeq
=
seq
,
msgRand
=
Random
.
nextInt
().
absoluteValue
,
syncCookie
=
EMPTY_BYTE_ARRAY
// ?: SyncCookie(time = currentTimeSeconds + client.timeDifference).toByteArray(SyncCookie.serializer()),
,
msgVia
=
1
syncCookie
=
EMPTY_BYTE_ARRAY
,
msgVia
=
1
)
)
}
...
...
@@ -260,7 +255,7 @@ internal class MessageSvc {
return
if
(
response
.
result
==
0
)
{
Response
.
SUCCESS
}
else
{
Response
.
Failed
(
response
.
errtype
,
response
.
errmsg
)
Response
.
Failed
(
response
.
result
,
response
.
errtype
,
response
.
errmsg
)
}
}
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/Guid.kt
View file @
23adcf6d
...
...
@@ -75,8 +75,3 @@ internal fun guidFlag(
flag
=
flag
or
(
macOrAndroidIdChangeFlag
.
value
shl
8
and
0
xFF00
)
return
flag
}
\ No newline at end of file
/**
* Defaults "%4;7t>;28<fc.5*6".toByteArray()
*/
fun
generateGuid
(
androidId
:
ByteArray
,
macAddress
:
ByteArray
):
ByteArray
=
md5
(
androidId
+
macAddress
)
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
View file @
23adcf6d
...
...
@@ -106,6 +106,28 @@ interface Group : Contact, CoroutineScope {
suspend
fun
quit
():
Boolean
companion
object
{
/**
* by @kar98k
*/
fun
calculateGroupIdByGroupCode
(
groupCode
:
Long
):
Long
{
var
left
:
Long
=
groupCode
/
1000000L
when
{
left
<=
10
->
left
+=
202
left
<=
19
->
left
+=
480
-
11
left
<=
66
->
left
+=
2100
-
20
left
<=
156
->
left
+=
2010
-
67
left
<=
209
->
left
+=
2147
-
157
left
<=
309
->
left
+=
4100
-
210
left
<=
499
->
left
+=
3800
-
310
}
return
left
*
1000000L
+
groupCode
%
1000000L
}
}
@MiraiExperimentalAPI
fun
toFullString
():
String
=
"Group(id=${this.id}, name=$name, owner=${owner.id}, members=${members.idContentString})"
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
View file @
23adcf6d
...
...
@@ -11,7 +11,8 @@
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.WeakRefProperty
import
kotlin.jvm.JvmName
import
kotlin.time.Duration
import
kotlin.time.ExperimentalTime
...
...
@@ -31,9 +32,11 @@ interface Member : QQ, Contact {
val
permission
:
MemberPermission
/**
* 群名片
* 群名片
. 可能为空.
*
* 在修改时将会异步上传至服务器. 无权限修改时将会抛出异常 [PermissionDeniedException]
*
* @see [groupCardOrNick] 获取非空群名片或昵称
*/
var
groupCard
:
String
...
...
@@ -48,7 +51,7 @@ interface Member : QQ, Contact {
* 禁言
*
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @return
仅
当机器人无权限禁言这个群成员时返回 `false`
* @return 当机器人无权限禁言这个群成员时返回 `false`
*
* @see Int.minutesToSeconds
* @see Int.hoursToSeconds
...
...
@@ -57,26 +60,31 @@ interface Member : QQ, Contact {
suspend
fun
mute
(
durationSeconds
:
Int
):
Boolean
/**
* 解除禁言. 在没有权限时会返回 `false`.
否则均返回 `true`.
* 解除禁言. 在没有权限时会返回 `false`.
*/
suspend
fun
unmute
():
Boolean
/**
* 踢出该成员. 机器人无权限时返回 `false`
*/
suspend
fun
kick
(
message
:
String
=
""
):
Boolean
/**
* 当且仅当 `[other] is [Member] && [other].id == this.id && [other].group == this.group` 时为 true
*/
override
fun
equals
(
other
:
Any
?):
Boolean
}
/**
* 获取非空群名片或昵称.
*
* 若 [群名片][Member.groupCard] 不为空则返回群名片, 为空则返回 [QQ.nick]
*/
val
Member
.
groupCardOrNick
:
String
get
()
=
this
.
groupCard
.
takeIf
{
it
.
isNotEmpty
()
}
?:
this
.
nick
@ExperimentalTime
suspend
inline
fun
Member
.
mute
(
duration
:
Duration
):
Boolean
{
require
(
duration
.
inDays
<=
30
)
{
"duration must be at most 1 month"
}
require
(
duration
.
inSeconds
>
0
)
{
"duration must be greater than 0 second"
}
return
this
.
mute
(
duration
.
inSeconds
.
toInt
())
}
\ No newline at end of file
@ExperimentalUnsignedTypes
suspend
inline
fun
Member
.
mute
(
durationSeconds
:
UInt
):
Boolean
{
require
(
durationSeconds
.
toInt
()
<=
30
*
24
*
3600
)
{
"duration must be at most 1 month"
}
return
this
.
mute
(
durationSeconds
.
toInt
())
// same bin rep.
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Permission.kt
View file @
23adcf6d
...
...
@@ -62,7 +62,7 @@ inline fun Member.isOwner(): Boolean = this.permission.isOwner()
inline
fun
Member
.
isAdministrator
():
Boolean
=
this
.
permission
.
isAdministrator
()
/**
*
时
管理员或群主
*
是
管理员或群主
*/
@Suppress
(
"NOTHING_TO_INLINE"
)
inline
fun
Member
.
isOperator
():
Boolean
=
this
.
permission
.
isOperator
()
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
View file @
23adcf6d
...
...
@@ -35,6 +35,11 @@ interface QQ : Contact, CoroutineScope {
*/
override
val
id
:
Long
/**
* 昵称
*/
val
nick
:
String
/**
* 请求头像下载链接
*/
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/data/Packet.kt
View file @
23adcf6d
...
...
@@ -14,7 +14,11 @@ package net.mamoe.mirai.data
*/
interface
Packet
object
NoPacket
:
Packet
object
NoPacket
:
Packet
{
override
fun
toString
():
String
{
return
"NoPacket"
}
}
/**
* PacketFactory 可以一次解析多个包出来. 它们将会被分别广播.
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessagePacket.kt
View file @
23adcf6d
...
...
@@ -89,6 +89,15 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) :
// endregion
// region
/**
* 引用这个消息.
*/
inline
fun
MessageChain
.
quote
():
MessageChain
=
this
.
quote
(
sender
as
?
Member
?:
error
(
"only group message can be quoted"
))
// endregion
// region 上传图片
suspend
inline
fun
ExternalImage
.
upload
():
Image
=
this
.
upload
(
subject
)
// endregion
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/At.kt
View file @
23adcf6d
...
...
@@ -12,6 +12,7 @@
package
net.mamoe.mirai.message.data
import
net.mamoe.mirai.contact.Member
import
net.mamoe.mirai.contact.groupCardOrNick
import
net.mamoe.mirai.utils.MiraiInternalAPI
...
...
@@ -20,7 +21,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
*/
class
At
@MiraiInternalAPI
constructor
(
val
target
:
Long
,
val
display
:
String
)
:
Message
{
@UseExperimental
(
MiraiInternalAPI
::
class
)
constructor
(
member
:
Member
)
:
this
(
member
.
id
,
"@${member.groupCard}"
)
constructor
(
member
:
Member
)
:
this
(
member
.
id
,
"@${member.groupCard
OrNick
}"
)
override
fun
toString
():
String
=
display
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageChain.kt
View file @
23adcf6d
...
...
@@ -135,18 +135,18 @@ inline fun List<Message>.toMessageChain(): MessageChain = MessageChain(this)
/**
* 获取第一个 [M] 类型的 [Message] 实例
*/
inline
fun
<
reified
M
:
Message
>
MessageChain
.
firstOrNull
():
M
essage
?
=
this
.
firstOrNull
{
it
is
M
}
inline
fun
<
reified
M
:
Message
>
MessageChain
.
firstOrNull
():
M
?
=
this
.
firstOrNull
{
it
is
M
}
as
M
?
/**
* 获取第一个 [M] 类型的 [Message] 实例
* @throws [NoSuchElementException] 如果找不到该类型的实例
*/
inline
fun
<
reified
M
:
Message
>
MessageChain
.
first
():
M
essage
=
this
.
first
{
it
is
M
}
inline
fun
<
reified
M
:
Message
>
MessageChain
.
first
():
M
=
this
.
first
{
it
is
M
}
as
M
/**
* 获取第一个 [M] 类型的 [Message] 实例
*/
inline
fun
<
reified
M
:
Message
>
MessageChain
.
any
():
Boolean
=
this
.
firstOrNull
{
it
is
M
}
!==
null
inline
fun
<
reified
M
:
Message
>
MessageChain
.
any
():
Boolean
=
this
.
any
{
it
is
M
}
/**
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/MessageSource.kt
View file @
23adcf6d
...
...
@@ -10,32 +10,18 @@
package
net.mamoe.mirai.message.data
/**
* 消息源, 用于被引用. 它将由协议模块实现为 `MessageSourceImpl`
* 消息源, 用于被引用. 它将由协议模块实现.
* 消息源只用于 [QuoteReply]
*
* `mirai-core-qqandroid`: `net.mamoe.mirai.qqandroid.message.MessageSourceFromMsg`
*/
interface
MessageSource
:
Message
{
companion
object
:
Message
.
Key
<
MessageSource
>
/* 以下属性均无 backing field, 即都是以 `get() =` 实现 */
/**
* 原消息序列号
*/
val
originalSeq
:
Int
/**
* 发送人 id
*/
val
senderId
:
Long
/**
* 群 id
*/
val
groupId
:
Long
/**
*
in seconds
*
实际上是个随机数, 但服务器确实是用它当做 uid
*/
val
time
:
Int
val
messageUid
:
Long
/**
* 固定返回空字符串 ("")
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/QuoteReply.kt
View file @
23adcf6d
...
...
@@ -9,12 +9,28 @@
package
net.mamoe.mirai.message.data
import
net.mamoe.mirai.contact.Member
import
net.mamoe.mirai.utils.MiraiInternalAPI
/**
* 群内的引用回复. 它将由协议模块实现为 `QuoteReplyImpl`
* 群内的引用回复.
* 总是使用 [quote] 来构造实例.
*/
interface
QuoteReply
:
Message
{
val
source
:
MessageSource
class
QuoteReply
@MiraiInternalAPI
constructor
(
val
source
:
MessageSource
)
:
Message
{
companion
object
Key
:
Message
.
Key
<
QuoteReply
>
override
fun
toString
():
String
=
""
}
/**
* 引用这条消息.
* 返回 `[QuoteReply] + [At] + [PlainText]`(必要的结构)
*/
fun
MessageChain
.
quote
(
sender
:
Member
):
MessageChain
{
this
.
firstOrNull
<
MessageSource
>()
?.
let
{
@UseExperimental
(
MiraiInternalAPI
::
class
)
return
QuoteReply
(
it
)
+
sender
.
at
()
+
" "
// required
}
error
(
"cannot find MessageSource"
)
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
View file @
23adcf6d
...
...
@@ -50,6 +50,10 @@ class ExternalImage(
data
:
ByteReadPacket
,
filename
:
String
):
ExternalImage
=
ExternalImage
(
width
,
height
,
md5
,
format
,
data
,
data
.
remaining
,
filename
)
fun
generateUUID
(
md5
:
ByteArray
):
String
{
return
"${md5[0..3]}-${md5[4..5]}-${md5[6..7]}-${md5[8..9]}-${md5[10..15]}"
}
}
val
format
:
String
=
...
...
@@ -83,7 +87,7 @@ class ExternalImage(
override
fun
toString
():
String
=
"[ExternalImage(${width}x$height $format)]"
fun
calculateImageResourceId
():
String
{
return
"{${
md5[0..3]}-${md5[4..5]}-${md5[6..7]}-${md5[8..9]}-${md5[10..15]
}}.$format"
return
"{${
generateUUID(md5)
}}.$format"
}
}
...
...
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