diff --git a/discord/src/commands/answer.rs b/discord/src/commands/answer.rs new file mode 100644 index 0000000..eca42dd --- /dev/null +++ b/discord/src/commands/answer.rs @@ -0,0 +1,68 @@ +use poise::serenity_prelude::{Attachment, CreateAttachment, CreateMessage, Mentionable}; + +use crate::{Context, Error}; + +#[poise::command( + prefix_command, + slash_command, + guild_only, +)] +pub async fn answer( + ctx: Context<'_>, + #[description = "Identifier of the quest to answer to"] + quest_id: u16, + #[description = "Text answer to the quest"] + text: Option, + #[description = "Attachment answer to the quest"] + files: Vec, +) -> Result<(), Error> { + let quests = ctx.data().config.load_quests(); + let Some(quest) = quests.iter().find(|q| q.id == quest_id) else { + let reply_string = format!("Quest #{quest_id} not found."); + ctx.reply(reply_string).await?; + return Ok(()); + }; + + if text.is_none() && files.len() == 0 { + let reply_string = "Please specify text or at least one attachment.".to_string(); + ctx.reply(reply_string).await?; + return Ok(()); + } + + let text_ans = match text { + Some(text) => format!("\n### Passed answer:\n{text}"), + None => String::new(), + }; + + let attachment_notice = if files.len() == 0 { String::new() } else { + "\nPassed answer has attachments.".to_string() + }; + + let content = format!("# From: {user}\n\ + ### Quest #{quest_id}: {quest_name}\n\ + ### Expected answer:\n\ + ||{quest_answer}||{text_ans}{attachment_notice}", + user = ctx.author().mention(), + quest_name = quest.name, + quest_answer = quest.answer, + ); + + let mut attachments: Vec = Vec::new(); + + for file in files { + let attachment = CreateAttachment::url(ctx, &file.url).await?; + attachments.push(attachment); + } + + let ans_channel = ctx.data().discord.answers_channel; + let message = CreateMessage::new() + .content(content) + .files(attachments); + + ans_channel.send_message(ctx, message).await?; + + let reply_string = "Your answer has been posted.".to_string(); + ctx.reply(reply_string).await?; + + Ok(()) +} diff --git a/discord/src/commands/init.rs b/discord/src/commands/init.rs index 1ac58ea..a0c4b9b 100644 --- a/discord/src/commands/init.rs +++ b/discord/src/commands/init.rs @@ -26,7 +26,7 @@ pub async fn init( dc.guild = guild; let path = &ctx.data().config.full_impl_path().unwrap(); let reply_string = match dc.save(path.parent().unwrap_or(Path::new("")).to_owned()) { - Ok(_) => "Please restart bot to apply changes".to_string(), + Ok(_) => "Settings updated, please restart bot to apply changes.".to_string(), Err(error) => { eprintln!("{error}"); ERROR_MSG.to_string() diff --git a/discord/src/commands/mod.rs b/discord/src/commands/mod.rs index 37b33ea..8e19a17 100644 --- a/discord/src/commands/mod.rs +++ b/discord/src/commands/mod.rs @@ -4,6 +4,7 @@ use crate::{Context, Error}; pub mod quest; pub mod init; +pub mod answer; pub const ERROR_MSG: &str = "Server error :("; diff --git a/discord/src/commands/quest.rs b/discord/src/commands/quest.rs index 71fb536..fa5172f 100644 --- a/discord/src/commands/quest.rs +++ b/discord/src/commands/quest.rs @@ -2,9 +2,7 @@ use std::str::FromStr; use squad_quest::{SquadObject, quest::{Quest, QuestDifficulty}}; use toml::value::Date; -use crate::{Context, Error}; - -const ERROR_MSG: &str = "Server error :("; +use crate::{Context, Error, commands::ERROR_MSG}; #[poise::command( prefix_command, diff --git a/discord/src/config.rs b/discord/src/config.rs index de4013c..0708d53 100644 --- a/discord/src/config.rs +++ b/discord/src/config.rs @@ -4,6 +4,15 @@ use poise::serenity_prelude::{ChannelId, GuildId, MessageId}; use serde::{Serialize, Deserialize}; use squad_quest::{SquadObject, config::Config, error::Error}; +#[derive(Serialize, Deserialize, Default, Clone)] +pub struct DiscordConfig { + pub guild: GuildId, + pub quests_channel: ChannelId, + pub answers_channel: ChannelId, + pub quests_messages: Vec, + pub pending_answers: Vec, +} + pub trait ConfigImpl { fn discord_impl(&self) -> Result; fn init_impl(&self) -> Result<(), Error>; @@ -25,14 +34,6 @@ impl ConfigImpl for Config { } } -#[derive(Serialize, Deserialize, Default, Clone)] -pub struct DiscordConfig { - pub guild: GuildId, - pub quests_channel: ChannelId, - pub answers_channel: ChannelId, - pub quests_messages: Vec, -} - impl SquadObject for DiscordConfig { fn load(path: PathBuf) -> Result { match std::fs::read_to_string(path) { diff --git a/discord/src/main.rs b/discord/src/main.rs index c73a2b5..950de6c 100644 --- a/discord/src/main.rs +++ b/discord/src/main.rs @@ -35,7 +35,8 @@ async fn main() { commands: vec![ commands::quest::quest(), commands::register(), - commands::init::init() + commands::init::init(), + commands::answer::answer(), ], ..Default::default() })