COM1_
TERMINAL MODEGET STARTED →
BOT://RECIPES

Bot API recipes

Deployable examples for server monitoring, CI alerts and IoT integration, plus practical troubleshooting.

BOT API / PRACTICAL RECIPES

Start with a scoped bot token and a running com1-bot-ingest Edge Function. Each recipe posts from a trusted server/script, never from client-side JavaScript.

Recipe A — Linux disk warning (Bash)

#!/usr/bin/env bash
set -euo pipefail
: "${COM1_PROJECT_URL:?set COM1_PROJECT_URL}"
: "${COM1_BOT_TOKEN:?set COM1_BOT_TOKEN}"
used=$(df -P / | awk 'NR==2 {gsub("%", "", $5); print $5}')
if (( used >= 90 )); then
  export USED_PERCENT="$used"
  python3 - <<'PYIN'
import json, os, urllib.request
payload = {
    'event_id': 'disk-' + str(__import__('time').time_ns()),
    'kind': 'alert', 'title': 'DISK SPACE LOW',
    'message': 'Root partition threshold reached',
    'level': 'warning',
    'fields': {'host': __import__('socket').gethostname(), 'used_percent': int(os.environ['USED_PERCENT'])}
}
url = os.environ['COM1_PROJECT_URL'].rstrip('/') + '/functions/v1/com1-bot-ingest'
req = urllib.request.Request(url, data=json.dumps(payload).encode(), method='POST', headers={
    'Content-Type': 'application/json', 'Authorization': 'Bearer ' + os.environ['COM1_BOT_TOKEN']})
with urllib.request.urlopen(req, timeout=15) as r: print(r.status)
PYIN
fi

Schedule the script with your own cron/systemd timer. Add local alert suppression/deduplication to avoid flooding chat every minute while the disk remains above threshold.

Recipe B — Website uptime status (Python)

import os, json, time, urllib.request, urllib.error
site = 'https://example.com/health'
try:
    with urllib.request.urlopen(site, timeout=8) as response:
        healthy, http_status = 200 <= response.status < 400, response.status
except Exception:
    healthy, http_status = False, 0

payload = {
    'event_id': 'health-' + str(int(time.time())),
    'kind': 'alert',
    'title': 'WEB HEALTH',
    'message': 'Service reachable' if healthy else 'Service unreachable',
    'level': 'success' if healthy else 'critical',
    'fields': {'site': site, 'status': http_status},
}
url = os.environ['COM1_PROJECT_URL'].rstrip('/') + '/functions/v1/com1-bot-ingest'
req = urllib.request.Request(url,
    data=json.dumps(payload).encode(), method='POST',
    headers={'Authorization': 'Bearer ' + os.environ['COM1_BOT_TOKEN'],
             'Content-Type': 'application/json'})
with urllib.request.urlopen(req, timeout=15) as r:
    print(r.status, r.read().decode())

This example is a single health check, not a hosted COM1 health-monitoring service. Run it from an environment you control and choose a sensible schedule.

Recipe C — CI completion alert (Node.js)

// Run as a Node 18+ server-side CI step.
const eventId = `ci-${process.env.BUILD_ID || Date.now()}`;
const payload = {
  event_id: eventId,
  kind: 'structured',
  title: 'BUILD FINISHED',
  message: 'Pipeline completed',
  fields: { repository: 'com1', branch: 'main', build: process.env.BUILD_ID || 'manual' },
};
const resp = await fetch(`${process.env.COM1_PROJECT_URL.replace(/\/$/, '')}/functions/v1/com1-bot-ingest`, {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.COM1_BOT_TOKEN}`, 'Content-Type': 'application/json' },
  body: JSON.stringify(payload),
});
if (!resp.ok) throw new Error(`COM1 bot ingest failed: HTTP ${resp.status}`);
console.log(await resp.text());

Recipe D — IoT home-server bridge

ESP32 sensors can POST telemetry to your own authenticated server, which validates, aggregates and rate-limits it before publishing a structured event into COM1. Avoid embedding the bot token in device firmware that may be extracted. A bot event can contain scalar fields like temperature_c, uptime_s and battery_pct. MQTT-to-COM1 bridging requires your own adapter until a native subscriber is deployed.

Bot API troubleshooting

SymptomWhat to check
No message appearsCorrect project URL/function name, deployed Edge Function, token destination, bot enabled, standard channel and owner membership.
401/403 or token rejectedToken copied fully? Revoked/expired? Permission for kind? Never swap in your Supabase service-role key.
Duplicate event / conflictSame event_id with changed JSON is a conflict; reuse ID only for an identical retry.
Rate limit responseSlow down, back off and check per-token minute/day limits in the bot console.
Invalid fieldsOnly scalar field values; 20 keys max, key names and lengths limited by migration.
Cannot use Secure Link channelBot token destinations intentionally require a standard conversation.
/bot @name not workingOwner enabled command link? User has command access? Public HTTPS callback configured? Deployed com1-bot-command working?
Private callback unreachableA local 192.168.x.x or localhost URL is not reachable from Supabase; use a properly protected public HTTPS endpoint.

Privacy: Do not post full request headers, raw tokens, personal messages or callback secrets when asking for debugging help.