summaryrefslogtreecommitdiff
path: root/server/registry/src/list.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/registry/src/list.rs')
-rw-r--r--server/registry/src/list.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/server/registry/src/list.rs b/server/registry/src/list.rs
new file mode 100644
index 00000000..eb1ddfbf
--- /dev/null
+++ b/server/registry/src/list.rs
@@ -0,0 +1,84 @@
+use crate::{PublicEntry, Registry};
+use anyhow::Result;
+use rocket::{
+ get,
+ http::MediaType,
+ request::{self, FromRequest, Outcome},
+ response::content::{RawHtml, RawJson},
+ Either, Request, State,
+};
+use std::sync::Arc;
+use tokio::sync::RwLock;
+
+#[get("/v1/list")]
+pub(super) async fn r_list(
+ registry: &State<Arc<RwLock<Registry>>>,
+ json: AcceptJson,
+) -> Either<RawJson<Arc<str>>, RawHtml<Arc<str>>> {
+ if json.0 {
+ Either::Left(RawJson(registry.read().await.json_response.clone()))
+ } else {
+ Either::Right(RawHtml(registry.read().await.html_response.clone()))
+ }
+}
+
+pub(super) fn generate_json_list(entries: &[PublicEntry]) -> Result<Arc<str>> {
+ Ok(serde_json::to_string(&entries)?.into())
+}
+pub(super) fn generate_html_list(entries: &[PublicEntry]) -> Result<Arc<str>> {
+ Ok(ListPage { entries }.to_string().into())
+}
+
+markup::define!(
+ ListPage<'a>(entries: &'a [PublicEntry]) {
+ @markup::doctype()
+ html {
+ head {
+ title {
+ "Hurry Curry! Server Registry"
+ }
+ }
+ body {
+ table {
+ tr { th {"Server"} th { "Players" } th { "Protocol" } }
+ @for e in *entries { tr {
+ td { details {
+ summary { @e.name }
+ ul { @for a in &e.address { li { @a } }}
+ } }
+ td { @e.players_online }
+ td { @e.version.0 "." @e.version.1 }
+ }}
+ }
+ }
+ }
+ }
+);
+
+pub struct AcceptJson(bool);
+impl<'r> FromRequest<'r> for AcceptJson {
+ type Error = ();
+ fn from_request<'life0, 'async_trait>(
+ request: &'r Request<'life0>,
+ ) -> ::core::pin::Pin<
+ Box<
+ dyn ::core::future::Future<Output = request::Outcome<Self, Self::Error>>
+ + ::core::marker::Send
+ + 'async_trait,
+ >,
+ >
+ where
+ 'r: 'async_trait,
+ 'life0: 'async_trait,
+ Self: 'async_trait,
+ {
+ Box::pin(async move {
+ Outcome::Success(AcceptJson(
+ request
+ .accept()
+ .map(|a| a.preferred().exact_eq(&MediaType::JSON))
+ .unwrap_or(false),
+ ))
+ })
+ }
+}