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)}
}))
}
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),
),
)
}