Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@randallb
Created March 24, 2023 18:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save randallb/4f057b89d81451f110bc1f03a2ca2661 to your computer and use it in GitHub Desktop.
Save randallb/4f057b89d81451f110bc1f03a2ca2661 to your computer and use it in GitHub Desktop.
I didn't write any of this code.

Holy shit.

GPT4 wrote all of this code. I can't believe it. I can build products literally in a single day now.

enum AppleScriptStatus {
SuccessString = "SUCCESS_STRING",
SuccessJSON = "SUCCESS_JSON",
Failure = "FAILURE",
}
type AppleScriptResult = {
data: string | { [key: string]: unknown };
status: AppleScriptStatus;
};
export default async function runAppleScript(script: string | string[]): Promise<AppleScriptResult> {
const cmd = ["osascript"];
const appleScript = Array.isArray(script) ? script : [script];
appleScript.forEach((scriptLine) => {
cmd.push("-e", scriptLine);
});
const p = Deno.run({
cmd,
stdout: "piped",
stderr: "piped",
});
const [rawOutput, rawError] = await Promise.all([
p.output(),
p.stderrOutput(),
]);
const status = await p.status();
p.close();
let result: AppleScriptResult;
if (status.success) {
const output = new TextDecoder().decode(rawOutput).trim();
let parsedData: string | { [key: string]: unknown };
let scriptStatus: AppleScriptStatus;
try {
parsedData = JSON.parse(output);
scriptStatus = AppleScriptStatus.SuccessJSON;
} catch (error) {
if (error instanceof SyntaxError) {
parsedData = output;
scriptStatus = AppleScriptStatus.SuccessString;
} else {
throw error;
}
}
result = { data: parsedData, status: scriptStatus };
} else {
const error = new TextDecoder().decode(rawError).trim();
result = { data: `AppleScript execution failed: ${error}`, status: AppleScriptStatus.Failure };
}
return result;
}
if (import.meta.main) {
const args = Deno.args;
if (args.length === 0) {
console.error("Error: Please provide AppleScript code as arguments.");
Deno.exit(1);
}
runAppleScript(args)
.then((output) => {
console.log(output);
})
.catch((error) => {
console.error("Error:", error.message);
});
}
<%
// Helper functions
function getFancyTime(date) {
const options = { hour: '2-digit', minute: '2-digit', timeZoneName: 'short' };
return new Intl.DateTimeFormat('en-US', options).format(date);
}
function getDayOfWeek(date) {
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
return days[date.getDay()];
}
// Variables
const today = new Date();
const todayTimestamp = Math.floor(today.getTime() / 1000); // Convert to Unix timestamp
const tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1);
const tomorrowTimestamp = Math.floor(tomorrow.getTime() / 1000); // Convert to Unix timestamp
const dayString = getDayOfWeek(today);
const timeString = getFancyTime(today);
// AppleScript to get tasks from OmniFocus
const omnifocusScript = `
use framework "Foundation"
use scripting additions
on convertToJson(recordsList)
set theList to current application's NSArray's arrayWithArray:recordsList
set jsonData to (current application's NSJSONSerialization's dataWithJSONObject:theList options:0 |error|:(missing value))
set jsonString to (current application's NSString's alloc()'s initWithData:jsonData encoding:(current application's NSUTF8StringEncoding))
return jsonString as text
end convertToJson
tell application "OmniFocus"
tell default document
set currentDate to current date
set beginningOfDay to (currentDate - (time of currentDate))
set endOfDay to (beginningOfDay + 86399) -- This is one second less than a full day.
set theTasks to every flattened task where its due date is greater than or equal to beginningOfDay and its due date is less than or equal to endOfDay
set taskList to {}
repeat with aTask in theTasks
set taskTags to tags of aTask
set tagNameList to {}
repeat with aTag in taskTags
set end of tagNameList to {name:name of aTag, id:id of aTag}
end repeat
set taskDueDate to due date of aTask
set dateString to taskDueDate as «class isot» as string -- Convert the date to an ISO 8601 format string
set taskInfo to {name:name of aTask, id:id of aTask, dueDate:dateString, completed:completed of aTask, projectName:name of containing project of aTask, tags:tagNameList}
set end of taskList to taskInfo
end repeat
return my convertToJson(taskList)
end tell
end tell
`.trim();
// GraphQL query for events
const gqlQuery = `query CalendarTemplateQuery($start: Int!, $end: Int!){
me {
name
calendar_meetings(start: $start, end: $end) {
nodes {
title
start_time
end_time
is_all_day_event
category
}
}
}
}
}
}`;
// Fetch data simultaneously
const [omnifocusTasksData, eventsData] = await Promise.all([
runAppleScript(omnifocusScript),
graphql(gqlQuery, { "start": todayTimestamp, "end": tomorrowTimestamp })
]);
console.log(dayString);
console.log(eventsData);
console.log(omnifocusTasksData)
const tasks = [];
const events = eventsData.me.calendar_meetings.nodes
%>
# <%# dayString %> <%= today.toISOString().split('T')[0] %>
[[<%= today.toISOString().split('T')[0].slice(0,8) + "W" + (Math.floor(today.getDate() / 7) + 1) %>]]
## Schedule (generated at <%= timeString %>)
<% events.forEach((event) => { %>
- [ ] <%= getFancyTime(new Date(event.start_time)) %> <%= event.title %>
<% }); %>
## Omnifocus tasks (generated at <%= timeString %>)
<% tasks.forEach((task) => {
const taskCompleted = task.completed ? 'x' : '';
const dueDateString = new Date(task.dueDate).toLocaleDateString('en-US', { month: 'short', day: '2-digit' });
const dueTimeString = getFancyTime(new Date(task.dueDate));
const taskTags = task.tags.length > 0 ? task.tags.map(tag => `[[#${tag.name}]]([#${tag.name} on OmniFocus](omnifocus:///perspective/Tag?name=${encodeURIComponent(tag.name)}))`).join(' ') : '';
%>
- [${taskCompleted}] [<%= task.name %>](omnifocus://task/<%= task.id %>) Due: <%= dueDateString %> at <%= dueTimeString %> <%= task.projectName %> <%= taskTags %>
<% }); %>
⬅ [[<%= new Date(today.setDate(today.getDate() - 1)).toISOString().split('T')[0] %>]] 🗓 [[<%= new Date(today.setDate(today.getDate() + 2)).toISOString().split('T')[0] %>]] ➡
#!/usr/bin/env deno run --allow-read --allow-write --allow-run
import { renderToString } from "https://deno.land/x/dejs@0.10.3/mod.ts";
import { parse } from "https://deno.land/std@0.179.0/flags/mod.ts";
import { resolve } from "https://deno.land/std@0.179.0/path/mod.ts";
import graphql from "rbcode/packages/graphql.ts";
import runAppleScript from "rbcode/packages/productivity/run_applescript.ts";
type Args = {
templatePath: string;
outputPath: string;
};
export default async function main({ templatePath, outputPath }: Args) {
const template = await Deno.readTextFile(templatePath);
const rendered = await renderToString(template, { graphql, runAppleScript });
await Deno.writeTextFile(outputPath, rendered.trim(), {
append: true
});
}
if (import.meta.main) {
const flags = parse(Deno.args);
const { template, output } = flags;
if (!template || !output) {
console.error("Error: Both --template and --output flags are required.");
Deno.exit(1);
}
const templatePath = resolve(template);
const outputPath = resolve(output);
await main({ templatePath, outputPath });
console.log(`Wrote: ${ outputPath } from template: ${ templatePath } `);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment