107 lines
3.3 KiB
Rust
107 lines
3.3 KiB
Rust
use crate::command::context::CommandContext;
|
|
use crate::command::handler::{CommandHandler, CommandMetadata};
|
|
use crate::command::response::{CommandError, CommandResponse, MessageKind};
|
|
use crate::command::Command;
|
|
use crate::storage::SessionStore;
|
|
use async_trait::async_trait;
|
|
use std::sync::Arc;
|
|
|
|
/// 列出话题命令处理器
|
|
pub struct ListSessionsCommandHandler {
|
|
store: Arc<SessionStore>,
|
|
}
|
|
|
|
impl ListSessionsCommandHandler {
|
|
pub fn new(store: Arc<SessionStore>) -> Self {
|
|
Self { store }
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl CommandHandler for ListSessionsCommandHandler {
|
|
fn can_handle(&self, cmd: &Command) -> bool {
|
|
matches!(cmd, Command::ListSessions { .. })
|
|
}
|
|
|
|
fn metadata(&self) -> Option<CommandMetadata> {
|
|
Some(CommandMetadata {
|
|
name: "list",
|
|
description: "列出所有话题",
|
|
usage: "/list [all]",
|
|
})
|
|
}
|
|
|
|
async fn handle(
|
|
&self,
|
|
cmd: Command,
|
|
ctx: CommandContext,
|
|
) -> Result<CommandResponse, CommandError> {
|
|
match cmd {
|
|
Command::ListSessions { include_archived } => {
|
|
handle_list_sessions(self, include_archived, ctx).await
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn handle_list_sessions(
|
|
handler: &ListSessionsCommandHandler,
|
|
_include_archived: bool,
|
|
ctx: CommandContext,
|
|
) -> Result<CommandResponse, CommandError> {
|
|
let session_id = ctx.session_id.as_deref()
|
|
.ok_or_else(|| CommandError::new("NO_SESSION", "No active session"))?;
|
|
|
|
let topics = handler
|
|
.store
|
|
.list_topics(session_id)
|
|
.map_err(|e| CommandError::new("LIST_TOPICS_ERROR", e.to_string()))?;
|
|
|
|
let current_topic_id = ctx.topic_id.as_deref().unwrap_or("");
|
|
|
|
let message = if topics.is_empty() {
|
|
"No topics found. Use /new <title> to create a topic.".to_string()
|
|
} else {
|
|
let mut lines = vec![format!("Found {} topic(s):", topics.len())];
|
|
lines.push(String::new());
|
|
|
|
for (idx, topic) in topics.iter().enumerate() {
|
|
let num = idx + 1;
|
|
let is_current = topic.id == current_topic_id;
|
|
let marker = if is_current { " *" } else { "" };
|
|
|
|
// 使用辅助方法获取消息数量
|
|
let msg_count = handler.store
|
|
.get_topic_message_count(&topic.id)
|
|
.unwrap_or(0);
|
|
|
|
lines.push(format!(
|
|
"{}. {}{} ({})",
|
|
num, topic.title, marker, msg_count
|
|
));
|
|
|
|
// 显示描述(如果有)
|
|
if let Some(ref desc) = topic.description {
|
|
if !desc.is_empty() {
|
|
lines.push(format!(" {}", desc));
|
|
}
|
|
}
|
|
}
|
|
|
|
lines.push(String::new());
|
|
lines.push("* = current topic".to_string());
|
|
lines.push("Use /use <number> to switch".to_string());
|
|
|
|
lines.join("\n")
|
|
};
|
|
|
|
let topics_json = serde_json::to_string(&topics)
|
|
.map_err(|e| CommandError::new("SERIALIZE_ERROR", e.to_string()))?;
|
|
|
|
Ok(CommandResponse::success(ctx.request_id)
|
|
.with_message(MessageKind::Notification, &message)
|
|
.with_metadata("topics", &topics_json)
|
|
.with_metadata("count", &topics.len().to_string())
|
|
.with_metadata("current_topic_id", current_topic_id))
|
|
} |