implement bare basic functionality!!!
This commit is contained in:
parent
5f9bb732b8
commit
ed87d3fb51
7 changed files with 238 additions and 13 deletions
|
@ -4,14 +4,16 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
http = "1"
|
||||
axum = { version = "0.7.5", features = [ "json", "macros" ] }
|
||||
axum-macros = "0.4.1"
|
||||
chrono = { version = "0.4", features = [ "serde" ] }
|
||||
chrono-tz = "0.10.0"
|
||||
maud = "0.26.0"
|
||||
sqlx = { version = "0.8.2", features = ["postgres", "runtime-tokio", "tls-rustls-ring", "uuid" ] }
|
||||
tokio = { version = "1.40.0", features = ["full"] }
|
||||
sqlx = { version = "0.8.2", features = [ "postgres", "runtime-tokio", "tls-rustls-ring", "uuid", "chrono" ] }
|
||||
tokio = { version = "1.40.0", features = [ "full" ] }
|
||||
tokio-tungstenite = "0.24.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde = { version = "1", features = [ "derive" ] }
|
||||
anyhow = "1"
|
||||
uuid = { version = "1.10.0", features = ["serde"] }
|
||||
uuid = { version = "1.10.0", features = [ "serde" ] }
|
||||
rand = "0.8.5"
|
||||
|
|
|
@ -10,8 +10,10 @@ create table chats (
|
|||
|
||||
create table messages (
|
||||
id uuid default (gen_random_uuid()) primary key,
|
||||
timestamp timestamptz default (now()),
|
||||
timestamp timestamptz not null default (now()),
|
||||
chat_id uuid not null references chats(id),
|
||||
content varchar(2000) not null,
|
||||
from_admin boolean not null
|
||||
)
|
||||
);
|
||||
|
||||
insert into chats (url_path) values ('tstcht');
|
||||
|
|
|
@ -1,18 +1,28 @@
|
|||
use axum::{
|
||||
extract::{Path, State},
|
||||
response::Html,
|
||||
Json,
|
||||
extract::{FromRef, Path, State},
|
||||
http::{
|
||||
header::{ACCEPT, CONTENT_TYPE},
|
||||
HeaderMap, HeaderValue, StatusCode,
|
||||
},
|
||||
response::{Html, IntoResponse, Redirect},
|
||||
Form, Json,
|
||||
};
|
||||
use maud::{html, Render};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{Pool, Postgres};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::model::{Chat, Message};
|
||||
use crate::{
|
||||
model::{Chat, Message},
|
||||
ADMIN_TOK,
|
||||
};
|
||||
|
||||
pub async fn get(
|
||||
Path(url_path): Path<String>,
|
||||
headers: HeaderMap,
|
||||
State(pool): State<Pool<Postgres>>,
|
||||
) -> Json<Vec<Message>> {
|
||||
) -> impl IntoResponse {
|
||||
println!("headers: {headers:#?}");
|
||||
let chat = sqlx::query_as!(Chat, r#"select * from chats where url_path = $1"#, url_path)
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
|
@ -25,5 +35,74 @@ pub async fn get(
|
|||
.fetch_all(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
Json(messages)
|
||||
|
||||
if Some(&HeaderValue::from_static("application/json")) == headers.get(ACCEPT) {
|
||||
Json(messages).into_response()
|
||||
} else {
|
||||
Html(
|
||||
html! {
|
||||
main {
|
||||
div #history {
|
||||
@for msg in &messages {
|
||||
div.message.(if msg.from_admin { "from_admin" } else { "from_user" }) {
|
||||
p { (msg.content) "(" (msg.timestamp) ")" }
|
||||
}
|
||||
}
|
||||
}
|
||||
form #send method="post"{
|
||||
textarea #msgcontent name="msgcontent" rows="1" cols="80" {}
|
||||
button type="submit" { "Send!" }
|
||||
}
|
||||
}
|
||||
}
|
||||
.into_string(),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// - validation of msg length
|
||||
// - fix terrible returns lmao
|
||||
pub async fn post(
|
||||
Path(url_path): Path<String>,
|
||||
headers: HeaderMap,
|
||||
State(pool): State<Pool<Postgres>>,
|
||||
Form(FormMessageBody { msgcontent: body }): Form<FormMessageBody>,
|
||||
) -> impl IntoResponse {
|
||||
let chat = sqlx::query_as!(Chat, r#"select * from chats where url_path = $1"#, url_path)
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
if body.len() > 2000 {
|
||||
return StatusCode::BAD_REQUEST.into_response();
|
||||
}
|
||||
|
||||
if headers.get("x-admin-tok") == Some(&HeaderValue::from_static(ADMIN_TOK)) {
|
||||
sqlx::query!(
|
||||
r#"insert into messages (chat_id, content, from_admin) values ($1, $2, true);"#,
|
||||
chat.id,
|
||||
body
|
||||
)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
StatusCode::OK.into_response()
|
||||
} else {
|
||||
sqlx::query!(
|
||||
r#"insert into messages (chat_id, content, from_admin) values ($1, $2, false);"#,
|
||||
chat.id,
|
||||
body
|
||||
)
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
Redirect::to(&format!("/{url_path}")).into_response()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct FormMessageBody {
|
||||
msgcontent: String,
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ async fn main() -> anyhow::Result<()> {
|
|||
|
||||
let app = Router::new()
|
||||
.route("/", get(|| async { "<h1>gay</h1>" }))
|
||||
.route("/:path", get(chat::get))
|
||||
.route("/:path", get(chat::get).post(chat::post))
|
||||
.with_state(pool.clone())
|
||||
.nest("/stat", stat::router(pool.clone()))
|
||||
.nest("/admin", admin::router(pool.clone()));
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use chrono::{DateTime, FixedOffset, Local, Utc};
|
||||
use serde::Serialize;
|
||||
use sqlx::{prelude::FromRow, Decode, Encode};
|
||||
use uuid::Uuid;
|
||||
|
@ -15,6 +16,7 @@ pub struct Message {
|
|||
// Uuid but sqlx doesnt impl serde traits for them
|
||||
pub id: Uuid,
|
||||
pub chat_id: Uuid,
|
||||
pub timestamp: DateTime<Utc>,
|
||||
|
||||
pub content: String,
|
||||
pub from_admin: bool,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue