← back to Dw Install Docs

canned/send.mjs

61 lines

#!/usr/bin/env node
// Send a canned reply (with its attachments) via George's /api/send-with-attachment.
// Usage: node canned/send.mjs <response-id> <to-email> [account]
//   account defaults to "info" (info@designerwallcoverings.com). Only "info" or
//   "steve-office" are supported by the George route.
// Auth + endpoint are read from the george MCP env in ~/.claude.json (the same
// credential the mcp__george__ tools use) — no separate secret to manage.
import fs from "node:fs";
import path from "node:path";

const [, , id, to, accountArg] = process.argv;
if (!id || !to) {
  console.error("Usage: node canned/send.mjs <response-id> <to-email> [account]");
  process.exit(1);
}
const account = accountArg || "info";
const repo = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..");

// 1. Load the canned response
const store = JSON.parse(fs.readFileSync(path.join(repo, "canned/responses.json"), "utf8"));
const r = store.responses.find((x) => x.id === id);
if (!r) {
  console.error(`No canned response "${id}". Available: ${store.responses.map((x) => x.id).join(", ")}`);
  process.exit(1);
}

// 2. Read George auth/endpoint from ~/.claude.json mcpServers.george.env
const cfg = JSON.parse(fs.readFileSync(path.join(process.env.HOME, ".claude.json"), "utf8"));
let env = null;
(function walk(o) {
  for (const k in o) {
    if (k === "mcpServers" && o[k] && o[k].george) { env = o[k].george.env; return; }
    if (o[k] && typeof o[k] === "object") walk(o[k]);
    if (env) return;
  }
})(cfg);
if (!env || !env.GEORGE_BASIC_AUTH) { console.error("No george MCP auth in ~/.claude.json"); process.exit(1); }
const base = (env.GEORGE_URL || "https://kamatera.tail79cb8e.ts.net:9850").replace(/\/$/, "");

const MIME = { ".pdf": "application/pdf", ".doc": "application/msword", ".png": "image/png", ".jpg": "image/jpeg" };
const attachments = (r.attachments || []).map((rel) => {
  const p = path.join(repo, rel);
  return {
    filename: path.basename(rel),
    content_base64: fs.readFileSync(p).toString("base64"),
    mime_type: MIME[path.extname(rel).toLowerCase()] || "application/octet-stream",
  };
});

const headers = { "Content-Type": "application/json", Authorization: "Basic " + env.GEORGE_BASIC_AUTH };
if (env.GEORGE_EXTERNAL_SEND_TOKEN) headers["X-Send-Approval"] = env.GEORGE_EXTERNAL_SEND_TOKEN;

const res = await fetch(base + "/api/send-with-attachment", {
  method: "POST",
  headers,
  body: JSON.stringify({ account, to, subject: r.subject, body: r.body, attachments }),
});
console.log("HTTP", res.status);
console.log(await res.text());
if (!res.ok) process.exit(1);