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
417276ac
Commit
417276ac
authored
Dec 02, 2019
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add mute and unmute
parent
8fa98f59
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
321 additions
and
32 deletions
+321
-32
UpdateLog.md
UpdateLog.md
+4
-2
gradle.properties
gradle.properties
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
.../src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
+31
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
...re/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
...e/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
+44
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt
...in/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt
+26
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
.../net.mamoe.mirai/event/internal/InternalEventListeners.kt
+5
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupPacket.kt
...e.mirai/network/protocol/tim/packet/action/GroupPacket.kt
+32
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/EventPacketFactory.kt
...i/network/protocol/tim/packet/event/EventPacketFactory.kt
+2
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberMute.kt
...moe.mirai/network/protocol/tim/packet/event/MemberMute.kt
+136
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Message.kt
....mamoe.mirai/network/protocol/tim/packet/event/Message.kt
+7
-4
mirai-debug/src/main/kotlin/HexDebuggerGui.kt
mirai-debug/src/main/kotlin/HexDebuggerGui.kt
+2
-2
mirai-debug/src/main/kotlin/PacketDebuger.kt
mirai-debug/src/main/kotlin/PacketDebuger.kt
+5
-3
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt
...rai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt
+25
-6
No files found.
UpdateLog.md
View file @
417276ac
...
...
@@ -2,5 +2,7 @@
## Main version 0
### 0.3.0
-
更新
\ No newline at end of file
### 0.6.0
-
新增: 禁言群成员
-
新增: 解禁群成员
-
修复: ContactList key 无法匹配
\ No newline at end of file
gradle.properties
View file @
417276ac
# style guide
kotlin.code.style
=
official
# config
mirai_version
=
0.
5.1
mirai_version
=
0.
6.0
kotlin.incremental.multiplatform
=
true
kotlin.parallel.tasks.in.project
=
true
# kotlin
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
View file @
417276ac
...
...
@@ -59,7 +59,7 @@ inline fun <R> Contact.withSession(block: BotSession.() -> R): R {
/**
* 只读联系人列表
*/
class
ContactList
<
C
:
Contact
>
@PublishedApi
internal
constructor
(
internal
val
delegate
:
MutableContactList
<
C
>)
:
Map
<
UInt
,
C
>
by
delegate
{
class
ContactList
<
C
:
Contact
>
@PublishedApi
internal
constructor
(
internal
val
delegate
:
MutableContactList
<
C
>)
:
Map
<
UInt
,
C
>
{
/**
* ID 列表的字符串表示.
* 如:
...
...
@@ -70,12 +70,41 @@ class ContactList<C : Contact> @PublishedApi internal constructor(internal val d
val
idContentString
:
String
get
()
=
this
.
keys
.
joinToString
(
prefix
=
"["
,
postfix
=
"]"
)
{
it
.
toLong
().
toString
()
}
override
fun
toString
():
String
=
delegate
.
toString
()
// TODO: 2019/12/2 应该使用属性代理, 但属性代理会导致 UInt 内联错误. 等待 kotlin 修复后替换
override
val
size
:
Int
get
()
=
delegate
.
size
override
fun
containsKey
(
key
:
UInt
):
Boolean
=
delegate
.
containsKey
(
key
)
override
fun
containsValue
(
value
:
C
):
Boolean
=
delegate
.
containsValue
(
value
)
override
fun
get
(
key
:
UInt
):
C
?
=
delegate
[
key
]
override
fun
isEmpty
():
Boolean
=
delegate
.
isEmpty
()
override
val
entries
:
MutableSet
<
MutableMap
.
MutableEntry
<
UInt
,
C
>>
get
()
=
delegate
.
entries
override
val
keys
:
MutableSet
<
UInt
>
get
()
=
delegate
.
keys
override
val
values
:
MutableCollection
<
C
>
get
()
=
delegate
.
values
}
/**
* 可修改联系人列表. 只会在内部使用.
*/
@PublishedApi
internal
class
MutableContactList
<
C
:
Contact
>
:
MutableMap
<
UInt
,
C
>
by
mutableMapOf
()
{
internal
class
MutableContactList
<
C
:
Contact
>
:
MutableMap
<
UInt
,
C
>
{
override
fun
toString
():
String
=
asIterable
().
joinToString
(
separator
=
", "
,
prefix
=
"ContactList("
,
postfix
=
")"
)
{
it
.
value
.
toString
()
}
// TODO: 2019/12/2 应该使用属性代理, 但属性代理会导致 UInt 内联错误. 等待 kotlin 修复后替换
private
val
delegate
=
mutableMapOf
<
UInt
,
C
>()
override
val
size
:
Int
get
()
=
delegate
.
size
override
fun
containsKey
(
key
:
UInt
):
Boolean
=
delegate
.
containsKey
(
key
)
override
fun
containsValue
(
value
:
C
):
Boolean
=
delegate
.
containsValue
(
value
)
override
fun
get
(
key
:
UInt
):
C
?
=
delegate
[
key
]
override
fun
isEmpty
():
Boolean
=
delegate
.
isEmpty
()
override
val
entries
:
MutableSet
<
MutableMap
.
MutableEntry
<
UInt
,
C
>>
get
()
=
delegate
.
entries
override
val
keys
:
MutableSet
<
UInt
>
get
()
=
delegate
.
keys
override
val
values
:
MutableCollection
<
C
>
get
()
=
delegate
.
values
override
fun
clear
()
=
delegate
.
clear
()
override
fun
put
(
key
:
UInt
,
value
:
C
):
C
?
=
delegate
.
put
(
key
,
value
)
override
fun
putAll
(
from
:
Map
<
out
UInt
,
C
>)
=
delegate
.
putAll
(
from
)
override
fun
remove
(
key
:
UInt
):
C
?
=
delegate
.
remove
(
key
)
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
View file @
417276ac
...
...
@@ -51,7 +51,7 @@ interface Group : Contact, Iterable<Member> {
/**
* 获取群成员. 若此 ID 的成员不存在, 则会抛出 [kotlin.NoSuchElementException]
*/
suspend
fun
getMember
(
id
:
UInt
):
Member
fun
getMember
(
id
:
UInt
):
Member
/**
* 更新群资料. 群资料会与服务器事件同步事件更新, 一般情况下不需要手动更新.
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Member.kt
View file @
417276ac
@
file
:
Suppress
(
"unused"
)
package
net.mamoe.mirai.contact
import
com.soywiz.klock.MonthSpan
import
com.soywiz.klock.TimeSpan
import
kotlin.time.Duration
import
kotlin.time.ExperimentalTime
/**
* 群成员.
*
* 使用 [QQ.equals]. 因此同 ID 的群成员和 QQ 是 `==` 的
*/
interface
Member
:
QQ
,
Contact
{
/**
...
...
@@ -15,8 +20,45 @@ interface Member : QQ, Contact {
* 权限
*/
val
permission
:
MemberPermission
/**
* 禁言
*
* @param durationSeconds 持续时间. 精确到秒. 范围区间表示为 `(0s, 30days]`. 超过范围则会抛出异常.
* @return 若机器人无权限禁言这个群成员, 返回 `false`
*/
suspend
fun
mute
(
durationSeconds
:
Int
):
Boolean
/**
* 解除禁言
*/
suspend
fun
unmute
()
}
@ExperimentalTime
suspend
inline
fun
Member
.
mute
(
duration
:
Duration
)
{
require
(
duration
.
inDays
>
30
)
{
"duration must be at most 1 month"
}
require
(
duration
.
inSeconds
>
0
)
{
"duration must be greater than 0 second"
}
this
.
mute
(
duration
.
inSeconds
.
toInt
())
}
suspend
inline
fun
Member
.
mute
(
duration
:
TimeSpan
)
{
require
(
duration
.
days
>
30
)
{
"duration must be at most 1 month"
}
require
(
duration
.
microseconds
>
0
)
{
"duration must be greater than 0 second"
}
this
.
mute
(
duration
.
seconds
.
toInt
())
}
suspend
inline
fun
Member
.
mute
(
duration
:
MonthSpan
)
{
require
(
duration
.
totalMonths
==
1
)
{
"if you pass a MonthSpan, it must be 1 month"
}
this
.
mute
(
duration
.
totalMonths
*
30
*
24
*
3600
)
}
@ExperimentalUnsignedTypes
suspend
inline
fun
Member
.
mute
(
durationSeconds
:
UInt
)
{
require
(
durationSeconds
.
toInt
()
<=
30
*
24
*
3600
)
{
"duration must be at most 1 month"
}
this
.
mute
(
durationSeconds
.
toInt
())
}
// same bin rep.
/**
* 群成员的权限
*/
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/internal/ContactImpl.kt
View file @
417276ac
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
,
"MemberVisibilityCanBePrivate"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"unused"
,
"MemberVisibilityCanBePrivate"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
package
net.mamoe.mirai.contact.internal
...
...
@@ -19,6 +19,7 @@ import net.mamoe.mirai.network.sessionKey
import
net.mamoe.mirai.qqAccount
import
net.mamoe.mirai.sendPacket
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.io.logStacktrace
import
net.mamoe.mirai.withSession
import
kotlin.coroutines.CoroutineContext
...
...
@@ -45,6 +46,7 @@ internal suspend fun Group(bot: Bot, groupId: GroupId, context: CoroutineContext
val
info
:
RawGroupInfo
=
try
{
bot
.
withSession
{
GroupPacket
.
QueryGroupInfo
(
qqAccount
,
groupId
.
toInternalId
(),
sessionKey
).
sendAndExpect
()
}
}
catch
(
e
:
Exception
)
{
e
.
logStacktrace
()
error
(
"Cannot obtain group info for id ${groupId.value}"
)
}
return
GroupImpl
(
bot
,
groupId
,
context
).
apply
{
this
.
info
=
info
.
parseBy
(
this
)
}
...
...
@@ -62,9 +64,9 @@ internal data class GroupImpl internal constructor(override val bot: Bot, val gr
override
val
announcement
:
String
get
()
=
info
.
announcement
override
val
members
:
ContactList
<
Member
>
get
()
=
info
.
members
override
suspend
fun
getMember
(
id
:
UInt
):
Member
=
override
fun
getMember
(
id
:
UInt
):
Member
=
if
(
members
.
containsKey
(
id
))
members
[
id
]
!!
else
throw
NoSuchElementException
(
"No such member whose id is $
id
in group ${groupId.value.toLong()}"
)
else
throw
NoSuchElementException
(
"No such member whose id is $
{id.toLong()}
in group ${groupId.value.toLong()}"
)
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
{
bot
.
sendPacket
(
GroupPacket
.
Message
(
bot
.
qqAccount
,
internalId
,
bot
.
sessionKey
,
message
))
...
...
@@ -124,5 +126,25 @@ internal data class QQImpl internal constructor(override val bot: Bot, override
*/
@PublishedApi
internal
data class
MemberImpl
(
private
val
delegate
:
QQ
,
override
val
group
:
Group
,
override
val
permission
:
MemberPermission
)
:
QQ
by
delegate
,
Member
{
override
fun
toString
():
String
=
"Member(id=${this.id}, permission=$permission)"
override
fun
toString
():
String
=
"Member(id=${this.id}, group=${group.id}, permission=$permission)"
override
suspend
fun
mute
(
durationSeconds
:
Int
):
Boolean
=
bot
.
withSession
{
require
(
durationSeconds
>
0
)
{
"duration must be greater than 0 second"
}
if
(
permission
==
MemberPermission
.
OWNER
)
return
false
when
(
group
.
getMember
(
bot
.
qqAccount
).
permission
)
{
MemberPermission
.
MEMBER
->
return
false
MemberPermission
.
OPERATOR
->
if
(
permission
==
MemberPermission
.
OPERATOR
)
return
false
MemberPermission
.
OWNER
->
{
}
}
GroupPacket
.
Mute
(
qqAccount
,
group
.
internalId
,
sessionKey
,
id
,
durationSeconds
.
toUInt
()).
sendAndExpect
<
GroupPacket
.
MuteResponse
>()
return
true
}
override
suspend
fun
unmute
():
Unit
=
bot
.
withSession
{
GroupPacket
.
Mute
(
qqAccount
,
group
.
internalId
,
sessionKey
,
id
,
0
u
).
sendAndExpect
<
GroupPacket
.
MuteResponse
>()
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
View file @
417276ac
...
...
@@ -9,6 +9,7 @@ import net.mamoe.mirai.event.ListeningStatus
import
net.mamoe.mirai.event.Subscribable
import
net.mamoe.mirai.event.events.BotEvent
import
net.mamoe.mirai.utils.internal.inlinedRemoveIf
import
net.mamoe.mirai.utils.io.logStacktrace
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.coroutineContext
import
kotlin.jvm.JvmField
...
...
@@ -98,7 +99,8 @@ internal class Handler<in E : Subscribable>
return
try
{
withContext
(
context
)
{
handler
.
invoke
(
event
)
}.
also
{
if
(
it
==
ListeningStatus
.
STOPPED
)
this
.
complete
()
}
}
catch
(
e
:
Throwable
)
{
this
.
completeExceptionally
(
e
)
e
.
logStacktrace
()
//this.completeExceptionally(e)
ListeningStatus
.
STOPPED
}
}
...
...
@@ -131,7 +133,8 @@ internal class HandlerWithBot<E : Subscribable> @PublishedApi internal construct
return
try
{
withContext
(
context
)
{
bot
.
handler
(
event
)
}.
also
{
if
(
it
==
ListeningStatus
.
STOPPED
)
complete
()
}
}
catch
(
e
:
Throwable
)
{
completeExceptionally
(
e
)
e
.
logStacktrace
()
//completeExceptionally(e)
ListeningStatus
.
STOPPED
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/GroupPacket.kt
View file @
417276ac
...
...
@@ -50,7 +50,8 @@ data class RawGroupInfo(
MemberImpl
(
this
@RawGroupInfo
.
owner
.
qq
(),
group
,
MemberPermission
.
OWNER
),
this
@RawGroupInfo
.
name
,
this
@RawGroupInfo
.
announcement
,
ContactList
(
this
@RawGroupInfo
.
members
.
mapValuesTo
(
MutableContactList
())
{
MemberImpl
(
it
.
key
.
qq
(),
group
,
MemberPermission
.
OWNER
)
})
ContactList
(
this
@RawGroupInfo
.
members
.
mapValuesTo
(
MutableContactList
<
Member
>())
{
MemberImpl
(
it
.
key
.
qq
(),
group
,
it
.
value
)
}
.
apply
{
put
(
owner
,
MemberImpl
(
owner
.
qq
(),
group
,
MemberPermission
.
OWNER
))
})
)
}
}
...
...
@@ -119,6 +120,29 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
writeZero
(
4
)
}
/**
* 禁言群成员
*/
@PacketVersion
(
date
=
"2019.12.2"
,
timVersion
=
"2.3.2 (21173)"
)
fun
Mute
(
bot
:
UInt
,
groupInternalId
:
GroupInternalId
,
sessionKey
:
SessionKey
,
target
:
UInt
,
/**
* 0 为取消
*/
timeSeconds
:
UInt
):
OutgoingPacket
=
buildSessionPacket
(
bot
,
sessionKey
,
name
=
"MuteMember"
)
{
writeUByte
(
0
x7Eu
)
writeGroup
(
groupInternalId
)
writeByte
(
0
x20
)
writeByte
(
0
x00
)
writeByte
(
0
x01
)
writeQQ
(
target
)
writeUInt
(
timeSeconds
)
}
interface
GroupPacketResponse
:
Packet
@NoLog
...
...
@@ -126,11 +150,17 @@ object GroupPacket : SessionPacketFactory<GroupPacket.GroupPacketResponse>() {
override
fun
toString
():
String
=
"GroupPacket.MessageResponse"
}
@NoLog
object
MuteResponse
:
Packet
,
GroupPacketResponse
{
override
fun
toString
():
String
=
"GroupPacket.MuteResponse"
}
@PacketVersion
(
date
=
"2019.11.27"
,
timVersion
=
"2.3.2 (21173)"
)
@UseExperimental
(
ExperimentalStdlibApi
::
class
)
override
suspend
fun
ByteReadPacket
.
decode
(
id
:
PacketId
,
sequenceId
:
UShort
,
handler
:
BotNetworkHandler
<
*
>):
GroupPacketResponse
=
handler
.
bot
.
withSession
{
override
suspend
fun
ByteReadPacket
.
decode
(
id
:
PacketId
,
sequenceId
:
UShort
,
handler
:
BotNetworkHandler
<
*
>):
GroupPacketResponse
{
return
when
(
readUByte
().
toUInt
())
{
0
x2Au
->
MessageResponse
0
x7Eu
->
MuteResponse
// 成功: 7E 00 22 96 29 7B;
0
x09u
->
{
if
(
readByte
().
toInt
()
==
0
)
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/EventPacketFactory.kt
View file @
417276ac
...
...
@@ -97,6 +97,7 @@ abstract class KnownEventParserAndHandler<TPacket : Packet>(override val id: USh
FriendAddRequestEventPacket
,
MemberGoneEventPacketHandler
,
ConnectionOccupiedPacketHandler
,
MemberJoinPacketHandler
MemberJoinPacketHandler
,
MemberMuteEventPacketParserAndHandler
)
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/MemberMute.kt
0 → 100644
View file @
417276ac
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.protocol.tim.packet.event
import
com.soywiz.klock.TimeSpan
import
com.soywiz.klock.seconds
import
com.soywiz.klock.toTimeString
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.discardExact
import
kotlinx.io.core.readUInt
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.Member
import
net.mamoe.mirai.getGroup
import
net.mamoe.mirai.qqAccount
// region mute
/**
* 某群成员被禁言事件
*/
@Suppress
(
"unused"
)
class
MemberMuteEvent
(
val
member
:
Member
,
override
val
duration
:
TimeSpan
,
override
val
operator
:
Member
)
:
MuteEvent
()
{
override
val
group
:
Group
get
()
=
operator
.
group
override
fun
toString
():
String
=
"MemberMuteEvent(member=${member.id}, group=${group.id}, operator=${operator.id}, duration=${duration.toTimeString()}"
}
/**
* 机器人被禁言事件
*/
class
BeingMutedEvent
(
override
val
duration
:
TimeSpan
,
override
val
operator
:
Member
)
:
MuteEvent
()
{
override
val
group
:
Group
get
()
=
operator
.
group
override
fun
toString
():
String
=
"BeingMutedEvent(group=${group.id}, operator=${operator.id}, duration=${duration.toTimeString()}"
}
sealed
class
MuteEvent
:
EventOfMute
()
{
abstract
override
val
operator
:
Member
abstract
override
val
group
:
Group
abstract
val
duration
:
TimeSpan
}
// endregion
// region unmute
/**
* 某群成员被解除禁言事件
*/
@Suppress
(
"unused"
)
class
MemberUnmuteEvent
(
val
member
:
Member
,
override
val
operator
:
Member
)
:
UnmuteEvent
()
{
override
val
group
:
Group
get
()
=
operator
.
group
override
fun
toString
():
String
=
"MemberUnmuteEvent(member=${member.id}, group=${group.id}, operator=${operator.id}"
}
/**
* 机器人被解除禁言事件
*/
class
BeingUnmutedEvent
(
override
val
operator
:
Member
)
:
UnmuteEvent
()
{
override
val
group
:
Group
get
()
=
operator
.
group
override
fun
toString
():
String
=
"BeingUnmutedEvent(group=${group.id}, operator=${operator.id}"
}
sealed
class
UnmuteEvent
:
EventOfMute
()
{
abstract
override
val
operator
:
Member
abstract
override
val
group
:
Group
}
// endregion
sealed
class
EventOfMute
:
EventPacket
{
abstract
val
operator
:
Member
abstract
val
group
:
Group
}
internal
object
MemberMuteEventPacketParserAndHandler
:
KnownEventParserAndHandler
<
EventOfMute
>(
0
x02DCu
)
{
override
suspend
fun
ByteReadPacket
.
parse
(
bot
:
Bot
,
identity
:
EventPacketIdentity
):
EventOfMute
{
//取消
//00 00 00 11 00 0A 00 04 01 00 00 00 00 0C 00 05 00 01 00
// 01 01
// 22 96 29 7B
// 0C 01
// 3E 03 3F A2
// 5D E5 12 EB
// 00 01
// 76 E4 B8 DD
// 00 00 00 00
// 禁言
//00 00 00 11 00 0A 00 04 01 00 00 00 00 0C 00 05 00 01 00
// 01
// 01
// 22 96 29 7B
// 0C
// 01
// 3E 03 3F A2
// 5D E5 07 85
// 00
// 01
// 76 E4 B8 DD
// 00 27 8D 00
discardExact
(
19
)
discardExact
(
2
)
val
group
=
bot
.
getGroup
(
readUInt
())
discardExact
(
2
)
val
operator
=
group
.
getMember
(
readUInt
())
discardExact
(
4
)
//time
discardExact
(
2
)
val
memberQQ
=
readUInt
()
val
durationSeconds
=
readUInt
().
toInt
()
return
if
(
durationSeconds
==
0
)
{
if
(
memberQQ
==
bot
.
qqAccount
)
{
BeingUnmutedEvent
(
operator
)
}
else
{
MemberUnmuteEvent
(
group
.
getMember
(
memberQQ
),
operator
)
}
}
else
{
val
duration
=
durationSeconds
.
seconds
if
(
memberQQ
==
bot
.
qqAccount
)
{
BeingMutedEvent
(
duration
,
operator
)
}
else
{
MemberMuteEvent
(
group
.
getMember
(
memberQQ
),
duration
,
operator
)
}
}
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/Message.kt
View file @
417276ac
...
...
@@ -7,10 +7,7 @@ import kotlinx.io.core.String
import
kotlinx.io.core.discardExact
import
kotlinx.io.core.readUInt
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.MemberPermission
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.contact.*
import
net.mamoe.mirai.event.BroadcastControllable
import
net.mamoe.mirai.event.events.BotEvent
import
net.mamoe.mirai.getGroup
...
...
@@ -98,6 +95,7 @@ abstract class MessagePacketBase<TSubject : Contact> : EventPacket, BotEvent() {
// region group message
@Suppress
(
"unused"
)
data class
GroupMessage
(
val
group
:
Group
,
val
senderName
:
String
,
...
...
@@ -110,6 +108,11 @@ data class GroupMessage(
)
:
MessagePacket
<
Group
>()
{
override
val
subject
:
Group
get
()
=
group
suspend
inline
fun
At
.
member
():
Member
=
group
.
getMember
(
this
.
target
)
suspend
inline
fun
UInt
.
member
():
Member
=
group
.
getMember
(
this
)
suspend
inline
fun
Long
.
member
():
Member
=
group
.
getMember
(
this
.
toUInt
())
}
@PacketVersion
(
date
=
"2019.11.2"
,
timVersion
=
"2.3.2 (21173)"
)
...
...
mirai-debug/src/main/kotlin/HexDebuggerGui.kt
View file @
417276ac
...
...
@@ -22,7 +22,7 @@ import java.awt.datatransfer.DataFlavor
/**
* How to run:
*
* `gradle run`
* `gradle
:mirai-debug:
run`
*/
class
Application
:
App
(
HexDebuggerGui
::
class
,
Styles
::
class
)
...
...
@@ -179,7 +179,7 @@ class HexDebuggerGui : View("s") {
override
val
root
=
hbox
{
//prefWidth = 735.0
minHeight
=
24
0.0
minHeight
=
30
0.0
prefHeight
=
minHeight
input
=
textarea
{
...
...
mirai-debug/src/main/kotlin/PacketDebuger.kt
View file @
417276ac
...
...
@@ -116,8 +116,8 @@ object PacketDebugger {
* 7. 运行完 `mov eax,dword ptr ss:[ebp+10]`
* 8. 查看内存, `eax` 到 `eax+10` 的 16 字节就是 `sessionKey`
*/
val
sessionKey
:
SessionKey
=
SessionKey
(
"
F7 3C 31 B5 E1 F1 E5 6A FA F7 95 79 AE 19 30 0
1"
.
hexToBytes
())
const
val
qq
:
UInt
=
761025446
u
val
sessionKey
:
SessionKey
=
SessionKey
(
"
06 23 F8 09 0D 2D 37 BE 2E FE 90 3A 7D E5 8F B
1"
.
hexToBytes
())
const
val
qq
:
UInt
=
1040400290
u
val
IgnoredPacketIdList
:
List
<
PacketId
>
=
listOf
(
KnownPacketId
.
FRIEND_ONLINE_STATUS_CHANGE
,
...
...
@@ -152,7 +152,9 @@ object PacketDebugger {
decodedBody
=
it
.
readBytes
()
ByteReadPacket
(
decodedBody
)
}
.
decode
(
id
,
sequenceId
,
DebugNetworkHandler
)
.
runCatching
{
decode
(
id
,
sequenceId
,
DebugNetworkHandler
)
}.
getOrElse
{
it
.
printStackTrace
();
null
}
}
}
...
...
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman/Main.kt
View file @
417276ac
...
...
@@ -2,6 +2,8 @@
package
demo.gentleman
import
com.soywiz.klock.months
import
com.soywiz.klock.seconds
import
kotlinx.coroutines.Dispatchers.IO
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.delay
...
...
@@ -9,8 +11,10 @@ import kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
net.mamoe.mirai.*
import
net.mamoe.mirai.contact.MemberPermission
import
net.mamoe.mirai.contact.mute
import
net.mamoe.mirai.event.Subscribable
import
net.mamoe.mirai.event.subscribeAlways
import
net.mamoe.mirai.event.subscribeGroupMessages
import
net.mamoe.mirai.event.subscribeMessages
import
net.mamoe.mirai.message.At
import
net.mamoe.mirai.message.Image
...
...
@@ -59,17 +63,32 @@ suspend fun main() {
it
.
approve
()
}
bot
.
subscribeGroupMessages
{
"群资料"
reply
{
group
.
updateGroupInfo
().
toString
().
reply
()
}
startsWith
(
"mt2months"
)
{
val
at
:
At
by
message
at
.
target
.
member
().
mute
(
1
.
months
)
}
startsWith
(
"mute"
)
{
val
at
:
At
by
message
at
.
target
.
member
().
mute
(
30
.
seconds
)
}
startsWith
(
"unmute"
)
{
val
at
:
At
by
message
at
.
target
.
member
().
unmute
()
}
}
bot
.
subscribeMessages
{
case
(
"at me"
)
{
At
(
sender
).
reply
()
}
"你好"
reply
"你好!"
"群资料"
reply
{
if
(
this
is
GroupMessage
)
{
group
.
updateGroupInfo
().
toString
().
reply
()
}
}
startsWith
(
"profile"
,
removePrefix
=
true
)
{
val
account
=
it
.
trim
()
if
(
account
.
isNotEmpty
())
{
...
...
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