Files
openclaw/tools/dba-inbox-check.cjs
Clawd Bot ca9b510922 chore: align with upstream openclaw/openclaw and overlay local additions
- Reset master to upstream/main (16,697 commits)
- Overlay 2,271 local-only files (skills, tools, workspace, configs, apps)
- Restore IDENTITY.md and USER.md templates
- Build verified, gateway running, Discord working

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 07:40:46 +01:00

100 lines
3.4 KiB
JavaScript

#!/usr/bin/env node
// dba-inbox-check.cjs — tjekker Outlook for nye DBA-beskeder
// Output: "NEW: <besked>" eller "NO_NEW"
const { join } = require('path');
const { homedir } = require('os');
const fs = require('fs');
const STATE_FILE = '/tmp/dba-inbox-state.json';
const CREDS_PATH = join(homedir(), '.openclaw/secrets/outlook-oauth.json');
async function refreshToken(creds) {
const res = await fetch('https://login.microsoftonline.com/consumers/oauth2/v2.0/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
client_id: creds.client_id,
refresh_token: creds.refresh_token,
grant_type: 'refresh_token',
scope: 'https://graph.microsoft.com/Mail.Read offline_access'
})
});
if (!res.ok) throw new Error(`Token refresh fejlede: ${res.status}`);
const data = await res.json();
// Save updated tokens
const updated = { ...creds, access_token: data.access_token, refresh_token: data.refresh_token || creds.refresh_token };
fs.writeFileSync(CREDS_PATH, JSON.stringify(updated, null, 2));
return data.access_token;
}
async function main() {
const creds = JSON.parse(fs.readFileSync(CREDS_PATH, 'utf8'));
let token = creds.access_token;
// Hent ulæste emails
let res = await fetch(
'https://graph.microsoft.com/v1.0/me/messages?$top=20&$filter=isRead eq false&$orderby=receivedDateTime desc&$select=id,subject,from,receivedDateTime,bodyPreview',
{ headers: { Authorization: `Bearer ${token}` } }
);
// Refresh token hvis udløbet
if (res.status === 401) {
token = await refreshToken(creds);
res = await fetch(
'https://graph.microsoft.com/v1.0/me/messages?$top=20&$filter=isRead eq false&$orderby=receivedDateTime desc&$select=id,subject,from,receivedDateTime,bodyPreview',
{ headers: { Authorization: `Bearer ${token}` } }
);
}
if (!res.ok) {
process.stderr.write(`Graph API fejl: ${res.status}\n`);
process.exit(1);
}
const { value: messages = [] } = await res.json();
// Filter: kun DBA-relaterede beskeder
const dbaEmails = messages.filter(m => {
const from = (m.from?.emailAddress?.address || '').toLowerCase();
const subject = (m.subject || '').toLowerCase();
const preview = (m.bodyPreview || '').toLowerCase();
return (
from.includes('dba.dk') || from.includes('vend.dk') || from.includes('finn.no') ||
subject.includes('ny besked') || subject.includes('har svaret') ||
preview.includes('har sendt dig en besked') || preview.includes('new message')
);
});
// Load previous state
let prev = { seenIds: [] };
try { prev = JSON.parse(fs.readFileSync(STATE_FILE, 'utf8')); } catch {}
const seenIds = new Set(prev.seenIds || []);
// Find nye beskeder
const newReplies = dbaEmails.filter(m => !seenIds.has(m.id));
// Gem state
fs.writeFileSync(STATE_FILE, JSON.stringify({
seenIds: [...new Set([...seenIds, ...dbaEmails.map(m => m.id)])].slice(-100),
checkedAt: new Date().toISOString()
}, null, 2));
if (newReplies.length === 0) {
console.log('NO_NEW');
return;
}
// Formater output
for (const m of newReplies) {
const subject = m.subject || '(intet emne)';
const preview = (m.bodyPreview || '').slice(0, 200).trim();
console.log(`NEW:📬 **Nyt DBA-svar!**\n**Emne:** ${subject}\n${preview}`);
}
}
main().catch(e => {
process.stderr.write(`Fejl: ${e.message}\n`);
process.exit(1);
});