aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLizzy Fleckenstein <eliasfleckenstein@web.de>2023-04-11 17:32:21 +0200
committerLizzy Fleckenstein <eliasfleckenstein@web.de>2023-04-11 17:32:21 +0200
commit85bc0425a64083586e0b7d6c45c0ad66ffb0946b (patch)
tree3142503c449c289ec1f4bf9a41739b7c8fe5aa5a /src
downloadminetest-servers-85bc0425a64083586e0b7d6c45c0ad66ffb0946b.tar.xz
Initial commit
Diffstat (limited to 'src')
-rw-r--r--src/main.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..9986096
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,82 @@
+use anyhow::anyhow;
+use clap::CommandFactory;
+use clap::Parser;
+use itertools::Itertools;
+use serde::Deserialize;
+use serde_json::Value as JsonValue;
+use std::{
+ collections::{BTreeMap, BTreeSet},
+ fmt,
+};
+
+fn main() -> anyhow::Result<()> {
+ #[derive(Parser, Debug)]
+ #[clap(author, version, about, long_about = None)]
+ struct Args {
+ /// Address of the server list
+ #[clap(short, long, value_parser, default_value_t = String::from("https://servers.minetest.net/list"))]
+ address: String,
+
+ /// List available keys
+ #[clap(short, long, action)]
+ show_keys: bool,
+
+ /// The key to look up. Use --show-keys to list available keys.
+ key: Option<String>,
+ }
+ let args = Args::parse();
+
+ #[derive(Deserialize)]
+ struct Payload {
+ list: Vec<BTreeMap<String, JsonValue>>,
+ }
+ let payload: Payload = reqwest::blocking::get(args.address)?.json()?;
+
+ if args.show_keys {
+ let keys: BTreeSet<&String> = payload.list.iter().flat_map(BTreeMap::keys).collect();
+ println!("available keys: {}", keys.iter().format(", "));
+ }
+
+ if let Some(key) = args.key {
+ let mut iter = payload
+ .list
+ .iter()
+ .flat_map(|server| server.get(&key).map(|value| (server, value)))
+ .peekable();
+
+ if iter.peek().is_none() {
+ return Err(anyhow!("invalid key"));
+ } else {
+ iter.for_each(|(server, value)| {
+ struct DisplayJson<'a>(Option<&'a JsonValue>);
+ impl<'a> fmt::Display for DisplayJson<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self.0 {
+ None => Ok(()),
+ Some(value) => match value {
+ JsonValue::String(x) => write!(f, "{x}"),
+ _ => write!(f, "{value}"),
+ },
+ }
+ }
+ }
+
+ let address = DisplayJson(server.get("address"));
+ let port = DisplayJson(server.get("port"));
+
+ if let JsonValue::Array(array) = value {
+ let prefix = format!("{address}:{port}"); // cache it
+ for value in array.iter() {
+ println!("{prefix}\t{}", DisplayJson(Some(value)));
+ }
+ } else {
+ println!("{address}:{port}\t{}", DisplayJson(Some(value)));
+ }
+ });
+ }
+ } else if !args.show_keys {
+ Args::command().print_help()?;
+ }
+
+ Ok(())
+}