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 tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
use mysql_async::params;
|
use mysql_async::params;
|
||||||
use mysql_async::{Pool, Conn};
|
use mysql_async::Pool;
|
||||||
use mysql_async::prelude::Queryable;
|
use mysql_async::prelude::Queryable;
|
||||||
use mysql_async::error::Error as SqlError;
|
use mysql_async::Error as SqlError;
|
||||||
use mysql_async::QueryResult;
|
|
||||||
use mysql_async::BinaryProtocol;
|
|
||||||
|
|
||||||
|
use crate::Response;
|
||||||
use crate::{Response, sql_err};
|
use crate::{UBigInt, BigInt};
|
||||||
use crate::{UBigInt, BigInt, VarChar};
|
|
||||||
use crate::{Message, UserMessage};
|
use crate::{Message, UserMessage};
|
||||||
|
|
||||||
use rand::RngCore;
|
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> {
|
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_sucess -> empty
|
||||||
//! @returns on_failure Err(SqlErr)
|
//! @returns on_failure Err(SqlErr)
|
||||||
|
|
||||||
let conn = p.get_conn().await?;
|
let mut conn = p.get_conn().await?;
|
||||||
let q = "INSERT INTO messages
|
let q = "INSERT INTO messages
|
||||||
(id, time, content, content_type, author_id, channel_id)
|
(id, time, content, content_type, author_id, channel_id)
|
||||||
VALUES (id, :time, :content, :ctype, :author, :channel)";
|
VALUES (id, :time, :content, :ctype, :author, :channel)";
|
||||||
@ -84,7 +51,7 @@ impl Message {
|
|||||||
if content.len() > 4_000 {
|
if content.len() > 4_000 {
|
||||||
Ok(Response::RestrictedInput("Large text not allowed".into()))
|
Ok(Response::RestrictedInput("Large text not allowed".into()))
|
||||||
} else {
|
} else {
|
||||||
let res = conn.prep_exec(q, params!{
|
let res = conn.exec_drop(q, params!{
|
||||||
"id" => id,
|
"id" => id,
|
||||||
"time" => now,
|
"time" => now,
|
||||||
"content" => content,
|
"content" => content,
|
||||||
@ -92,8 +59,13 @@ impl Message {
|
|||||||
"author" => uid,
|
"author" => uid,
|
||||||
"channel" => cid
|
"channel" => cid
|
||||||
}).await;
|
}).await;
|
||||||
|
match Ok(res) {
|
||||||
|
Ok(_) => {
|
||||||
let msg = Message::new(id, now, content, content_type, uid, cid);
|
let msg = Message::new(id, now, content, content_type, uid, cid);
|
||||||
Self::message_passthrough_no_err(res, msg)
|
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 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,
|
"id" => id,
|
||||||
"time" => now,
|
"time" => now,
|
||||||
"content" => &content_ref, // store a ref to a file instead of the actual payload
|
"content" => &content_ref, // store a ref to a file instead of the actual payload
|
||||||
@ -125,13 +97,13 @@ impl Message {
|
|||||||
"author" => uid,
|
"author" => uid,
|
||||||
"channel" => cid
|
"channel" => cid
|
||||||
}).await;
|
}).await;
|
||||||
let msg = Message::new(id, now, content, content_type, uid, cid);
|
if let Ok(ret) = res {
|
||||||
if let Ok(ret) = Self::message_passthrough_no_err(res, msg) {
|
|
||||||
// now save the data to disk
|
// now save the data to disk
|
||||||
match fs::File::create(content_ref).await {
|
match fs::File::create(content_ref).await {
|
||||||
Ok(mut file) => {
|
Ok(mut file) => {
|
||||||
file.write_all(content.as_bytes()).await.expect("Failed to write, but the ref is saved");
|
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(_) => {
|
Err(_) => {
|
||||||
Ok(Response::Other("Saved ref but couldn't save file data".into()))
|
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()))
|
Ok(Response::RestrictedInput("Invalid start/end parameters".into()))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let conn = p.get_conn().await?;
|
let mut conn = p.get_conn().await?;
|
||||||
let limit = if let Some(limit) = limit {
|
let limit = if let Some(limit) = limit {
|
||||||
match limit {
|
match limit {
|
||||||
1 ..= MAX_MESSAGES => limit,
|
1 ..= MAX_MESSAGES => limit,
|
||||||
@ -172,17 +144,13 @@ impl Message {
|
|||||||
WHERE channel_id = :channel AND time >= :start AND time < :end
|
WHERE channel_id = :channel AND time >= :start AND time < :end
|
||||||
LIMIT :limit";
|
LIMIT :limit";
|
||||||
|
|
||||||
let select_result = conn.prep_exec(
|
let params = params!{
|
||||||
q, params!{
|
|
||||||
"start" => start,
|
"start" => start,
|
||||||
"end" => end,
|
"end" => end,
|
||||||
"channel" => channel_id,
|
"channel" => channel_id,
|
||||||
"limit" => limit
|
"limit" => limit
|
||||||
}).await?;
|
};
|
||||||
|
let messages = conn.exec_map(q, params, |(name, id, time, content, content_type, author_id)| {
|
||||||
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 {
|
UserMessage {
|
||||||
id,
|
id,
|
||||||
time,
|
time,
|
||||||
@ -202,7 +170,7 @@ impl Message {
|
|||||||
//! @returns on success : Set(Vec<Messages>)
|
//! @returns on success : Set(Vec<Messages>)
|
||||||
//! @returns on user failure : RestrictedInput(String)
|
//! @returns on user failure : RestrictedInput(String)
|
||||||
//! @returns on failure : Err(SqlError)
|
//! @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{
|
let limit = if let Some(limit) = limit{
|
||||||
match limit {
|
match limit {
|
||||||
1 ..= MAX_MESSAGES => limit,
|
1 ..= MAX_MESSAGES => limit,
|
||||||
@ -221,11 +189,8 @@ impl Message {
|
|||||||
"limit" => limit
|
"limit" => limit
|
||||||
};
|
};
|
||||||
|
|
||||||
let select_result = conn.prep_exec(q, params).await?;
|
let messages = conn.exec_map(q, params,
|
||||||
|
|(id, time, content, content_type, author_id)| {
|
||||||
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 {
|
Self {
|
||||||
id,
|
id,
|
||||||
time,
|
time,
|
||||||
|
Loading…
Reference in New Issue
Block a user