From b92eaa1241cb5f975570c408b8d8af86ccb4b1d0 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Tue, 9 Dec 2025 16:07:41 +0300 Subject: [PATCH] feat: Added DiscordConfig for future usage - Added crate::error::Error::IsNotImplemented - Added Config::full_impl_path - Added Config::discord_impl for discord crate --- discord/src/config.rs | 79 +++++++++++++++++++++++++++++++++++++++++++ discord/src/main.rs | 10 +++++- src/config/mod.rs | 15 ++++++++ src/error.rs | 3 ++ 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 discord/src/config.rs diff --git a/discord/src/config.rs b/discord/src/config.rs new file mode 100644 index 0000000..8323e3d --- /dev/null +++ b/discord/src/config.rs @@ -0,0 +1,79 @@ +use std::{io::Write, path::PathBuf}; + +use poise::serenity_prelude::{ChannelId, GuildId, MessageId}; +use serde::{Serialize, Deserialize}; +use squad_quest::{SquadObject, config::Config, error::Error}; + +pub trait ConfigImpl { + fn discord_impl(&self) -> Result; +} + +impl ConfigImpl for Config { + fn discord_impl(&self) -> Result { + let Some(path) = &self.impl_path else { + return Err(Error::IsNotImplemented); + }; + DiscordConfig::load(path.clone()) + } +} + +#[derive(Serialize, Deserialize)] +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) { + Ok(string) => { + match toml::from_str::(&string) { + Ok(object) => Ok(object), + Err(error) => Err(Error::TomlDeserializeError(error)) + } + }, + Err(error) => Err(Error::IoError(error)) + } + } + + fn delete(path: PathBuf) -> Result<(), Error> { + match Self::load(path.clone()) { + Ok(_) => { + if let Err(error) = std::fs::remove_file(path) { + return Err(Error::IoError(error)); + } + + Ok(()) + }, + Err(error) => Err(error) + } + } + + fn save(&self, path: PathBuf) -> Result<(), Error> { + let filename = "discord.toml".to_string(); + let mut full_path = path; + full_path.push(filename); + + let str = match toml::to_string_pretty(&self) { + Ok(string) => string, + Err(error) => { + return Err(Error::TomlSerializeError(error)); + } + }; + + let mut file = match std::fs::File::create(full_path) { + Ok(f) => f, + Err(error) => { + return Err(Error::IoError(error)); + } + }; + + if let Err(error) = file.write_all(str.as_bytes()) { + return Err(Error::IoError(error)); + } + + Ok(()) + } +} diff --git a/discord/src/main.rs b/discord/src/main.rs index cbbdc3b..deae174 100644 --- a/discord/src/main.rs +++ b/discord/src/main.rs @@ -3,11 +3,15 @@ use dotenvy::dotenv; use poise::serenity_prelude as serenity; use squad_quest::config::Config; +use crate::config::{ConfigImpl, DiscordConfig}; + mod commands; mod cli; +mod config; struct Data { pub config: Config, + pub discord: DiscordConfig, } type Error = Box; type Context<'a> = poise::Context<'a, Data, Error>; @@ -18,6 +22,7 @@ async fn main() { let cli = cli::Cli::parse(); let config = Config::load(cli.config.clone()); + let discord = config.discord_impl().expect("config does not define impl_path"); let token = std::env::var("DISCORD_TOKEN").expect("missing DISCORD_TOKEN"); let intents = serenity::GatewayIntents::non_privileged(); @@ -30,7 +35,10 @@ async fn main() { .setup(|ctx, _ready, framework| { Box::pin(async move { poise::builtins::register_globally(ctx, &framework.options().commands).await?; - Ok(Data {config}) + Ok(Data { + config, + discord, + }) }) }) .build(); diff --git a/src/config/mod.rs b/src/config/mod.rs index bb6850b..9544042 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -357,4 +357,19 @@ impl Config { path.push(self.map.clone()); path } + + /// Returns full path to implementation config TOML, if defined + /// This path will be relative to working directory + /// Only makes sense if using inside binary crate, + /// which provides implementation config + pub fn full_impl_path(&self) -> Option { + match &self.impl_path { + Some(impl_path) => { + let mut path = self.path.clone(); + path.push(impl_path.clone()); + Some(path) + }, + None => None, + } + } } diff --git a/src/error.rs b/src/error.rs index 6db1382..abb475c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -15,6 +15,8 @@ pub enum Error { TomlSerializeError(toml::ser::Error), /// toml::de::Error happened when loading TomlDeserializeError(toml::de::Error), + /// Implementation config is None, so crate binary is not implemented. + IsNotImplemented, } impl fmt::Display for Error { @@ -24,6 +26,7 @@ impl fmt::Display for Error { Self::IoError(error) => write!(f, "{error}"), Self::TomlSerializeError(error) => write!(f, "{error}"), Self::TomlDeserializeError(error) => write!(f, "{error}"), + Self::IsNotImplemented => write!(f, "implementation not found"), } } }