← back to Wine Finder Next

lib/services/slackNotifier.js

155 lines

const axios = require('axios');

class SlackNotifier {
  constructor() {
    this.webhookUrl = process.env.SLACK_WEBHOOK_URL;
    this.enabled = !!this.webhookUrl;
  }

  // Check if Slack integration is enabled
  isEnabled() {
    return this.enabled && this.webhookUrl && this.webhookUrl.startsWith('https://hooks.slack.com');
  }

  // Send a price spike alert to Slack
  async sendPriceSpikeAlert(wineData, oldPrice, newPrice, percentageIncrease) {
    try {
      if (!this.isEnabled()) {
        console.warn('Slack webhook not configured. Skipping notification.');
        return { success: false, error: 'Slack not configured' };
      }

      const message = {
        text: `🚨 Wine Price Alert!`,
        blocks: [
          {
            type: 'header',
            text: {
              type: 'plain_text',
              text: '🚨 Wine Price Spike Detected!',
              emoji: true
            }
          },
          {
            type: 'section',
            fields: [
              {
                type: 'mrkdwn',
                text: `*Wine:*\n${wineData.name}`
              },
              {
                type: 'mrkdwn',
                text: `*Source:*\n${wineData.source || 'K&L Wine Merchants'}`
              }
            ]
          },
          {
            type: 'section',
            fields: [
              {
                type: 'mrkdwn',
                text: `*Previous Price:*\n$${oldPrice.toFixed(2)}`
              },
              {
                type: 'mrkdwn',
                text: `*Current Price:*\n$${newPrice.toFixed(2)}`
              }
            ]
          },
          {
            type: 'section',
            text: {
              type: 'mrkdwn',
              text: `*Price Increase:* ${percentageIncrease.toFixed(1)}% 📈`
            }
          }
        ]
      };

      // Add URL if available
      if (wineData.url) {
        message.blocks.push({
          type: 'section',
          text: {
            type: 'mrkdwn',
            text: `<${wineData.url}|View on ${wineData.source}>`
          }
        });
      }

      message.blocks.push({
        type: 'context',
        elements: [
          {
            type: 'mrkdwn',
            text: `🍷 Red Thunder Wine Tracker | ${new Date().toLocaleString()}`
          }
        ]
      });

      // Send to Slack
      await axios.post(this.webhookUrl, message, {
        headers: {
          'Content-Type': 'application/json'
        },
        timeout: 10000
      });

      console.log(`✅ Slack alert sent for ${wineData.name}`);
      return { success: true };

    } catch (error) {
      console.error('Error sending Slack notification:', error.message);
      return { success: false, error: error.message };
    }
  }

  // Send a general notification
  async sendNotification(message) {
    try {
      if (!this.isEnabled()) {
        console.warn('Slack webhook not configured. Skipping notification.');
        return { success: false, error: 'Slack not configured' };
      }

      const payload = {
        text: message,
        blocks: [
          {
            type: 'section',
            text: {
              type: 'mrkdwn',
              text: message
            }
          },
          {
            type: 'context',
            elements: [
              {
                type: 'mrkdwn',
                text: `🍷 Red Thunder Wine Tracker | ${new Date().toLocaleString()}`
              }
            ]
          }
        ]
      };

      await axios.post(this.webhookUrl, payload, {
        headers: {
          'Content-Type': 'application/json'
        },
        timeout: 10000
      });

      console.log('✅ Slack notification sent');
      return { success: true };

    } catch (error) {
      console.error('Error sending Slack notification:', error.message);
      return { success: false, error: error.message };
    }
  }
}

module.exports = new SlackNotifier();