Removing passthrough for message send handler
This means we get more opaque errors for the clients but it also results in way less code to maintain
This commit is contained in:
parent
d88948385d
commit
15b56353b8
@ -4,15 +4,12 @@ use tokio::fs;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
use mysql_async::params;
|
||||
use mysql_async::{Pool, Conn};
|
||||
use mysql_async::Pool;
|
||||
use mysql_async::prelude::Queryable;
|
||||
use mysql_async::error::Error as SqlError;
|
||||
use mysql_async::QueryResult;
|
||||
use mysql_async::BinaryProtocol;
|
||||
use mysql_async::Error as SqlError;
|
||||
|
||||
|
||||
use crate::{Response, sql_err};
|
||||
use crate::{UBigInt, BigInt, VarChar};
|
||||
use crate::Response;
|
||||
use crate::{UBigInt, BigInt};
|
||||
use crate::{Message, UserMessage};
|
||||
|
||||
use rand::RngCore;
|
||||
@ -33,42 +30,12 @@ impl Message {
|
||||
}
|
||||
}
|
||||
|
||||
fn message_passthrough_no_err(res: Result<QueryResult<Conn, BinaryProtocol>, SqlError>, passthrough: Self)
|
||||
-> Result<Response<Self>, SqlError> {
|
||||
/* You shouldn't have cum here.webm
|
||||
* Basically sending messages with mysql is kinda painful so we
|
||||
* do some special error checking by hand to see if
|
||||
* a message was sent to an existing channel.
|
||||
* The whole point of this is to avoid sending back a 500 to user clients
|
||||
* which may cause confusing error handling in userland. This means we have
|
||||
* confusing error handling on the server side but one of the parties has to
|
||||
* do this stupid check so fuck it at least its mostly pointers anyway
|
||||
*/
|
||||
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::Row(passthrough));
|
||||
}
|
||||
}
|
||||
|
||||
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 mut conn = p.get_conn().await?;
|
||||
let q = "INSERT INTO messages
|
||||
(id, time, content, content_type, author_id, channel_id)
|
||||
VALUES (id, :time, :content, :ctype, :author, :channel)";
|
||||
@ -84,7 +51,7 @@ impl Message {
|
||||
if content.len() > 4_000 {
|
||||
Ok(Response::RestrictedInput("Large text not allowed".into()))
|
||||
} else {
|
||||
let res = conn.prep_exec(q, params!{
|
||||
let res = conn.exec_drop(q, params!{
|
||||
"id" => id,
|
||||
"time" => now,
|
||||
"content" => content,
|
||||
@ -92,8 +59,13 @@ impl Message {
|
||||
"author" => uid,
|
||||
"channel" => cid
|
||||
}).await;
|
||||
let msg = Message::new(id, now, content, content_type, uid, cid);
|
||||
Self::message_passthrough_no_err(res, msg)
|
||||
match Ok(res) {
|
||||
Ok(_) => {
|
||||
let msg = Message::new(id, now, content, content_type, uid, cid);
|
||||
Ok(Response::Row(msg))
|
||||
},
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
@ -117,7 +89,7 @@ impl Message {
|
||||
};
|
||||
let content_ref = format!("{cid}-{time}.{ext}", cid=cid, time=now, ext=extension);
|
||||
|
||||
let res = conn.prep_exec(q, params!{
|
||||
let res = conn.exec_drop(q, params!{
|
||||
"id" => id,
|
||||
"time" => now,
|
||||
"content" => &content_ref, // store a ref to a file instead of the actual payload
|
||||
@ -125,13 +97,13 @@ impl Message {
|
||||
"author" => uid,
|
||||
"channel" => cid
|
||||
}).await;
|
||||
let msg = Message::new(id, now, content, content_type, uid, cid);
|
||||
if let Ok(ret) = Self::message_passthrough_no_err(res, msg) {
|
||||
if let Ok(ret) = res {
|
||||
// now save the data to disk
|
||||
match fs::File::create(content_ref).await {
|
||||
Ok(mut file) => {
|
||||
file.write_all(content.as_bytes()).await.expect("Failed to write, but the ref is saved");
|
||||
Ok(ret)
|
||||
let msg = Message::new(id, now, content, content_type, uid, cid);
|
||||
Ok(Response::Row(msg))
|
||||
},
|
||||
Err(_) => {
|
||||
Ok(Response::Other("Saved ref but couldn't save file data".into()))
|
||||
@ -156,7 +128,7 @@ impl Message {
|
||||
Ok(Response::RestrictedInput("Invalid start/end parameters".into()))
|
||||
}
|
||||
else {
|
||||
let conn = p.get_conn().await?;
|
||||
let mut conn = p.get_conn().await?;
|
||||
let limit = if let Some(limit) = limit {
|
||||
match limit {
|
||||
1 ..= MAX_MESSAGES => limit,
|
||||
@ -172,17 +144,13 @@ impl Message {
|
||||
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);
|
||||
let params = params!{
|
||||
"start" => start,
|
||||
"end" => end,
|
||||
"channel" => channel_id,
|
||||
"limit" => limit
|
||||
};
|
||||
let messages = conn.exec_map(q, params, |(name, id, time, content, content_type, author_id)| {
|
||||
UserMessage {
|
||||
id,
|
||||
time,
|
||||
@ -202,7 +170,7 @@ impl Message {
|
||||
//! @returns on success : Set(Vec<Messages>)
|
||||
//! @returns on user failure : RestrictedInput(String)
|
||||
//! @returns on failure : Err(SqlError)
|
||||
let conn = p.get_conn().await?;
|
||||
let mut conn = p.get_conn().await?;
|
||||
let limit = if let Some(limit) = limit{
|
||||
match limit {
|
||||
1 ..= MAX_MESSAGES => limit,
|
||||
@ -221,11 +189,8 @@ impl Message {
|
||||
"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);
|
||||
let messages = conn.exec_map(q, params,
|
||||
|(id, time, content, content_type, author_id)| {
|
||||
Self {
|
||||
id,
|
||||
time,
|
||||
|
Loading…
Reference in New Issue
Block a user