- 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>
184 lines
6.3 KiB
JavaScript
184 lines
6.3 KiB
JavaScript
#!/usr/bin/env node
|
|
const fs = require("fs");
|
|
const https = require("https");
|
|
const { homedir } = require("os");
|
|
const { join } = require("path");
|
|
|
|
function httpsRequest(url, options = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
const req = https.request(url, options, (res) => {
|
|
let data = "";
|
|
res.on("data", (chunk) => (data += chunk));
|
|
res.on("end", () => {
|
|
if (res.statusCode >= 400) {
|
|
reject(new Error(`HTTP ${res.statusCode}: ${data}`));
|
|
} else {
|
|
resolve(JSON.parse(data));
|
|
}
|
|
});
|
|
});
|
|
req.on("error", reject);
|
|
if (options.body) req.write(options.body);
|
|
req.end();
|
|
});
|
|
}
|
|
|
|
async function getGoogleAccessToken(creds) {
|
|
const body = new URLSearchParams({
|
|
client_id: creds.client_id,
|
|
client_secret: creds.client_secret,
|
|
refresh_token: creds.refresh_token,
|
|
grant_type: "refresh_token",
|
|
}).toString();
|
|
|
|
const data = await httpsRequest("https://oauth2.googleapis.com/token", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
"Content-Length": Buffer.byteLength(body),
|
|
},
|
|
body,
|
|
});
|
|
|
|
return data.access_token;
|
|
}
|
|
|
|
async function getMicrosoftAccessToken(creds) {
|
|
const 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",
|
|
}).toString();
|
|
|
|
const tenant = creds.tenant || "consumers";
|
|
const data = await httpsRequest(`https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
"Content-Length": Buffer.byteLength(body),
|
|
},
|
|
body,
|
|
});
|
|
|
|
return data.access_token;
|
|
}
|
|
|
|
async function searchGmail(accessToken, query, maxResults = 20) {
|
|
const encodedQuery = encodeURIComponent(query);
|
|
const url = `https://gmail.googleapis.com/gmail/v1/users/me/messages?maxResults=${maxResults}&q=${encodedQuery}`;
|
|
return await httpsRequest(url, {
|
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
});
|
|
}
|
|
|
|
async function getGmailMessage(accessToken, id) {
|
|
const url = `https://gmail.googleapis.com/gmail/v1/users/me/messages/${id}`;
|
|
return await httpsRequest(url, {
|
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
});
|
|
}
|
|
|
|
async function searchOutlook(accessToken, query, maxResults = 20) {
|
|
const url = `https://graph.microsoft.com/v1.0/me/messages?$top=${maxResults}&$search="${query}"`;
|
|
return await httpsRequest(url, {
|
|
headers: { Authorization: `Bearer ${accessToken}` },
|
|
});
|
|
}
|
|
|
|
function getHeader(headers, name) {
|
|
const h = headers.find((h) => h.name.toLowerCase() === name.toLowerCase());
|
|
return h ? h.value : "";
|
|
}
|
|
|
|
async function main() {
|
|
const searchQuery = process.argv[2] || "BIOS graphics GPU grafikkort";
|
|
|
|
console.log(`🔍 Searching for: "${searchQuery}"\n`);
|
|
|
|
// Gmail
|
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
console.log("📧 Gmail");
|
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
|
|
|
const gmailCreds = JSON.parse(
|
|
fs.readFileSync(join(homedir(), ".openclaw/secrets/google-oauth.json"), "utf8"),
|
|
);
|
|
const gmailToken = await getGoogleAccessToken(gmailCreds);
|
|
const gmailResults = await searchGmail(gmailToken, searchQuery);
|
|
|
|
if (gmailResults.messages && gmailResults.messages.length > 0) {
|
|
for (const msg of gmailResults.messages.slice(0, 5)) {
|
|
const full = await getGmailMessage(gmailToken, msg.id);
|
|
const from = getHeader(full.payload.headers, "From");
|
|
const subject = getHeader(full.payload.headers, "Subject");
|
|
const date = getHeader(full.payload.headers, "Date");
|
|
const labels = full.labelIds || [];
|
|
const isUnread = labels.includes("UNREAD");
|
|
|
|
console.log(`${isUnread ? "🔴" : "✅"} From: ${from}`);
|
|
console.log(` Subject: ${subject}`);
|
|
console.log(` Date: ${date}`);
|
|
console.log(` Preview: ${full.snippet}`);
|
|
console.log("---");
|
|
}
|
|
} else {
|
|
console.log("No matches found.\n");
|
|
}
|
|
|
|
// Outlook
|
|
console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
console.log("📧 Outlook");
|
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
|
|
|
const outlookCreds = JSON.parse(
|
|
fs.readFileSync(join(homedir(), ".openclaw/secrets/outlook-oauth.json"), "utf8"),
|
|
);
|
|
const outlookToken = await getMicrosoftAccessToken(outlookCreds);
|
|
const outlookResults = await searchOutlook(outlookToken, searchQuery);
|
|
|
|
if (outlookResults.value && outlookResults.value.length > 0) {
|
|
for (const msg of outlookResults.value.slice(0, 5)) {
|
|
console.log(
|
|
`${msg.isRead ? "✅" : "🔴"} From: ${msg.from?.emailAddress?.name || msg.from?.emailAddress?.address}`,
|
|
);
|
|
console.log(` Subject: ${msg.subject}`);
|
|
console.log(` Date: ${msg.receivedDateTime}`);
|
|
console.log(` Preview: ${msg.bodyPreview}`);
|
|
console.log("---");
|
|
}
|
|
} else {
|
|
console.log("No matches found.\n");
|
|
}
|
|
|
|
// Office365
|
|
console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
console.log("📧 Office365");
|
|
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
|
|
|
const o365Creds = JSON.parse(
|
|
fs.readFileSync(join(homedir(), ".openclaw/secrets/outlook-o365-oauth.json"), "utf8"),
|
|
);
|
|
const o365Token = await getMicrosoftAccessToken(o365Creds);
|
|
const o365Results = await searchOutlook(o365Token, searchQuery);
|
|
|
|
if (o365Results.value && o365Results.value.length > 0) {
|
|
for (const msg of o365Results.value.slice(0, 5)) {
|
|
console.log(
|
|
`${msg.isRead ? "✅" : "🔴"} From: ${msg.from?.emailAddress?.name || msg.from?.emailAddress?.address}`,
|
|
);
|
|
console.log(` Subject: ${msg.subject}`);
|
|
console.log(` Date: ${msg.receivedDateTime}`);
|
|
console.log(` Preview: ${msg.bodyPreview}`);
|
|
console.log("---");
|
|
}
|
|
} else {
|
|
console.log("No matches found.\n");
|
|
}
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error("Error:", err.message);
|
|
process.exit(1);
|
|
});
|