← back to Ventura Claw

server/connectors/colorapi.js

54 lines

// The Color API — no key. https://www.thecolorapi.com/docs
const BASE = "https://www.thecolorapi.com";
async function call(path) {
  const r = await fetch(`${BASE}${path}`, {
    headers: { Accept: "application/json", "User-Agent": "VenturaClaw/1.0" },
    signal: AbortSignal.timeout(12_000),
  });
  if (!r.ok) throw new Error(`colorapi ${r.status}`);
  return r.json();
}
function normHex(h) {
  if (!h) return null;
  let s = String(h).trim().replace(/^#/, "");
  if (s.length === 3) s = s.split("").map(c => c + c).join("");
  if (!/^[0-9a-fA-F]{6}$/.test(s)) return null;
  return s.toLowerCase();
}
module.exports = {
  meta: { id: "colorapi", name: "Color API", category: "creative", docsUrl: "https://www.thecolorapi.com/docs", auth: "none", realImpl: true },
  fields: [],
  configured() { return true; },
  async health() {
    try {
      const d = await call("/id?hex=d4a04a&format=json");
      return { ok: true, label: `live · sample: ${d.name?.value || "named"}` };
    } catch (e) { return { ok: false, reason: e.message }; }
  },
  actions: {
    async "identify"({ hex, rgb }) {
      const h = normHex(hex);
      if (!h && !rgb) throw new Error("hex or rgb required");
      const qs = h ? `hex=${h}` : `rgb=${encodeURIComponent(rgb)}`;
      const d = await call(`/id?${qs}&format=json`);
      return {
        hex: d.hex?.value, name: d.name?.value, rgb: d.rgb?.value,
        hsl: d.hsl?.value, cmyk: d.cmyk?.value,
        contrast_text: d.contrast?.value,
        nearest_named: d.name?.exact_match_name === false ? d.name?.closest_named_hex : null,
      };
    },
    async "scheme"({ hex, mode, count }) {
      const h = normHex(hex);
      if (!h) throw new Error("hex required");
      const qs = new URLSearchParams({ hex: h, mode: mode || "analogic", count: String(Math.min(count || 5, 10)), format: "json" });
      const d = await call(`/scheme?${qs}`);
      return {
        seed: d.seed?.hex?.value, mode: d.mode,
        colors: (d.colors || []).map(c => ({ hex: c.hex?.value, name: c.name?.value, rgb: c.rgb?.value })),
        scheme_image: d.image?.bare,
      };
    },
  },
};