about summary refs log tree commit diff
path: root/src/command/leaderboard.rs
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2025-08-03 22:08:44 -0500
committergennyble <gen@nyble.dev>2025-08-03 22:08:44 -0500
commit76c1f83074e84a21eb5f5a69b160b1facbeb9cac (patch)
tree9a53a3a5d65678a41dfbbac1c91d26b46de06768 /src/command/leaderboard.rs
parent61927e384d5fc07c7094d0cdf77b8c246d456a63 (diff)
downloadleaberblord-76c1f83074e84a21eb5f5a69b160b1facbeb9cac.tar.gz
leaberblord-76c1f83074e84a21eb5f5a69b160b1facbeb9cac.zip
code cleanup; break commands into their own module
Diffstat (limited to 'src/command/leaderboard.rs')
-rw-r--r--src/command/leaderboard.rs91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/command/leaderboard.rs b/src/command/leaderboard.rs
new file mode 100644
index 0000000..97971f5
--- /dev/null
+++ b/src/command/leaderboard.rs
@@ -0,0 +1,91 @@
+use std::sync::Arc;
+
+use twilight_model::{
+	application::interaction::application_command::{CommandData, CommandOptionValue},
+	http::interaction::InteractionResponseData,
+	id::{Id, marker::GuildMarker},
+};
+use twilight_util::builder::{InteractionResponseDataBuilder, embed::EmbedBuilder};
+
+use crate::{brain::Brain, database::Error as DbError, fail, util};
+
+enum Style {
+	TiesEqual,
+	TiesBroken,
+}
+
+pub fn leaderboard(
+	brain: Arc<Brain>,
+	guild: Id<GuildMarker>,
+	data: Option<&CommandData>,
+) -> InteractionResponseData {
+	let board = brain.db.get_leaderboard(guild.get());
+
+	let mut style = Style::TiesBroken;
+	if let Some(data) = data {
+		for opt in &data.options {
+			match opt.name.as_str() {
+				"style" => match &opt.value {
+					CommandOptionValue::String(raw) => match raw.as_str() {
+						"equal" => style = Style::TiesEqual,
+						"broken" => style = Style::TiesBroken,
+						_ => {
+							return fail!(format!(
+								"{raw} is not a valid style option. Try 'equal' or 'broken'"
+							));
+						}
+					},
+					_ => unreachable!(),
+				},
+				_ => unreachable!(),
+			}
+		}
+	}
+
+	match board {
+		Err(DbError::TableNotExist) => {
+			fail!("No leaderboard exists for this server! Create one by giving someone points.")
+		}
+		Err(DbError::UserNotExist) => unreachable!(),
+		Ok(data) => {
+			let placed = util::tiebreak_shared_positions(data);
+
+			let str = match style {
+				Style::TiesEqual => placed
+					.into_iter()
+					.map(|placement| {
+						if placement.placement_first_of_tie {
+							format!(
+								"`{:>2}` <@{}>: {}",
+								placement.placement_tie,
+								placement.row.user_id,
+								placement.row.points
+							)
+						} else {
+							format!(
+								"`  ` <@{}>: {}",
+								placement.row.user_id, placement.row.points
+							)
+						}
+					})
+					.collect::<Vec<String>>()
+					.join("\n"),
+				Style::TiesBroken => placed
+					.into_iter()
+					.map(|placement| {
+						format!(
+							"`{:>2}` <@{}>: {}",
+							placement.placement, placement.row.user_id, placement.row.points
+						)
+					})
+					.collect::<Vec<String>>()
+					.join("\n"),
+			};
+
+			let embed = EmbedBuilder::new().description(str).build();
+			InteractionResponseDataBuilder::new()
+				.embeds([embed])
+				.build()
+		}
+	}
+}