use super::{ fetch_base_data, for_client, get_cookie_map_for_headers, get_cookie_map_for_req, html_response, res_to_error, }; use crate::components::{Comment, CommunityLink, Content, HTPage, TimeAgo, UserLink}; use crate::resp_types::{JustUser, RespCommunityInfoMaybeYour, RespList, RespPostInfo}; use crate::util::author_is_me; use std::sync::Arc; async fn page_post( params: (i64,), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let (post_id,) = params; let lang = crate::get_lang_for_req(&req); let cookies = get_cookie_map_for_req(&req)?; let base_data = fetch_base_data(&ctx.backend_host, &ctx.http_client, req.headers(), &cookies).await?; let api_res = res_to_error( ctx.http_client .request(for_client( hyper::Request::get(format!( "{}/api/unstable/posts/{}{}", ctx.backend_host, post_id, if base_data.login.is_some() { "?include_your=true" } else { "" }, )) .body(Default::default())?, req.headers(), &cookies, )?) .await?, ) .await?; let api_res = hyper::body::to_bytes(api_res.into_body()).await?; let post: RespPostInfo = serde_json::from_slice(&api_res)?; let is_community_moderator = if base_data.login.is_some() { let api_res = res_to_error( ctx.http_client .request(for_client( hyper::Request::get(format!( "{}/api/unstable/communities/{}?include_your=true", ctx.backend_host, post.as_ref().community.id, )) .body(Default::default())?, req.headers(), &cookies, )?) .await?, ) .await?; let api_res = hyper::body::to_bytes(api_res.into_body()).await?; let info: RespCommunityInfoMaybeYour = serde_json::from_slice(&api_res)?; info.you_are_moderator.unwrap() } else { false }; let title = post.as_ref().as_ref().title.as_ref(); Ok(html_response(render::html! { { if post.approved { None } else { Some(render::rsx! {
{lang.tr("post_not_approved", None)}
}) } }

{title}

{lang.tr("score", Some(&fluent::fluent_args!["score" => post.score]))} {" "} { if base_data.login.is_some() { Some(if post.your_vote.is_some() { render::rsx! {

} } else { render::rsx! {
} }) } else { None } } { if is_community_moderator { Some(if post.approved { render::rsx! {
} } else { render::rsx! {
} }) } else { None } }

{lang.tr("submitted", None)} {" "} {" "}{lang.tr("by", None)}{" "} {" "}{lang.tr("to", None)}{" "}

{ match &post.as_ref().href { None => None, Some(href) => { Some(render::rsx! {

{href.as_ref()}

}) } } } { if author_is_me(&post.as_ref().author, &base_data.login) { Some(render::rsx! {

{lang.tr("delete", None)}

}) } else { None } }

{"Comments"}

{ if base_data.login.is_some() { Some(render::rsx! {
}) } else { None } }
    { post.comments.iter().map(|comment| { render::rsx! { } }).collect::>() }
})) } async fn page_post_delete( params: (i64,), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let (post_id,) = params; let lang = crate::get_lang_for_req(&req); let cookies = get_cookie_map_for_req(&req)?; let base_data = fetch_base_data(&ctx.backend_host, &ctx.http_client, req.headers(), &cookies).await?; let api_res = res_to_error( ctx.http_client .request(for_client( hyper::Request::get(format!( "{}/api/unstable/posts/{}", ctx.backend_host, post_id )) .body(Default::default())?, req.headers(), &cookies, )?) .await?, ) .await?; let api_res = hyper::body::to_bytes(api_res.into_body()).await?; let post: RespPostInfo = serde_json::from_slice(&api_res)?; Ok(html_response(render::html! {

{post.as_ref().as_ref().title.as_ref()}

{lang.tr("post_delete_question", None)}

{lang.tr("no_cancel", None)} {" "}
})) } async fn handler_post_delete_confirm( params: (i64,), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let (post_id,) = params; let cookies = get_cookie_map_for_req(&req)?; res_to_error( ctx.http_client .request(for_client( hyper::Request::delete(format!( "{}/api/unstable/posts/{}", ctx.backend_host, post_id, )) .body("".into())?, req.headers(), &cookies, )?) .await?, ) .await?; Ok(hyper::Response::builder() .status(hyper::StatusCode::SEE_OTHER) .header(hyper::header::LOCATION, "/") .body("Successfully deleted.".into())?) } async fn handler_post_like( params: (i64,), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let (post_id,) = params; let cookies = get_cookie_map_for_req(&req)?; res_to_error( ctx.http_client .request(for_client( hyper::Request::put(format!( "{}/api/unstable/posts/{}/your_vote", ctx.backend_host, post_id )) .body("{}".into())?, req.headers(), &cookies, )?) .await?, ) .await?; Ok(hyper::Response::builder() .status(hyper::StatusCode::SEE_OTHER) .header(hyper::header::LOCATION, format!("/posts/{}", post_id)) .body("Successfully liked.".into())?) } async fn page_post_likes( params: (i64,), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let (post_id,) = params; let lang = crate::get_lang_for_req(&req); let cookies = get_cookie_map_for_req(&req)?; let base_data = fetch_base_data(&ctx.backend_host, &ctx.http_client, req.headers(), &cookies).await?; let api_res = res_to_error( ctx.http_client .request(for_client( hyper::Request::get(format!( "{}/api/unstable/posts/{}/votes", ctx.backend_host, post_id, )) .body(Default::default())?, req.headers(), &cookies, )?) .await?, ) .await?; let api_res = hyper::body::to_bytes(api_res.into_body()).await?; let api_res: RespList = serde_json::from_slice(&api_res)?; Ok(html_response(render::html! { { if api_res.items.is_empty() { Some(render::rsx! {

{lang.tr("post_likes_nothing", None)}

}) } else { None } } { if api_res.items.is_empty() { None } else { Some(render::rsx! { <>

{lang.tr("liked_by", None)}

    { api_res.items.iter().map(|like| { render::rsx! {
  • } }) .collect::>() } { if api_res.next_page.is_some() { Some(render::rsx! {
  • {lang.tr("and_more", None)}
  • }) } else { None } }
}) } }
})) } async fn handler_post_unlike( params: (i64,), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let (post_id,) = params; let cookies = get_cookie_map_for_req(&req)?; res_to_error( ctx.http_client .request(for_client( hyper::Request::delete(format!( "{}/api/unstable/posts/{}/your_vote", ctx.backend_host, post_id )) .body(Default::default())?, req.headers(), &cookies, )?) .await?, ) .await?; Ok(hyper::Response::builder() .status(hyper::StatusCode::SEE_OTHER) .header(hyper::header::LOCATION, format!("/posts/{}", post_id)) .body("Successfully unliked.".into())?) } async fn handler_post_submit_reply( params: (i64,), ctx: Arc, req: hyper::Request, ) -> Result, crate::Error> { let (post_id,) = params; let (req_parts, body) = req.into_parts(); let cookies = get_cookie_map_for_headers(&req_parts.headers)?; let body = hyper::body::to_bytes(body).await?; let body: serde_json::Value = serde_urlencoded::from_bytes(&body)?; let body = serde_json::to_vec(&body)?; res_to_error( ctx.http_client .request(for_client( hyper::Request::post(format!( "{}/api/unstable/posts/{}/replies", ctx.backend_host, post_id )) .body(body.into())?, &req_parts.headers, &cookies, )?) .await?, ) .await?; Ok(hyper::Response::builder() .status(hyper::StatusCode::SEE_OTHER) .header(hyper::header::LOCATION, format!("/posts/{}", post_id)) .body("Successfully posted.".into())?) } pub fn route_posts() -> crate::RouteNode<()> { crate::RouteNode::new().with_child_parse::( crate::RouteNode::new() .with_handler_async("GET", page_post) .with_child( "delete", crate::RouteNode::new() .with_handler_async("GET", page_post_delete) .with_child( "confirm", crate::RouteNode::new() .with_handler_async("POST", handler_post_delete_confirm), ), ) .with_child( "like", crate::RouteNode::new().with_handler_async("POST", handler_post_like), ) .with_child( "likes", crate::RouteNode::new().with_handler_async("GET", page_post_likes), ) .with_child( "unlike", crate::RouteNode::new().with_handler_async("POST", handler_post_unlike), ) .with_child( "submit_reply", crate::RouteNode::new().with_handler_async("POST", handler_post_submit_reply), ), ) }