about summary refs log tree commit diff
path: root/src/command/add_points.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/command/add_points.rs')
-rw-r--r--src/command/add_points.rs110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/command/add_points.rs b/src/command/add_points.rs
new file mode 100644
index 0000000..453be2d
--- /dev/null
+++ b/src/command/add_points.rs
@@ -0,0 +1,110 @@
+use std::sync::Arc;
+
+use twilight_model::{
+	application::interaction::application_command::{CommandData, CommandOptionValue},
+	gateway::payload::incoming::InteractionCreate,
+	http::interaction::InteractionResponseData,
+	id::{
+		Id,
+		marker::{GuildMarker, UserMarker},
+	},
+};
+use twilight_util::builder::{InteractionResponseDataBuilder, embed::EmbedBuilder};
+
+use crate::{
+	bail,
+	brain::Brain,
+	database::{BoardRow, Error as DbError, PermissionSetting},
+	success, util,
+};
+
+pub async fn add_points(
+	brain: Arc<Brain>,
+	guild: Id<GuildMarker>,
+	create: &InteractionCreate,
+	data: &CommandData,
+) -> InteractionResponseData {
+	let mut points = None;
+	let mut users: Vec<Id<UserMarker>> = vec![];
+
+	for opt in &data.options {
+		match opt.name.as_str() {
+			"points" => match opt.value {
+				CommandOptionValue::Integer(num) => points = Some(num),
+				_ => unreachable!(),
+			},
+			"users" => match &opt.value {
+				CommandOptionValue::String(raw) => {
+					let mentions = util::extract_user_mentions(&raw);
+					users = mentions;
+				}
+				_ => unreachable!(),
+			},
+			_ => unreachable!(),
+		}
+	}
+
+	if users.len() == 0 {
+		bail!("No users mentioned! Who do we add points to?")
+	}
+
+	let (points, points_display, points_verb) = match points {
+		Some(p) if p > 0 => (p, p, "added to"),
+		Some(p) if p < 0 => (p, -p, "removed from"),
+		Some(0) => {
+			return success!("adding 0 points is a no-operation! I won't do anything :)");
+		}
+		Some(_) | None => unreachable!(),
+	};
+
+	brain.create_leaderboard_if_not_exists(guild);
+
+	let settings = brain.db.get_leaderboard_settings(guild.get()).unwrap();
+	if let PermissionSetting::RoleRequired = settings.permission {
+		if let Some(role) = settings.role {
+			let member = create.member.clone().unwrap();
+			let found_role = member.roles.iter().find(|vrole| vrole.get() == role);
+
+			if found_role.is_none() {
+				bail!("You do not have the right permissions to change the score");
+			}
+		} else {
+			// Seeing as the role is a required input on the subcommand, this
+			// would only happen with direct database fiddling or like, some
+			// really weird arcane bullshit?
+			bail!(
+				"Permissions set to Role Required, but no role is set. \
+				This shouldn't be able to happen. \
+				Maybe try to set the permissions again?"
+			);
+		}
+	}
+
+	for user in &users {
+		match brain.db.give_user_points(guild.get(), user.get(), points) {
+			Err(DbError::UserNotExist) => {
+				let member = brain.guild_member(guild, *user).await;
+				let row = BoardRow {
+					user_id: user.get(),
+					user_handle: member.handle,
+					user_nickname: member.nick.or(member.global_name),
+					points,
+				};
+				brain.db.add_user_to_leaderboard(guild.get(), row).unwrap();
+			}
+			_ => (),
+		}
+	}
+
+	let users_string = users
+		.into_iter()
+		.map(|u| format!("<@{u}>"))
+		.collect::<Vec<String>>()
+		.join(", ");
+
+	let msg = format!("{points_display} points {points_verb} {users_string}");
+	let embed = EmbedBuilder::new().description(msg).build();
+	InteractionResponseDataBuilder::new()
+		.embeds([embed])
+		.build()
+}