UNPKG

@puberty-labs/bi-tch

Version:

BiTCH-MCP: Autonomous AI Coordination Platform - BETA: ZombieDust Protocol operational! Revolutionary AI-to-AI coordination with pure MCP integration. FOLLOW BETA RELEASES for latest features!

363 lines (312 loc) โ€ข 10.1 kB
/** * BitchNotifier - Sends notifications with attitude * * Handles system notifications for urgent bitch-messages, * bitch-slaps, and other important workspace drama. * * Because sometimes you need to get someone's attention aggressively. */ const notifier = require('node-notifier'); const path = require('path'); const chalk = require('chalk'); const { BitchError } = require('./ErrorHandler'); class BitchNotifier { constructor() { this.isEnabled = true; this.soundEnabled = true; this.iconPath = this.getNotificationIcon(); } /** * Get the notification icon path */ getNotificationIcon() { // In a real implementation, we'd bundle an icon file // For now, we'll use the system default return null; } /** * Send a priority notification */ async sendPriorityNotification(targetWorkspace, message) { if (!this.isEnabled) { console.log(chalk.gray('๐Ÿ“ต Notifications disabled')); return; } try { const notificationData = { title: `๐Ÿšจ Urgent BiTCH Message`, message: `From: ${targetWorkspace}\n${this.truncateMessage(message)}`, icon: this.iconPath, sound: this.soundEnabled ? 'Basso' : false, timeout: 10, actions: ['Reply', 'Ignore'], dropdownLabel: 'BiTCH Actions', closeLabel: 'Dismiss', wait: false }; await this.sendNotification(notificationData); console.log(chalk.green('๐Ÿ”” Priority notification sent')); } catch (error) { console.log(chalk.yellow(`โš ๏ธ Failed to send priority notification: ${error.message}`)); } } /** * Send a bitch-slap notification (maximum urgency) */ async sendBitchSlap(targetWorkspace, message) { if (!this.isEnabled) { console.log(chalk.gray('๐Ÿ“ต Notifications disabled')); return; } try { const slapMessages = [ '๐Ÿ‘‹ BITCH-SLAP INCOMING!', '๐Ÿ’ฅ WAKE UP CALL!', '๐Ÿšจ URGENT BITCH ALERT!', 'โšก PRIORITY INTERRUPT!', '๐Ÿ”ฅ EMERGENCY BITCH-UATION!' ]; const randomSlapTitle = slapMessages[Math.floor(Math.random() * slapMessages.length)]; const notificationData = { title: randomSlapTitle, message: `${targetWorkspace} needs your attention NOW!\n${this.truncateMessage(message)}`, icon: this.iconPath, sound: this.soundEnabled ? 'Funk' : false, timeout: 15, actions: ['Respond', 'Snooze'], dropdownLabel: 'Emergency Actions', closeLabel: 'I\'m awake!', wait: false, urgency: 'critical' }; await this.sendNotification(notificationData); // Send multiple notifications for maximum annoyance setTimeout(() => { this.sendNotification({ ...notificationData, title: '๐Ÿ‘‹ Still waiting...', message: 'Your BiTCH is getting impatient.', timeout: 5 }); }, 3000); console.log(chalk.red('๐Ÿ‘‹ BITCH-SLAP notification delivered with maximum prejudice!')); } catch (error) { console.log(chalk.yellow(`โš ๏ธ Failed to send bitch-slap: ${error.message}`)); } } /** * Send a regular message notification */ async sendMessageNotification(from, message, priority = false) { if (!this.isEnabled) { return; } try { const title = priority ? '๐Ÿšจ Priority BiTCH Message' : '๐Ÿ“จ New BiTCH Message'; const sound = priority ? 'Basso' : 'Blow'; const notificationData = { title, message: `From: ${from}\n${this.truncateMessage(message)}`, icon: this.iconPath, sound: this.soundEnabled ? sound : false, timeout: priority ? 10 : 5, actions: priority ? ['Reply', 'Mark Read'] : ['View'], wait: false }; await this.sendNotification(notificationData); console.log(chalk.blue(`๐Ÿ”” Message notification sent (${priority ? 'priority' : 'normal'})`)); } catch (error) { console.log(chalk.gray(`โš ๏ธ Failed to send message notification: ${error.message}`)); } } /** * Send a workspace status notification */ async sendWorkspaceStatusNotification(status, details) { if (!this.isEnabled) { return; } try { const statusEmojis = { 'connected': '๐ŸŸข', 'disconnected': '๐Ÿ”ด', 'error': '๐Ÿ’ฅ', 'warning': 'โš ๏ธ', 'info': '๐Ÿ’ก' }; const notificationData = { title: `${statusEmojis[status] || '๐Ÿ“Š'} BiTCH Workspace Status`, message: details, icon: this.iconPath, sound: this.soundEnabled && status === 'error' ? 'Basso' : false, timeout: 5, wait: false }; await this.sendNotification(notificationData); } catch (error) { console.log(chalk.gray(`โš ๏ธ Failed to send status notification: ${error.message}`)); } } /** * Send a custom notification with BiTCH personality */ async sendCustomNotification(title, message, options = {}) { if (!this.isEnabled) { return; } try { const bitchyTitles = { 'success': '๐ŸŽ‰ BiTCH Success (Shocking!)', 'error': '๐Ÿ’ฅ BiTCH Error (Typical)', 'warning': 'โš ๏ธ BiTCH Warning (Listen Up)', 'info': '๐Ÿ’ก BiTCH Info (Pay Attention)', 'reminder': 'โฐ BiTCH Reminder (Don\'t Forget)' }; const finalTitle = bitchyTitles[options.type] || title; const notificationData = { title: finalTitle, message: this.addBitchPersonality(message), icon: this.iconPath, sound: this.soundEnabled ? (options.sound || 'Blow') : false, timeout: options.timeout || 5, actions: options.actions || ['OK'], wait: false, ...options }; await this.sendNotification(notificationData); } catch (error) { console.log(chalk.gray(`โš ๏ธ Failed to send custom notification: ${error.message}`)); } } /** * Send the actual notification using node-notifier */ async sendNotification(notificationData) { return new Promise((resolve, reject) => { notifier.notify(notificationData, (error, response) => { if (error) { reject(error); } else { resolve(response); } }); }); } /** * Truncate message for notification display */ truncateMessage(message, maxLength = 100) { if (message.length <= maxLength) { return message; } return message.substring(0, maxLength - 3) + '...'; } /** * Add BiTCH personality to notification messages */ addBitchPersonality(message) { const personalityPhrases = [ 'Just so you know', 'FYI', 'In case you care', 'Thought you should know', 'Breaking news', 'Update from your BiTCH' ]; const randomPhrase = personalityPhrases[Math.floor(Math.random() * personalityPhrases.length)]; return `${randomPhrase}: ${message}`; } /** * Enable/disable notifications */ setEnabled(enabled) { this.isEnabled = enabled; console.log(chalk.cyan(`๐Ÿ”” Notifications ${enabled ? 'enabled' : 'disabled'}`)); } /** * Enable/disable notification sounds */ setSoundEnabled(enabled) { this.soundEnabled = enabled; console.log(chalk.cyan(`๐Ÿ”Š Notification sounds ${enabled ? 'enabled' : 'disabled'}`)); } /** * Test notifications */ async testNotifications() { try { console.log(chalk.cyan('๐Ÿงช Testing BiTCH notifications...')); // Test basic notification await this.sendCustomNotification('BiTCH Test', 'If you can see this, notifications are working!', { type: 'info', timeout: 3 }); // Test priority notification setTimeout(async () => { await this.sendPriorityNotification('Test Workspace', 'This is a test priority message'); }, 2000); // Test bitch-slap (if user confirms) setTimeout(async () => { console.log(chalk.yellow('โš ๏ธ Testing bitch-slap notification in 3 seconds...')); setTimeout(async () => { await this.sendBitchSlap('Test Workspace', 'This is a test bitch-slap (don\'t worry, it\'s just a test)'); }, 3000); }, 4000); console.log(chalk.green('โœ… Notification test sequence initiated')); } catch (error) { throw new BitchError(`Notification test failed: ${error.message}`, 'NOTIFICATION_TEST_FAILED'); } } /** * Get notification statistics */ getNotificationStats() { // This would be implemented with actual tracking return { enabled: this.isEnabled, soundEnabled: this.soundEnabled, totalSent: 0, prioritySent: 0, bitchSlapsSent: 0, lastSent: null, platform: process.platform }; } /** * Schedule a delayed notification */ async scheduleNotification(title, message, delayMs, options = {}) { setTimeout(async () => { try { await this.sendCustomNotification(title, message, { ...options, type: 'reminder' }); } catch (error) { console.log(chalk.gray(`โš ๏ธ Scheduled notification failed: ${error.message}`)); } }, delayMs); console.log(chalk.blue(`โฐ Notification scheduled for ${Math.round(delayMs / 1000)} seconds`)); } /** * Send a notification when BiTCH starts up */ async sendStartupNotification() { if (!this.isEnabled) { return; } const startupMessages = [ 'BiTCH is ready to cause some drama!', 'Your workspace communication assistant is online.', 'Ready to facilitate some professional bitching.', 'BiTCH initialized. Let the workspace drama begin!', 'Communication bridge established. Start complaining!' ]; const randomMessage = startupMessages[Math.floor(Math.random() * startupMessages.length)]; await this.sendCustomNotification('BiTCH Online', randomMessage, { type: 'success', timeout: 3 }); } } module.exports = BitchNotifier;