#!/usr/bin/env node // dba-inbox-check.cjs — tjekker Outlook for nye DBA-beskeder // Output: "NEW: " 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); });