freechat/json-api/db/src/messages.rs
shockrah 988aa9f155 Removal of chrono and async_trait as dependancy in db-lib
Removig chrono from api code as well

Removing chrono as dep in api code
+ Using Content-Type for /message/send content type

Updating cargo lists for removal of fluff deps

Removal of more fluff

Addking makefile to avoid compiling debug builds by accident while developing
2021-03-20 14:59:06 -07:00

151 lines
5.0 KiB
Rust

use std::time::{SystemTime, UNIX_EPOCH};
use mysql_async::{params, Pool};
use mysql_async::prelude::Queryable;
use mysql_async::error::Error as SqlError;
use crate::{Response, sql_err};
use crate::{UBigInt, BigInt, VarChar};
use crate::{Message, UserMessage};
const MAX_MESSAGES: u64 = 1000;
impl Message {
pub async fn send(p: &Pool, content: &str, content_type: &str, cid: UBigInt, uid: UBigInt) -> Result<Response<Self>, SqlError> {
//! @returns on_sucess -> empty
//! @returns on_failure Err(SqlErr)
let conn = p.get_conn().await?;
let q = "INSERT INTO messages
(time, content, content_type, author_id, channel_id)
VALUES (:time, :content, :ctype, :author, :channel)";
let now: i64 = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("System time `NOW` failed")
.as_millis() as i64;
let res = conn.prep_exec(q, params!{
"time" => now,
"content" => content,
"ctype" => content_type,
"author" => uid,
"channel" => cid
}).await;
if let Err(e) = res {
return match e {
SqlError::Server(err) => {
if err.code == 1452 {
return Ok(Response::RestrictedInput("Channel not found".into()))
}
else {
Ok(Response::Other(sql_err!("db::messages::send")))
}
},
_ => Ok(Response::Other(sql_err!("db::messages::send")))
}
}
// all good response
else {
return Ok(Response::Empty);
}
}
pub async fn get_time_range(p: &Pool, channel_id: UBigInt, start: BigInt, end: BigInt, limit: Option<u64>) -> Result<Response<UserMessage>, SqlError> {
//! @returns on success : Set(Vec<Messages>)
//! @returns on userfail: RestrictedInput(message)
//! @returns on error : Err(SqlError)
if start >= end {
Ok(Response::RestrictedInput("Invalid start/end parameters".into()))
}
else {
let conn = p.get_conn().await?;
let limit = if let Some(limit) = limit {
match limit {
1 ..= MAX_MESSAGES => limit,
_ => MAX_MESSAGES
}
} else {
MAX_MESSAGES
};
let q = " SELECT mem.name, msg.id, msg.time, msg.content, msg.content_type, msg.author_id
FROM messages as msg
JOIN members as mem ON mem.id = msg.author_id
WHERE channel_id = :channel AND time >= :start AND time < :end
LIMIT :limit";
let select_result = conn.prep_exec(
q, params!{
"start" => start,
"end" => end,
"channel" => channel_id,
"limit" => limit
}).await?;
let(_conn, messages) = select_result.map_and_drop(|row| {
type Tuple = (VarChar, UBigInt, BigInt, String, String, UBigInt);
let (name, id, time, content, content_type, author_id): Tuple = mysql_async::from_row(row);
UserMessage {
id,
time,
content,
content_type,
author_id,
name,
channel_id
}
}).await?;
Ok(Response::Set(messages))
}
}
pub async fn get_from_id(p: &Pool, channel_id: UBigInt, start: UBigInt, limit: Option<UBigInt>) -> Result<Response<Self>, SqlError> {
//! @returns on success : Set(Vec<Messages>)
//! @returns on user failure : RestrictedInput(String)
//! @returns on failure : Err(SqlError)
let conn = p.get_conn().await?;
let limit = if let Some(limit) = limit{
match limit {
1 ..= MAX_MESSAGES => limit,
_ => MAX_MESSAGES
}
} else {
MAX_MESSAGES // messages at a time
};
let q = "SELECT id, time, content, content_type, author_id FROM messages WHERE
channel_id = :channel AND id >= :start LIMIT :limit";
let params = params!{
"channel" => channel_id,
"start" => start,
"limit" => limit
};
let select_result = conn.prep_exec(q, params).await?;
let (_conn, messages) = select_result.map_and_drop(|row| {
type Tuple = (UBigInt, BigInt, VarChar, VarChar, UBigInt);
let (id, time, content, content_type, author_id): Tuple = mysql_async::from_row(row);
Self {
id,
time,
content,
content_type,
author_id,
channel_id
}
}).await?;
Ok(Response::Set(messages))
}
}