#!/usr/bin/env ts-node import BringApi from 'bring-shopping'; interface Credentials { mail: string; password: string; } interface BringItem { name: string; specification: string; } interface BringItems { uuid: string; status: string; purchase: BringItem[]; recently: BringItem[]; } // Load credentials from environment variables const CREDENTIALS: Credentials = { mail: process.env.BRING_EMAIL || '', password: process.env.BRING_PASSWORD || '' }; const LIST_UUID: string = process.env.BRING_LIST_UUID || ''; // Validate required environment variables if (!CREDENTIALS.mail || !CREDENTIALS.password || !LIST_UUID) { console.error('Error: Missing required environment variables'); console.error('Please set: BRING_EMAIL, BRING_PASSWORD, BRING_LIST_UUID'); console.error('See SKILL.md for setup instructions'); process.exit(1); } async function main(): Promise { const args: string[] = process.argv.slice(2); const command: string | undefined = args[0]; if (!command) { console.error('Usage: bring [args...]'); process.exit(1); } const bring = new BringApi(CREDENTIALS); try { await bring.login(); switch (command) { case 'add': await addItem(bring, args.slice(1)); break; case 'list': await listItems(bring); break; case 'remove': await removeItem(bring, args.slice(1)); break; case 'recent': await recentItems(bring); break; default: console.error(`Unknown command: ${command}`); console.error('Available commands: add, list, remove, recent'); process.exit(1); } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; console.error('Error:', errorMessage); process.exit(1); } } /** * Add an item to the shopping list */ async function addItem(bring: any, args: string[]): Promise { const itemName: string | undefined = args[0]; const specification: string = args.slice(1).join(' ') || ''; if (!itemName) { console.error('Usage: bring add [specification]'); process.exit(1); } await bring.saveItem(LIST_UUID, itemName, specification); if (specification) { console.log(`✓ "${itemName}" (${specification}) added to shopping list`); } else { console.log(`✓ "${itemName}" added to shopping list`); } } /** * List all items currently on the shopping list */ async function listItems(bring: any): Promise { const items: BringItems = await bring.getItems(LIST_UUID); if (items.purchase.length === 0) { console.log('Shopping list is empty'); return; } console.log('Shopping list:'); console.log(''); items.purchase.forEach((item: BringItem, index: number) => { if (item.specification) { console.log(`${index + 1}. ${item.name} (${item.specification})`); } else { console.log(`${index + 1}. ${item.name}`); } }); } /** * Remove an item from the shopping list (mark as purchased) */ async function removeItem(bring: any, args: string[]): Promise { const itemName: string = args.join(' '); if (!itemName) { console.error('Usage: bring remove '); process.exit(1); } await bring.removeItem(LIST_UUID, itemName); console.log(`✓ "${itemName}" removed from shopping list`); } /** * Show recently purchased items */ async function recentItems(bring: any): Promise { const items: BringItems = await bring.getItems(LIST_UUID); if (items.recently.length === 0) { console.log('No recently purchased items'); return; } console.log('Recently purchased:'); console.log(''); items.recently.slice(0, 10).forEach((item: BringItem, index: number) => { if (item.specification) { console.log(`${index + 1}. ${item.name} (${item.specification})`); } else { console.log(`${index + 1}. ${item.name}`); } }); } main();