mirror of
https://github.com/hanzoskill/asana.git
synced 2026-10-30 21:01:00 +00:00
107 lines
2.8 KiB
JavaScript
107 lines
2.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Very small helper to map chat-ish input into an asana_api.mjs command.
|
|
*
|
|
* This is NOT required for Hanzo Bot, but makes it easy to support both:
|
|
* - explicit commands: "/asana projects"
|
|
* - natural language: "list tasks assigned to me"
|
|
*
|
|
* Usage:
|
|
* node asana/scripts/asana_chat.mjs --text "list tasks assigned to me"
|
|
*
|
|
* Output: a JSON object { cmd, args: [] }
|
|
*/
|
|
|
|
function die(msg) {
|
|
console.error(msg);
|
|
process.exit(1);
|
|
}
|
|
|
|
function parseArgs(argv) {
|
|
const flags = {};
|
|
for (let i = 0; i < argv.length; i++) {
|
|
const a = argv[i];
|
|
if (a.startsWith('--')) {
|
|
const k = a.slice(2);
|
|
const v = argv[i + 1] && !argv[i + 1].startsWith('--') ? argv[++i] : true;
|
|
flags[k] = v;
|
|
}
|
|
}
|
|
return flags;
|
|
}
|
|
|
|
function norm(s) {
|
|
return String(s || '')
|
|
.trim()
|
|
.replace(/\s+/g, ' ');
|
|
}
|
|
|
|
function parseDateRange(text) {
|
|
// very simple: from YYYY-MM-DD to YYYY-MM-DD
|
|
const m = text.match(/from\s+(\d{4}-\d{2}-\d{2})\s+to\s+(\d{4}-\d{2}-\d{2})/i);
|
|
if (!m) return null;
|
|
return { from: m[1], to: m[2] };
|
|
}
|
|
|
|
function main() {
|
|
const flags = parseArgs(process.argv.slice(2));
|
|
const text = norm(flags.text);
|
|
if (!text) die('Missing --text');
|
|
|
|
// Slash style
|
|
if (text.toLowerCase().startsWith('/asana ')) {
|
|
const rest = text.slice(7).trim();
|
|
const parts = rest.split(' ');
|
|
return console.log(
|
|
JSON.stringify(
|
|
{
|
|
cmd: parts[0],
|
|
args: parts.slice(1),
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
);
|
|
}
|
|
|
|
const t = text.toLowerCase();
|
|
|
|
// Natural language patterns
|
|
if (t.includes('list') && t.includes('workspace')) {
|
|
return console.log(JSON.stringify({ cmd: 'workspaces', args: [] }, null, 2));
|
|
}
|
|
|
|
if ((t.includes('list') || t.includes('show')) && t.includes('project')) {
|
|
return console.log(JSON.stringify({ cmd: 'projects', args: [] }, null, 2));
|
|
}
|
|
|
|
if (t.includes('assigned to me') || t.includes('my tasks')) {
|
|
// Optional: "in <project>" requires project gid/name resolution at a higher layer.
|
|
return console.log(JSON.stringify({ cmd: 'tasks-assigned', args: ['--assignee', 'me'] }, null, 2));
|
|
}
|
|
|
|
if (t.includes('all tasks in') || t.includes('tasks in project')) {
|
|
// Expect the caller to provide --project elsewhere.
|
|
return console.log(JSON.stringify({ cmd: 'tasks-in-project', args: [] }, null, 2));
|
|
}
|
|
|
|
const dr = parseDateRange(text);
|
|
if (dr) {
|
|
// Asana search uses query params; due_on.after / due_on.before are common.
|
|
return console.log(
|
|
JSON.stringify(
|
|
{
|
|
cmd: 'search-tasks',
|
|
args: ['--assignee', 'me', '--due_on.after', dr.from, '--due_on.before', dr.to],
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
);
|
|
}
|
|
|
|
return console.log(JSON.stringify({ cmd: 'unknown', args: [], note: 'No rule matched.' }, null, 2));
|
|
}
|
|
|
|
main();
|