concord 1.4.1

A terminal user interface client for Discord
Documentation
use crate::discord::VoiceStateInfo;
use crate::discord::ids::{
    Id,
    marker::{ChannelMarker, GuildMarker, UserMarker},
};

use super::DiscordState;

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VoiceParticipantState {
    pub user_id: Id<UserMarker>,
    pub display_name: String,
    pub deaf: bool,
    pub mute: bool,
    pub self_deaf: bool,
    pub self_mute: bool,
    pub self_stream: bool,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub(super) struct VoiceState {
    channel_id: Id<ChannelMarker>,
    user_id: Id<UserMarker>,
    deaf: bool,
    mute: bool,
    self_deaf: bool,
    self_mute: bool,
    self_stream: bool,
}

impl DiscordState {
    pub fn voice_participants_for_channel(
        &self,
        guild_id: Id<GuildMarker>,
        channel_id: Id<ChannelMarker>,
    ) -> Vec<VoiceParticipantState> {
        let mut participants: Vec<VoiceParticipantState> = self
            .voice
            .states
            .iter()
            .filter(|((state_guild_id, _), state)| {
                *state_guild_id == guild_id && state.channel_id == channel_id
            })
            .map(|(_, state)| VoiceParticipantState {
                user_id: state.user_id,
                display_name: self
                    .member_display_name(guild_id, state.user_id)
                    .map(str::to_owned)
                    .unwrap_or_else(|| format!("user-{}", state.user_id.get())),
                deaf: state.deaf,
                mute: state.mute,
                self_deaf: state.self_deaf,
                self_mute: state.self_mute,
                self_stream: state.self_stream,
            })
            .collect();
        participants.sort_by(|left, right| {
            left.display_name
                .to_lowercase()
                .cmp(&right.display_name.to_lowercase())
                .then(left.user_id.cmp(&right.user_id))
        });
        participants
    }

    pub(super) fn update_voice_state(&mut self, state: &VoiceStateInfo) {
        let key = (state.guild_id, state.user_id);
        if let Some(channel_id) = state.channel_id {
            self.voice.states.insert(
                key,
                VoiceState {
                    channel_id,
                    user_id: state.user_id,
                    deaf: state.deaf,
                    mute: state.mute,
                    self_deaf: state.self_deaf,
                    self_mute: state.self_mute,
                    self_stream: state.self_stream,
                },
            );
        } else {
            self.voice.states.remove(&key);
        }
    }

    pub(super) fn remove_voice_state(
        &mut self,
        guild_id: Id<GuildMarker>,
        user_id: Id<UserMarker>,
    ) {
        self.voice.states.remove(&(guild_id, user_id));
    }

    pub(super) fn remove_voice_states_for_guild(&mut self, guild_id: Id<GuildMarker>) {
        self.voice
            .states
            .retain(|(state_guild_id, _), _| *state_guild_id != guild_id);
    }

    pub(super) fn remove_voice_states_for_channel(&mut self, channel_id: Id<ChannelMarker>) {
        self.voice
            .states
            .retain(|_, state| state.channel_id != channel_id);
    }
}