Skip to content

Commit 85b6784

Browse files
plossonclaude
andcommitted
feat(gmail): add filter output formatters
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 67b6c3c commit 85b6784

1 file changed

Lines changed: 85 additions & 1 deletion

File tree

src/utils/output.ts

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { homedir } from 'os';
2-
import type { GmailMessage, GmailAttachmentInfo, GmailLabel } from '../types/gmail';
2+
import type { GmailMessage, GmailAttachmentInfo, GmailLabel, GmailFilter, GmailFilterCriteria, GmailFilterAction } from '../types/gmail';
33
import type { GChatMessage, GChatSpace, GChatMember, GChatUser } from '../types/gchat';
44
import type { GDocsDocument, GDocsCreateResult } from '../types/gdocs';
55
import type { GDriveFile, GDriveDownloadResult, GDriveUploadResult } from '../types/gdrive';
@@ -1241,3 +1241,87 @@ export function printWhatsAppParticipantsResult(
12411241
console.log(` ${r.participant}: ${r.status}`);
12421242
}
12431243
}
1244+
1245+
function resolveLabelNames(ids: string[] | undefined, labelNamesById: Map<string, string>): string[] {
1246+
if (!ids?.length) return [];
1247+
return ids.map((id) => labelNamesById.get(id) ?? id);
1248+
}
1249+
1250+
function summarizeFilterCriteria(c: GmailFilterCriteria): string {
1251+
const parts: string[] = [];
1252+
if (c.from) parts.push(`from:${c.from}`);
1253+
if (c.to) parts.push(`to:${c.to}`);
1254+
if (c.subject) parts.push(`subject:${c.subject}`);
1255+
if (c.query) parts.push(`query:${c.query}`);
1256+
if (c.negatedQuery) parts.push(`-query:${c.negatedQuery}`);
1257+
if (c.hasAttachment) parts.push('has:attachment');
1258+
if (c.excludeChats) parts.push('exclude:chats');
1259+
if (typeof c.size === 'number' && c.sizeComparison) {
1260+
parts.push(`size:${c.sizeComparison}:${c.size}`);
1261+
}
1262+
return parts.length ? parts.join(' ') : '(no criteria)';
1263+
}
1264+
1265+
function summarizeFilterAction(a: GmailFilterAction, labelNamesById: Map<string, string>): string {
1266+
const parts: string[] = [];
1267+
for (const name of resolveLabelNames(a.addLabelIds, labelNamesById)) parts.push(`+${name}`);
1268+
for (const name of resolveLabelNames(a.removeLabelIds, labelNamesById)) parts.push(`-${name}`);
1269+
if (a.forward) parts.push(`forward:${a.forward}`);
1270+
return parts.length ? parts.join(' ') : '(no action)';
1271+
}
1272+
1273+
export function printFilterList(filters: GmailFilter[], labelNamesById: Map<string, string>): void {
1274+
if (filters.length === 0) {
1275+
console.log('No filters found');
1276+
return;
1277+
}
1278+
const idWidth = Math.max(2, ...filters.map((f) => f.id.length));
1279+
for (const filter of filters) {
1280+
const criteria = summarizeFilterCriteria(filter.criteria);
1281+
const action = summarizeFilterAction(filter.action, labelNamesById);
1282+
console.log(`${filter.id.padEnd(idWidth)} ${criteria} -> ${action}`);
1283+
}
1284+
console.log(`\n${filters.length} filter(s)`);
1285+
}
1286+
1287+
export function printFilter(filter: GmailFilter, labelNamesById: Map<string, string>): void {
1288+
console.log(`ID: ${filter.id}`);
1289+
1290+
const c = filter.criteria;
1291+
const criteriaLines: string[] = [];
1292+
if (c.from) criteriaLines.push(` From: ${c.from}`);
1293+
if (c.to) criteriaLines.push(` To: ${c.to}`);
1294+
if (c.subject) criteriaLines.push(` Subject: ${c.subject}`);
1295+
if (c.query) criteriaLines.push(` Query: ${c.query}`);
1296+
if (c.negatedQuery) criteriaLines.push(` Negated query: ${c.negatedQuery}`);
1297+
if (c.hasAttachment) criteriaLines.push(` Has attachment: yes`);
1298+
if (c.excludeChats) criteriaLines.push(` Exclude chats: yes`);
1299+
if (typeof c.size === 'number' && c.sizeComparison) {
1300+
criteriaLines.push(` Size: ${c.sizeComparison} ${c.size} bytes`);
1301+
}
1302+
if (criteriaLines.length) {
1303+
console.log('Criteria:');
1304+
for (const line of criteriaLines) console.log(line);
1305+
}
1306+
1307+
const a = filter.action;
1308+
const actionLines: string[] = [];
1309+
const apply = resolveLabelNames(a.addLabelIds, labelNamesById);
1310+
const remove = resolveLabelNames(a.removeLabelIds, labelNamesById);
1311+
if (apply.length) actionLines.push(` Apply labels: ${apply.join(', ')}`);
1312+
if (remove.length) actionLines.push(` Remove labels: ${remove.join(', ')}`);
1313+
if (a.forward) actionLines.push(` Forward: ${a.forward}`);
1314+
if (actionLines.length) {
1315+
console.log('Action:');
1316+
for (const line of actionLines) console.log(line);
1317+
}
1318+
}
1319+
1320+
export function printFilterCreated(filter: GmailFilter, labelNamesById: Map<string, string>): void {
1321+
console.log(`Created filter: ${filter.id}`);
1322+
console.log(` ${summarizeFilterCriteria(filter.criteria)} -> ${summarizeFilterAction(filter.action, labelNamesById)}`);
1323+
}
1324+
1325+
export function printFilterDeleted(id: string): void {
1326+
console.log(`Deleted filter: ${id}`);
1327+
}

0 commit comments

Comments
 (0)