mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-04 05:07:00 +08:00
Add mute and unmute
This commit is contained in:
parent
8fa98f5938
commit
417276acda
@ -2,5 +2,7 @@
|
||||
|
||||
## Main version 0
|
||||
|
||||
### 0.3.0
|
||||
- 更新
|
||||
### 0.6.0
|
||||
- 新增: 禁言群成员
|
||||
- 新增: 解禁群成员
|
||||
- 修复: ContactList key 无法匹配
|
@ -1,7 +1,7 @@
|
||||
# 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
|
||||
|
@ -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)
|
||||
}
|
@ -51,7 +51,7 @@ interface Group : Contact, Iterable<Member> {
|
||||
/**
|
||||
* 获取群成员. 若此 ID 的成员不存在, 则会抛出 [kotlin.NoSuchElementException]
|
||||
*/
|
||||
suspend fun getMember(id: UInt): Member
|
||||
fun getMember(id: UInt): Member
|
||||
|
||||
/**
|
||||
* 更新群资料. 群资料会与服务器事件同步事件更新, 一般情况下不需要手动更新.
|
||||
|
@ -1,9 +1,14 @@
|
||||
@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.
|
||||
|
||||
/**
|
||||
* 群成员的权限
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
@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, 0u).sendAndExpect<GroupPacket.MuteResponse>()
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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(0x7Eu)
|
||||
writeGroup(groupInternalId)
|
||||
writeByte(0x20)
|
||||
writeByte(0x00)
|
||||
writeByte(0x01)
|
||||
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()) {
|
||||
0x2Au -> MessageResponse
|
||||
0x7Eu -> MuteResponse // 成功: 7E 00 22 96 29 7B;
|
||||
|
||||
0x09u -> {
|
||||
if (readByte().toInt() == 0) {
|
||||
|
@ -97,6 +97,7 @@ abstract class KnownEventParserAndHandler<TPacket : Packet>(override val id: USh
|
||||
FriendAddRequestEventPacket,
|
||||
MemberGoneEventPacketHandler,
|
||||
ConnectionOccupiedPacketHandler,
|
||||
MemberJoinPacketHandler
|
||||
MemberJoinPacketHandler,
|
||||
MemberMuteEventPacketParserAndHandler
|
||||
)
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
@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>(0x02DCu) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)")
|
||||
|
@ -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 = 240.0
|
||||
minHeight = 300.0
|
||||
prefHeight = minHeight
|
||||
|
||||
input = textarea {
|
||||
|
@ -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 01".hexToBytes())
|
||||
const val qq: UInt = 761025446u
|
||||
val sessionKey: SessionKey = SessionKey("06 23 F8 09 0D 2D 37 BE 2E FE 90 3A 7D E5 8F B1".hexToBytes())
|
||||
const val qq: UInt = 1040400290u
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()) {
|
||||
|
Loading…
Reference in New Issue
Block a user