use std::borrow::Cow; use mysql_async::{Conn, Pool, params}; use mysql_async::prelude::{Queryable}; use mysql_async::error::Error; use hyper::{Response, Body, StatusCode}; use serde_json::Value; use chrono::Utc; use crate::members::Member; use crate::channels::{Channel, ChannelID, ChannelType}; struct Message { author: Member, date: u64, // used as thr primary key in our table content: String, channel: Channel } fn validate_params(p: &Value, keys: Vec<&str>) -> bool { let mut fail = false; for key in keys.iter() { if let None = p.get(key) { fail = true; break; } } return fail == false; } async fn update_messages_table(pool: &Pool, secret: &str, content: Option<&str>, id: Option) -> Result<(), mysql_async::error::Error> { match (content, id) { (Some(content), Some(id)) => { let conn = pool.get_conn().await?; // get the user data first since we kinda need it // make sure the channel exists const CID_QUERY: &'static str = "SELECT kind from `channels` WHERE id = :id"; let (conn, row): (Conn, Option) = conn .first_exec(CID_QUERY, params!{"id"=>id}) .await?; let channel_exists = match row { Some(r) => r == ChannelType::Text.as_i32(), None => false }; // may as well grab the user id now since the fail case is going to be rare (hopefully) const UID_QUERY : &'static str = "SELECT userid FROM `keys` WHERE `secret` = :secret"; let (conn, row): (Conn, Option) = conn .first_exec(UID_QUERY, params!{"secret"=>secret}) .await?; // for a message entry we need: (DATE, CONTENT, AUTHOR_ID, Channel_id) if channel_exists { // NOTE: not checking if the user exists as our auth model does that // for us already conn.batch_exec( "INSERT INTO `messages` (id, content, author_id, channel_id) \ VALUES (:mid, :content, :aid, :cid)", params!{ "mid" => Utc::now().timestamp() as u64, "content" => content, "aid" => row.expect("uid is None when it should have come back as Some(u64):\ Occurence in "), "cid" => id }).await?; Ok(()) } else { let x = Cow::from("Channel does not exist"); Err(Error::Other(x)) } } _ => { let x = Cow::from("Missing required parameters to create message"); Err(Error::Other(x)) } } } pub async fn send_message(pool: &Pool, response: &mut Response, params: Value) { /* * @content: expecting string type * @id: expecting the channel id that we're posting data to */ if validate_params(¶ms, vec!["content", "id"]) { // now we prepare some arguments for our db and send them down the wire let content = params.get("content").unwrap().as_str(); let id = params.get("id").unwrap().as_u64(); let secret: &str = params.get("secret").unwrap().as_str().unwrap(); //auth sucess guarantees this param is fine match update_messages_table(pool, secret, content, id).await { Ok(_) => *response.status_mut() = StatusCode::OK, Err(_err) => *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR } } }