Files
Clawd BotandClaude Opus 4.6 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 <[email protected]>
2026-03-03 07:40:46 +01:00

152 lines
4.5 KiB
JavaScript

const { execSync } = require("child_process");
const path = require("path");
// Configuration
const LIMIT = 50; // Process max 50 emails per account per run
const OUTLOOK_SCRIPTS_DIR = "/home/alex/clawd/skills/outlook/scripts";
const OUTLOOK_PROFILES = [
{ name: "Personal", dir: process.env.HOME + "/.outlook-mcp-personal" },
{ name: "Work", dir: process.env.HOME + "/.outlook-mcp-o365" },
];
function log(msg) {
console.log(`[${new Date().toISOString()}] ${msg}`);
}
function execCmd(cmd, env = {}) {
try {
return execSync(cmd, { encoding: "utf8", env: { ...process.env, ...env }, stdio: "pipe" });
} catch (e) {
log(`Error executing command: ${cmd}`);
log(e.message);
return null;
}
}
// --- Gmail ---
function processGmail() {
log("Checking Gmail...");
try {
const res = execCmd(
`npx -y mcporter call --server google-workspace --tool "gmail.search" --args '{"query":"is:unread", "maxResults":${LIMIT}}' --output json`,
);
if (!res) {
return;
}
const data = JSON.parse(res);
if (!data.messages || data.messages.length === 0) {
log("Gmail: No unread messages.");
return;
}
log(`Gmail: Found ${data.messages.length} unread messages.`);
for (const msgStub of data.messages) {
// Get details for summary
const detailsJson = execCmd(
`npx -y mcporter call --server google-workspace --tool "gmail.get" --args '{"messageId":"${msgStub.id}"}' --output json`,
);
if (detailsJson) {
let details;
try {
details = JSON.parse(detailsJson);
} catch (err) {
log(`Gmail: Failed to parse details JSON for ${msgStub.id}: ${err.message}`);
continue;
}
let subject = "(No Subject)";
let from = "(Unknown)";
// Handle mcporter simplified object
if (details.subject) {
subject = details.subject;
}
if (details.from) {
from = details.from;
}
// Handle raw Gmail API object
if (details.payload && details.payload.headers) {
subject = details.payload.headers.find((h) => h.name === "Subject")?.value || subject;
from = details.payload.headers.find((h) => h.name === "From")?.value || from;
} else if (!details.subject && !details.from) {
log(
`Gmail: Unexpected structure for ${msgStub.id}. Keys: ${Object.keys(details).join(", ")}`,
);
}
log(`[Gmail] ${from}: ${subject}`);
}
// Mark as read
execCmd(
`npx -y mcporter call --server google-workspace --tool "gmail.modify" --args '{"messageId":"${msgStub.id}","removeLabelIds":["UNREAD"]}' --output json`,
);
}
} catch (e) {
log(`Gmail Error: ${e.message}`);
}
}
// --- Outlook ---
function processOutlook(profile) {
log(`Checking Outlook (${profile.name})...`);
// Get token
const tokenScript = path.join(OUTLOOK_SCRIPTS_DIR, "outlook-token.sh");
// Ensure token is fresh
execCmd(`${tokenScript} refresh`, { OUTLOOK_CONFIG_DIR: profile.dir });
const token = execCmd(`${tokenScript} get`, { OUTLOOK_CONFIG_DIR: profile.dir })?.trim();
if (!token) {
log(`Outlook (${profile.name}): Could not get token.`);
return;
}
// Fetch unread
const url = `https://graph.microsoft.com/v1.0/me/messages?$filter=isRead%20eq%20false&$top=${LIMIT}&$select=id,subject,from,receivedDateTime`;
const curlCmd = `curl -s "${url}" -H "Authorization: Bearer ${token}"`;
const res = execCmd(curlCmd);
if (!res) {
return;
}
try {
const data = JSON.parse(res);
if (!data.value || data.value.length === 0) {
log(`Outlook (${profile.name}): No unread messages.`);
return;
}
log(`Outlook (${profile.name}): Found ${data.value.length} unread messages.`);
for (const msg of data.value) {
const subject = msg.subject || "(No Subject)";
const from = msg.from?.emailAddress?.address || "(Unknown)";
log(`[Outlook-${profile.name}] ${from}: ${subject}`);
// Mark as read
const patchCmd = `curl -s -X PATCH "https://graph.microsoft.com/v1.0/me/messages/${msg.id}" -H "Authorization: Bearer ${token}" -H "Content-Type: application/json" -d '{"isRead":true}'`;
execCmd(patchCmd);
}
} catch (e) {
log(`Outlook (${profile.name}) Error: ${e.message}`);
}
}
// --- Main ---
function main() {
log("Starting Email Sweep...");
processGmail();
for (const profile of OUTLOOK_PROFILES) {
processOutlook(profile);
}
log("Email Sweep Completed.");
}
main();