From 03656e99a361868fd863d8094662655b25b6af64 Mon Sep 17 00:00:00 2001 From: Zomatree Date: Sun, 5 Jun 2022 03:05:39 +0100 Subject: [PATCH] feat(revcord): post message request handling --- crates/revcord/api/src/main.rs | 8 +- .../routes/channels/messages/message_send.rs | 92 +++++++++++++++++++ .../api/src/routes/channels/messages/mod.rs | 1 + crates/revcord/api/src/routes/channels/mod.rs | 3 + crates/revcord/api/src/routes/mod.rs | 5 +- crates/revcord/models/src/lib.rs | 6 +- 6 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 crates/revcord/api/src/routes/channels/messages/message_send.rs create mode 100644 crates/revcord/api/src/routes/channels/messages/mod.rs diff --git a/crates/revcord/api/src/main.rs b/crates/revcord/api/src/main.rs index 7dfe2fa0..c04e99a8 100644 --- a/crates/revcord/api/src/main.rs +++ b/crates/revcord/api/src/main.rs @@ -62,12 +62,16 @@ async fn main() { let auth = Auth::new(mongo_db.database("revolt"), Config::default()); let rocket = rocket::build(); - routes::mount(rocket) + let r = routes::mount(rocket) .mount("/", rocket_cors::catch_all_options_routes()) .manage(auth) .manage(db) .manage(cors.clone()) - .attach(cors) + .attach(cors); + + let config = r.figment().clone().merge((rocket::Config::PORT, 1111)); + + r.configure(config) .launch() .await .unwrap(); diff --git a/crates/revcord/api/src/routes/channels/messages/message_send.rs b/crates/revcord/api/src/routes/channels/messages/message_send.rs new file mode 100644 index 00000000..d7ca20a7 --- /dev/null +++ b/crates/revcord/api/src/routes/channels/messages/message_send.rs @@ -0,0 +1,92 @@ +use std::collections::HashMap; + +use revolt_quark::{Database, Ref, Result, EmptyResponse, Error}; +use revcord_models::{ user::User}; +use rocket::{serde::json::Json, form::{FromForm, Form, ValueField, Result as FormResult, DataField, Errors as FormErrors, Error as FormError}, data::{FromData, Outcome, Data}, http::Status, fs::TempFile, }; +use rocket_okapi::request::OpenApiFromData; +use serde::{Deserialize, Serialize}; +use validator::Validate; + +#[derive(Debug, FromForm)] +pub struct MessagePostForm<'r> { + pub payload_json: Option, + pub files: HashMap> +} + +#[derive(Serialize, Deserialize, Validate, JsonSchema, Debug, Clone)] +pub struct MessagePostJson { + pub content: Option, + pub tts: Option, + // pub embeds: Option>, + // pub allows_mentions: Option, + // pub message_reference: Option, + // pub attachments: Option>, + pub flags: Option +} + +#[async_trait] +impl<'r> rocket::form::FromFormField<'r> for MessagePostJson { // specify the full path because otherwise Json::from_data messes up + fn from_value(field: ValueField<'r>) -> FormResult<'r, Self> { + serde_json::from_str(field.value).map_err(|e| { + let mut errors = FormErrors::new(); + errors.push(FormError::validation(format!("{e:?}"))); + errors + }) + } + + async fn from_data(_: DataField<'r, '_>) -> FormResult<'r, Self> { + let mut errors = FormErrors::new(); + errors.push(FormError::validation("payload_json must be a string")); + Err(errors) + } +} + +#[derive(Debug)] +pub enum MessageBody<'r> { + Form(MessagePostForm<'r>), + Json(MessagePostJson) +} + +#[async_trait] +impl<'r> FromData<'r> for MessageBody<'r> { + type Error = Error; + + async fn from_data(req: &'r rocket::Request<'_>, data: Data<'r>) -> Outcome<'r, Self> { + if let Some(content_type) = req.headers().get_one("content-type") { + println!("{content_type}"); + match content_type.split(';').next().unwrap() { + "application/json" => { + match Json::::from_data(req, data).await { + Outcome::Success(json) => Outcome::Success(Self::Json(json.into_inner())), + Outcome::Failure(_) => Outcome::Failure((Status::BadRequest, Error::LabelMe)), + _ => unreachable!() + } + }, + "multipart/form-data" => { + match Form::::from_data(req, data).await { + Outcome::Success(form) => Outcome::Success(Self::Form(form.into_inner())), + Outcome::Failure(_) => Outcome::Failure((Status::BadRequest, Error::LabelMe)), + _ => unreachable!() + } + }, + _ => Outcome::Failure((Status::BadRequest, Error::LabelMe)) + } + } else { + Outcome::Failure((Status::BadRequest, Error::LabelMe)) + } + } +} + +impl<'r> OpenApiFromData<'r> for MessageBody<'r> { + fn request_body(gen: &mut rocket_okapi::gen::OpenApiGenerator) -> rocket_okapi::Result { + Ok(rocket_okapi::okapi::openapi3::RequestBody::default()) + } +} + +#[openapi(tag = "Messages")] +#[post("//messages", data="")] +pub async fn req(user: User, target: Ref, body: MessageBody<'_>) -> Result { + println!("{body:?}"); + + Ok(EmptyResponse) +} diff --git a/crates/revcord/api/src/routes/channels/messages/mod.rs b/crates/revcord/api/src/routes/channels/messages/mod.rs new file mode 100644 index 00000000..bc4a92c6 --- /dev/null +++ b/crates/revcord/api/src/routes/channels/messages/mod.rs @@ -0,0 +1 @@ +pub mod message_send; diff --git a/crates/revcord/api/src/routes/channels/mod.rs b/crates/revcord/api/src/routes/channels/mod.rs index c762536b..4a10a5f0 100644 --- a/crates/revcord/api/src/routes/channels/mod.rs +++ b/crates/revcord/api/src/routes/channels/mod.rs @@ -1,10 +1,13 @@ use rocket::Route; use rocket_okapi::okapi::openapi3::OpenApi; +mod messages; + mod fetch_channel; pub fn routes() -> (Vec, OpenApi) { openapi_get_routes_spec![ fetch_channel::req, + messages::message_send::req ] } diff --git a/crates/revcord/api/src/routes/mod.rs b/crates/revcord/api/src/routes/mod.rs index 3407b81a..0d3e04f0 100644 --- a/crates/revcord/api/src/routes/mod.rs +++ b/crates/revcord/api/src/routes/mod.rs @@ -19,5 +19,8 @@ pub fn mount(mut rocket: Rocket) -> Rocket { fn custom_openapi_spec() -> OpenApi { - OpenApi::default() + OpenApi { + openapi: OpenApi::default_version(), + ..Default::default() + } } diff --git a/crates/revcord/models/src/lib.rs b/crates/revcord/models/src/lib.rs index 9d96be9e..e2c9a64b 100644 --- a/crates/revcord/models/src/lib.rs +++ b/crates/revcord/models/src/lib.rs @@ -16,9 +16,11 @@ pub trait QuarkConversion: Sized { } pub fn to_snowflake(ulid: S) -> twilight_model::id::Id { - todo!() + unsafe { + twilight_model::id::Id::new_unchecked(1) + } } pub fn to_ulid(snowflake: twilight_model::id::Id) -> String { - todo!() + String::from("1") }