diff options
3 files changed, 65 insertions, 18 deletions
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelManager.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelManager.kt index 47780fb..07b5662 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelManager.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelManager.kt @@ -168,6 +168,44 @@ class ChannelManager( } /** + * Answers whether a player belongs to a channel without handing out the member list. + * + * [getChannelMembers] copies the list defensively, which is the wrong price to pay for a + * question that only needs to scan it. + * + * @param channelId The ID of the channel. + * @param playerId The UUID of the player. + * @return Result containing true if the player is a member. + * @throws ChannelNotFoundException if the channel does not exist. + */ + fun isMember( + channelId: String, + playerId: UUID, + ): Result<Boolean> { + channelsCache[channelId] + ?: return Result.failure(ChannelNotFoundException(channelId)) + + val members = membersCache[channelId] ?: return Result.success(false) + return Result.success(members.any { it.playerId == playerId }) + } + + /** + * Returns the ids of every existing channel the player belongs to. + * + * Walks the membership lists once in place; asking per channel meant copying every channel's + * member list to answer a question about one player. + * + * @param playerId The UUID of the player. + */ + fun channelIdsOf(playerId: UUID): List<String> = + membersCache + .asSequence() + .filter { (channelId, members) -> + channelsCache.containsKey(channelId) && members.any { it.playerId == playerId } + }.map { it.key } + .toList() + + /** * Adds a member to a channel. * * @param channelId The ID of the channel. diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManager.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManager.kt index 3833376..6ce2672 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManager.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManager.kt @@ -45,10 +45,7 @@ class ChannelMembershipManager( fun isMember( playerId: UUID, channelId: String, - ): Result<Boolean> = - channelManager.getChannelMembers(channelId).map { members -> - members.any { it.playerId == playerId } - } + ): Result<Boolean> = channelManager.isMember(channelId, playerId) /** * Gets the role of a member in a channel. @@ -338,18 +335,5 @@ class ChannelMembershipManager( * @param playerId The UUID of the player. * @return Result containing a list of channel IDs where the player is a member. */ - fun getPlayerChannels(playerId: UUID): Result<List<String>> { - val allChannels = - channelManager.getAllChannels().getOrElse { - return Result.failure(it) - } - - val playerChannels = - allChannels - .filter { channel -> - isMember(playerId, channel.id).getOrElse { false } - }.map { it.id } - - return Result.success(playerChannels) - } + fun getPlayerChannels(playerId: UUID): Result<List<String>> = Result.success(channelManager.channelIdsOf(playerId)) } diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManagerTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManagerTest.kt index 28e1c82..02c4d1a 100644 --- a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManagerTest.kt +++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/chat/channel/ChannelMembershipManagerTest.kt @@ -472,4 +472,29 @@ class ChannelMembershipManagerTest { assertIs<ChannelPlayerBannedException>(result.exceptionOrNull()) } + + @Test + fun `isMember should fail for a channel that does not exist`() { + val (membership, _, _) = createManagers() + + val result = membership.isMember(createTestUUID(1), "no-such-ch") + + assertIs<ChannelNotFoundException>(result.exceptionOrNull()) + } + + @Test + fun `getPlayerChannels should not report a deleted channel`() { + val ownerId = createTestUUID(1) + val playerId = createTestUUID(2) + val (membership, channelManager, _) = createManagers() + channelManager.createChannel(createTestChannel(id = "keep-ch", name = "Keep", ownerId = ownerId)) + channelManager.createChannel(createTestChannel(id = "drop-ch", name = "Drop", ownerId = ownerId)) + membership.joinChannel(playerId, "keep-ch") + channelManager.setPlayerChannel(playerId, null) + membership.joinChannel(playerId, "drop-ch") + + channelManager.deleteChannel("drop-ch", ownerId) + + assertEquals(listOf("keep-ch"), membership.getPlayerChannels(playerId).getOrThrow()) + } } |
