← back to Slack To Steve
preflight.mjs
55 lines
// preflight.mjs — is the two-way pipe ready to go live?
// Checks: token valid, channel resolvable, and whether the READ scope
// (channels:history) has been granted yet. Prints READY / BLOCKED with the gap.
// $0 — hits Slack Web API only (auth.test + one conversations.history probe).
import fs from 'fs';
import path from 'path';
const ENV = loadEnv(path.join(process.cwd(), '.env'));
const TOKEN = ENV.SLACK_BOT_TOKEN || process.env.SLACK_BOT_TOKEN;
const CHANNEL = ENV.SLACK_CHANNEL_ID || process.env.SLACK_CHANNEL_ID || '';
function loadEnv(p) {
const o = {};
try {
for (const line of fs.readFileSync(p, 'utf8').split('\n')) {
const m = line.match(/^([A-Z0-9_]+)=(.*)$/);
if (m) o[m[1]] = m[2].replace(/^['"]|['"]$/g, '');
}
} catch {}
return o;
}
async function slack(method, params = {}) {
const url = 'https://slack.com/api/' + method + '?' + new URLSearchParams(params);
const r = await fetch(url, { headers: { Authorization: 'Bearer ' + TOKEN } });
return r.json();
}
(async () => {
if (!TOKEN) { console.log('BLOCKED — no SLACK_BOT_TOKEN (copy .env.example → .env)'); process.exit(1); }
const auth = await slack('auth.test');
if (!auth.ok) { console.log('BLOCKED — token invalid: ' + auth.error); process.exit(1); }
console.log(`token OK — bot @${auth.user} on team ${auth.team} (${auth.team_id})`);
// WRITE check is implicit (chat:write present). READ check = probe history.
let readOK = false, readErr = null;
if (CHANNEL) {
const h = await slack('conversations.history', { channel: CHANNEL, limit: 1 });
readOK = !!h.ok;
readErr = h.error || null;
} else {
readErr = 'no SLACK_CHANNEL_ID set';
}
if (readOK) {
console.log('READ OK — channels:history is granted and the channel is readable.');
console.log('\n✅ READY — run `node ingest.mjs` (or install the launchd plist) to go live.');
} else if (readErr === 'missing_scope') {
console.log('READ BLOCKED — token still lacks channels:history.');
console.log('\n⛔ NOT READY — Steve must add channels:history to the Slack app + reinstall (see README).');
} else {
console.log('READ BLOCKED — ' + readErr + (readErr === 'not_in_channel' ? ' (invite the bot to the channel)' : ''));
console.log('\n⛔ NOT READY — resolve the above, then re-run preflight.');
}
})();