feat: Implemented guild check

- Also added more error logging
This commit is contained in:
Alexey 2025-12-24 17:46:22 +03:00
commit d188bba16e
8 changed files with 51 additions and 9 deletions

View file

@ -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", "Устанавливает текущий баланс пользователя"),

View file

@ -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", "Отправить ответ на квест на проверку"),
)]

View file

@ -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)"),
)]

View file

@ -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", "Переместиться в другую разблокированную комнату"),
)]

View file

@ -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<bool, Error> {
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}");
}

View file

@ -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<Option<Message>, 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<DateWrapper> 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<Messag
slash_command,
required_permissions = "ADMINISTRATOR",
guild_only,
check = "guild",
name_localized("ru", "опубликовать"),
description_localized("ru", "Отметить квест как публичный и отправить его сообщение в канал квестов"),
)]
@ -378,6 +383,7 @@ pub async fn publish(
slash_command,
required_permissions = "ADMINISTRATOR",
guild_only,
check = "guild",
name_localized("ru", "удалить"),
description_localized("ru", "Удалить квест (и его сообщение, если он был опубликован)"),
)]

View file

@ -1,12 +1,13 @@
use poise::serenity_prelude::{Attachment, ChannelId, CreateAttachment, CreateMessage, EditMessage, MessageId, UserId};
use crate::{Context, Error};
use crate::{Context, Error, commands::guild};
#[poise::command(
prefix_command,
slash_command,
required_permissions = "ADMINISTRATOR",
guild_only,
check = "guild",
subcommands("msg", "edit", "undo"),
name_localized("ru", "сообщение"),
)]
@ -20,6 +21,7 @@ pub async fn social( _ctx: Context<'_> ) -> 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", "Удалить сообщение в канале или в ЛС"),
)]

View file

@ -21,6 +21,7 @@ pub enum Error {
RoomAlreadyUnlocked(u16),
CannotReach(u16),
TimerSet,
NotThisGuild,
}
impl From<serenity::Error> 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),
}