use super::route_prelude::*;
use std::collections::HashMap;
#[derive(Template, Clone)]
#[template(path = "bookmarks/public.gmi", escape = "txt")]
struct PublicBookmarksListTemplate {
bookmarks: Bookmarks,
events: HashMap<EventId, Event>,
}
pub fn event_to_bookmarks(event: Event) -> Bookmarks {
let mut bookmarks = Bookmarks::default();
bookmarks.event_ids.extend(event.tags.event_ids());
bookmarks
.hashtags
.extend(event.tags.hashtags().map(str::to_string));
bookmarks
.coordinate
.extend(event.tags.coordinates().map(|c| c.to_owned()));
bookmarks
}
pub async fn bookmark_public_add(
ctx: RouteContext,
user: &'static mut CaracalUser,
) -> Response {
let Ok(public_key) = user.public_key().await else {
return resp_signer_error();
};
let Ok(events) = user
.fetch_quick(
Filter::new()
.kind(Kind::Bookmarks)
.author(public_key)
.limit(1),
)
.await
else {
return resp_fetch_events_error();
};
let mut bookmarks = match events.first_owned() {
Some(event) => event_to_bookmarks(event),
None => {
Bookmarks::default()
}
};
if let Some(event_id) = ctx.event_id() {
bookmarks.event_ids.push(event_id);
} else if let Some(hashtag) = ctx.hashtag() {
bookmarks.hashtags.push(hashtag);
}
match user.send_builder(EventBuilder::bookmarks(bookmarks)).await {
Ok(_) => Response::temporary_redirect("/bookmarks/public"),
Err(err) => Response::temporary_failure(format!("{err}")),
}
}
pub async fn public_bookmarks(
_ctx: RouteContext,
user: &'static mut CaracalUser,
) -> Response {
let Ok(public_key) = user.public_key().await else {
return resp_signer_error();
};
let Ok(events) = user
.fetch_quick(
Filter::new()
.kind(Kind::Bookmarks)
.author(public_key)
.limit(1),
)
.await
else {
return resp_fetch_events_error();
};
let bookmarks = if let Some(event) = events.first_owned() {
event_to_bookmarks(event)
} else {
Bookmarks::default()
};
let Ok(bm_events) = user
.fetch_quick(Filter::new().ids(bookmarks.event_ids.clone()))
.await
else {
return resp_fetch_events_error();
};
let mut events: HashMap<EventId, Event> = HashMap::new();
for event in bm_events {
events.insert(event.id, event);
}
Response::success(WindTemplate::render(PublicBookmarksListTemplate {
bookmarks,
events,
}))
}
pub async fn public_bookmarks_delete_event(
ctx: RouteContext,
user: &'static mut CaracalUser,
) -> Response {
let Some(event_id) = ctx.event_id() else {
return resp_invalid_params();
};
let Ok(public_key) = user.public_key().await else {
return resp_signer_error();
};
let Ok(Some(event)) = user
.fetch_quick(
Filter::new()
.kind(Kind::Bookmarks)
.author(public_key)
.limit(1),
)
.await
.map(|events| events.first_owned())
else {
return resp_fetch_events_error();
};
let mut bookmarks = event_to_bookmarks(event);
if bookmarks.event_ids.contains(&event_id) {
bookmarks.event_ids.retain(|id| *id != event_id);
}
match user.send_builder(EventBuilder::bookmarks(bookmarks)).await {
Ok(_) => Response::temporary_redirect("/bookmarks/public"),
Err(err) => Response::temporary_failure(format!("{err}")),
}
}