From 7a559767e1632e56c3ce860dfb51987abd11d6e4 Mon Sep 17 00:00:00 2001 From: Amp Date: Sat, 26 Sep 2026 21:07:01 +0000 Subject: [PATCH 1/3] fix(docs): call Todoist API v1 directly in the Todoist example script The example relied on the Todoist plugin's internal api object, which no longer exposes getTasks/getProjects/getSections/closeTask, and Todoist's REST v2 API now returns 410 Gone. The script now calls https://api.todoist.com/api/v1 with a token from a QuickAdd secret setting, follows cursor pagination, and makes completing imported tasks an opt-out checkbox. Amp-Thread-ID: https://ampcode.com/threads/T-01a0df6d-45d0-75e7-8b10-3ce80c6ed75d Co-authored-by: Christian Bager Bach Houmann --- docs/public/scripts/TodoistScript.js | 215 +++++++++------ .../Examples/Capture_FetchTasksFromTodoist.md | 46 ++-- .../Images/Todoist-GetAllTasksFromProject.png | Bin 28559 -> 0 bytes .../docs/Images/Todoist-ScriptSettings.png | Bin 0 -> 78576 bytes tests/examples/todoistScript.test.ts | 249 ++++++++++++++++++ 5 files changed, 414 insertions(+), 96 deletions(-) delete mode 100644 docs/src/content/docs/docs/Images/Todoist-GetAllTasksFromProject.png create mode 100644 docs/src/content/docs/docs/Images/Todoist-ScriptSettings.png create mode 100644 tests/examples/todoistScript.test.ts diff --git a/docs/public/scripts/TodoistScript.js b/docs/public/scripts/TodoistScript.js index ca26d327f..28cc57a38 100644 --- a/docs/public/scripts/TodoistScript.js +++ b/docs/public/scripts/TodoistScript.js @@ -1,99 +1,164 @@ -module.exports = {SelectFromAllTasks, GetAllTasksFromProject, GetAllTasksFromSection}; - -const getTodoistPluginApi = (app) => app.plugins.plugins["todoist-sync-plugin"].api; - -/* API */ -async function SelectFromAllTasks(params) { - const tasks = await getAllTasks(params); +// Imports Todoist tasks into a note as Tasks-plugin checklist items. +// Talks to the Todoist API v1 directly: https://developer.todoist.com/api/v1/ +// Docs: https://quickadd.obsidian.guide/docs/Examples/Capture_FetchTasksFromTodoist +const API_TOKEN = "Todoist API token"; +const COMPLETE_TASKS = "Complete imported tasks in Todoist"; +const TODOIST_API = "https://api.todoist.com/api/v1"; + +module.exports = { + entry: async (params, settings) => { + const exports = {SelectFromAllTasks, GetAllTasksFromProject, GetAllTasksFromSection}; + const names = Object.keys(exports); + const selected = await params.quickAddApi.suggester(names, names, "Import Todoist tasks"); + if (!selected) return ""; + return exports[selected](params, settings); + }, + settings: { + name: "Todoist", + author: "Christian B. B. Houmann", + options: { + [API_TOKEN]: { + type: "secret", + id: "todoist-api-token", + placeholder: "Paste API token", + description: "From Todoist's Developer settings.", + }, + [COMPLETE_TASKS]: { + type: "checkbox", + defaultValue: true, + description: "Mark each imported task as complete in Todoist, so it is only imported once.", + }, + }, + }, + SelectFromAllTasks, + GetAllTasksFromProject, + GetAllTasksFromSection, +}; + +/* Exports */ +async function SelectFromAllTasks(params, settings) { + const todoist = createTodoistClient(params, settings); + const tasks = await todoist.getAll("/tasks"); if (tasks.length === 0) { - new Notice("No tasks."); - return; + new params.obsidian.Notice("No tasks in Todoist."); + return ""; } - const selectedTasks = await selectTasks(params, tasks); - await closeSelectedTasks(params.app, selectedTasks); - return formatTasksToTasksPluginTask(selectedTasks); -} + const labels = tasks.map((task, index) => `${index + 1}. ${task.content}`); + const selectedLabels = await params.quickAddApi.checkboxPrompt(labels); + const selectedTasks = tasks.filter((_, index) => selectedLabels.includes(labels[index])); -async function GetAllTasksFromProject(params) { - const [allTasks, projects] = await Promise.all([getAllTasks(params), getProjects(params.app)]); - const targetProject = await params.quickAddApi.suggester(project => { - project.tasks = allTasks.filter(task => task.projectID === project.id); + return importTasks(params, settings, todoist, selectedTasks, "your selection"); +} - return `${project.name} (${project.tasks.length})`; - }, projects); - if (!targetProject) return; +async function GetAllTasksFromProject(params, settings) { + const todoist = createTodoistClient(params, settings); + const [projects, tasks] = await Promise.all([todoist.getAll("/projects"), todoist.getAll("/tasks")]); + const tasksIn = (project) => tasks.filter(task => task.project_id === project.id); - if (targetProject.tasks.length === 0) { - new Notice(`No tasks in '${targetProject.name}'.`); - return; - } else { - new Notice(`Added ${targetProject.tasks.length} tasks from '${targetProject.name}'.`) - } + const project = await params.quickAddApi.suggester( + projects.map(project => `${project.name} (${tasksIn(project).length})`), + projects, + "Import all tasks from project", + ); + if (!project) return ""; - await closeSelectedTasks(params.app, targetProject.tasks); - return formatTasksToTasksPluginTask(targetProject.tasks); + return importTasks(params, settings, todoist, tasksIn(project), `'${project.name}'`); } -async function GetAllTasksFromSection(params) { - const [projects, sections, allTasks] = await Promise.all([getProjects(params.app), getSections(params.app), getAllTasks(params)]); - - const targetSection = await params.quickAddApi.suggester(section => { - const sectionProject = projects.find(project => project.id === section["project_id"]); - section.tasks = allTasks.filter(task => task.sectionID === section.id); - return `${sectionProject.name} > ${section.name} (${section.tasks.length})`; - }, sections); +async function GetAllTasksFromSection(params, settings) { + const todoist = createTodoistClient(params, settings); + const [projects, sections, tasks] = await Promise.all([ + todoist.getAll("/projects"), + todoist.getAll("/sections"), + todoist.getAll("/tasks"), + ]); + const tasksIn = (section) => tasks.filter(task => task.section_id === section.id); + const projectName = (section) => projects.find(project => project.id === section.project_id)?.name ?? "?"; + + const section = await params.quickAddApi.suggester( + sections.map(section => `${projectName(section)} > ${section.name} (${tasksIn(section).length})`), + sections, + "Import all tasks from section", + ); + if (!section) return ""; + + return importTasks(params, settings, todoist, tasksIn(section), `'${section.name}'`); +} - if (targetSection.tasks.length === 0) { - new Notice(`No tasks in '${targetSection.name}'.`); - return; - } else { - new Notice(`Added ${targetSection.tasks.length} tasks from '${targetSection.name}'.`) +/* Helpers */ +async function importTasks(params, settings, todoist, tasks, sourceName) { + if (tasks.length === 0) { + new params.obsidian.Notice(`No tasks in ${sourceName}.`); + return ""; } - await closeSelectedTasks(targetSection.tasks); - return formatTasksToTasksPluginTask(targetSection.tasks); -} + // Format before completing: a recurring task gets a new due date when completed. + const output = formatTasksToTasksPluginTask(tasks); -/* Helpers */ -async function getAllTasks(params) { - const api = getTodoistPluginApi(params.app); - const {ok: tasks} = await api.getTasks(); - return tasks; -} + // IMPORTANT: this completes the imported tasks in Todoist. + // Untick "Complete imported tasks in Todoist" in the script settings to keep them open. + if (settings[COMPLETE_TASKS]) await closeSelectedTasks(todoist, tasks); -async function selectTasks(params, tasks) { - const selectedTaskNames = await params.quickAddApi.checkboxPrompt(tasks.map(task => task.content)); - return tasks.filter(task => selectedTaskNames.some(t => t.contains(task.content))); + new params.obsidian.Notice(`Added ${tasks.length} ${tasks.length === 1 ? "task" : "tasks"} from ${sourceName}.`); + return output; } -async function closeSelectedTasks(app, tasks) { - const api = getTodoistPluginApi(app); - tasks.forEach(async task => await api.closeTask(task.id)); +async function closeSelectedTasks(todoist, tasks) { + for (const task of tasks) { + await todoist.request("POST", `/tasks/${task.id}/close`); + } } function formatTasksToTasksPluginTask(tasks) { - return tasks.map(task => - task.rawDatetime ? - task = `- [ ] ${task.content} 📅 ${task.rawDatetime.format("YYYY-MM-DD")}` : - task = `- [ ] ${task.content}` - ).join("\n") + "\n"; + return tasks.map(task => { + const dueDate = formatDueDate(task.due); + return dueDate ? `- [ ] ${task.content} 📅 ${dueDate}` : `- [ ] ${task.content}`; + }).join("\n") + "\n"; } -async function getTasksGroupedByProject(app) { - const api = getTodoistPluginApi(app); - const {ok: projects} = await api.getTasksGroupedByProject(); - return projects; +// `due.date` is "YYYY-MM-DD", a floating "YYYY-MM-DDTHH:mm:ss", or a UTC +// "YYYY-MM-DDTHH:mm:ssZ" for tasks with a fixed time zone. +function formatDueDate(due) { + if (!due?.date) return null; + if (due.date.endsWith("Z")) return window.moment(due.date).format("YYYY-MM-DD"); + return due.date.slice(0, 10); } -async function getProjects(app) { - const api = getTodoistPluginApi(app); - const {ok: projects} = await api.getProjects(); - return projects; -} +function createTodoistClient(params, settings) { + const token = settings[API_TOKEN]; + if (!token) { + throw new Error("Add your Todoist API token in the Todoist script's settings (the gear next to the script in your macro)."); + } -async function getSections(app) { - const api = getTodoistPluginApi(app); - const {ok: sections} = await api.getSections(); - return sections; -} \ No newline at end of file + async function request(method, path) { + const response = await params.obsidian.requestUrl({ + url: `${TODOIST_API}${path}`, + method, + headers: {Authorization: `Bearer ${token}`}, + throw: false, + }); + if (response.status === 401 || response.status === 403) { + throw new Error(`Todoist rejected the API token (HTTP ${response.status}). Check the token in the Todoist script's settings.`); + } + if (response.status >= 400) { + throw new Error(`Todoist request ${method} ${path.split("?")[0]} failed with HTTP ${response.status}.`); + } + return response.text ? response.json : null; + } + + // List endpoints are paginated: follow `next_cursor` until it is null. + async function getAll(path) { + const results = []; + let cursor = null; + do { + const query = `?limit=200${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}`; + const page = await request("GET", `${path}${query}`); + results.push(...page.results); + cursor = page.next_cursor; + } while (cursor); + return results; + } + + return {request, getAll}; +} diff --git a/docs/src/content/docs/docs/Examples/Capture_FetchTasksFromTodoist.md b/docs/src/content/docs/docs/Examples/Capture_FetchTasksFromTodoist.md index fa72c1196..bb54ae370 100644 --- a/docs/src/content/docs/docs/Examples/Capture_FetchTasksFromTodoist.md +++ b/docs/src/content/docs/docs/Examples/Capture_FetchTasksFromTodoist.md @@ -8,8 +8,9 @@ You end up with one QuickAdd command that pulls tasks from your Todoist account ## Prerequisites -- The [Todoist](https://github.com/jamiebrynes7/obsidian-todoist-plugin) plugin for Obsidian, set up with your API key. There is a link to grab the key in the plugin's settings. -- A [macro](/docs/Choices/MacroChoice/) that runs the Todoist Script (set up below). +- A Todoist API token. In Todoist, open **Settings → Integrations → Developer** and copy the **API token**. The script talks to the [Todoist API](https://developer.todoist.com/api/v1/) directly, so you don't need the Todoist plugin for Obsidian. +- The Todoist Script, saved in your vault as a `.js` file, for example `scripts/todoistTaskSync.js`. Don't save it inside the `.obsidian` folder - QuickAdd ignores scripts there. +- A [macro](/docs/Choices/MacroChoice/) that runs the script, and a [Capture choice](/docs/Choices/CaptureChoice/) that writes its output to a note (set up below). ## How it works @@ -19,41 +20,44 @@ The Todoist Script has three exports, `SelectFromAllTasks`, `GetAllTasksFromProj - `GetAllTasksFromProject` will prompt you for a project and get all tasks from that project, and - `GetAllTasksFromSection` will prompt you for a section and get all tasks from that section. -Personally, I just let QuickAdd ask me which one to execute. +If you run the macro as-is, the script asks you which one to run. To always run one of them, reference it in the Capture format with `::`, for example `{{MACRO:Todoist::GetAllTasksFromProject}}`. -However, when you are entering the user script in the macro, you can add `::GetAllTasksFromProject` (or, `::` followed by any of the other exports) to directly call one of the exported functions. +:::caution[Imported tasks are completed in Todoist] +By default, the script completes every task it imports, so the same task isn't imported twice. Recurring tasks move to their next occurrence instead. To keep the tasks open in Todoist, untick **Complete imported tasks in Todoist** in the script's settings. +::: -![Get all tasks from project](../Images/Todoist-GetAllTasksFromProject.png) +## Setup -**IMPORTANT:** If you do _NOT_ want this script to complete tasks in Todoist that you put into your vault, remove the function call to `closeSelectedTasks`. +1. Save the Todoist Script to your vault, for example as `scripts/todoistTaskSync.js`. +2. In **Settings → QuickAdd**, add a [Macro choice](/docs/Choices/MacroChoice/) named `Todoist`, and add the script to its command list. Add the script by its file name only - don't add `::GetAllTasksFromProject` there, because the script's settings are only available when the command points at the whole script. +3. Click the gear (⚙️) next to the script command, and paste your Todoist API token into **Todoist API token**. QuickAdd keeps it in Obsidian's secret storage, not in `data.json`. Leave **Complete imported tasks in Todoist** ticked, or untick it to leave tasks open in Todoist. -Now, you will need a [Capture choice](/docs/Choices/CaptureChoice/) with the following settings. + ![Todoist script settings](../Images/Todoist-ScriptSettings.png) -- _Capture to:_ the path to the file where you want to store the tasks. -- _Capture format:_ Enabled - and in the format, write `{{MACRO:}}` where `MACRONAME` is the name of the macro that you made earlier. +4. Add a [Capture choice](/docs/Choices/CaptureChoice/) with these settings: + - _Capture to:_ the path to the file where you want to store the tasks. + - _Capture format:_ Enabled - and in the format, write `{{MACRO:Todoist}}` to be asked which export to run, or `{{MACRO:Todoist::GetAllTasksFromProject}}` (or any of the other exports) to run that one directly. + +You can make one Capture choice per export, so each has its own command. ## What you get The tasks are written in this format: -`- [ ] 📆 ` +`- [ ] 📅 ` -Which equals: `- [ ] Buy groceries 📆 2021-06-27` +Which equals: `- [ ] Buy groceries 📅 2021-06-27` This task will be recognized by the Tasks plugin for Obsidian, as well. If there isn't a date set for the task, they'll simply be entered as `- [ ] Buy groceries`. -### Steps - -_NOTE:_ If you simply follow the process below, you will be asked which export to execute each time. -That is fine - if you want to be asked - but you can also make separate [Capture choices](/docs/Choices/CaptureChoice/) for each exported function, meaning, it'll execute that function without asking you which one to execute. -Just set up the macro as shown in the image above. +## Troubleshooting -1. Set up the Todoist plugin - grab the API key from your Todoist account. There's a link in the plugin's settings. -2. Download the Todoist Script (linked above) and add it to your vault as a javascript file. I'd encourage you to call it something like todoistTaskSync.js to be explicit. -3. Follow along with what I do in the gif below - -![GKkCNWZHLv](https://user-images.githubusercontent.com/29108628/123500983-26ad2880-d642-11eb-9e45-b537271312d1.gif) +- **"Add your Todoist API token in the Todoist script's settings"**: open the macro, click the gear next to the script command, and paste the token. If the script command's name ends in `::SomeExport`, remove that part so the gear shows the settings. +- **"Todoist rejected the API token (HTTP 401)"**: the token is wrong or was reset. Copy it again from Todoist's Developer settings. +- **"Secret setting ... is unavailable. Re-enter it on this device."**: secrets are stored per device. Paste the token again on this device. ### Installation video +This older video shows the general flow of adding a user script to a macro and a Capture choice. It predates the API token setting: instead of setting up the Todoist plugin, paste your token in the script's settings as described above. + https://user-images.githubusercontent.com/29108628/123511101-bde4a100-d67f-11eb-90c1-5bd146c5d0f2.mp4 diff --git a/docs/src/content/docs/docs/Images/Todoist-GetAllTasksFromProject.png b/docs/src/content/docs/docs/Images/Todoist-GetAllTasksFromProject.png deleted file mode 100644 index 61771624be3e8a256330ddfe7816a053d339bdb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28559 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 F{{wcJ3IPBB literal 0 HcmV?d00001 diff --git a/tests/examples/todoistScript.test.ts b/tests/examples/todoistScript.test.ts new file mode 100644 index 000000000..aa5bc0b19 --- /dev/null +++ b/tests/examples/todoistScript.test.ts @@ -0,0 +1,249 @@ +import { readFileSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import moment from "moment"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +const scriptPath = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + "../../docs/public/scripts/TodoistScript.js", +); + +type ScriptFn = (params: unknown, settings: Record) => Promise; +type TodoistScript = { + entry: ScriptFn; + settings: { options: Record }; + SelectFromAllTasks: ScriptFn; + GetAllTasksFromProject: ScriptFn; + GetAllTasksFromSection: ScriptFn; +}; + +const TOKEN = "Todoist API token"; +const COMPLETE = "Complete imported tasks in Todoist"; + +function loadScript(): TodoistScript { + const source = readFileSync(scriptPath, "utf8"); + const module = { exports: {} as TodoistScript }; + new Function("module", "exports", source)(module, module.exports); + return module.exports; +} + +type Task = { + id: string; + content: string; + project_id: string; + section_id: string | null; + due: { date: string } | null; +}; + +const projects = [ + { id: "p-home", name: "Home" }, + { id: "p-work", name: "Work" }, +]; +const sections = [ + { id: "s-errands", project_id: "p-home", name: "Errands" }, + { id: "s-garden", project_id: "p-home", name: "Garden" }, +]; +// More tasks than one page, so a client that ignores `next_cursor` misses some. +const tasks: Task[] = [ + { id: "t1", content: "Buy oat milk", project_id: "p-home", section_id: "s-errands", due: { date: "2031-01-15" } }, + { id: "t2", content: "Return library books", project_id: "p-home", section_id: "s-errands", due: null }, + { id: "t3", content: "Water the plants", project_id: "p-home", section_id: "s-garden", due: { date: "2031-03-20T09:00:00" } }, + { id: "t4", content: "Plan picnic", project_id: "p-home", section_id: null, due: null }, + { id: "t5", content: "Send report", project_id: "p-work", section_id: null, due: { date: "2031-02-03T23:30:00Z" } }, + { id: "t6", content: "Plan picnic", project_id: "p-work", section_id: null, due: null }, +]; + +const PAGE_SIZE = 2; + +function createTodoist(options: { status?: number } = {}) { + const closed: string[] = []; + const requests: Array<{ method: string; url: string; auth?: string }> = []; + + const requestUrl = vi.fn( + async (request: { url: string; method?: string; headers?: Record }) => { + const method = request.method ?? "GET"; + requests.push({ method, url: request.url, auth: request.headers?.Authorization }); + if (options.status) return { status: options.status, text: "", json: null }; + + const url = new URL(request.url); + expect(url.origin + url.pathname.replace(/\/[^/]+(\/close)$/, "/:id$1")).toMatch( + /^https:\/\/api\.todoist\.com\/api\/v1\/(tasks|projects|sections|tasks\/:id\/close)$/, + ); + + const close = url.pathname.match(/\/tasks\/([^/]+)\/close$/); + if (close && method === "POST") { + closed.push(close[1]); + return { status: 204, text: "", json: null }; + } + + const collection = { tasks, projects, sections }[url.pathname.split("/").pop() as string]; + if (!collection || method !== "GET") return { status: 404, text: "", json: null }; + expect(Number(url.searchParams.get("limit"))).toBeLessThanOrEqual(200); + const start = Number(url.searchParams.get("cursor") ?? 0); + const end = start + PAGE_SIZE; + const body = { + results: collection.slice(start, end), + next_cursor: end < collection.length ? String(end) : null, + }; + return { status: 200, text: JSON.stringify(body), json: body }; + }, + ); + + return { requestUrl, closed, requests }; +} + +function setup(options: { + settings?: Record; + suggest?: (labels: string[]) => number; + check?: (labels: string[]) => string[]; + status?: number; +} = {}) { + const todoist = createTodoist({ status: options.status }); + const notices: string[] = []; + const suggester = vi.fn(async (labels: string[], items: unknown[]) => + items[options.suggest ? options.suggest(labels) : 0], + ); + const checkboxPrompt = vi.fn(async (labels: string[]) => options.check?.(labels) ?? []); + const params = { + obsidian: { + requestUrl: todoist.requestUrl, + Notice: class { + constructor(message: string) { + notices.push(message); + } + }, + }, + quickAddApi: { suggester, checkboxPrompt }, + }; + const settings = { [TOKEN]: "test-token", [COMPLETE]: true, ...options.settings }; + return { params, settings, notices, suggester, checkboxPrompt, ...todoist }; +} + +function localDate(iso: string) { + const d = new Date(iso); + const pad = (n: number) => String(n).padStart(2, "0"); + return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; +} + +describe("Todoist example script", () => { + beforeEach(() => { + (window as unknown as { moment: typeof moment }).moment = moment; + }); + afterEach(() => { + delete (window as unknown as { moment?: typeof moment }).moment; + }); + + it("declares the API token as a secret setting and completion as an opt-out checkbox", () => { + const { settings } = loadScript(); + expect(settings.options[TOKEN]).toMatchObject({ type: "secret", id: "todoist-api-token" }); + expect(settings.options[COMPLETE]).toMatchObject({ type: "checkbox", defaultValue: true }); + }); + + it("imports every task in a project, across pages and sections, then completes them", async () => { + const ctx = setup({ suggest: (labels) => labels.indexOf("Home (4)") }); + + const output = await loadScript().GetAllTasksFromProject(ctx.params, ctx.settings); + + expect(output).toBe( + [ + "- [ ] Buy oat milk 📅 2031-01-15", + "- [ ] Return library books", + "- [ ] Water the plants 📅 2031-03-20", + "- [ ] Plan picnic", + "", + ].join("\n"), + ); + expect(ctx.suggester.mock.calls[0][0]).toEqual(["Home (4)", "Work (2)"]); + expect(ctx.closed).toEqual(["t1", "t2", "t3", "t4"]); + expect(ctx.notices).toEqual(["Added 4 tasks from 'Home'."]); + expect(new Set(ctx.requests.map((r) => r.auth))).toEqual(new Set(["Bearer test-token"])); + }); + + it("imports only the chosen section's tasks", async () => { + const ctx = setup({ suggest: (labels) => labels.indexOf("Home > Garden (1)") }); + + const output = await loadScript().GetAllTasksFromSection(ctx.params, ctx.settings); + + expect(ctx.suggester.mock.calls[0][0]).toEqual(["Home > Errands (2)", "Home > Garden (1)"]); + expect(output).toBe("- [ ] Water the plants 📅 2031-03-20\n"); + expect(ctx.closed).toEqual(["t3"]); + }); + + it("imports only the checked tasks, telling apart tasks with the same name", async () => { + const ctx = setup({ check: (labels) => [labels[5]] }); + + const output = await loadScript().SelectFromAllTasks(ctx.params, ctx.settings); + + expect(ctx.checkboxPrompt.mock.calls[0][0]).toHaveLength(6); + expect(output).toBe("- [ ] Plan picnic\n"); + expect(ctx.closed).toEqual(["t6"]); + }); + + it("writes a fixed-time-zone due date (UTC in the API) as the local date", async () => { + const originalTz = process.env.TZ; + process.env.TZ = "Asia/Tokyo"; // 2031-02-03T23:30Z is 08:30 on Feb 4 in Tokyo + try { + const ctx = setup({ check: (labels) => labels.filter((l) => l.endsWith("Send report")) }); + + const output = await loadScript().SelectFromAllTasks(ctx.params, ctx.settings); + + expect(output).toBe("- [ ] Send report 📅 2031-02-04\n"); + } finally { + if (originalTz === undefined) delete process.env.TZ; + else process.env.TZ = originalTz; + } + }); + + it("leaves tasks open in Todoist when completion is turned off", async () => { + const ctx = setup({ settings: { [COMPLETE]: false }, suggest: (labels) => labels.indexOf("Work (2)") }); + + const output = await loadScript().GetAllTasksFromProject(ctx.params, ctx.settings); + + expect(output).toBe(`- [ ] Send report 📅 ${localDate("2031-02-03T23:30:00Z")}\n- [ ] Plan picnic\n`); + expect(ctx.closed).toEqual([]); + expect(ctx.requests.every((r) => r.method === "GET")).toBe(true); + }); + + it("imports nothing when no task is checked", async () => { + const ctx = setup({ check: () => [] }); + + const output = await loadScript().SelectFromAllTasks(ctx.params, ctx.settings); + + expect(output).toBe(""); + expect(ctx.closed).toEqual([]); + }); + + it("asks which export to run when the macro calls the script without `::`", async () => { + const ctx = setup({ + suggest: (labels) => + labels.includes("GetAllTasksFromSection") ? labels.indexOf("GetAllTasksFromSection") : 0, + }); + + const output = await loadScript().entry(ctx.params, ctx.settings); + + expect(ctx.suggester.mock.calls[0][0]).toEqual([ + "SelectFromAllTasks", + "GetAllTasksFromProject", + "GetAllTasksFromSection", + ]); + expect(output).toBe("- [ ] Buy oat milk 📅 2031-01-15\n- [ ] Return library books\n"); + }); + + it("explains a missing token without calling Todoist", async () => { + const ctx = setup({ settings: { [TOKEN]: "" } }); + + await expect(loadScript().GetAllTasksFromProject(ctx.params, ctx.settings)).rejects.toThrow( + /Add your Todoist API token/, + ); + expect(ctx.requestUrl).not.toHaveBeenCalled(); + }); + + it("explains a rejected token", async () => { + const ctx = setup({ status: 401 }); + + await expect(loadScript().SelectFromAllTasks(ctx.params, ctx.settings)).rejects.toThrow( + "Todoist rejected the API token (HTTP 401).", + ); + }); +}); From c0bbba59d329d8d5fdb62a0b41ac0b9cae22237b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 26 Sep 2026 21:13:47 +0000 Subject: [PATCH 2/3] fix(docs): keep Todoist capture when mid-batch close fails If a close POST fails after earlier tasks already completed, still return the formatted output with a notice so QuickAdd writes the note instead of dropping the capture. Covers Macroscope High and Codex P1 on #1814. Co-authored-by: Christian Bager Bach Houmann --- docs/public/scripts/TodoistScript.js | 10 ++++++- tests/examples/todoistScript.test.ts | 41 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/docs/public/scripts/TodoistScript.js b/docs/public/scripts/TodoistScript.js index 28cc57a38..fdba0d53c 100644 --- a/docs/public/scripts/TodoistScript.js +++ b/docs/public/scripts/TodoistScript.js @@ -98,7 +98,15 @@ async function importTasks(params, settings, todoist, tasks, sourceName) { // IMPORTANT: this completes the imported tasks in Todoist. // Untick "Complete imported tasks in Todoist" in the script settings to keep them open. - if (settings[COMPLETE_TASKS]) await closeSelectedTasks(todoist, tasks); + // Always return `output` even if a close fails mid-batch: earlier tasks may + // already be completed in Todoist and would otherwise be lost from the capture. + if (settings[COMPLETE_TASKS]) { + try { + await closeSelectedTasks(todoist, tasks); + } catch { + new params.obsidian.Notice("Some imported tasks could not be completed in Todoist. They are still in the note."); + } + } new params.obsidian.Notice(`Added ${tasks.length} ${tasks.length === 1 ? "task" : "tasks"} from ${sourceName}.`); return output; diff --git a/tests/examples/todoistScript.test.ts b/tests/examples/todoistScript.test.ts index aa5bc0b19..6c796e971 100644 --- a/tests/examples/todoistScript.test.ts +++ b/tests/examples/todoistScript.test.ts @@ -205,6 +205,47 @@ describe("Todoist example script", () => { expect(ctx.requests.every((r) => r.method === "GET")).toBe(true); }); + it("still returns the capture when a mid-batch close fails", async () => { + const ctx = setup({ suggest: (labels) => labels.indexOf("Home (4)") }); + ctx.requestUrl.mockImplementation(async (request: { url: string; method?: string; headers?: Record }) => { + const method = request.method ?? "GET"; + ctx.requests.push({ method, url: request.url, auth: request.headers?.Authorization }); + const url = new URL(request.url); + const close = url.pathname.match(/\/tasks\/([^/]+)\/close$/); + if (close && method === "POST") { + if (close[1] === "t2") return { status: 503, text: "", json: null }; + ctx.closed.push(close[1]); + return { status: 204, text: "", json: null }; + } + const collection = { tasks, projects, sections }[url.pathname.split("/").pop() as string]; + if (!collection || method !== "GET") return { status: 404, text: "", json: null }; + const start = Number(url.searchParams.get("cursor") ?? 0); + const end = start + PAGE_SIZE; + const body = { + results: collection.slice(start, end), + next_cursor: end < collection.length ? String(end) : null, + }; + return { status: 200, text: JSON.stringify(body), json: body }; + }); + + const output = await loadScript().GetAllTasksFromProject(ctx.params, ctx.settings); + + expect(output).toBe( + [ + "- [ ] Buy oat milk 📅 2031-01-15", + "- [ ] Return library books", + "- [ ] Water the plants 📅 2031-03-20", + "- [ ] Plan picnic", + "", + ].join("\n"), + ); + expect(ctx.closed).toEqual(["t1"]); + expect(ctx.notices).toContain( + "Some imported tasks could not be completed in Todoist. They are still in the note.", + ); + expect(ctx.notices).toContain("Added 4 tasks from 'Home'."); + }); + it("imports nothing when no task is checked", async () => { const ctx = setup({ check: () => [] }); From b0367edbc47e1a419c58b5a4d2e9124fbaa9adc1 Mon Sep 17 00:00:00 2001 From: Amp Date: Sat, 26 Sep 2026 21:15:21 +0000 Subject: [PATCH 3/3] fix(docs): keep completing Todoist tasks after one close fails Close each imported task independently instead of stopping at the first failed request, and report exactly how many are still open in Todoist. The capture still gets every imported task. Amp-Thread-ID: https://ampcode.com/threads/T-01a0df6d-45d0-75e7-8b10-3ce80c6ed75d Co-authored-by: Christian Bager Bach Houmann --- docs/public/scripts/TodoistScript.js | 20 +++++++++----- tests/examples/todoistScript.test.ts | 41 ++++++++-------------------- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/docs/public/scripts/TodoistScript.js b/docs/public/scripts/TodoistScript.js index fdba0d53c..e408cbad4 100644 --- a/docs/public/scripts/TodoistScript.js +++ b/docs/public/scripts/TodoistScript.js @@ -98,13 +98,10 @@ async function importTasks(params, settings, todoist, tasks, sourceName) { // IMPORTANT: this completes the imported tasks in Todoist. // Untick "Complete imported tasks in Todoist" in the script settings to keep them open. - // Always return `output` even if a close fails mid-batch: earlier tasks may - // already be completed in Todoist and would otherwise be lost from the capture. if (settings[COMPLETE_TASKS]) { - try { - await closeSelectedTasks(todoist, tasks); - } catch { - new params.obsidian.Notice("Some imported tasks could not be completed in Todoist. They are still in the note."); + const failed = await closeSelectedTasks(todoist, tasks); + if (failed.length > 0) { + new params.obsidian.Notice(`Could not complete ${failed.length} of ${tasks.length} imported tasks in Todoist; they are still open there.`, 10000); } } @@ -112,10 +109,19 @@ async function importTasks(params, settings, todoist, tasks, sourceName) { return output; } +// Returns the tasks that could not be completed. The note still gets every +// imported task, so a failed close never loses one that was already closed. async function closeSelectedTasks(todoist, tasks) { + const failed = []; for (const task of tasks) { - await todoist.request("POST", `/tasks/${task.id}/close`); + try { + await todoist.request("POST", `/tasks/${task.id}/close`); + } catch (error) { + console.error(`Todoist: could not complete task ${task.id}`, error); + failed.push(task); + } } + return failed; } function formatTasksToTasksPluginTask(tasks) { diff --git a/tests/examples/todoistScript.test.ts b/tests/examples/todoistScript.test.ts index 6c796e971..cfaac5e9d 100644 --- a/tests/examples/todoistScript.test.ts +++ b/tests/examples/todoistScript.test.ts @@ -56,7 +56,7 @@ const tasks: Task[] = [ const PAGE_SIZE = 2; -function createTodoist(options: { status?: number } = {}) { +function createTodoist(options: { status?: number; failClose?: string[] } = {}) { const closed: string[] = []; const requests: Array<{ method: string; url: string; auth?: string }> = []; @@ -73,6 +73,7 @@ function createTodoist(options: { status?: number } = {}) { const close = url.pathname.match(/\/tasks\/([^/]+)\/close$/); if (close && method === "POST") { + if (options.failClose?.includes(close[1])) return { status: 500, text: "", json: null }; closed.push(close[1]); return { status: 204, text: "", json: null }; } @@ -98,8 +99,9 @@ function setup(options: { suggest?: (labels: string[]) => number; check?: (labels: string[]) => string[]; status?: number; + failClose?: string[]; } = {}) { - const todoist = createTodoist({ status: options.status }); + const todoist = createTodoist({ status: options.status, failClose: options.failClose }); const notices: string[] = []; const suggester = vi.fn(async (labels: string[], items: unknown[]) => items[options.suggest ? options.suggest(labels) : 0], @@ -205,28 +207,9 @@ describe("Todoist example script", () => { expect(ctx.requests.every((r) => r.method === "GET")).toBe(true); }); - it("still returns the capture when a mid-batch close fails", async () => { - const ctx = setup({ suggest: (labels) => labels.indexOf("Home (4)") }); - ctx.requestUrl.mockImplementation(async (request: { url: string; method?: string; headers?: Record }) => { - const method = request.method ?? "GET"; - ctx.requests.push({ method, url: request.url, auth: request.headers?.Authorization }); - const url = new URL(request.url); - const close = url.pathname.match(/\/tasks\/([^/]+)\/close$/); - if (close && method === "POST") { - if (close[1] === "t2") return { status: 503, text: "", json: null }; - ctx.closed.push(close[1]); - return { status: 204, text: "", json: null }; - } - const collection = { tasks, projects, sections }[url.pathname.split("/").pop() as string]; - if (!collection || method !== "GET") return { status: 404, text: "", json: null }; - const start = Number(url.searchParams.get("cursor") ?? 0); - const end = start + PAGE_SIZE; - const body = { - results: collection.slice(start, end), - next_cursor: end < collection.length ? String(end) : null, - }; - return { status: 200, text: JSON.stringify(body), json: body }; - }); + it("still returns the capture and completes the rest when a mid-batch close fails", async () => { + const ctx = setup({ failClose: ["t2"], suggest: (labels) => labels.indexOf("Home (4)") }); + vi.spyOn(console, "error").mockImplementation(() => undefined); const output = await loadScript().GetAllTasksFromProject(ctx.params, ctx.settings); @@ -239,11 +222,11 @@ describe("Todoist example script", () => { "", ].join("\n"), ); - expect(ctx.closed).toEqual(["t1"]); - expect(ctx.notices).toContain( - "Some imported tasks could not be completed in Todoist. They are still in the note.", - ); - expect(ctx.notices).toContain("Added 4 tasks from 'Home'."); + expect(ctx.closed).toEqual(["t1", "t3", "t4"]); + expect(ctx.notices).toEqual([ + "Could not complete 1 of 4 imported tasks in Todoist; they are still open there.", + "Added 4 tasks from 'Home'.", + ]); }); it("imports nothing when no task is checked", async () => {