158 lines
6.0 KiB
Rust
158 lines
6.0 KiB
Rust
use mysql_async::Pool;
|
|
use hyper::{Response, Body, HeaderMap, StatusCode};
|
|
use hyper::body::to_bytes;
|
|
use hyper::body::Bytes;
|
|
use serde_json::json;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use crate::http::set_json_body;
|
|
use crate::qs_param;
|
|
use db::Message;
|
|
|
|
pub async fn get_by_time(pool: &Pool, response: &mut Response<Body>, params: HashMap<String, String>) {
|
|
/*
|
|
* Has a ton of required parameters just be warned
|
|
* @channel: channel id we're looking at
|
|
* @start-time: how long ago do we start searching
|
|
* @end-time: how long ago do we stop searching
|
|
* {
|
|
* "channel_id": 1,
|
|
* "start_time": unix_now - 24 hours
|
|
* "end_time": unix_now - 23 hours
|
|
* }
|
|
*
|
|
*/
|
|
let channel_id = qs_param!(params, "channel_id", u64);
|
|
let start_time = qs_param!(params, "start_time", i64);
|
|
let end_time = qs_param!(params, "end_time", i64);
|
|
let limit = qs_param!(params, "limit", u64);
|
|
|
|
// TODO: flatten me mommy
|
|
if let (Some(channel), Some(start), Some(end)) = (channel_id, start_time, end_time) {
|
|
match Message::get_time_range(pool, channel, start, end, limit).await {
|
|
Ok(db_response) => {
|
|
match db_response {
|
|
// this absolute lack of data streaming is prolly gonna suck like
|
|
// a whore in hell week for performance but lets pretend servers don't get massive
|
|
db::Response::Set(messages) => set_json_body(response, json!({"messages": messages})),
|
|
db::Response::RestrictedInput(_/*error message to log*/) => {
|
|
*response.status_mut() = StatusCode::BAD_REQUEST;
|
|
}
|
|
_ => {
|
|
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
|
}
|
|
};
|
|
},
|
|
Err(e) => {
|
|
eprintln!("{}", e);
|
|
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
|
}
|
|
};
|
|
} else {
|
|
*response.status_mut() = StatusCode::BAD_REQUEST;
|
|
}
|
|
}
|
|
|
|
pub async fn send_message(pool: &Pool, response: &mut Response<Body>, body: Body, headers: HeaderMap, params: HashMap<String, String>) {
|
|
/*
|
|
* Message content is sent in the message body
|
|
* @channel_id: channel id that we're going to send a message to
|
|
* @content-type in the headers
|
|
* TODO: more features here because send_message is a large handler
|
|
*/
|
|
use db::Response::*;
|
|
|
|
// NOTE: auth module guarantees that id will be present so the unwrap is safe
|
|
let uid = qs_param!(params, "id", u64).unwrap();
|
|
let ctype: Option<&str> = match headers.get("Content-Type") {
|
|
Some(hval) => {
|
|
match hval.to_str() {
|
|
Ok(s) => Some(s),
|
|
_ => None
|
|
}
|
|
},
|
|
None => None
|
|
};
|
|
|
|
let channel_id = qs_param!(params, "channel_id", u64);
|
|
|
|
// Black magic
|
|
let body_bytes: &[u8] = &to_bytes(body).await.unwrap_or(Bytes::new());
|
|
let content = String::from_utf8_lossy(body_bytes);
|
|
|
|
// 400 on empty bodies or missing channel id's
|
|
if content.len() == 0 || channel_id.is_none() || ctype.is_none() {
|
|
*response.status_mut() = StatusCode::BAD_REQUEST;
|
|
} else {
|
|
// block away wrong content types
|
|
const CONTENT_TYPES: [&'static str;7] = [
|
|
"text/plain",
|
|
"image/png", "image/jpeg", "image/jpg",
|
|
"application/webm", "application/mp4",
|
|
"application/mp3"
|
|
];
|
|
if CONTENT_TYPES.contains(&ctype.unwrap()) == false {
|
|
*response.status_mut() = StatusCode::BAD_REQUEST;
|
|
}
|
|
else {
|
|
// Safe unwrap with ctype - its container type is checked prior
|
|
match db::Message::send(pool, &content, ctype.unwrap(), channel_id.unwrap(), uid).await {
|
|
#[cfg(feature = "rtc")]
|
|
Ok(Row(msg)) => {
|
|
use crate::rtc;
|
|
rtc::new_message(pool, msg).await;
|
|
},
|
|
// All ok but nothing to do without rtc enabled
|
|
#[cfg(not(feature = "rtc"))]
|
|
Ok(Row(_)) => {},
|
|
Ok(RestrictedInput(_msg)) => *response.status_mut() = StatusCode::BAD_REQUEST,
|
|
Ok(Other(msg)) => {
|
|
eprintln!("{}", msg);
|
|
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
|
},
|
|
Ok(_) => {}, // Can't happen because no branches return remaining variants
|
|
Err(e) => {
|
|
eprintln!("/message/send error: {}", e);
|
|
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn recent_messages(pool: &Pool, response: &mut Response<Body>, params: HashMap<String, String>) {
|
|
let limit = qs_param!(params, "limit", i32);
|
|
let channel_id = qs_param!(params, "channel_id", u64);
|
|
|
|
if let (Some(channel_id), Some(limit)) = (channel_id, limit) {
|
|
println!("channel_id: {}", channel_id);
|
|
// NOTE: using match here to capture+log the error from the database
|
|
match Message::last_n(pool, limit, channel_id).await {
|
|
Ok(dbresp) => {
|
|
match dbresp {
|
|
// 200
|
|
db::Response::Set(messages) =>
|
|
set_json_body(response, json!({"messages": messages})),
|
|
// 404 - assuming the request channel does not exist
|
|
db::Response::Empty =>
|
|
*response.status_mut() = StatusCode::NOT_FOUND,
|
|
// 400
|
|
db::Response::RestrictedInput(msg) => {
|
|
*response.status_mut() = StatusCode::BAD_REQUEST;
|
|
set_json_body(response, json!({"error": msg}));
|
|
},
|
|
// unreachable branch
|
|
_ => {}
|
|
}
|
|
},
|
|
Err(e) => {
|
|
eprintln!("{}", e);
|
|
}
|
|
}
|
|
} else {
|
|
*response.status_mut() = StatusCode::BAD_REQUEST;
|
|
}
|
|
}
|
|
|