Files
openclaw/skills/gmail-reader/search-gmail-only.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

104 lines
3.0 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 getAccessToken(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 searchGmail(accessToken, query, maxResults = 30) {
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 getMessage(accessToken, id) {
const url = `https://gmail.googleapis.com/gmail/v1/users/me/messages/${id}`;
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] || "newer_than:30d";
console.log(`🔍 Searching Gmail for: "${searchQuery}"\n`);
const creds = JSON.parse(
fs.readFileSync(join(homedir(), ".openclaw/secrets/google-oauth.json"), "utf8"),
);
const accessToken = await getAccessToken(creds);
const results = await searchGmail(accessToken, searchQuery);
if (!results.messages || results.messages.length === 0) {
console.log("No matches found.\n");
return;
}
console.log(`Found ${results.messages.length} message(s)\n`);
for (const msg of results.messages) {
const full = await getMessage(accessToken, 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("---");
}
}
main().catch((err) => {
console.error("Error:", err.message);
process.exit(1);
});