perplexity-hackathon-LawMitra / perplexity_hackathon / src / services / twilioService.ts
twilioService.ts
Raw
import twilio from 'twilio';
import config from '../config';
import { store } from '../utils/tempStore';
import axios from 'axios';
import fs from 'fs';
import path from 'path';
import { promisify } from 'util';

const writeFile = promisify(fs.writeFile);

interface WhatsAppMessage {
  text?: string;
  mediaUrl?: string;
  from: string;
}

export class TwilioService {
  private client: twilio.Twilio;
  private readonly uploadsDir: string;

  constructor() {
    this.client = twilio(
      config.twilio.accountSid,
      config.twilio.authToken
    );
    this.uploadsDir = path.join(__dirname, '../../tmp/uploads');
    fs.mkdirSync(this.uploadsDir, { recursive: true });
  }

  async downloadVoiceMessage(mediaUrl: string): Promise<string> {
    try {
      const response = await axios({
        method: 'GET',
        url: mediaUrl,
        responseType: 'arraybuffer',
        auth: {
          username: config.twilio.accountSid,
          password: config.twilio.authToken,
        },
      });

      const fileName = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}.ogg`;
      const filePath = path.join(this.uploadsDir, fileName);
      
      await writeFile(filePath, response.data);
      return filePath;
    } catch (error) {
      console.error('Error downloading voice message:', error);
      throw new Error('Failed to download voice message');
    }
  }

  async sendTextMessage(to: string, message: string): Promise<void> {
    try {
      await this.client.messages.create({
        from: `whatsapp:${config.twilio.phoneNumber}`,
        to: `whatsapp:${to}`,
        body: message,
      });
    } catch (error) {
      console.error('Error sending WhatsApp message:', error);
      throw new Error('Failed to send WhatsApp message');
    }
  }

  async sendVoiceMessage(to: string, audioPath: string): Promise<void> {
    try {
      await this.client.messages.create({
        from: `whatsapp:${config.twilio.phoneNumber}`,
        to: `whatsapp:${to}`,
        mediaUrl: [audioPath],
      });
    } catch (error) {
      console.error('Error sending WhatsApp voice message:', error);
      throw new Error('Failed to send WhatsApp voice message');
    }
  }

  async sendSimplifiedResponse(
    to: string,
    simplified: {
      summary: string;
      keyPoints: string[];
      simplified: string;
    }
  ): Promise<void> {
    const message = `๐Ÿ“ Summary: ${simplified.summary}\n\n` +
      '๐Ÿ”‘ Key Points:\n' +
      simplified.keyPoints.map(point => `โ€ข ${point}`).join('\n') + '\n\n' +
      '๐Ÿ“š Detailed Explanation:\n' +
      simplified.simplified;

    await this.sendTextMessage(to, message);
  }

  validateWebhook(twilioSignature: string, url: string, params: any): boolean {
    return twilio.validateRequest(
      config.twilio.authToken,
      twilioSignature,
      url,
      params
    );
  }
}

export const twilioService = new TwilioService();