Skip to content

Commit 314e026

Browse files
committed
chore(faq): Support the entire message data rather than just an embed
1 parent 689496f commit 314e026

3 files changed

Lines changed: 37 additions & 19 deletions

File tree

bot/src/commands/faq.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use twilight_model::guild::Permissions;
1010
use twilight_model::http::interaction::{InteractionResponse, InteractionResponseType};
1111
use twilight_model::oauth::ApplicationIntegrationType;
1212
use twilight_util::builder::command::CommandBuilder;
13-
use twilight_util::builder::InteractionResponseDataBuilder;
1413

1514
use crate::commands::CommandHandler;
1615

@@ -70,13 +69,10 @@ impl CommandHandler for Faq<'_> {
7069
let CommandOptionValue::String(query) = &query.value else {
7170
anyhow::bail!("expected string query option");
7271
};
73-
let Some(embed) = ctx.cfg.faq_option_embed(query) else {
72+
let Some(mut response) = ctx.cfg.faq_option_response(query) else {
7473
anyhow::bail!("unknown query option: {}", query);
7574
};
7675

77-
// Create the response builder with an embed
78-
let mut response_builder = InteractionResponseDataBuilder::new().embeds([embed]);
79-
8076
// Add mention if provided
8177
let mention = data
8278
.options
@@ -87,15 +83,20 @@ impl CommandHandler for Faq<'_> {
8783
let CommandOptionValue::User(u_id) = mention.value else {
8884
anyhow::bail!("expected user option");
8985
};
90-
response_builder = response_builder.content(format!("<@{u_id}>"));
86+
// Either set the content to the response or prepend it to the response
87+
response.content = response
88+
.content
89+
.map_or(Some(format!("<@{u_id}>")), |content| {
90+
Some(format!("<@{u_id}> {content}"))
91+
});
9192
}
9293

9394
// Send the response
9495
ctx.http
9596
.interaction(self.cmd.application_id)
9697
.create_response(self.cmd.id, &self.cmd.token, &InteractionResponse {
9798
kind: InteractionResponseType::ChannelMessageWithSource,
98-
data: Some(response_builder.build()),
99+
data: Some(response),
99100
})
100101
.await?;
101102

bot/src/config.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use anyhow::Context;
22
use serde::Deserialize;
33
use twilight_model::application::command::{CommandOptionChoice, CommandOptionChoiceValue};
4-
use twilight_model::channel::message::Embed;
4+
use twilight_model::http::interaction::InteractionResponseData;
55
use twilight_model::id::marker::RoleMarker;
66
use twilight_model::id::Id;
77

@@ -24,13 +24,16 @@ pub(crate) struct RoleConfig {
2424

2525
/// Configuration for an option of the FAQ command.
2626
#[derive(Deserialize, Debug)]
27-
struct FaqOption {
27+
pub(crate) struct FaqOption {
2828
/// The label of the option (displayed to the user).
2929
label: String,
3030
/// The value of the option (used as the identifier).
3131
value: String,
3232
/// The embed to be sent when this option is selected.
33-
embed: Embed,
33+
// pub(crate) embed: Embed,
34+
/// The components to be included with the embed.
35+
// pub(crate) components: Option<Vec<Component>>,
36+
pub(crate) response: InteractionResponseData,
3437
}
3538

3639
impl Config {
@@ -46,22 +49,21 @@ impl Config {
4649
.collect()
4750
}
4851

49-
/// Returns the embed associated with a given FAQ option value.
50-
pub(crate) fn faq_option_embed<S>(&self, value: S) -> Option<Embed>
52+
/// Returns the FAQ option corresponding to the given value.
53+
pub(crate) fn faq_option_response<S>(&self, value: S) -> Option<InteractionResponseData>
5154
where
5255
S: AsRef<str>,
5356
{
5457
self.faq_options
5558
.iter()
5659
.find(|opt| opt.value == value.as_ref())
57-
.map(|opt| opt.embed.clone())
60+
.map(|opt| opt.response.clone())
5861
}
5962
}
6063

6164
/// Loads the configuration from a YAML file.
62-
#[tracing::instrument(ret)]
63-
pub(crate) fn load_config() -> Result<Config, anyhow::Error> {
64-
let cfg_yaml = std::fs::read(config_path()).context("read config file")?;
65+
pub(crate) fn load_config(path: String) -> Result<Config, anyhow::Error> {
66+
let cfg_yaml = std::fs::read(path).context("read config file")?;
6567
serde_yaml::from_slice(&cfg_yaml).context("parse config file")
6668
}
6769

bot/src/main.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ mod components;
33
mod config;
44
mod modals;
55

6-
use std::env;
76
use std::sync::Arc;
87

98
use anyhow::Context as _;
@@ -21,12 +20,28 @@ pub(crate) struct Context {
2120
request: Arc<reqwest::Client>,
2221
}
2322

23+
fn validate_config() -> anyhow::Result<()> {
24+
let path = std::env::args()
25+
.nth(2)
26+
.unwrap_or_else(|| "magnolia.cfg.yml".to_string());
27+
config::load_config(path)?;
28+
Ok(())
29+
}
30+
2431
#[tokio::main]
2532
async fn main() -> anyhow::Result<()> {
2633
// Initialize the tracing subscriber.
2734
tracing_subscriber::fmt::init();
2835

29-
let token = env::var("DISCORD_TOKEN").context("get DISCORD_TOKEN env")?;
36+
// Validate the config file.
37+
if let Some(arg) = std::env::args().nth(1) {
38+
if arg == "validate-config" {
39+
validate_config()?;
40+
return Ok(());
41+
}
42+
}
43+
44+
let token = std::env::var("DISCORD_TOKEN").context("get DISCORD_TOKEN env")?;
3045

3146
// Use intents to only receive guild message events.
3247
let shard = Shard::new(ShardId::ONE, token.clone(), Intents::empty());
@@ -41,7 +56,7 @@ async fn main() -> anyhow::Result<()> {
4156
.build();
4257

4358
// Parse the config file.
44-
let cfg = Arc::new(config::load_config()?);
59+
let cfg = Arc::new(config::load_config(config::config_path())?);
4560
let req_client = Arc::new(reqwest::Client::new());
4661

4762
// Initialize the state.

0 commit comments

Comments
 (0)