use mysql_async::{params, Pool}; use mysql_async::prelude::Queryable; use mysql_async::Error as SqlError; use crate::{Channel, UBigInt, Integer}; use crate::Response; use rand::RngCore; pub const VOICE_CHANNEL: Integer = 1; pub const TEXT_CHANNEL: Integer = 2; pub const MAX_NAME_LEN: usize = 256; pub const MAX_DESCRIPTION_LEN: usize = 2048; impl Channel { pub async fn get(p: &Pool, id: u64) -> Result, SqlError> { let mut conn = p.get_conn().await?; let q = "SELECT name, description, kind, badge_ids FROM channels WHERE id = :id"; let params = params!{"id" => id}; let row: Option<(String, Option, i32, String)> = conn.exec_first(q, params).await?; if let Some(row) = row { let badge_ids: Vec = serde_json::from_str(&row.3).unwrap_or(Vec::new()); let chan = Channel { id, name: row.0, description: row.1, kind: row.2, badge_ids }; Ok(Some(chan)) } else { Ok(None) } } pub async fn filter(p: &Pool, kind: Integer) -> Result, SqlError> { //! @returns -> on success : Ok(Response::Set(Vec)) //! @throw -> on sql fail : Err(SqlError) if kind == VOICE_CHANNEL || kind ==TEXT_CHANNEL { let mut conn = p.get_conn().await?; let q = "SELECT id, name, description, kind, badge_ids FROM channels WHERE kind = :kind"; let params = params!{"kind" => kind}; type Row = (u64, String, Option, i32, String); let channels = conn.exec_map(q, params, |(id, name, description, kind, badge_ids): Row| { let badge_ids: Vec = serde_json::from_str(&badge_ids).unwrap_or(Vec::new()); Channel { id, name, description, kind, badge_ids } }).await?; Ok(Response::Set(channels)) } else { return Ok(Response::RestrictedInput("Channel kind is invalid".into())); } } pub async fn add(p: &Pool, name: &str, description: &str, kind: Integer) -> Result, SqlError> { //! @returns on success -> Response::Row //! @returns on user failure -> Response::RestrictedInput(msg) // bounds are literally [1, 2] if kind == TEXT_CHANNEL || kind == VOICE_CHANNEL { let mut conn = p.get_conn().await?; // Badge id's are not required here as they have a default server-side // value of '[]' let q = "INSERT INTO channels (id, name, description, kind) VALUES (:i, :n, :d, :k)"; let id = rand::rngs::OsRng.next_u64(); // generate id's randomly for channels conn.exec_drop(q, params!{ "i" => id, "n" => name, "d" => description, "k" => kind }).await?; Ok(Response::Row(Self { id, name: name.to_string(), description: Some(description.to_string()), kind, badge_ids: Vec::new() })) } else { return Ok(Response::RestrictedInput(String::from("Invalid channel type"))); } } pub async fn delete(p: &Pool, id: UBigInt) -> Result, SqlError> { //! Deletes channel given UBigInt as the row key //! @param p -> SqlPool //! @param id -> UBigInt //! @return on success -> Response::Success //! @return on server failure -> Response::Other let mut conn = p.get_conn().await?; let q = "DELETE FROM channels WHERE id = :id"; conn.exec_drop(q, params!{"id" => id}).await?; Ok(Response::Success) } }