channels modules have newly updated list endpoints
/channels/create requires a rework however
This commit is contained in:
parent
188184460f
commit
f9bc6b3dc9
@ -8,7 +8,10 @@ use crate::{VarChar, UBigInt, Integer};
|
|||||||
use crate::common::FromDB;
|
use crate::common::FromDB;
|
||||||
use crate::{sql_err, no_conn, Response};
|
use crate::{sql_err, no_conn, Response};
|
||||||
|
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[derive(Serialize)]
|
||||||
pub struct Channel {
|
pub struct Channel {
|
||||||
pub id: UBigInt,
|
pub id: UBigInt,
|
||||||
pub name: VarChar,
|
pub name: VarChar,
|
||||||
@ -16,8 +19,11 @@ pub struct Channel {
|
|||||||
pub kind: Integer
|
pub kind: Integer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const VOICE_CHANNEL: Integer = 1;
|
||||||
|
pub const TEXT_CHANNEL: Integer = 2;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl FromDB<Channel> for Channel {
|
impl FromDB<Channel, Integer> for Channel {
|
||||||
// id name desc kind
|
// id name desc kind
|
||||||
type Row = Option<(UBigInt, VarChar, Option<VarChar>, Integer)>;
|
type Row = Option<(UBigInt, VarChar, Option<VarChar>, Integer)>;
|
||||||
|
|
||||||
@ -91,4 +97,62 @@ impl FromDB<Channel> for Channel {
|
|||||||
}
|
}
|
||||||
return Response::Other(no_conn!("Member::FromDB::delete"))
|
return Response::Other(no_conn!("Member::FromDB::delete"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn filter(p: &Pool, kind: Integer) -> Response<Channel> {
|
||||||
|
//! @returns -> on success : Response::Set(Vec<Channel>)
|
||||||
|
//! @returns -> on empty set : Response::Set(EmptyVector)
|
||||||
|
//! @params -> on fail : Response::Other
|
||||||
|
|
||||||
|
// NOTE: used for mapping datasets to vectors
|
||||||
|
let map_rows = |row| {
|
||||||
|
let (id, name, desc, k): (UBigInt, VarChar, Option<VarChar>, Integer) =
|
||||||
|
mysql_async::from_row(row);
|
||||||
|
Channel {
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
description: desc,
|
||||||
|
kind: k
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return match (p.get_conn().await, kind) {
|
||||||
|
// Filter for text/voice channels specifically
|
||||||
|
(Ok(conn), VOICE_CHANNEL..=TEXT_CHANNEL) => { // @NOTE: voice channel and text_channel are literally 1 & 2 respectively
|
||||||
|
let q = "SELECT id, name, description, kind FROM channels WHERE kind = :kind";
|
||||||
|
let q_result = conn.prep_exec(q, params!{"kind" => kind}).await;
|
||||||
|
if let Ok(res) = q_result {
|
||||||
|
let mapping_result = res.map_and_drop(map_rows).await;
|
||||||
|
return match mapping_result {
|
||||||
|
Ok((_, channels)) => Response::Set(channels),
|
||||||
|
Err(_) => Response::Other(sql_err!("db::Channels::filter @with params"))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Response::Other(sql_err!(""))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
* Here we are attempting to get all the channels with no filters applied
|
||||||
|
* This should fetch everything basically in our channels registry
|
||||||
|
*/
|
||||||
|
(Ok(conn), _) => {
|
||||||
|
let q = "SELECT id, name, description, kind FROM channels";
|
||||||
|
if let Ok(query) = conn.prep_exec(q, ()).await {
|
||||||
|
let mapping_r = query.map_and_drop(map_rows).await;
|
||||||
|
|
||||||
|
return match mapping_r {
|
||||||
|
Ok((_, channels)) => Response::Set(channels),
|
||||||
|
Err(_) => Response::Other(sql_err!("db::Channels::filter @no params"))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Response::Other(sql_err!("db::Channels::filter @no params @no initial query"))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(Err(_), _) => {Response::Other(no_conn!("Channel::FromDB::filter"))}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Channel {
|
||||||
|
pub async fn add() {}
|
||||||
}
|
}
|
||||||
|
@ -1,159 +1,40 @@
|
|||||||
use hyper::{StatusCode, Response, Body};
|
use hyper::{
|
||||||
use hyper::header::HeaderValue;
|
StatusCode, Response, Body,
|
||||||
|
header::HeaderValue
|
||||||
|
};
|
||||||
|
|
||||||
use mysql_async::{Conn, Pool};
|
use mysql_async::Pool;
|
||||||
use mysql_async::error::Error;
|
|
||||||
use mysql_async::prelude::{params, Queryable};
|
|
||||||
|
|
||||||
use serde_json::Value;
|
use serde_json::{Value, to_string};
|
||||||
|
|
||||||
use db::{
|
use db::{
|
||||||
self,
|
self,
|
||||||
UBigInt, VarChar, Integer,
|
common::FromDB,
|
||||||
common::FromDB
|
channels::Channel
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ChannelType {
|
|
||||||
Voice,
|
|
||||||
Text,
|
|
||||||
Undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ChannelType {
|
|
||||||
// These funcs are mainly here to help translation from mysql
|
|
||||||
pub fn from_i32(x: i32) -> ChannelType {
|
|
||||||
match x {
|
|
||||||
1 => ChannelType::Voice,
|
|
||||||
2 => ChannelType::Text,
|
|
||||||
_ => ChannelType::Undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn as_i32(&self) -> i32 {
|
|
||||||
match self {
|
|
||||||
ChannelType::Voice => 1,
|
|
||||||
ChannelType::Text => 2,
|
|
||||||
ChannelType::Undefined => 3,
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Primary way of interpretting sql data on our channels table
|
|
||||||
pub struct Channel {
|
|
||||||
pub id: u64,
|
|
||||||
pub name: String,
|
|
||||||
pub description: String,
|
|
||||||
pub kind: ChannelType
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct InsertableChannel {
|
|
||||||
name: String,
|
|
||||||
kind: ChannelType
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Channel {
|
|
||||||
/*
|
|
||||||
* When our sql library queries things we generally get back tuples rather reasily
|
|
||||||
* we can use this method to get something that makes more sense
|
|
||||||
*/
|
|
||||||
fn from_tup(tup: (UBigInt, VarChar, Option<VarChar>, Integer)) -> Channel {
|
|
||||||
let desc = match tup.2 {
|
|
||||||
Some(val) => val,
|
|
||||||
None => "None".into()
|
|
||||||
};
|
|
||||||
|
|
||||||
Channel {
|
|
||||||
id: tup.0,
|
|
||||||
name: tup.1,
|
|
||||||
description: desc,
|
|
||||||
kind: ChannelType::from_i32(tup.3)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* When responding with some channel data to the client we use json
|
|
||||||
* this itemizes a single struct as the following(without the pretty output)
|
|
||||||
* {
|
|
||||||
* "id": id<i32>,
|
|
||||||
* "name": "<some name here>",
|
|
||||||
* "description": Option<"<description here>">,
|
|
||||||
* "kind": kind<i32>
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
fn as_json_str(&self) -> String {
|
|
||||||
let mut base = String::from("{");
|
|
||||||
base.push_str(&format!("\"id\":{},", self.id));
|
|
||||||
base.push_str(&format!("\"name\":\"{}\",", self.name));
|
|
||||||
base.push_str(&format!("\"description\":\"{}\",", self.description));
|
|
||||||
base.push_str(&format!("\"kind\":{}}}", self.kind.as_i32()));
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Forwarding SQL errors as we can handle those error in caller site for this leaf function
|
|
||||||
* On success we back a Vec<Channel> which we can JSON'ify later and use as a response
|
|
||||||
*/
|
|
||||||
async fn get_channels_vec(conn: Conn) -> Result<Vec<Channel>, Error> {
|
|
||||||
let rows_db = conn.prep_exec(r"SELECT * FROM channels", ()).await?;
|
|
||||||
let (_, rows) = rows_db.map_and_drop(|row| {
|
|
||||||
let (id, name, desc, kind): (UBigInt, VarChar, Option<VarChar>, Integer) = mysql_async::from_row(row);
|
|
||||||
Channel::from_tup((id, name, desc, kind))
|
|
||||||
}).await?;
|
|
||||||
|
|
||||||
Ok(rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn list_channels(pool: &Pool, response: &mut Response<Body>) {
|
pub async fn list_channels(pool: &Pool, response: &mut Response<Body>) {
|
||||||
/*
|
/*
|
||||||
* Primary dispatcher for dealing with the CHANNELS_LIST route
|
* @user-params -> for now none as i don't feel like dealing with it
|
||||||
* For the most part this function will have a lot more error handling as it
|
* @TODO: add in a let var that actually
|
||||||
* should know what kind of issues its child functions will have
|
|
||||||
*/
|
*/
|
||||||
if let Ok(conn) = pool.get_conn().await {
|
return match db::channels::Channel::filter(pool, 0).await {
|
||||||
match get_channels_vec(conn).await {
|
db::Response::Set(channels) => {
|
||||||
Ok(chans) => {
|
response.headers_mut().insert("Content type",
|
||||||
*response.status_mut() = StatusCode::OK;
|
HeaderValue::from_static("json/application"));
|
||||||
response.headers_mut().insert("Content-Type",
|
|
||||||
HeaderValue::from_static("application/json"));
|
|
||||||
|
|
||||||
// At this point we build the content of our response body
|
*response.body_mut() = Body::from(to_string(&channels).unwrap_or("{}".into()))
|
||||||
// which is a json payload hence why there is weird string manipulation
|
|
||||||
// because we're trying to avoid dependancy issues and serializing things ourselves
|
|
||||||
let mut new_body = String::from("{\"channels\":[");
|
|
||||||
for chan in chans.iter() {
|
|
||||||
let s = format!("{},", chan.as_json_str());
|
|
||||||
new_body.push_str(&s);
|
|
||||||
}
|
|
||||||
if new_body.ends_with(',') {new_body.pop();}
|
|
||||||
new_body.push_str("]}");
|
|
||||||
|
|
||||||
*response.body_mut() = Body::from(new_body);
|
|
||||||
},
|
},
|
||||||
Err(_) => {
|
db::Response::Other(_msg) => *response.status_mut() = hyper::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
_ => *response.status_mut() = hyper::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
}
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async fn insert_channel(pool: &Pool, name: &str, desc: &str, kind: i64) -> Result<(), Error>{
|
|
||||||
let conn = pool.get_conn().await?;
|
|
||||||
conn.prep_exec(
|
|
||||||
"INSERT INTO channels (name, description, kind) VALUES (:name, :description, :kind)",
|
|
||||||
params!{"name" => name, "kind" => kind, "description" => desc}).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_channel(pool: &Pool, response: &mut Response<Body>, params: Value) {
|
pub async fn create_channel(pool: &Pool, response: &mut Response<Body>, params: Value) {
|
||||||
/*
|
/*
|
||||||
* Create a channel base on a few parameters that may or may not be there
|
* Create a channel base on a few parameters that may or may not be there
|
||||||
|
* @responds with the data of the newly created channel
|
||||||
*/
|
*/
|
||||||
// Theres an extra un-needed unwrap to be cut out from this proc
|
// Theres an extra un-needed unwrap to be cut out from this proc
|
||||||
// specifically with the desc parameter
|
// specifically with the desc parameter
|
||||||
@ -165,13 +46,6 @@ pub async fn create_channel(pool: &Pool, response: &mut Response<Body>, params:
|
|||||||
};
|
};
|
||||||
match req_params {
|
match req_params {
|
||||||
(Some(name), Some(desc), Some(kind)) => {
|
(Some(name), Some(desc), Some(kind)) => {
|
||||||
match insert_channel(pool, name, desc, kind).await {
|
|
||||||
Err(e) => {
|
|
||||||
println!("SERVER ERROR: {}", e);
|
|
||||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// basically one of the parameter gets failed so we bail on all of this
|
// basically one of the parameter gets failed so we bail on all of this
|
||||||
_ => *response.status_mut() = StatusCode::BAD_REQUEST
|
_ => *response.status_mut() = StatusCode::BAD_REQUEST
|
||||||
@ -180,7 +54,6 @@ pub async fn create_channel(pool: &Pool, response: &mut Response<Body>, params:
|
|||||||
|
|
||||||
pub async fn delete_channel(pool: &Pool, response: &mut Response<Body>, params: Value) {
|
pub async fn delete_channel(pool: &Pool, response: &mut Response<Body>, params: Value) {
|
||||||
// make sure we have the right parameters provided
|
// make sure we have the right parameters provided
|
||||||
use db::channels::Channel;
|
|
||||||
if let Some(name) = params.get("channel_id") {
|
if let Some(name) = params.get("channel_id") {
|
||||||
if let Some(id) = name.as_u64() {
|
if let Some(id) = name.as_u64() {
|
||||||
// TODO: something more intelligent with the logging im ngl
|
// TODO: something more intelligent with the logging im ngl
|
||||||
|
Loading…
Reference in New Issue
Block a user