huskies: merge 472_story_discord_chat_transport
This commit is contained in:
@@ -64,7 +64,8 @@ pub struct BotConfig {
|
||||
/// manually while the bot is running.
|
||||
#[serde(default)]
|
||||
pub ambient_rooms: Vec<String>,
|
||||
/// Chat transport to use: `"matrix"` (default) or `"whatsapp"`.
|
||||
/// Chat transport to use: `"matrix"` (default), `"whatsapp"`, `"slack"`,
|
||||
/// or `"discord"`.
|
||||
///
|
||||
/// Selects which [`ChatTransport`] implementation the bot uses for
|
||||
/// sending and editing messages. Currently only read during bot
|
||||
@@ -134,6 +135,20 @@ pub struct BotConfig {
|
||||
/// Slack channel IDs the bot should listen in.
|
||||
#[serde(default)]
|
||||
pub slack_channel_ids: Vec<String>,
|
||||
|
||||
// ── Discord Bot API fields ──────────────────────────────────────
|
||||
// These are only required when `transport = "discord"`.
|
||||
|
||||
/// Discord bot token from the Discord Developer Portal.
|
||||
#[serde(default)]
|
||||
pub discord_bot_token: Option<String>,
|
||||
/// Discord channel IDs the bot should listen in.
|
||||
#[serde(default)]
|
||||
pub discord_channel_ids: Vec<String>,
|
||||
/// Discord user IDs allowed to interact with the bot.
|
||||
/// When empty or absent, all users in configured channels are allowed.
|
||||
#[serde(default)]
|
||||
pub discord_allowed_users: Vec<String>,
|
||||
}
|
||||
|
||||
fn default_transport() -> String {
|
||||
@@ -241,6 +256,22 @@ impl BotConfig {
|
||||
);
|
||||
return None;
|
||||
}
|
||||
} else if config.transport == "discord" {
|
||||
// Validate Discord-specific fields.
|
||||
if config.discord_bot_token.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
eprintln!(
|
||||
"[bot] bot.toml: transport=\"discord\" requires \
|
||||
discord_bot_token"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
if config.discord_channel_ids.is_empty() {
|
||||
eprintln!(
|
||||
"[bot] bot.toml: transport=\"discord\" requires \
|
||||
at least one discord_channel_ids entry"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
// Default transport is Matrix — validate Matrix-specific fields.
|
||||
if config.homeserver.as_ref().is_none_or(|s| s.is_empty()) {
|
||||
@@ -1054,4 +1085,99 @@ whatsapp_allowed_phones = ["+15551234567", "+15559876543"]
|
||||
vec!["+15551234567", "+15559876543"]
|
||||
);
|
||||
}
|
||||
|
||||
// ── Discord config tests ──────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn load_discord_transport_reads_config() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let sk = tmp.path().join(".huskies");
|
||||
fs::create_dir_all(&sk).unwrap();
|
||||
fs::write(
|
||||
sk.join("bot.toml"),
|
||||
r#"
|
||||
enabled = true
|
||||
transport = "discord"
|
||||
discord_bot_token = "Bot.Token.Here"
|
||||
discord_channel_ids = ["123456789012345678"]
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
let config = BotConfig::load(tmp.path()).unwrap();
|
||||
assert_eq!(config.transport, "discord");
|
||||
assert_eq!(
|
||||
config.discord_bot_token.as_deref(),
|
||||
Some("Bot.Token.Here")
|
||||
);
|
||||
assert_eq!(
|
||||
config.discord_channel_ids,
|
||||
vec!["123456789012345678"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_discord_returns_none_when_missing_bot_token() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let sk = tmp.path().join(".huskies");
|
||||
fs::create_dir_all(&sk).unwrap();
|
||||
fs::write(
|
||||
sk.join("bot.toml"),
|
||||
r#"
|
||||
enabled = true
|
||||
transport = "discord"
|
||||
discord_channel_ids = ["123456789012345678"]
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(BotConfig::load(tmp.path()).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn load_discord_returns_none_when_missing_channel_ids() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let sk = tmp.path().join(".huskies");
|
||||
fs::create_dir_all(&sk).unwrap();
|
||||
fs::write(
|
||||
sk.join("bot.toml"),
|
||||
r#"
|
||||
enabled = true
|
||||
transport = "discord"
|
||||
discord_bot_token = "Bot.Token.Here"
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(BotConfig::load(tmp.path()).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn discord_allowed_users_defaults_to_empty_when_absent() {
|
||||
let config: BotConfig = toml::from_str(
|
||||
r#"
|
||||
enabled = true
|
||||
transport = "discord"
|
||||
discord_bot_token = "Bot.Token.Here"
|
||||
discord_channel_ids = ["123456789"]
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(config.discord_allowed_users.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn discord_allowed_users_deserializes_list() {
|
||||
let config: BotConfig = toml::from_str(
|
||||
r#"
|
||||
enabled = true
|
||||
transport = "discord"
|
||||
discord_bot_token = "Bot.Token.Here"
|
||||
discord_channel_ids = ["123456789"]
|
||||
discord_allowed_users = ["111222333", "444555666"]
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
config.discord_allowed_users,
|
||||
vec!["111222333", "444555666"]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user