//! Chat Pinnd(पिण्ड) is Actor to manage Websocket Chat related action use std::collections::HashMap; use actix::prelude::*; use actix_broker::BrokerSubscribe; use vecmap::VecMap; use ws_sansad::WsSansad; use crate::{errors, ws_sansad, messages as ms}; #[allow(dead_code)] pub struct ChatPinnd { grih: HashMap, // id, Grih vyaktigat_waitlist: Vec, vyakti: VecMap // id, vayakti } pub struct Grih { length: Option, loog: Vec> } #[derive(Clone)] pub struct Vyakti { name: String, tags: Vec } pub struct VyaktiWatchlist { kunjika: String, addr: Addr } impl Actor for ChatPinnd { type Context = Context; fn started(&mut self, ctx: &mut Self::Context) { // for actix broker self.subscribe_system_async::(ctx); self.subscribe_system_async::(ctx); } } // Set information of user impl Handler for ChatPinnd { type Result = Option; fn handle(&mut self, msg: ms::SetInfoVyakti, _: &mut Self::Context) -> Self::Result { // check if vayakti info is not modified and do key exist if !msg.modify { if self.vyakti.key_exist(&msg.kunjika) { return Some("Kunjika Exists".to_owned()); } } // change value self.vyakti.insert(msg.kunjika, Vyakti { name: msg.name, tags: msg.tags }); None } } /// Join grih impl Handler for ChatPinnd { type Result = Result<(), errors::GrihFullError>; fn handle(&mut self, msg: ms::JoinGrih, _: &mut Self::Context) -> Self::Result { match self.grih.get_mut(&msg.grih_kunjika) { // check if group exist Some(grih) =>{ // exist // check if group have no space left if let Some(n) = grih.length { if grih.loog.len() >= n { return Err(errors::GrihFullError); } } grih.loog.push(msg.addr); let username = self.vyakti.get(&msg.kunjika).unwrap().name.to_owned(); let kunjika = msg.kunjika.clone(); grih.loog.iter().for_each(move |a: &Addr| { a.do_send(ms::WsConnected { name: username.clone(), kunjika: kunjika.clone() }) }); }, None => { // don't exist // add group and notify self.grih.insert(msg.grih_kunjika, Grih { length: msg.length, loog: vec![msg.addr.clone()] }); msg.addr.do_send(ms::WsConnected { name: self.vyakti.get(&msg.kunjika).unwrap().name.to_owned(), kunjika: msg.kunjika.clone() }); } } Ok(()) } } /// Join random vayakti /// Works as: /// Check if watchlist is empty, if yes add the kunjika andaddr to watchlist /// if watchlist have people get 0th person an connect it impl Handler for ChatPinnd { type Result = Option<()>; fn handle(&mut self, msg: ms::JoinRandom, _: &mut Self::Context) -> Self::Result { // Check if watch list is empty if self.vyaktigat_waitlist.len() == 0 { self.vyaktigat_waitlist.push(VyaktiWatchlist { kunjika: msg.kunjika, addr: msg.addr }); return None; } // connect 0th person let vayakti_watchlist = self.vyaktigat_waitlist.remove(0); let vayakti1 = self.vyakti.get(&msg.kunjika).unwrap(); let vayakti2 = self.vyakti.get(&vayakti_watchlist.kunjika).unwrap(); let group_kunjika = format!("gupt_{}>{}",msg.kunjika, vayakti_watchlist.kunjika); self.grih.insert(group_kunjika.clone(), Grih { length: Some(2), loog: vec![msg.addr.clone(), vayakti_watchlist.addr.clone()] }); // notify about connection msg.addr.do_send(ms::WsConnectedRandom { ajnyat_name: vayakti2.name.clone(), grih_kunjika: group_kunjika.clone() }); vayakti_watchlist.addr.do_send(ms::WsConnectedRandom { ajnyat_name: vayakti1.name.clone(), grih_kunjika: group_kunjika.clone() }); Some(()) } } /// send text to exryone impl Handler for ChatPinnd { type Result = (); fn handle(&mut self, msg: ms::SendText, _: &mut Self::Context) -> Self::Result { if let Some(grih) = self.grih.get(&msg.grih_kunjika) { grih.loog.iter().for_each(|c| { c.do_send(ms::WsMessage { sender: msg.kunjika.clone(), text: msg.text.clone(), }); }); } } } /// Notifiy a user disconnected and trim grih impl Handler for ChatPinnd { type Result = (); fn handle(&mut self, msg: ms::LeaveUser, _: &mut Self::Context) -> Self::Result { if let Some(grih) = self.grih.get_mut(&msg.grih_kunjika) { if let Some(i) = grih.loog.iter().position(|x| x == &msg.addr) { grih.loog.remove(i); } if grih.loog.len() == 0 { self.grih.remove(&msg.grih_kunjika); } else { grih.loog.iter().for_each(|a| { a.do_send(ms::WsDisconnected { kunjika: msg.kunjika.clone() }) }); } } } } impl Default for ChatPinnd { fn default() -> Self { ChatPinnd { grih: HashMap::new(), vyaktigat_waitlist: Vec::new(), vyakti: VecMap::new() } } } impl SystemService for ChatPinnd {} impl Supervised for ChatPinnd {}