Files
2025-11-30 08:35:59 +08:00

127 lines
3.6 KiB
JavaScript

#!/usr/bin/env osascript -l JavaScript
// Get all OmniFocus projects with full folder hierarchy
// Returns JSON with project names, folders, and structure
function run() {
const app = Application('OmniFocus');
app.includeStandardAdditions = true;
const doc = app.defaultDocument;
const folders = doc.folders();
const projects = doc.flattenedProjects();
// Build folder structure
const folderStructure = [];
function processFolder(folder, depth = 0) {
const folderInfo = {
id: folder.id(),
name: folder.name(),
depth: depth,
projects: [],
subfolders: []
};
// Get projects in this folder
try {
const folderProjects = folder.projects();
for (let i = 0; i < folderProjects.length; i++) {
const proj = folderProjects[i];
folderInfo.projects.push({
id: proj.id(),
name: proj.name(),
status: proj.status(),
taskCount: proj.numberOfAvailableTasks()
});
}
} catch (e) {
// No projects in folder
}
// Get subfolders
try {
const subfolders = folder.folders();
for (let i = 0; i < subfolders.length; i++) {
folderInfo.subfolders.push(processFolder(subfolders[i], depth + 1));
}
} catch (e) {
// No subfolders
}
return folderInfo;
}
// Process top-level folders
for (let i = 0; i < folders.length; i++) {
folderStructure.push(processFolder(folders[i], 0));
}
// Get standalone projects (not in folders)
const standaloneProjects = [];
for (let i = 0; i < projects.length; i++) {
const proj = projects[i];
try {
const container = proj.container();
// If container is the document itself, it's standalone
if (container.class() === 'document') {
standaloneProjects.push({
id: proj.id(),
name: proj.name(),
status: proj.status(),
taskCount: proj.numberOfAvailableTasks()
});
}
} catch (e) {
// Skip if can't determine container
}
}
// Build flat list for easy lookup
const flatList = [];
function flattenStructure(folders, path = '') {
for (const folder of folders) {
const currentPath = path ? `${path} > ${folder.name}` : folder.name;
for (const proj of folder.projects) {
flatList.push({
id: proj.id,
name: proj.name,
path: `${currentPath} > ${proj.name}`,
folder: folder.name,
status: proj.status,
taskCount: proj.taskCount
});
}
if (folder.subfolders.length > 0) {
flattenStructure(folder.subfolders, currentPath);
}
}
}
flattenStructure(folderStructure);
// Add standalone projects
for (const proj of standaloneProjects) {
flatList.push({
id: proj.id,
name: proj.name,
path: proj.name,
folder: null,
status: proj.status,
taskCount: proj.taskCount
});
}
const result = {
total_projects: flatList.length,
folder_structure: folderStructure,
standalone_projects: standaloneProjects,
flat_list: flatList
};
return JSON.stringify(result, null, 2);
}