83 lines
2.4 KiB
Rust
83 lines
2.4 KiB
Rust
use crate::command::context::CommandContext;
|
|
use crate::command::handler::{CommandHandler, CommandMetadata};
|
|
use crate::command::response::{CommandError, CommandResponse};
|
|
use crate::command::Command;
|
|
use crate::protocol::TodoItemSummary;
|
|
use crate::storage::SessionStore;
|
|
use async_trait::async_trait;
|
|
use std::sync::Arc;
|
|
|
|
pub struct ListTodosCommandHandler {
|
|
store: Arc<SessionStore>,
|
|
}
|
|
|
|
impl ListTodosCommandHandler {
|
|
pub fn new(store: Arc<SessionStore>) -> Self {
|
|
Self { store }
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl CommandHandler for ListTodosCommandHandler {
|
|
fn can_handle(&self, cmd: &Command) -> bool {
|
|
matches!(cmd, Command::ListTodos)
|
|
}
|
|
|
|
fn metadata(&self) -> Option<CommandMetadata> {
|
|
Some(CommandMetadata {
|
|
name: "list_todos",
|
|
description: "列出当前 Todo 列表",
|
|
usage: "/list_todos",
|
|
})
|
|
}
|
|
|
|
async fn handle(
|
|
&self,
|
|
_cmd: Command,
|
|
ctx: CommandContext,
|
|
) -> Result<CommandResponse, CommandError> {
|
|
// scope_key = topic_id.unwrap_or(session_id)
|
|
let scope_key = ctx
|
|
.topic_id
|
|
.as_deref()
|
|
.filter(|t| !t.is_empty())
|
|
.or(ctx.session_id.as_deref())
|
|
.ok_or_else(|| {
|
|
CommandError::new(
|
|
"MISSING_CONTEXT",
|
|
"Cannot list todos: no session_id or topic_id in command context",
|
|
)
|
|
})?;
|
|
|
|
let records = self
|
|
.store
|
|
.list_todos(scope_key)
|
|
.map_err(|e| CommandError::new("LIST_TODOS_ERROR", e.to_string()))?;
|
|
|
|
tracing::info!(
|
|
scope_key = %scope_key,
|
|
record_count = records.len(),
|
|
"list_todos handler: reading from store"
|
|
);
|
|
|
|
let summaries: Vec<TodoItemSummary> = records
|
|
.into_iter()
|
|
.map(|r| TodoItemSummary {
|
|
id: r.id,
|
|
content: r.content,
|
|
status: r.status,
|
|
priority: r.priority,
|
|
created_at: r.created_at,
|
|
updated_at: r.updated_at,
|
|
})
|
|
.collect();
|
|
|
|
let todos_json = serde_json::to_string(&summaries)
|
|
.map_err(|e| CommandError::new("SERIALIZE_ERROR", e.to_string()))?;
|
|
|
|
Ok(CommandResponse::success(ctx.request_id)
|
|
.with_metadata("todos", &todos_json)
|
|
.with_metadata("todos_scope_key", scope_key))
|
|
}
|
|
}
|