test merge

Merge lark.rs features (dedup, encryption, group filtering, rich text parsing)
into feishu.rs with FeishuRegion toggle (cn/intl). Single [channels.feishu]
config handles both domestic Feishu and international Lark via region field.

- Expand FeishuConfig: region, webhook_path, verification_token, encrypt_key_env, bot_names
- Add FeishuRegion enum with domain switching (open.feishu.cn / open.larksuite.com)
- Add AES-256-CBC event decryption, message/event dedup, group chat filtering
- Update channel_bridge.rs wiring for full config
- Update routes.rs ChannelMeta with new UI fields (region basic, rest advanced)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
pluginmd
2026-03-15 17:39:56 +03:00
committed by GitHub
co-authored by Claude Opus 4.6
parent eb87e3fd42
commit d2ea030f03
4 changed files with 757 additions and 219 deletions
+12 -1
View File
@@ -1411,10 +1411,21 @@ pub async fn start_channel_bridge_with_config(
// Feishu/Lark
if let Some(ref fs_config) = config.feishu {
if let Some(secret) = read_token(&fs_config.app_secret_env, "Feishu") {
let adapter = Arc::new(FeishuAdapter::new(
let region =
openfang_channels::feishu::FeishuRegion::parse_region(&fs_config.region);
let encrypt_key = fs_config
.encrypt_key_env
.as_ref()
.and_then(|env| read_token(env, "Feishu encrypt_key"));
let adapter = Arc::new(FeishuAdapter::with_config(
fs_config.app_id.clone(),
secret,
fs_config.webhook_port,
region,
Some(fs_config.webhook_path.clone()),
fs_config.verification_token.clone(),
encrypt_key,
fs_config.bot_names.clone(),
));
adapters.push((adapter, fs_config.default_agent.clone()));
}
+8 -3
View File
@@ -1850,18 +1850,23 @@ const CHANNEL_REGISTRY: &[ChannelMeta] = &[
},
ChannelMeta {
name: "feishu", display_name: "Feishu/Lark", icon: "FS",
description: "Feishu/Lark Open Platform adapter",
description: "Feishu/Lark Open Platform adapter (supports China & International)",
category: "enterprise", difficulty: "Easy", setup_time: "~3 min",
quick_setup: "Paste your App ID and App Secret",
setup_type: "form",
fields: &[
ChannelField { key: "app_id", label: "App ID", field_type: FieldType::Text, env_var: None, required: true, placeholder: "cli_abc123", advanced: false },
ChannelField { key: "app_secret_env", label: "App Secret", field_type: FieldType::Secret, env_var: Some("FEISHU_APP_SECRET"), required: true, placeholder: "abc123...", advanced: false },
ChannelField { key: "region", label: "Region", field_type: FieldType::Text, env_var: None, required: false, placeholder: "cn or intl", advanced: false },
ChannelField { key: "webhook_port", label: "Webhook Port", field_type: FieldType::Number, env_var: None, required: false, placeholder: "8453", advanced: true },
ChannelField { key: "webhook_path", label: "Webhook Path", field_type: FieldType::Text, env_var: None, required: false, placeholder: "/feishu/webhook", advanced: true },
ChannelField { key: "verification_token", label: "Verification Token", field_type: FieldType::Text, env_var: None, required: false, placeholder: "verify-token", advanced: true },
ChannelField { key: "encrypt_key_env", label: "Encrypt Key", field_type: FieldType::Secret, env_var: Some("FEISHU_ENCRYPT_KEY"), required: false, placeholder: "encrypt-key", advanced: true },
ChannelField { key: "bot_names", label: "Bot Names", field_type: FieldType::List, env_var: None, required: false, placeholder: "MyBot, Assistant", advanced: true },
ChannelField { key: "default_agent", label: "Default Agent", field_type: FieldType::Text, env_var: None, required: false, placeholder: "assistant", advanced: true },
],
setup_steps: &["Create an app at open.feishu.cn", "Copy App ID and Secret", "Paste them below"],
config_template: "[channels.feishu]\napp_id = \"\"\napp_secret_env = \"FEISHU_APP_SECRET\"",
setup_steps: &["Create an app at open.feishu.cn (CN) or open.larksuite.com (International)", "Copy App ID and Secret", "Set region: cn (Feishu) or intl (Lark)"],
config_template: "[channels.feishu]\napp_id = \"\"\napp_secret_env = \"FEISHU_APP_SECRET\"\nregion = \"cn\"",
},
ChannelMeta {
name: "dingtalk", display_name: "DingTalk", icon: "DT",
File diff suppressed because it is too large Load Diff
+19
View File
@@ -2371,6 +2371,9 @@ impl Default for BlueskyConfig {
}
/// Feishu/Lark Open Platform channel adapter configuration.
///
/// Supports both Feishu (China domestic, `open.feishu.cn`) and Lark
/// (International, `open.larksuite.com`) via the `region` field.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct FeishuConfig {
@@ -2380,6 +2383,17 @@ pub struct FeishuConfig {
pub app_secret_env: String,
/// Port for the incoming webhook.
pub webhook_port: u16,
/// Region: "cn" for Feishu (open.feishu.cn), "intl" for Lark (open.larksuite.com).
pub region: String,
/// Webhook URL path (default: "/feishu/webhook").
pub webhook_path: String,
/// Optional verification token for webhook event validation.
pub verification_token: Option<String>,
/// Env var name holding the encrypt key for event decryption (AES-256-CBC).
pub encrypt_key_env: Option<String>,
/// Bot name aliases for group-chat @mention detection.
#[serde(default)]
pub bot_names: Vec<String>,
/// Default agent name to route messages to.
pub default_agent: Option<String>,
/// Per-channel behavior overrides.
@@ -2393,6 +2407,11 @@ impl Default for FeishuConfig {
app_id: String::new(),
app_secret_env: "FEISHU_APP_SECRET".to_string(),
webhook_port: 8453,
region: "cn".to_string(),
webhook_path: "/feishu/webhook".to_string(),
verification_token: None,
encrypt_key_env: None,
bot_names: Vec::new(),
default_agent: None,
overrides: ChannelOverrides::default(),
}