diff --git a/discord/src/commands/account.rs b/discord/src/commands/account.rs index 2d5d6f3..2b81750 100644 --- a/discord/src/commands/account.rs +++ b/discord/src/commands/account.rs @@ -1,7 +1,7 @@ use poise::serenity_prelude::User; use squad_quest::{SquadObject, account::Account, map::Map}; -use crate::{Context, Error, account::{account_full_balance, account_user_id, fetch_or_init_account}, strings::StringFormatter}; +use crate::{Context, Error, account::{account_full_balance, account_user_id, fetch_or_init_account}, strings::StringFormatter, commands::guild}; async fn account_balance_string( ctx: &Context<'_>, @@ -26,6 +26,7 @@ async fn account_balance_string( prefix_command, slash_command, guild_only, + check = "guild", required_permissions = "ADMINISTRATOR", name_localized("ru", "сбросить"), description_localized("ru", "Сбросить аккаунт пользователя, вкл. баланс, открытые комнаты и пройденные квесты"), @@ -63,6 +64,7 @@ pub async fn reset( prefix_command, slash_command, guild_only, + check = "guild", name_localized("ru", "счет"), description_localized("ru", "Отобразить таблицу лидеров"), )] @@ -106,6 +108,7 @@ pub async fn scoreboard( prefix_command, slash_command, guild_only, + check = "guild", subcommands("give", "set"), name_localized("ru", "баланс"), )] @@ -120,6 +123,7 @@ pub async fn balance( prefix_command, slash_command, guild_only, + check = "guild", name_localized("ru", "передать"), description_localized("ru", "Передать очки другому пользователю"), )] @@ -178,6 +182,7 @@ pub async fn give( prefix_command, slash_command, guild_only, + check = "guild", required_permissions = "ADMINISTRATOR", name_localized("ru", "установить"), description_localized("ru", "Устанавливает текущий баланс пользователя"), diff --git a/discord/src/commands/answer.rs b/discord/src/commands/answer.rs index 523db8f..2dd280a 100644 --- a/discord/src/commands/answer.rs +++ b/discord/src/commands/answer.rs @@ -1,13 +1,14 @@ use poise::serenity_prelude::{Attachment, ComponentInteractionCollector, CreateActionRow, CreateAttachment, CreateButton, CreateMessage, EditMessage}; use squad_quest::SquadObject; -use crate::{Context, Error, account::fetch_or_init_account}; +use crate::{Context, Error, account::fetch_or_init_account, commands::guild}; /// Send an answer to the quest for review #[poise::command( prefix_command, slash_command, guild_only, + check = "guild", name_localized("ru", "ответить"), description_localized("ru", "Отправить ответ на квест на проверку"), )] diff --git a/discord/src/commands/init.rs b/discord/src/commands/init.rs index fb6e6c3..b4fd02e 100644 --- a/discord/src/commands/init.rs +++ b/discord/src/commands/init.rs @@ -4,7 +4,7 @@ use poise::{CreateReply, serenity_prelude::ChannelId}; use squad_quest::SquadObject; use toml::value::Time; -use crate::{Context, Error, timer::DailyTimer}; +use crate::{Context, Error, timer::DailyTimer, commands::guild}; /// Set channels to post quests and answers to #[poise::command( @@ -12,6 +12,7 @@ use crate::{Context, Error, timer::DailyTimer}; slash_command, required_permissions = "ADMINISTRATOR", guild_only, + check = "guild", name_localized("ru", "инит"), description_localized("ru", "Установить каналы для публикации квестов и ответов"), )] @@ -75,6 +76,7 @@ fn seconds(time: Time) -> u64 { slash_command, required_permissions = "ADMINISTRATOR", guild_only, + check = "guild", name_localized("ru", "таймер"), description_localized("ru", "Включить таймер публикации по заданной временной метке UTC (МСК -3)"), )] diff --git a/discord/src/commands/map.rs b/discord/src/commands/map.rs index 064595d..e22f2e4 100644 --- a/discord/src/commands/map.rs +++ b/discord/src/commands/map.rs @@ -1,12 +1,13 @@ use squad_quest::{SquadObject, map::Map}; -use crate::{Context, account::fetch_or_init_account, error::Error}; +use crate::{Context, account::fetch_or_init_account, error::Error, commands::guild}; /// Unlock specified room if it is reachable and you have required amount of points #[poise::command( prefix_command, slash_command, guild_only, + check = "guild", name_localized("ru", "открыть"), description_localized("ru", "Открывает указанную комнату, если хватает очков и до нее можно добраться"), )] @@ -55,6 +56,7 @@ pub async fn unlock( prefix_command, slash_command, guild_only, + check = "guild", name_localized("ru", "пойти"), description_localized("ru", "Переместиться в другую разблокированную комнату"), )] diff --git a/discord/src/commands/mod.rs b/discord/src/commands/mod.rs index 85d3ee8..b274168 100644 --- a/discord/src/commands/mod.rs +++ b/discord/src/commands/mod.rs @@ -1,5 +1,5 @@ use std::error::Error as StdError; -use poise::CreateReply; +use poise::{CreateReply, serenity_prelude::GuildId}; use crate::{Context, Data, Error}; @@ -10,6 +10,18 @@ pub mod social; pub mod account; pub mod map; +pub async fn guild(ctx: Context<'_>) -> Result { + let id = ctx.guild_id().expect("guild-only command"); + let guard = ctx.data().discord.lock().expect("shouldn't be locked"); + let expected_id = guard.guild; + + if expected_id != GuildId::default() && id != expected_id { + return Err(Error::NotThisGuild); + } + + Ok(true) +} + #[poise::command(prefix_command)] pub async fn register(ctx: Context<'_>) -> Result<(), Error> { poise::builtins::register_application_commands_buttons(ctx).await?; @@ -36,10 +48,17 @@ pub async fn error_handler(error: poise::FrameworkError<'_, Data, Error>) { eprintln!("ERROR:"); print_error_recursively(&error); if let Some(ctx) = error.ctx() { + let user = ctx.author().display_name(); + eprintln!("User: {user} ({id})", id = ctx.author().id); + let response = match error { - poise::FrameworkError::Command { error, .. } => format!("Internal server error: {error}"), + poise::FrameworkError::Command { error, .. } => { + eprintln!("Invokation string: {}", ctx.invocation_string()); + format!("Internal server error: {error}") + }, _ => format!("Internal server error: {error}"), }; + if let Err(error) = ctx.send(CreateReply::default().content(response).ephemeral(true)).await { eprintln!("Couldn't send error message: {error}"); } diff --git a/discord/src/commands/quest.rs b/discord/src/commands/quest.rs index 1d73544..489d70c 100644 --- a/discord/src/commands/quest.rs +++ b/discord/src/commands/quest.rs @@ -3,7 +3,7 @@ use std::{future, str::FromStr}; use poise::serenity_prelude::{CreateMessage, EditMessage, Message, futures::StreamExt}; use squad_quest::{SquadObject, quest::{Quest, QuestDifficulty}}; use toml::value::Date; -use crate::{Context, Error}; +use crate::{Context, Error,commands::guild}; async fn find_quest_message(ctx: Context<'_>, id: u16) -> Result, Error>{ ctx.defer().await?; @@ -34,6 +34,7 @@ fn make_quest_message_content(ctx: Context<'_>, quest: &Quest) -> String { prefix_command, slash_command, guild_only, + check = "guild", subcommands("list", "create", "update", "publish", "delete"), required_permissions = "ADMINISTRATOR", name_localized("ru", "квест"), @@ -49,6 +50,7 @@ pub async fn quest( prefix_command, slash_command, guild_only, + check = "guild", required_permissions = "ADMINISTRATOR", name_localized("ru", "список"), description_localized("ru", "Вывести все квесты") @@ -114,6 +116,7 @@ impl From for Date { slash_command, required_permissions = "ADMINISTRATOR", guild_only, + check = "guild", name_localized("ru", "создать"), description_localized("ru", "Создать квест и получить его идентификатор"), )] @@ -202,6 +205,7 @@ pub async fn create( slash_command, required_permissions = "ADMINISTRATOR", guild_only, + check = "guild", name_localized("ru", "обновить"), description_localized("ru", "Обновить выбранные значения указанного квеста"), )] @@ -339,6 +343,7 @@ pub async fn publish_inner(ctx: Context<'_>, quest: &mut Quest) -> Result ) -> Result<(), Error> { slash_command, required_permissions = "ADMINISTRATOR", guild_only, + check = "guild", name_localized("ru", "написать"), description_localized("ru", "Отправить сообщение пользователю или в канал"), )] @@ -98,6 +100,7 @@ pub async fn msg ( slash_command, required_permissions = "ADMINISTRATOR", guild_only, + check = "guild", name_localized("ru", "редактировать"), description_localized("ru", "Редактировать сообщение в канале или в ЛС"), )] @@ -177,6 +180,7 @@ pub async fn edit ( slash_command, required_permissions = "ADMINISTRATOR", guild_only, + check = "guild", name_localized("ru", "удалить"), description_localized("ru", "Удалить сообщение в канале или в ЛС"), )] diff --git a/discord/src/error.rs b/discord/src/error.rs index 8d8b442..fe80e0d 100644 --- a/discord/src/error.rs +++ b/discord/src/error.rs @@ -21,6 +21,7 @@ pub enum Error { RoomAlreadyUnlocked(u16), CannotReach(u16), TimerSet, + NotThisGuild, } impl From for Error { @@ -65,6 +66,7 @@ impl Display for Error { Self::RoomAlreadyUnlocked(id) => write!(f, "room #{id} is already unlocked for this user"), Self::CannotReach(id) => write!(f, "user cannot reach room #{id}"), Self::TimerSet => write!(f, "timer is already set"), + Self::NotThisGuild => write!(f, "cannot be used in this guild"), } } } @@ -84,7 +86,8 @@ impl std::error::Error for Error { Self::RoomNotFound(_) | Self::RoomAlreadyUnlocked(_) | Self::CannotReach(_) | - Self::TimerSet => None, + Self::TimerSet | + Self::NotThisGuild => None, Self::SerenityError(error) => Some(error), Self::SquadQuestError(error) => Some(error), }