Not sure what you mean by “Apple blocking AppleScript” — AS is alive and well in MacOS and I run AppleScripts controlling OF daily. Can you share the script that has stopped working for you?
NB: This is a JS script, which I missed.
Now it works, the path (set after the script) was wrong.
But if Applescript works for you this would be good news. There are a lot of users who have complained about it, and all of the scripts don’t work anymore. Which OS do you use?
//
// Build a summary of OmniFocus tasks completed today.
//
// This is intended to be run as a TextExpander macro,
// but will work anywhere you can invoke a JS script.
//
// v 1.0.2 (full release history at bottom)
var NoProjectMarker = "No Project";
getTaskSummary();
function getTaskSummary() {
var doc = Application('OmniFocus').defaultDocument;
var thisMorning = startOfDay();
var tasks = doc.flattenedTasks.whose({completionDate: {'>=':thisMorning} })();
if (tasks.length == 0) {
return "No tasks completed. Done something without writing it down?";
}
// Group tasks by project, then extract progressed projects (projects with
// completed tasks) from allProjects. This gives us the list of projects
// in the same order as OmniFocus’s UI.
var groupedTasks = groupArrayByKey(tasks, function(v) {
var proj = v.containingProject();
if (proj) {
return proj.id();
}
return NoProjectMarker;
});
var allProjects = doc.flattenedProjects();
var progressedProjects = allProjects.filter(function(p) {
return p.id() in groupedTasks;
});
// Build the summary
var summary = progressedProjects.reduce(function(s,p){
return s + summaryForProject(p);
}, "");
var tasksWithNoProject = groupedTasks[NoProjectMarker];
if (tasksWithNoProject) {
summary += summaryForTasksWithTitle(tasksWithNoProject, "No Project\n");
}
return summary;
// This needs to be in this scope because it captures groupedTasks
function summaryForProject(p) {
var projectID = p.id();
var tasks = groupedTasks[projectID].filter(function(t) {
return projectID != t.id(); // Don't include the project itself
});
return summaryForTasksWithTitle(tasks, projectSummaryLine(p));
}
function summaryForTasksWithTitle(tasks, title) {
return title + tasks.reduce(summaryForTasks,"") + "\n";
}
}
// Reducing function to summarize a list of tasks
function summaryForTasks(s,t) {
return s + lineForTask(t);
}
// Create a summary line for a project
function projectSummaryLine(project) {
var tokens = [];
tokens.push(project.name());
var remainingStatus = remainingStatusForProject(project);
if (remainingStatus != "") {
tokens.push("(" + remainingStatus + ")");
}
return tokens.join(" ") + "\n";
}
// This is appended to the end of a project line
function remainingStatusForProject(project) {
if (!project.completedByChildren()) {
return "";
}
var remainingCount = project.numberOfTasks() - project.numberOfCompletedTasks();
if (remainingCount == 0) {
return "complete";
}
return remainingCount + " remaining";
}
function lineForTask(task) {
return " ✓ " + task.name() + "\n";
}
// Group an array of items by the key returned by this function
function groupArrayByKey(array,keyForValue) {
var dict = {};
for (var i = 0; i < array.length; i++) {
var value = array[i];
var key = keyForValue(value);
if (!(key in dict)) {
dict[key] = [];
}
dict[key].push(value);
}
return dict;
}
function startOfDay() {
// The day started at midnight this morning
var d = new Date();
d.setHours(0);
d.setMinutes(0);
d.setSeconds(0);
return d;
}
// Release History
// 1.0 Initial release
// 1.0.1 Fix for tasks without a project
// 1.0.2 Relaxed the type checking (!== is too strict)
Ok this is a JS script.
• WAIT, I think the path is wrong.
I think it receives less attention these days as of course AS is Mac only — automations based on Omni’s JS can run on iPad and iPhone too — but both OF3 and indeed the OF4 beta on Mac remain Apple scriptable