[mock] fix mockHonorMember (#2473)

* fix mirai-core-mock honorMember

* add comments

* manually fetch honor data

* update implement

* remove deprecated

* chore: update test cases

* improve style
This commit is contained in:
Eritque arcus 2023-03-29 10:29:54 -04:00 committed by GitHub
parent e2d7332ac0
commit 1a8af784dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 166 additions and 38 deletions

View File

@ -17,7 +17,6 @@ import net.mamoe.mirai.contact.NormalMember
import net.mamoe.mirai.data.GroupHonorType
import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.MemberHonorChangeEvent
import net.mamoe.mirai.event.events.MemberJoinRequestEvent
import net.mamoe.mirai.mock.MockBot
import net.mamoe.mirai.mock.MockBotDSL
@ -51,6 +50,11 @@ public interface MockGroup : Group, MockContact, MockMsgSyncSupport {
* @see changeHonorMember
*/
@MockBotDSL
@Deprecated(
"use active.changeHonorMember",
ReplaceWith(".active.changeHonorMember(member, honorType)"),
level = DeprecationLevel.ERROR
)
public val honorMembers: MutableMap<GroupHonorType, MockNormalMember>
/**
@ -61,10 +65,11 @@ public interface MockGroup : Group, MockContact, MockMsgSyncSupport {
* 此外如果 [honorType] [GroupHonorType.TALKATIVE],
* 会额外广播 [net.mamoe.mirai.event.events.GroupTalkativeChangeEvent].
*
* 如果不需要广播事件, 可直接更改 [MockGroup.honorMembers]
* 如果不需要广播事件, 可直接使用 [MockGroupActive.mockSetHonorHistory]
*/
@MockBotDSL
public fun changeHonorMember(member: MockNormalMember, honorType: GroupHonorType)
public fun changeHonorMember(member: MockNormalMember, honorType: GroupHonorType) {
active.changeHonorMember(member, honorType)
}
/**
* 获取群控制面板

View File

@ -11,6 +11,9 @@ package net.mamoe.mirai.mock.contact.active
import net.mamoe.mirai.contact.active.*
import net.mamoe.mirai.data.GroupHonorType
import net.mamoe.mirai.event.events.MemberHonorChangeEvent
import net.mamoe.mirai.mock.MockBotDSL
import net.mamoe.mirai.mock.contact.MockNormalMember
public interface MockGroupActive : GroupActive {
/**
@ -39,4 +42,17 @@ public interface MockGroupActive : GroupActive {
* @see queryActiveRank
*/
public fun mockSetRankRecords(list: List<ActiveRankRecord>)
/**
* 更改拥有群荣耀的群成员.
*
* 会自动广播 [MemberHonorChangeEvent.Achieve] [MemberHonorChangeEvent.Lose] 等相关事件.
*
* 此外如果 [honorType] [GroupHonorType.TALKATIVE],
* 会额外广播 [net.mamoe.mirai.event.events.GroupTalkativeChangeEvent].
*
* 如果不需要广播事件, 可直接使用 [mockSetHonorHistory]
*/
@MockBotDSL
public fun changeHonorMember(member: MockNormalMember, honorType: GroupHonorType)
}

View File

@ -52,6 +52,11 @@ internal class MockGroupImpl(
) : AbstractMockContact(
parentCoroutineContext, bot, id
), MockGroup {
@Deprecated(
"use active.changeHonorMember",
replaceWith = ReplaceWith(".active.changeHonorMember(member, honorType)"),
level = DeprecationLevel.ERROR
)
override val honorMembers: MutableMap<GroupHonorType, MockNormalMember> = ConcurrentHashMap()
private val txFileSystem by lazy { bot.mock().tmpResourceServer.mockServerFileDisk.newFsSystem() }
@ -61,17 +66,6 @@ internal class MockGroupImpl(
override val active: MockGroupActive by lazy { MockGroupActiveImpl(this) }
override fun changeHonorMember(member: MockNormalMember, honorType: GroupHonorType) {
val onm = honorMembers[honorType]
honorMembers[honorType] = member
// reference net.mamoe.mirai.internal.network.notice.group.NoticePipelineContext.processGeneralGrayTip, GroupNotificationProcessor.kt#361L
if (honorType == GroupHonorType.TALKATIVE) {
if (onm != null) GroupTalkativeChangeEvent(this, member, onm).broadcastBlocking()
}
if (onm != null) MemberHonorChangeEvent.Lose(onm, honorType).broadcastBlocking()
MemberHonorChangeEvent.Achieve(member, honorType).broadcastBlocking()
}
override fun appendMember(mockMember: MemberInfo): MockGroup {
addMember(mockMember)
return this

View File

@ -12,14 +12,15 @@ package net.mamoe.mirai.mock.internal.contact.active
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.contact.active.ActiveChart
import net.mamoe.mirai.contact.active.ActiveHonorList
import net.mamoe.mirai.contact.active.ActiveRankRecord
import net.mamoe.mirai.contact.active.ActiveRecord
import net.mamoe.mirai.contact.active.*
import net.mamoe.mirai.contact.checkBotPermission
import net.mamoe.mirai.data.GroupHonorType
import net.mamoe.mirai.event.events.GroupTalkativeChangeEvent
import net.mamoe.mirai.event.events.MemberHonorChangeEvent
import net.mamoe.mirai.mock.contact.MockNormalMember
import net.mamoe.mirai.mock.contact.active.MockGroupActive
import net.mamoe.mirai.mock.internal.contact.MockGroupImpl
import net.mamoe.mirai.mock.utils.broadcastBlocking
import net.mamoe.mirai.utils.ConcurrentHashMap
import net.mamoe.mirai.utils.JavaFriendlyAPI
import net.mamoe.mirai.utils.asImmutable
@ -82,6 +83,33 @@ internal class MockGroupActiveImpl(
private var honorHistories: MutableMap<GroupHonorType, ActiveHonorList> = ConcurrentHashMap()
@Suppress("INVISIBLE_MEMBER") // for ActiveHonorInfo
override fun changeHonorMember(member: MockNormalMember, honorType: GroupHonorType) {
val old = honorHistories[honorType]
val info = ActiveHonorInfo(member.nameCard, member.id, member.avatarUrl, member, 0, 0, 0)
if (old == null) {
// if not history record found, add a new one with current honor member
honorHistories[honorType] = ActiveHonorList(honorType, info, emptyList())
} else if (old.current?.memberId != info.memberId) {
honorHistories[honorType] =
ActiveHonorList(honorType, info, old.current?.let {
old.records.plus(it)
} ?: old.records)
if (old.current != null) {
if (honorType == GroupHonorType.TALKATIVE) {
GroupTalkativeChangeEvent(
this.group,
member,
old.current!!.member!!
).broadcastBlocking()
}
MemberHonorChangeEvent.Lose(old.current!!.member!!, honorType).broadcastBlocking()
}
}
MemberHonorChangeEvent.Achieve(member, honorType).broadcastBlocking()
}
override suspend fun queryHonorHistory(type: GroupHonorType): ActiveHonorList {
return honorHistories.getOrElse(type) { ActiveHonorList(type, null, listOf()) }
}

View File

@ -163,25 +163,6 @@ internal class MockGroupTest : MockBotTestBase() {
assertEquals(0, fsroot.listFilesCollection().size)
}
@Test
internal fun testMemberHonorChangeEvent() = runTest {
runAndReceiveEventBroadcast {
val group = bot.addGroup(111, "aa")
val member1 = group.addMember(simpleMemberInfo(222, "bb", permission = MemberPermission.MEMBER))
val member2 = group.addMember(simpleMemberInfo(333, "cc", permission = MemberPermission.MEMBER))
group.honorMembers[GroupHonorType.TALKATIVE] = member1
group.changeHonorMember(member2, GroupHonorType.TALKATIVE)
}.let { events ->
assertEquals(3, events.size)
assertIsInstance<GroupTalkativeChangeEvent>(events[0])
assertIsInstance<MemberHonorChangeEvent.Lose>(events[1])
assertEquals(222, events[1].cast<MemberHonorChangeEvent.Lose>().member.id)
assertIsInstance<MemberHonorChangeEvent.Achieve>(events[2])
assertEquals(GroupHonorType.TALKATIVE, events[2].cast<MemberHonorChangeEvent.Achieve>().honorType)
assertEquals(333, events[2].cast<MemberHonorChangeEvent.Achieve>().member.id)
}
}
@Test
internal fun testGroupFileUpload() = runTest {
val files = bot.addGroup(111, "aaa").files
@ -457,4 +438,108 @@ internal class MockGroupTest : MockBotTestBase() {
}
}
}
@Test
fun testHonorMember() = runTest {
val group = bot.addGroup(1, "")
val member1 = group.addMember(2, "")
val member2 = group.addMember(3, "")
assertEquals(emptyList(), group.active.queryHonorHistory(GroupHonorType.TALKATIVE).records)
runAndReceiveEventBroadcast {
group.active.changeHonorMember(member1, GroupHonorType.TALKATIVE)
}.let { events ->
assertEquals(1, events.size)
assertIsInstance<MemberHonorChangeEvent.Achieve>(events[0]) {
assertEquals(GroupHonorType.TALKATIVE, this.honorType)
assertEquals(member1, this.member)
assertEquals(group, this.group)
}
}
assertEquals(member1, group.active.queryHonorHistory(GroupHonorType.TALKATIVE).current!!.member!!)
assertEquals(emptyList(), group.active.queryHonorHistory(GroupHonorType.TALKATIVE).records)
runAndReceiveEventBroadcast {
group.active.changeHonorMember(member2, GroupHonorType.TALKATIVE)
}.let { events ->
assertEquals(3, events.size)
assertIsInstance<GroupTalkativeChangeEvent>(events[0]) {
assertEquals(member2, this.now)
assertEquals(member1, this.previous)
assertEquals(group, this.group)
}
assertIsInstance<MemberHonorChangeEvent.Lose>(events[1]) {
assertEquals(GroupHonorType.TALKATIVE, this.honorType)
assertEquals(member1, this.member)
assertEquals(group, this.group)
}
assertIsInstance<MemberHonorChangeEvent.Achieve>(events[2]) {
assertEquals(GroupHonorType.TALKATIVE, this.honorType)
assertEquals(member2, this.member)
assertEquals(group, this.group)
}
}
assertEquals(member2, group.active.queryHonorHistory(GroupHonorType.TALKATIVE).current!!.member!!)
// it.member must exist
assertEquals(
listOf(member1),
group.active.queryHonorHistory(GroupHonorType.TALKATIVE).records.map { it.member!! })
runAndReceiveEventBroadcast {
group.active.changeHonorMember(member1, GroupHonorType.TALKATIVE)
}.let { events ->
assertEquals(3, events.size)
assertIsInstance<GroupTalkativeChangeEvent>(events[0]) {
assertEquals(member1, this.now)
assertEquals(member2, this.previous)
assertEquals(group, this.group)
}
assertIsInstance<MemberHonorChangeEvent.Lose>(events[1]) {
assertEquals(GroupHonorType.TALKATIVE, this.honorType)
assertEquals(member2, this.member)
assertEquals(group, this.group)
}
assertIsInstance<MemberHonorChangeEvent.Achieve>(events[2]) {
assertEquals(GroupHonorType.TALKATIVE, this.honorType)
assertEquals(member1, this.member)
assertEquals(group, this.group)
}
}
assertEquals(member1, group.active.queryHonorHistory(GroupHonorType.TALKATIVE).current!!.member!!)
assertEquals(
listOf(member1, member2),
group.active.queryHonorHistory(GroupHonorType.TALKATIVE).records.map { it.member!! })
runAndReceiveEventBroadcast {
group.active.changeHonorMember(member1, GroupHonorType.BRONZE)
}.let { events ->
assertEquals(1, events.size)
assertIsInstance<MemberHonorChangeEvent.Achieve>(events[0]) {
assertEquals(GroupHonorType.BRONZE, this.honorType)
assertEquals(member1, this.member)
assertEquals(group, this.group)
}
}
assertEquals(member1, group.active.queryHonorHistory(GroupHonorType.BRONZE).current!!.member!!)
assertEquals(emptyList(), group.active.queryHonorHistory(GroupHonorType.BRONZE).records)
runAndReceiveEventBroadcast {
group.active.changeHonorMember(member2, GroupHonorType.BRONZE)
}.let { events ->
assertEquals(2, events.size)
assertIsInstance<MemberHonorChangeEvent.Lose>(events[0]) {
assertEquals(GroupHonorType.BRONZE, this.honorType)
assertEquals(member1, this.member)
assertEquals(group, this.group)
}
assertIsInstance<MemberHonorChangeEvent.Achieve>(events[1]) {
assertEquals(GroupHonorType.BRONZE, this.honorType)
assertEquals(member2, this.member)
assertEquals(group, this.group)
}
}
assertEquals(member2, group.active.queryHonorHistory(GroupHonorType.BRONZE).current!!.member!!)
assertEquals(listOf(member1), group.active.queryHonorHistory(GroupHonorType.BRONZE).records.map { it.member!! })
}
}