初步集成消息通道,支持Telegram + Lark机器人

This commit is contained in:
xintaofei
2026-03-30 22:51:49 +08:00
parent 544abbd15d
commit d18cec33bf
44 changed files with 4106 additions and 11 deletions

View File

@@ -0,0 +1,185 @@
use std::sync::Arc;
use axum::{extract::Extension, Json};
use serde::Deserialize;
use crate::app_error::AppCommandError;
use crate::app_state::AppState;
use crate::commands::chat_channel as cc_commands;
use crate::models::chat_channel::{ChannelStatusInfo, ChatChannelInfo, ChatChannelMessageLogInfo};
// ---------------------------------------------------------------------------
// Param structs
// ---------------------------------------------------------------------------
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateChatChannelParams {
pub name: String,
pub channel_type: String,
pub config_json: String,
pub enabled: bool,
pub daily_report_enabled: bool,
pub daily_report_time: Option<String>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateChatChannelParams {
pub id: i32,
pub name: Option<String>,
pub enabled: Option<bool>,
pub config_json: Option<String>,
pub event_filter_json: Option<Option<String>>,
pub daily_report_enabled: Option<bool>,
pub daily_report_time: Option<Option<String>>,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelIdParams {
pub id: i32,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SaveTokenParams {
pub channel_id: i32,
pub token: String,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ChannelIdOnlyParams {
pub channel_id: i32,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListMessagesParams {
pub channel_id: i32,
pub limit: Option<u64>,
pub offset: Option<u64>,
}
// ---------------------------------------------------------------------------
// Handlers
// ---------------------------------------------------------------------------
pub async fn list_chat_channels(
Extension(state): Extension<Arc<AppState>>,
) -> Result<Json<Vec<ChatChannelInfo>>, AppCommandError> {
let result = cc_commands::list_chat_channels_core(&state.db).await?;
Ok(Json(result))
}
pub async fn create_chat_channel(
Extension(state): Extension<Arc<AppState>>,
Json(params): Json<CreateChatChannelParams>,
) -> Result<Json<ChatChannelInfo>, AppCommandError> {
let result = cc_commands::create_chat_channel_core(
&state.db,
params.name,
params.channel_type,
params.config_json,
params.enabled,
params.daily_report_enabled,
params.daily_report_time,
)
.await?;
Ok(Json(result))
}
pub async fn update_chat_channel(
Extension(state): Extension<Arc<AppState>>,
Json(params): Json<UpdateChatChannelParams>,
) -> Result<Json<ChatChannelInfo>, AppCommandError> {
let result = cc_commands::update_chat_channel_core(
&state.db,
params.id,
params.name,
params.enabled,
params.config_json,
params.event_filter_json,
params.daily_report_enabled,
params.daily_report_time,
)
.await?;
Ok(Json(result))
}
pub async fn delete_chat_channel(
Extension(state): Extension<Arc<AppState>>,
Json(params): Json<ChannelIdParams>,
) -> Result<Json<()>, AppCommandError> {
cc_commands::delete_chat_channel_core(&state.db, params.id).await?;
Ok(Json(()))
}
pub async fn save_chat_channel_token(
Json(params): Json<SaveTokenParams>,
) -> Result<Json<()>, AppCommandError> {
cc_commands::save_chat_channel_token_core(params.channel_id, &params.token)?;
Ok(Json(()))
}
pub async fn get_chat_channel_has_token(
Json(params): Json<ChannelIdOnlyParams>,
) -> Result<Json<bool>, AppCommandError> {
let has = cc_commands::get_chat_channel_has_token_core(params.channel_id)?;
Ok(Json(has))
}
pub async fn delete_chat_channel_token(
Json(params): Json<ChannelIdOnlyParams>,
) -> Result<Json<()>, AppCommandError> {
cc_commands::delete_chat_channel_token_core(params.channel_id)?;
Ok(Json(()))
}
pub async fn connect_chat_channel(
Extension(state): Extension<Arc<AppState>>,
Json(params): Json<ChannelIdParams>,
) -> Result<Json<()>, AppCommandError> {
cc_commands::connect_chat_channel_core(&state.db, &state.chat_channel_manager, params.id)
.await?;
Ok(Json(()))
}
pub async fn disconnect_chat_channel(
Extension(state): Extension<Arc<AppState>>,
Json(params): Json<ChannelIdParams>,
) -> Result<Json<()>, AppCommandError> {
cc_commands::disconnect_chat_channel_core(&state.chat_channel_manager, params.id).await?;
Ok(Json(()))
}
pub async fn test_chat_channel(
Extension(state): Extension<Arc<AppState>>,
Json(params): Json<ChannelIdParams>,
) -> Result<Json<()>, AppCommandError> {
cc_commands::test_chat_channel_core(&state.db, params.id).await?;
Ok(Json(()))
}
pub async fn get_chat_channel_status(
Extension(state): Extension<Arc<AppState>>,
) -> Result<Json<Vec<ChannelStatusInfo>>, AppCommandError> {
let result =
cc_commands::get_chat_channel_status_core(&state.chat_channel_manager).await?;
Ok(Json(result))
}
pub async fn list_chat_channel_messages(
Extension(state): Extension<Arc<AppState>>,
Json(params): Json<ListMessagesParams>,
) -> Result<Json<Vec<ChatChannelMessageLogInfo>>, AppCommandError> {
let result = cc_commands::list_chat_channel_messages_core(
&state.db,
params.channel_id,
params.limit,
params.offset,
)
.await?;
Ok(Json(result))
}

View File

@@ -1,13 +1,14 @@
mod error;
pub mod acp;
pub mod chat_channel;
pub mod conversations;
pub mod files;
pub mod folders;
pub mod acp;
pub mod terminal;
pub mod system_settings;
pub mod version_control;
pub mod folder_commands;
pub mod mcp;
pub mod folders;
pub mod git;
pub mod mcp;
pub mod project_boot;
pub mod system_settings;
pub mod terminal;
pub mod version_control;
pub mod web_server;

View File

@@ -245,6 +245,7 @@ pub async fn start_web_server(
emitter: crate::web::event_bridge::EventEmitter::Tauri(app.clone()),
data_dir: app.path().app_data_dir().unwrap_or_default(),
web_server_state: WebServerState::new(), // placeholder; not used by handlers
chat_channel_manager: crate::app_state::default_chat_channel_manager(),
});
let router = router::build_router(app_state, token.clone(), static_dir);

View File

@@ -180,6 +180,19 @@ pub fn build_router(state: Arc<AppState>, token: String, static_dir: std::path::
.route("/start_web_server", post(handlers::web_server::start_web_server))
.route("/stop_web_server", post(handlers::web_server::stop_web_server))
.route("/check_app_update", post(handlers::web_server::check_app_update))
// ─── Chat Channels ───
.route("/list_chat_channels", post(handlers::chat_channel::list_chat_channels))
.route("/create_chat_channel", post(handlers::chat_channel::create_chat_channel))
.route("/update_chat_channel", post(handlers::chat_channel::update_chat_channel))
.route("/delete_chat_channel", post(handlers::chat_channel::delete_chat_channel))
.route("/save_chat_channel_token", post(handlers::chat_channel::save_chat_channel_token))
.route("/get_chat_channel_has_token", post(handlers::chat_channel::get_chat_channel_has_token))
.route("/delete_chat_channel_token", post(handlers::chat_channel::delete_chat_channel_token))
.route("/connect_chat_channel", post(handlers::chat_channel::connect_chat_channel))
.route("/disconnect_chat_channel", post(handlers::chat_channel::disconnect_chat_channel))
.route("/test_chat_channel", post(handlers::chat_channel::test_chat_channel))
.route("/get_chat_channel_status", post(handlers::chat_channel::get_chat_channel_status))
.route("/list_chat_channel_messages", post(handlers::chat_channel::list_chat_channel_messages))
// ─── Terminal ───
.route("/terminal_spawn", post(handlers::terminal::terminal_spawn))
.route("/terminal_write", post(handlers::terminal::terminal_write))