feat: add GET /users/{id}/feed.rss per-user RSS feed handler
This commit is contained in:
@@ -362,13 +362,14 @@ pub mod posters {
|
|||||||
|
|
||||||
pub mod rss {
|
pub mod rss {
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::State,
|
extract::{Path, State},
|
||||||
http::header,
|
http::header,
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
};
|
};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use application::{queries::GetDiaryQuery, use_cases::get_diary};
|
use application::{queries::GetDiaryQuery, use_cases::get_diary};
|
||||||
use domain::{errors::DomainError, models::SortDirection};
|
use domain::{errors::DomainError, models::SortDirection, value_objects::UserId};
|
||||||
|
|
||||||
use crate::{errors::ApiError, state::AppState};
|
use crate::{errors::ApiError, state::AppState};
|
||||||
|
|
||||||
@@ -387,6 +388,38 @@ pub mod rss {
|
|||||||
.map_err(|e| ApiError(DomainError::InfrastructureError(e)))?;
|
.map_err(|e| ApiError(DomainError::InfrastructureError(e)))?;
|
||||||
Ok(([(header::CONTENT_TYPE, "application/rss+xml; charset=utf-8")], xml))
|
Ok(([(header::CONTENT_TYPE, "application/rss+xml; charset=utf-8")], xml))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_user_feed(
|
||||||
|
State(state): State<AppState>,
|
||||||
|
Path(user_id): Path<Uuid>,
|
||||||
|
) -> Result<impl IntoResponse, ApiError> {
|
||||||
|
let user = state
|
||||||
|
.app_ctx
|
||||||
|
.user_repository
|
||||||
|
.find_by_id(&UserId::from_uuid(user_id))
|
||||||
|
.await
|
||||||
|
.map_err(ApiError)?
|
||||||
|
.ok_or_else(|| ApiError(DomainError::NotFound(format!("User {user_id}"))))?;
|
||||||
|
|
||||||
|
let query = GetDiaryQuery {
|
||||||
|
limit: Some(50),
|
||||||
|
offset: Some(0),
|
||||||
|
sort_by: Some(SortDirection::Descending),
|
||||||
|
movie_id: None,
|
||||||
|
user_id: Some(user_id),
|
||||||
|
};
|
||||||
|
let page = get_diary::execute(&state.app_ctx, query).await?;
|
||||||
|
|
||||||
|
let display_name = user.email().value().split('@').next().unwrap_or("User");
|
||||||
|
let title = format!("{}'s Movie Diary", display_name);
|
||||||
|
|
||||||
|
let xml = state
|
||||||
|
.rss_renderer
|
||||||
|
.render_feed(&page.items, &title)
|
||||||
|
.map_err(|e| ApiError(DomainError::InfrastructureError(e)))?;
|
||||||
|
|
||||||
|
Ok(([(header::CONTENT_TYPE, "application/rss+xml; charset=utf-8")], xml))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod api {
|
pub mod api {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ fn html_routes() -> Router<AppState> {
|
|||||||
.route("/reviews/{id}/delete", routing::post(handlers::html::post_delete_review))
|
.route("/reviews/{id}/delete", routing::post(handlers::html::post_delete_review))
|
||||||
.route("/posters/{path}", routing::get(handlers::posters::get_poster))
|
.route("/posters/{path}", routing::get(handlers::posters::get_poster))
|
||||||
.route("/feed.rss", routing::get(handlers::rss::get_feed))
|
.route("/feed.rss", routing::get(handlers::rss::get_feed))
|
||||||
|
.route("/users/{id}/feed.rss", routing::get(handlers::rss::get_user_feed))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn api_routes() -> Router<AppState> {
|
fn api_routes() -> Router<AppState> {
|
||||||
|
|||||||
Reference in New Issue
Block a user