about summary refs log tree commit diff
path: root/src/command/add_points.rs
blob: 453be2de76c42e66ddab5ddb6e23072297b1c84d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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()
}