mirror of
https://github.com/RightNow-AI/openfang.git
synced 2026-04-25 17:25:11 +02:00
Merge pull request #1024 from Hypn0sis/fix/crypto-discord-free-response
fix: crypto provider, silent failure debug, Discord free_response_channels
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -45,3 +45,6 @@ Thumbs.db
|
||||
*.swo
|
||||
*~
|
||||
.serena/
|
||||
|
||||
# Personal deploy scripts
|
||||
scripts/deploy-remote.sh
|
||||
|
||||
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -4180,6 +4180,7 @@ dependencies = [
|
||||
"openfang-wire",
|
||||
"rand 0.8.5",
|
||||
"reqwest 0.12.28",
|
||||
"rustls 0.23.37",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"subtle",
|
||||
|
||||
@@ -63,6 +63,7 @@ clap_complete = "4"
|
||||
|
||||
# HTTP client (for LLM drivers)
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "multipart", "rustls-tls", "gzip", "deflate", "brotli"] }
|
||||
rustls = { version = "0.23", default-features = false, features = ["ring"] }
|
||||
|
||||
# Async trait
|
||||
async-trait = "0.1"
|
||||
|
||||
@@ -816,6 +816,19 @@ impl ChannelBridgeHandle for KernelBridgeAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
async fn free_response_channels(&self, channel_type: &str) -> Vec<String> {
|
||||
let channels = &self.kernel.config.channels;
|
||||
match channel_type {
|
||||
"discord" => channels
|
||||
.discord
|
||||
.as_ref()
|
||||
.map(|c| c.free_response_channels.clone())
|
||||
.unwrap_or_default(),
|
||||
// Add other channel types here as needed (e.g., "telegram" => ...)
|
||||
_ => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn authorize_channel_user(
|
||||
&self,
|
||||
channel_type: &str,
|
||||
|
||||
@@ -220,6 +220,13 @@ pub trait ChannelBridgeHandle: Send + Sync {
|
||||
None
|
||||
}
|
||||
|
||||
/// Get channel IDs that respond without requiring @mention (free response mode).
|
||||
///
|
||||
/// Returns an empty vector if the channel type is not configured or has no free response channels.
|
||||
async fn free_response_channels(&self, _channel_type: &str) -> Vec<String> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
/// Record a delivery result for tracking (optional — default no-op).
|
||||
///
|
||||
/// `thread_id` preserves Telegram forum-topic context so cron/workflow
|
||||
@@ -660,16 +667,23 @@ async fn dispatch_message(
|
||||
}
|
||||
}
|
||||
GroupPolicy::MentionOnly => {
|
||||
// Only allow messages where the bot was @mentioned or commands.
|
||||
let was_mentioned = message
|
||||
.metadata
|
||||
.get("was_mentioned")
|
||||
.and_then(|v| v.as_bool())
|
||||
.unwrap_or(false);
|
||||
let is_command = matches!(&message.content, ChannelContent::Command { .. });
|
||||
if !was_mentioned && !is_command {
|
||||
debug!("Ignoring group message on {ct_str} (group_policy=mention_only, not mentioned)");
|
||||
return;
|
||||
// Check if this channel is in the free_response list - if so, allow all messages
|
||||
let free_channels = handle.free_response_channels(ct_str).await;
|
||||
let channel_id = &message.sender.platform_id;
|
||||
let is_free_channel = free_channels.iter().any(|id| id == channel_id);
|
||||
|
||||
if !is_free_channel {
|
||||
// Only allow messages where the bot was @mentioned or commands.
|
||||
let was_mentioned = message
|
||||
.metadata
|
||||
.get("was_mentioned")
|
||||
.and_then(|v| v.as_bool())
|
||||
.unwrap_or(false);
|
||||
let is_command = matches!(&message.content, ChannelContent::Command { .. });
|
||||
if !was_mentioned && !is_command {
|
||||
debug!("Ignoring group message on {ct_str} (group_policy=mention_only, not mentioned)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
GroupPolicy::All => {}
|
||||
|
||||
@@ -33,6 +33,7 @@ subtle = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
rustls = { workspace = true }
|
||||
cron = "0.15"
|
||||
zeroize = { workspace = true }
|
||||
|
||||
|
||||
@@ -511,6 +511,13 @@ impl OpenFangKernel {
|
||||
|
||||
/// Boot the kernel with an explicit configuration.
|
||||
pub fn boot_with_config(mut config: KernelConfig) -> KernelResult<Self> {
|
||||
if rustls::crypto::ring::default_provider()
|
||||
.install_default()
|
||||
.is_err()
|
||||
{
|
||||
debug!("rustls crypto provider already installed, skipping");
|
||||
}
|
||||
|
||||
use openfang_types::config::KernelMode;
|
||||
|
||||
// Env var overrides — useful for Docker where config.toml is baked in.
|
||||
|
||||
@@ -1792,6 +1792,10 @@ pub struct DiscordConfig {
|
||||
/// Default channel ID for outgoing messages when no recipient is specified.
|
||||
#[serde(default)]
|
||||
pub default_channel_id: Option<String>,
|
||||
/// Channel IDs that respond without requiring @mention (free response mode).
|
||||
/// In these channels, the bot responds to all group messages without needing to be mentioned.
|
||||
#[serde(default, deserialize_with = "deserialize_string_or_int_vec")]
|
||||
pub free_response_channels: Vec<String>,
|
||||
/// Per-channel behavior overrides.
|
||||
#[serde(default)]
|
||||
pub overrides: ChannelOverrides,
|
||||
@@ -1807,6 +1811,7 @@ impl Default for DiscordConfig {
|
||||
intents: 37376,
|
||||
ignore_bots: true,
|
||||
default_channel_id: None,
|
||||
free_response_channels: vec![],
|
||||
overrides: ChannelOverrides::default(),
|
||||
}
|
||||
}
|
||||
@@ -3706,6 +3711,26 @@ mod tests {
|
||||
assert!(dc2.ignore_bots);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_discord_config_free_response_channels_deserialization() {
|
||||
// Test with free_response_channels as list of strings
|
||||
let toml_str = r#"
|
||||
bot_token_env = "DISCORD_BOT_TOKEN"
|
||||
free_response_channels = ["123456789", "987654321"]
|
||||
"#;
|
||||
let dc: DiscordConfig = toml::from_str(toml_str).unwrap();
|
||||
assert_eq!(dc.free_response_channels.len(), 2);
|
||||
assert_eq!(dc.free_response_channels[0], "123456789");
|
||||
assert_eq!(dc.free_response_channels[1], "987654321");
|
||||
|
||||
// Test default (empty list)
|
||||
let toml_str2 = r#"
|
||||
bot_token_env = "DISCORD_BOT_TOKEN"
|
||||
"#;
|
||||
let dc2: DiscordConfig = toml::from_str(toml_str2).unwrap();
|
||||
assert!(dc2.free_response_channels.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slack_config_defaults() {
|
||||
let sl = SlackConfig::default();
|
||||
|
||||
Reference in New Issue
Block a user