2025-08-26 00:24:12 -04:00
|
|
|
use crate::{
|
|
|
|
State, get_user_from_token,
|
|
|
|
routes::{
|
|
|
|
default_context,
|
|
|
|
pages::{PaginatedQuery, misc::render_error},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
use axum::{
|
|
|
|
Extension,
|
|
|
|
extract::{Path, Query},
|
|
|
|
response::{Html, IntoResponse},
|
|
|
|
};
|
|
|
|
use axum_extra::extract::CookieJar;
|
2025-08-27 20:22:12 -04:00
|
|
|
use serde::Deserialize;
|
2025-08-26 00:24:12 -04:00
|
|
|
use tetratto_core::model::Error;
|
|
|
|
|
|
|
|
pub async fn list_request(
|
|
|
|
jar: CookieJar,
|
|
|
|
Extension(data): Extension<State>,
|
|
|
|
Query(props): Query<PaginatedQuery>,
|
|
|
|
) -> impl IntoResponse {
|
|
|
|
let (ref data, ref tera, ref build_code) = *data.read().await;
|
|
|
|
let user = match get_user_from_token!(jar, data.2) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => {
|
|
|
|
return Err(render_error(Error::NotAllowed, tera, data.0.0.clone(), None).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2025-09-01 20:17:32 -04:00
|
|
|
if let Err(e) = data.2.update_user_missed_messages_count(user.id, 0).await {
|
|
|
|
return Err(render_error(e, tera, data.0.0.clone(), Some(user)).await);
|
|
|
|
}
|
|
|
|
|
2025-08-26 00:24:12 -04:00
|
|
|
let chats = match data.get_chats_by_member(user.id, 12, props.page).await {
|
|
|
|
Ok(x) => data.fill_chats(x).await,
|
|
|
|
Err(e) => {
|
|
|
|
return Err(render_error(e, tera, data.0.0.clone(), Some(user)).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut ctx = default_context(&data.0.0, &build_code, &Some(user));
|
|
|
|
|
|
|
|
ctx.insert("chats", &chats);
|
|
|
|
ctx.insert("page", &props.page);
|
|
|
|
|
|
|
|
Ok(Html(tera.render("chats.lisp", &ctx).unwrap()))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn chat_request(
|
|
|
|
jar: CookieJar,
|
|
|
|
Extension(data): Extension<State>,
|
|
|
|
Path(id): Path<usize>,
|
|
|
|
Query(props): Query<PaginatedQuery>,
|
|
|
|
) -> impl IntoResponse {
|
|
|
|
let (ref data, ref tera, ref build_code) = *data.read().await;
|
|
|
|
let user = match get_user_from_token!(jar, data.2) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => {
|
|
|
|
return Err(render_error(Error::NotAllowed, tera, data.0.0.clone(), None).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let (chat, members) = match data.get_chat_by_id(id).await {
|
|
|
|
Ok(x) => {
|
|
|
|
if !x.members.contains(&user.id) {
|
|
|
|
return Err(
|
|
|
|
render_error(Error::NotAllowed, tera, data.0.0.clone(), Some(user)).await,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
data.fill_chat(x).await
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
return Err(render_error(e, tera, data.0.0.clone(), Some(user)).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2025-08-28 20:26:38 -04:00
|
|
|
let messages = match data.get_messages_by_chat(id, 24, props.page).await {
|
2025-08-26 00:24:12 -04:00
|
|
|
Ok(x) => x,
|
|
|
|
Err(e) => {
|
|
|
|
return Err(render_error(e, tera, data.0.0.clone(), Some(user)).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut ctx = default_context(&data.0.0, &build_code, &Some(user));
|
|
|
|
|
|
|
|
ctx.insert("chat", &chat);
|
|
|
|
ctx.insert("members", &members);
|
|
|
|
ctx.insert("messages", &messages);
|
|
|
|
|
|
|
|
Ok(Html(tera.render("chat.lisp", &ctx).unwrap()))
|
|
|
|
}
|
2025-08-26 21:27:11 -04:00
|
|
|
|
|
|
|
pub async fn single_message_request(
|
|
|
|
jar: CookieJar,
|
|
|
|
Extension(data): Extension<State>,
|
|
|
|
Path(id): Path<usize>,
|
|
|
|
) -> impl IntoResponse {
|
|
|
|
let (ref data, ref tera, ref build_code) = *data.read().await;
|
|
|
|
let user = match get_user_from_token!(jar, data.2) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => {
|
|
|
|
return Err(render_error(Error::NotAllowed, tera, data.0.0.clone(), None).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let message = match data.get_message_by_id(id).await {
|
|
|
|
Ok(x) => x,
|
|
|
|
Err(e) => {
|
|
|
|
return Err(render_error(e, tera, data.0.0.clone(), Some(user)).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut ctx = default_context(&data.0.0, &build_code, &Some(user));
|
|
|
|
ctx.insert("message", &message);
|
|
|
|
Ok(Html(tera.render("message.lisp", &ctx).unwrap()))
|
|
|
|
}
|
|
|
|
|
2025-08-27 20:22:12 -04:00
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct MessagesProps {
|
|
|
|
pub use_id: String,
|
|
|
|
}
|
|
|
|
|
2025-08-26 21:27:11 -04:00
|
|
|
pub async fn messages_request(
|
|
|
|
jar: CookieJar,
|
|
|
|
Extension(data): Extension<State>,
|
|
|
|
Path((id, before)): Path<(usize, usize)>,
|
2025-08-27 20:22:12 -04:00
|
|
|
Query(props): Query<MessagesProps>,
|
2025-08-26 21:27:11 -04:00
|
|
|
) -> impl IntoResponse {
|
|
|
|
let (ref data, ref tera, ref build_code) = *data.read().await;
|
|
|
|
let user = match get_user_from_token!(jar, data.2) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => {
|
|
|
|
return Err(render_error(Error::NotAllowed, tera, data.0.0.clone(), None).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2025-08-27 20:22:12 -04:00
|
|
|
let messages = match if before > 0 {
|
2025-08-28 20:26:38 -04:00
|
|
|
data.get_messages_by_chat_before(id, before, 24, 0).await
|
2025-08-27 20:22:12 -04:00
|
|
|
} else {
|
2025-08-28 20:26:38 -04:00
|
|
|
data.get_messages_by_chat(id, 24, 0).await
|
2025-08-27 20:22:12 -04:00
|
|
|
} {
|
2025-08-26 21:27:11 -04:00
|
|
|
Ok(x) => x,
|
|
|
|
Err(e) => {
|
|
|
|
return Err(render_error(e, tera, data.0.0.clone(), Some(user)).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut ctx = default_context(&data.0.0, &build_code, &Some(user));
|
2025-08-27 20:22:12 -04:00
|
|
|
|
|
|
|
ctx.insert(
|
2025-08-28 20:26:38 -04:00
|
|
|
"last_message_time",
|
|
|
|
&match messages.last() {
|
2025-08-27 20:22:12 -04:00
|
|
|
Some(x) => x.created,
|
|
|
|
None => 0,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2025-08-26 21:27:11 -04:00
|
|
|
ctx.insert("messages", &messages);
|
2025-08-27 20:22:12 -04:00
|
|
|
ctx.insert("id", &props.use_id);
|
|
|
|
|
2025-08-26 21:27:11 -04:00
|
|
|
Ok(Html(tera.render("messages.lisp", &ctx).unwrap()))
|
|
|
|
}
|
2025-08-27 20:22:12 -04:00
|
|
|
|
|
|
|
pub async fn read_receipt_request(
|
|
|
|
jar: CookieJar,
|
|
|
|
Extension(data): Extension<State>,
|
|
|
|
Path(id): Path<usize>,
|
|
|
|
) -> impl IntoResponse {
|
|
|
|
let (ref data, ref tera, ref build_code) = *data.read().await;
|
|
|
|
let user = match get_user_from_token!(jar, data.2) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => {
|
|
|
|
return Err(render_error(Error::NotAllowed, tera, data.0.0.clone(), None).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let chat = match data.get_chat_by_id(id).await {
|
|
|
|
Ok(x) => x,
|
|
|
|
Err(e) => {
|
|
|
|
return Err(render_error(e, tera, data.0.0.clone(), Some(user)).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut ctx = default_context(&data.0.0, &build_code, &Some(user));
|
|
|
|
ctx.insert("chat", &chat);
|
|
|
|
Ok(Html(tera.render("read_receipt.lisp", &ctx).unwrap()))
|
|
|
|
}
|
2025-09-01 20:17:32 -04:00
|
|
|
|
|
|
|
pub async fn manage_chat_request(
|
|
|
|
jar: CookieJar,
|
|
|
|
Extension(data): Extension<State>,
|
|
|
|
Path(id): Path<usize>,
|
|
|
|
) -> impl IntoResponse {
|
|
|
|
let (ref data, ref tera, ref build_code) = *data.read().await;
|
|
|
|
let user = match get_user_from_token!(jar, data.2) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => {
|
|
|
|
return Err(render_error(Error::NotAllowed, tera, data.0.0.clone(), None).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let (chat, members) = match data.get_chat_by_id(id).await {
|
|
|
|
Ok(x) => {
|
|
|
|
if !x.members.contains(&user.id) {
|
|
|
|
return Err(
|
|
|
|
render_error(Error::NotAllowed, tera, data.0.0.clone(), Some(user)).await,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
data.fill_chat(x).await
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
return Err(render_error(e, tera, data.0.0.clone(), Some(user)).await);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let is_owner = chat.owner() == user.id;
|
|
|
|
|
|
|
|
let mut ctx = default_context(&data.0.0, &build_code, &Some(user));
|
|
|
|
|
|
|
|
ctx.insert("chat", &chat);
|
|
|
|
ctx.insert("members", &members);
|
|
|
|
ctx.insert("is_owner", &is_owner);
|
|
|
|
|
|
|
|
Ok(Html(tera.render("manage.lisp", &ctx).unwrap()))
|
|
|
|
}
|