//! Poll event handlers on `MessageService`. use std::sync::Arc; use uuid::Uuid; use crate::ImksError; use crate::socket::socket::Socket; use super::message::MessageService; impl MessageService { /// Handle `poll:vote` — cast a vote on a poll option. pub async fn poll_vote( &self, socket: Arc, data: &serde_json::Value, ) -> crate::ImksResult<()> { let user_id = self.user_id(&socket)?; let arr = data .as_array() .and_then(|a| a.first()) .ok_or_else(|| ImksError::InvalidInput("Expected [payload] array".into()))?; let poll_id: Uuid = Self::parse_field(arr, "poll_id")?; let option_id: Uuid = Self::parse_field(arr, "option_id")?; let target = self.repo.get_poll_target(poll_id, option_id).await?; let channel_id = target.channel_id; let channel_id_str = channel_id.to_string(); let user_id_str = user_id.to_string(); self.ensure_readable(&channel_id_str, &user_id_str).await?; self.ensure_member(&channel_id_str, &user_id_str).await?; let target = self .repo .cast_vote_checked(poll_id, option_id, user_id) .await?; if let Some(result) = self .repo .get_poll_result(target.message_id, user_id) .await? && let Some(ns) = self.namespaces.get_namespace(&socket.namespace) { ns.emit_to_room( &target.channel_id.to_string(), "poll:updated", serde_json::to_value(&result).unwrap_or_default(), ) .await; } Ok(()) } /// Handle `poll:vote:remove` — retract a vote. pub async fn poll_remove_vote( &self, socket: Arc, data: &serde_json::Value, ) -> crate::ImksResult<()> { let user_id = self.user_id(&socket)?; let arr = data .as_array() .and_then(|a| a.first()) .ok_or_else(|| ImksError::InvalidInput("Expected [payload] array".into()))?; let poll_id: Uuid = Self::parse_field(arr, "poll_id")?; let option_id: Uuid = Self::parse_field(arr, "option_id")?; let target = self.repo.get_poll_target(poll_id, option_id).await?; let channel_id_str = target.channel_id.to_string(); let user_id_str = user_id.to_string(); self.ensure_readable(&channel_id_str, &user_id_str).await?; self.ensure_member(&channel_id_str, &user_id_str).await?; if let Some(target) = self .repo .remove_vote_checked(poll_id, option_id, user_id) .await? && let Some(result) = self .repo .get_poll_result(target.message_id, user_id) .await? && let Some(ns) = self.namespaces.get_namespace(&socket.namespace) { ns.emit_to_room( &target.channel_id.to_string(), "poll:updated", serde_json::to_value(&result).unwrap_or_default(), ) .await; } Ok(()) } }