Files
diplom/src/web/route/channel/message/page.rs
2025-05-20 11:13:56 +03:00

60 lines
1.6 KiB
Rust

use axum::Json;
use axum::extract::{Path, Query, State};
use axum::response::IntoResponse;
use serde::Deserialize;
use tracing::error;
use validator::Validate;
use crate::state::AppState;
use crate::web::context::UserContext;
use crate::web::entity::message::Message;
use crate::{entity, web};
#[derive(Debug, Deserialize, Validate)]
#[serde(rename_all = "camelCase")]
pub struct PageParams {
#[serde(default = "limit_default")]
#[validate(range(min = 1, max = 100))]
pub limit: u32,
#[serde(default)]
pub before: Option<entity::message::Id>,
}
fn limit_default() -> u32 {
50
}
pub async fn page(
State(state): State<AppState>,
context: UserContext,
Path(channel_id): Path<entity::channel::Id>,
Query(params): Query<PageParams>,
) -> web::Result<impl IntoResponse> {
// TODO: check permissions
match params.validate() {
Ok(_) => {},
Err(e) => return Err(web::error::ClientError::ValidationFailed(e).into()),
};
let messages_futures = state
.database
.select_channel_messages_paginated(channel_id, params.before, params.limit as i64)
.await?
.into_iter()
.map(|message| async {
let attachments = state
.database
.select_message_attachments(message.id)
.await?
.into_iter()
.map(web::entity::file::File::from)
.collect::<Vec<_>>();
Ok::<_, web::Error>(Message::from_message_with_attachments(message, attachments))
});
let messages = futures::future::try_join_all(messages_futures).await?;
Ok(Json(messages))
}