هذا الالتزام موجود في:
2025-12-19 13:59:48 +03:00
التزام dc8a03e647
4 ملفات معدلة مع 570 إضافات و0 حذوفات

233
database.py Normal file
عرض الملف

@@ -0,0 +1,233 @@
"""
SQLite database manager for TODO MCP server.
"""
import sqlite3
from datetime import datetime
from typing import List, Dict, Any, Optional
from pathlib import Path
from date_utils import parse_relative_date, get_date_for_query
class TodoDatabase:
"""Manages SQLite database for TODO items"""
def __init__(self, db_path: str = "todos.db"):
"""
Initialize database connection.
Args:
db_path: Path to SQLite database file
"""
self.db_path = db_path
self.conn = None
self._init_database()
def _init_database(self):
"""Create database and tables if they don't exist"""
self.conn = sqlite3.connect(self.db_path, check_same_thread=False)
self.conn.row_factory = sqlite3.Row # Return rows as dictionaries
cursor = self.conn.cursor()
cursor.execute(
"""
CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
description TEXT,
created_date TEXT NOT NULL,
due_date TEXT,
status TEXT NOT NULL DEFAULT 'pending',
completed_date TEXT
)
"""
)
self.conn.commit()
def create_todo(
self,
title: str,
description: str = "",
relative_days: Optional[int] = None,
) -> Dict[str, Any]:
"""
Create a new TODO item.
Args:
title: TODO title
description: TODO description
relative_days: Relative due date (0=today, +1=tomorrow, -1=yesterday, etc.)
Returns:
Created TODO item as dictionary
"""
created_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Convert relative days to absolute date
due_date = get_date_for_query(relative_days)
cursor = self.conn.cursor()
cursor.execute(
"""
INSERT INTO todos (title, description, created_date, due_date, status)
VALUES (?, ?, ?, ?, 'pending')
""",
(title, description, created_date, due_date),
)
self.conn.commit()
todo_id = cursor.lastrowid
return self.get_todo(todo_id)
def get_todo(self, todo_id: int) -> Optional[Dict[str, Any]]:
"""
Get a TODO by ID.
Args:
todo_id: TODO ID
Returns:
TODO item as dictionary or None if not found
"""
cursor = self.conn.cursor()
cursor.execute("SELECT * FROM todos WHERE id = ?", (todo_id,))
row = cursor.fetchone()
if row:
return dict(row)
return None
def list_todos(
self,
relative_days: Optional[int] = None,
status: Optional[str] = None,
) -> List[Dict[str, Any]]:
"""
List TODO items with optional filtering.
Args:
relative_days: Filter by relative due date (0=today, +1=tomorrow, etc.)
status: Filter by status ('pending', 'completed')
Returns:
List of TODO items
"""
query = "SELECT * FROM todos WHERE 1=1"
params = []
if relative_days is not None:
# Convert relative days to absolute date for filtering
date = parse_relative_date(relative_days)
query += " AND due_date LIKE ?"
params.append(f"{date}%")
if status:
query += " AND status = ?"
params.append(status)
query += " ORDER BY due_date ASC, created_date ASC"
cursor = self.conn.cursor()
cursor.execute(query, params)
rows = cursor.fetchall()
return [dict(row) for row in rows]
def update_todo(
self,
todo_id: int,
title: Optional[str] = None,
description: Optional[str] = None,
relative_days: Optional[int] = None,
) -> Optional[Dict[str, Any]]:
"""
Update a TODO item.
Args:
todo_id: TODO ID
title: New title (optional)
description: New description (optional)
relative_days: New relative due date (optional, 0=today, +1=tomorrow, etc.)
Returns:
Updated TODO item or None if not found
"""
# Build dynamic update query
updates = []
params = []
if title is not None:
updates.append("title = ?")
params.append(title)
if description is not None:
updates.append("description = ?")
params.append(description)
if relative_days is not None:
# Convert relative days to absolute date
due_date = parse_relative_date(relative_days)
updates.append("due_date = ?")
params.append(due_date)
if not updates:
return self.get_todo(todo_id)
params.append(todo_id)
query = f"UPDATE todos SET {', '.join(updates)} WHERE id = ?"
cursor = self.conn.cursor()
cursor.execute(query, params)
self.conn.commit()
if cursor.rowcount > 0:
return self.get_todo(todo_id)
return None
def mark_complete(self, todo_id: int) -> Optional[Dict[str, Any]]:
"""
Mark a TODO as completed.
Args:
todo_id: TODO ID
Returns:
Updated TODO item or None if not found
"""
completed_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
cursor = self.conn.cursor()
cursor.execute(
"""
UPDATE todos
SET status = 'completed', completed_date = ?
WHERE id = ?
""",
(completed_date, todo_id),
)
self.conn.commit()
if cursor.rowcount > 0:
return self.get_todo(todo_id)
return None
def delete_todo(self, todo_id: int) -> bool:
"""
Delete a TODO item.
Args:
todo_id: TODO ID
Returns:
True if deleted, False if not found
"""
cursor = self.conn.cursor()
cursor.execute("DELETE FROM todos WHERE id = ?", (todo_id,))
self.conn.commit()
return cursor.rowcount > 0
def close(self):
"""Close database connection"""
if self.conn:
self.conn.close()