use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use crate::secret::SecretString;
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ChannelsConfig {
#[serde(default)]
pub telegram: TelegramConfig,
#[serde(default)]
pub slack: SlackConfig,
#[serde(default)]
pub discord: DiscordConfig,
#[serde(default)]
pub whatsapp: WhatsAppConfig,
#[serde(default)]
pub feishu: FeishuConfig,
#[serde(default)]
pub dingtalk: DingTalkConfig,
#[serde(default)]
pub mochat: MochatConfig,
#[serde(default)]
pub email: EmailConfig,
#[serde(default)]
pub qq: QQConfig,
#[serde(flatten)]
pub extra: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct TelegramConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default)]
pub token: SecretString,
#[serde(default, alias = "tokenEnv")]
pub token_env: Option<String>,
#[serde(default, alias = "allowFrom")]
pub allow_from: Vec<String>,
#[serde(default)]
pub proxy: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SlackConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default = "default_slack_mode")]
pub mode: String,
#[serde(default = "default_webhook_path", alias = "webhookPath")]
pub webhook_path: String,
#[serde(default, alias = "botToken")]
pub bot_token: SecretString,
#[serde(default, alias = "botTokenEnv")]
pub bot_token_env: Option<String>,
#[serde(default, alias = "appToken")]
pub app_token: SecretString,
#[serde(default, alias = "appTokenEnv")]
pub app_token_env: Option<String>,
#[serde(default = "super::default_true", alias = "userTokenReadOnly")]
pub user_token_read_only: bool,
#[serde(default = "default_group_policy", alias = "groupPolicy")]
pub group_policy: String,
#[serde(default, alias = "groupAllowFrom")]
pub group_allow_from: Vec<String>,
#[serde(default)]
pub dm: SlackDMConfig,
}
fn default_slack_mode() -> String {
"socket".into()
}
fn default_webhook_path() -> String {
"/slack/events".into()
}
fn default_group_policy() -> String {
"mention".into()
}
impl Default for SlackConfig {
fn default() -> Self {
Self {
enabled: false,
mode: default_slack_mode(),
webhook_path: default_webhook_path(),
bot_token: SecretString::default(),
bot_token_env: None,
app_token: SecretString::default(),
app_token_env: None,
user_token_read_only: true,
group_policy: default_group_policy(),
group_allow_from: Vec::new(),
dm: SlackDMConfig::default(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SlackDMConfig {
#[serde(default = "super::default_true")]
pub enabled: bool,
#[serde(default = "default_dm_policy")]
pub policy: String,
#[serde(default, alias = "allowFrom")]
pub allow_from: Vec<String>,
}
fn default_dm_policy() -> String {
"open".into()
}
impl Default for SlackDMConfig {
fn default() -> Self {
Self {
enabled: true,
policy: default_dm_policy(),
allow_from: Vec::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiscordConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default)]
pub token: SecretString,
#[serde(default, alias = "tokenEnv")]
pub token_env: Option<String>,
#[serde(default, alias = "allowFrom")]
pub allow_from: Vec<String>,
#[serde(default = "default_discord_gateway_url", alias = "gatewayUrl")]
pub gateway_url: String,
#[serde(default = "default_discord_intents")]
pub intents: u32,
}
fn default_discord_gateway_url() -> String {
"wss://gateway.discord.gg/?v=10&encoding=json".into()
}
fn default_discord_intents() -> u32 {
37377 }
impl Default for DiscordConfig {
fn default() -> Self {
Self {
enabled: false,
token: SecretString::default(),
token_env: None,
allow_from: Vec::new(),
gateway_url: default_discord_gateway_url(),
intents: default_discord_intents(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WhatsAppConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default = "default_whatsapp_bridge_url", alias = "bridgeUrl")]
pub bridge_url: String,
#[serde(default, alias = "bridgeToken")]
pub bridge_token: SecretString,
#[serde(default, alias = "allowFrom")]
pub allow_from: Vec<String>,
}
fn default_whatsapp_bridge_url() -> String {
"ws://localhost:3001".into()
}
impl Default for WhatsAppConfig {
fn default() -> Self {
Self {
enabled: false,
bridge_url: default_whatsapp_bridge_url(),
bridge_token: SecretString::default(),
allow_from: Vec::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct FeishuConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default, alias = "appId")]
pub app_id: String,
#[serde(default, alias = "appSecret")]
pub app_secret: SecretString,
#[serde(default, alias = "encryptKey")]
pub encrypt_key: String,
#[serde(default, alias = "verificationToken")]
pub verification_token: SecretString,
#[serde(default, alias = "allowFrom")]
pub allow_from: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct DingTalkConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default, alias = "clientId")]
pub client_id: String,
#[serde(default, alias = "clientSecret")]
pub client_secret: SecretString,
#[serde(default, alias = "allowFrom")]
pub allow_from: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MochatMentionConfig {
#[serde(default, alias = "requireInGroups")]
pub require_in_groups: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MochatGroupRule {
#[serde(default, alias = "requireMention")]
pub require_mention: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MochatConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default = "default_mochat_base_url", alias = "baseUrl")]
pub base_url: String,
#[serde(default, alias = "socketUrl")]
pub socket_url: String,
#[serde(default = "default_socket_path", alias = "socketPath")]
pub socket_path: String,
#[serde(default, alias = "socketDisableMsgpack")]
pub socket_disable_msgpack: bool,
#[serde(default = "default_1000", alias = "socketReconnectDelayMs")]
pub socket_reconnect_delay_ms: i64,
#[serde(default = "default_10000", alias = "socketMaxReconnectDelayMs")]
pub socket_max_reconnect_delay_ms: i64,
#[serde(default = "default_10000", alias = "socketConnectTimeoutMs")]
pub socket_connect_timeout_ms: i64,
#[serde(default = "default_30000", alias = "refreshIntervalMs")]
pub refresh_interval_ms: i64,
#[serde(default = "default_25000", alias = "watchTimeoutMs")]
pub watch_timeout_ms: i64,
#[serde(default = "default_100", alias = "watchLimit")]
pub watch_limit: i64,
#[serde(default = "default_500", alias = "retryDelayMs")]
pub retry_delay_ms: i64,
#[serde(default, alias = "maxRetryAttempts")]
pub max_retry_attempts: i64,
#[serde(default, alias = "clawToken")]
pub claw_token: SecretString,
#[serde(default, alias = "agentUserId")]
pub agent_user_id: String,
#[serde(default)]
pub sessions: Vec<String>,
#[serde(default)]
pub panels: Vec<String>,
#[serde(default, alias = "allowFrom")]
pub allow_from: Vec<String>,
#[serde(default)]
pub mention: MochatMentionConfig,
#[serde(default)]
pub groups: HashMap<String, MochatGroupRule>,
#[serde(default = "default_reply_delay_mode", alias = "replyDelayMode")]
pub reply_delay_mode: String,
#[serde(default = "default_120000", alias = "replyDelayMs")]
pub reply_delay_ms: i64,
}
fn default_mochat_base_url() -> String {
"https://mochat.io".into()
}
fn default_socket_path() -> String {
"/socket.io".into()
}
fn default_reply_delay_mode() -> String {
"non-mention".into()
}
fn default_1000() -> i64 {
1000
}
fn default_10000() -> i64 {
10000
}
fn default_30000() -> i64 {
30000
}
fn default_25000() -> i64 {
25000
}
fn default_100() -> i64 {
100
}
fn default_500() -> i64 {
500
}
fn default_120000() -> i64 {
120000
}
impl Default for MochatConfig {
fn default() -> Self {
Self {
enabled: false,
base_url: default_mochat_base_url(),
socket_url: String::new(),
socket_path: default_socket_path(),
socket_disable_msgpack: false,
socket_reconnect_delay_ms: default_1000(),
socket_max_reconnect_delay_ms: default_10000(),
socket_connect_timeout_ms: default_10000(),
refresh_interval_ms: default_30000(),
watch_timeout_ms: default_25000(),
watch_limit: default_100(),
retry_delay_ms: default_500(),
max_retry_attempts: 0,
claw_token: SecretString::default(),
agent_user_id: String::new(),
sessions: Vec::new(),
panels: Vec::new(),
allow_from: Vec::new(),
mention: MochatMentionConfig::default(),
groups: HashMap::new(),
reply_delay_mode: default_reply_delay_mode(),
reply_delay_ms: default_120000(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmailConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default, alias = "consentGranted")]
pub consent_granted: bool,
#[serde(default, alias = "imapHost")]
pub imap_host: String,
#[serde(default = "default_imap_port", alias = "imapPort")]
pub imap_port: u16,
#[serde(default, alias = "imapUsername")]
pub imap_username: String,
#[serde(default, alias = "imapPassword")]
pub imap_password: SecretString,
#[serde(default = "default_imap_mailbox", alias = "imapMailbox")]
pub imap_mailbox: String,
#[serde(default = "super::default_true", alias = "imapUseSsl")]
pub imap_use_ssl: bool,
#[serde(default, alias = "smtpHost")]
pub smtp_host: String,
#[serde(default = "default_smtp_port", alias = "smtpPort")]
pub smtp_port: u16,
#[serde(default, alias = "smtpUsername")]
pub smtp_username: String,
#[serde(default, alias = "smtpPassword")]
pub smtp_password: SecretString,
#[serde(default = "super::default_true", alias = "smtpUseTls")]
pub smtp_use_tls: bool,
#[serde(default, alias = "smtpUseSsl")]
pub smtp_use_ssl: bool,
#[serde(default, alias = "fromAddress")]
pub from_address: String,
#[serde(default = "super::default_true", alias = "autoReplyEnabled")]
pub auto_reply_enabled: bool,
#[serde(default = "default_poll_interval", alias = "pollIntervalSeconds")]
pub poll_interval_seconds: u32,
#[serde(default = "super::default_true", alias = "markSeen")]
pub mark_seen: bool,
#[serde(default = "default_max_body_chars", alias = "maxBodyChars")]
pub max_body_chars: u32,
#[serde(default = "default_subject_prefix", alias = "subjectPrefix")]
pub subject_prefix: String,
#[serde(default, alias = "allowFrom")]
pub allow_from: Vec<String>,
}
fn default_imap_port() -> u16 {
993
}
fn default_imap_mailbox() -> String {
"INBOX".into()
}
fn default_smtp_port() -> u16 {
587
}
fn default_poll_interval() -> u32 {
30
}
fn default_max_body_chars() -> u32 {
12000
}
fn default_subject_prefix() -> String {
"Re: ".into()
}
impl Default for EmailConfig {
fn default() -> Self {
Self {
enabled: false,
consent_granted: false,
imap_host: String::new(),
imap_port: default_imap_port(),
imap_username: String::new(),
imap_password: SecretString::default(),
imap_mailbox: default_imap_mailbox(),
imap_use_ssl: true,
smtp_host: String::new(),
smtp_port: default_smtp_port(),
smtp_username: String::new(),
smtp_password: SecretString::default(),
smtp_use_tls: true,
smtp_use_ssl: false,
from_address: String::new(),
auto_reply_enabled: true,
poll_interval_seconds: default_poll_interval(),
mark_seen: true,
max_body_chars: default_max_body_chars(),
subject_prefix: default_subject_prefix(),
allow_from: Vec::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct QQConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default, alias = "appId")]
pub app_id: String,
#[serde(default)]
pub secret: SecretString,
#[serde(default, alias = "allowFrom")]
pub allow_from: Vec<String>,
}