From 945c34590677e161a711ccaff0e1077197b1b178 Mon Sep 17 00:00:00 2001 From: Doot Agent Date: Mon, 6 Jul 2026 00:00:59 +0000 Subject: feat: remove Todoist integration entirely Native tasks (native_tasks table) fully replace Todoist. All Todoist API code, store functions, handlers, routes, templates, and tests have been removed. Migration 021 drops the now-unused tasks cache table. Co-Authored-By: Claude Sonnet 4.6 --- internal/store/sqlite.go | 241 ++--------------------------------------------- 1 file changed, 6 insertions(+), 235 deletions(-) (limited to 'internal/store/sqlite.go') diff --git a/internal/store/sqlite.go b/internal/store/sqlite.go index f9c9a6b..a6e9fd4 100644 --- a/internal/store/sqlite.go +++ b/internal/store/sqlite.go @@ -2,7 +2,6 @@ package store import ( "database/sql" - "encoding/json" "errors" "fmt" "log" @@ -19,11 +18,10 @@ import ( // Cache key constants const ( - CacheKeyTodoistTasks = "todoist_tasks" - CacheKeyTrelloBoards = "trello_boards" - CacheKeyPlanToEatMeals = "plantoeat_meals" - CacheKeyGoogleCalendar = "google_calendar" - CacheKeyGoogleTasks = "google_tasks" + CacheKeyTrelloBoards = "trello_boards" + CacheKeyPlanToEatMeals = "plantoeat_meals" + CacheKeyGoogleCalendar = "google_calendar" + CacheKeyGoogleTasks = "google_tasks" ) type Store struct { @@ -139,177 +137,6 @@ func (s *Store) runMigrations() error { return nil } -// Tasks operations - -// scanTask scans a single task row from the database -func scanTask(rows *sql.Rows) (models.Task, error) { - var task models.Task - var labelsJSON string - var dueDate sql.NullTime - - err := rows.Scan( - &task.ID, - &task.Content, - &task.Description, - &task.ProjectID, - &task.ProjectName, - &dueDate, - &task.Priority, - &task.Completed, - &labelsJSON, - &task.URL, - &task.CreatedAt, - ) - if err != nil { - return task, err - } - - if dueDate.Valid { - task.DueDate = &dueDate.Time - } - - if err := json.Unmarshal([]byte(labelsJSON), &task.Labels); err != nil { - log.Printf("Warning: failed to unmarshal labels for task %s: %v", task.ID, err) - task.Labels = []string{} - } - return task, nil -} - -// scanTasks scans multiple task rows from the database -func scanTasks(rows *sql.Rows) ([]models.Task, error) { - var tasks []models.Task - for rows.Next() { - task, err := scanTask(rows) - if err != nil { - return nil, err - } - tasks = append(tasks, task) - } - return tasks, rows.Err() -} - -// SaveTasks saves multiple tasks to the database -func (s *Store) SaveTasks(tasks []models.Task) error { - tx, err := s.db.Begin() - if err != nil { - return err - } - defer func() { _ = tx.Rollback() }() - - // Clear existing tasks first to remove stale data - if _, err := tx.Exec(`DELETE FROM tasks`); err != nil { - return err - } - - stmt, err := tx.Prepare(` - INSERT OR REPLACE INTO tasks - (id, content, description, project_id, project_name, due_date, priority, completed, labels, url, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) - `) - if err != nil { - return err - } - defer func() { _ = stmt.Close() }() - - for _, task := range tasks { - labelsJSON, err := json.Marshal(task.Labels) - if err != nil { - log.Printf("Warning: failed to marshal labels for task %s: %v", task.ID, err) - labelsJSON = []byte("[]") - } - _, err = stmt.Exec( - task.ID, - task.Content, - task.Description, - task.ProjectID, - task.ProjectName, - task.DueDate, - task.Priority, - task.Completed, - string(labelsJSON), - task.URL, - task.CreatedAt, - ) - if err != nil { - return err - } - } - - return tx.Commit() -} - -// GetTasks retrieves all tasks from the database -func (s *Store) GetTasks() ([]models.Task, error) { - rows, err := s.db.Query(` - SELECT id, content, description, project_id, project_name, due_date, priority, completed, labels, url, created_at - FROM tasks - ORDER BY completed ASC, CASE WHEN due_date IS NULL THEN 1 ELSE 0 END, due_date ASC, priority DESC - `) - if err != nil { - return nil, err - } - defer func() { _ = rows.Close() }() - return scanTasks(rows) -} - -// DeleteTask removes a task from the cache by ID -func (s *Store) DeleteTask(id string) error { - _, err := s.db.Exec(`DELETE FROM tasks WHERE id = ?`, id) - return err -} - -// UpsertTask inserts or updates a single task -func (s *Store) UpsertTask(task models.Task) error { - labelsJSON, err := json.Marshal(task.Labels) - if err != nil { - log.Printf("Warning: failed to marshal labels for task %s: %v", task.ID, err) - labelsJSON = []byte("[]") - } - _, err = s.db.Exec(` - INSERT OR REPLACE INTO tasks - (id, content, description, project_id, project_name, due_date, priority, completed, labels, url, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) - `, - task.ID, - task.Content, - task.Description, - task.ProjectID, - task.ProjectName, - task.DueDate, - task.Priority, - task.Completed, - string(labelsJSON), - task.URL, - task.CreatedAt, - ) - return err -} - -// DeleteTasksByIDs removes multiple tasks by ID -func (s *Store) DeleteTasksByIDs(ids []string) error { - if len(ids) == 0 { - return nil - } - tx, err := s.db.Begin() - if err != nil { - return err - } - defer func() { _ = tx.Rollback() }() - - stmt, err := tx.Prepare(`DELETE FROM tasks WHERE id = ?`) - if err != nil { - return err - } - defer func() { _ = stmt.Close() }() - - for _, id := range ids { - if _, err := stmt.Exec(id); err != nil { - return err - } - } - return tx.Commit() -} - // Meals operations // SaveMeals saves multiple meals to the database @@ -707,38 +534,6 @@ func (s *Store) GetShoppingItemChecks(source string) (map[string]bool, error) { return checks, rows.Err() } -// GetTasksByDateRange retrieves tasks due within a specific date range, -// including overdue tasks (due before start) so they appear in the timeline. -func (s *Store) GetTasksByDateRange(start, end time.Time) ([]models.Task, error) { - rows, err := s.db.Query(` - SELECT id, content, description, project_id, project_name, due_date, priority, completed, labels, url, created_at - FROM tasks - WHERE due_date IS NOT NULL AND due_date <= ? - AND completed = FALSE - ORDER BY due_date ASC, priority DESC - `, end) - if err != nil { - return nil, err - } - defer func() { _ = rows.Close() }() - return scanTasks(rows) -} - -// GetUndatedTasks retrieves incomplete tasks with no due date. -func (s *Store) GetUndatedTasks() ([]models.Task, error) { - rows, err := s.db.Query(` - SELECT id, content, description, project_id, project_name, due_date, priority, completed, labels, url, created_at - FROM tasks - WHERE due_date IS NULL AND completed = FALSE - ORDER BY priority DESC, created_at ASC - `) - if err != nil { - return nil, err - } - defer func() { _ = rows.Close() }() - return scanTasks(rows) -} - // GetMealsByDateRange retrieves meals within a specific date range func (s *Store) GetMealsByDateRange(start, end time.Time) ([]models.Meal, error) { return s.GetMeals(start, end) @@ -1508,35 +1303,11 @@ func (s *Store) SyncSourceConfigs(source, itemType string, items []models.Source // InvalidateAllCaches removes cache metadata for all known cache keys func (s *Store) InvalidateAllCaches() error { - _, err := s.db.Exec(`DELETE FROM cache_metadata WHERE key IN (?, ?, ?, ?, ?)`, - CacheKeyTodoistTasks, CacheKeyTrelloBoards, CacheKeyPlanToEatMeals, CacheKeyGoogleCalendar, CacheKeyGoogleTasks) + _, err := s.db.Exec(`DELETE FROM cache_metadata WHERE key IN (?, ?, ?, ?)`, + CacheKeyTrelloBoards, CacheKeyPlanToEatMeals, CacheKeyGoogleCalendar, CacheKeyGoogleTasks) return err } -// GetProjectsFromTasks returns distinct projects from the tasks table -func (s *Store) GetProjectsFromTasks() ([]models.Project, error) { - rows, err := s.db.Query(` - SELECT DISTINCT project_id, project_name - FROM tasks - WHERE project_id != '' - ORDER BY project_name - `) - if err != nil { - return nil, err - } - defer func() { _ = rows.Close() }() - - var projects []models.Project - for rows.Next() { - var p models.Project - if err := rows.Scan(&p.ID, &p.Name); err != nil { - return nil, err - } - projects = append(projects, p) - } - return projects, rows.Err() -} - // Feature toggles // GetFeatureToggles returns all feature toggles -- cgit v1.2.3