diff --git a/src/modules/twilio/twilio.service.ts b/src/modules/twilio/twilio.service.ts index 7ed378552..e5c366d0c 100644 --- a/src/modules/twilio/twilio.service.ts +++ b/src/modules/twilio/twilio.service.ts @@ -1,17 +1,47 @@ import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import Twilio from 'twilio'; +import twilio from 'twilio'; +import PQueue from 'p-queue'; +import pRetry from 'p-retry'; +import TwilioClient from 'twilio/lib/rest/Twilio'; +import { MessageListInstanceCreateOptions } from 'twilio/lib/rest/api/v2010/account/message'; @Injectable() export class TwilioService { - twilio: Twilio; + twilio: TwilioClient; logger = new Logger('twilio'); + private queue = new PQueue({ concurrency: 1 }); constructor(private configService: ConfigService) { - const twilioApiKey = this.configService.get('sms.twilioApiKey'); - if (!twilioApiKey) this.logger.warn('Twilio API key not found'); - this.twilio = new Twilio(twilioApiKey ?? '', { - apiVersion: '2020-08-27', - }); + const twilioAccountSid = this.configService.get( + 'sms.twilioAccountSid', + ); + const twilioAuthToken = this.configService.get( + 'sms.twilioAuthToken', + ); + if (!twilioAccountSid || !twilioAuthToken) + this.logger.warn('Twilio account SID/auth token not found'); + this.twilio = twilio(twilioAccountSid ?? '', twilioAuthToken ?? ''); + } + + send(options: MessageListInstanceCreateOptions) { + this.queue + .add(() => + pRetry(() => this.sendSms(options), { + retries: 3, + onFailedAttempt: (error) => { + this.logger.error( + `SMS to ${options.to} failed, retrying (${error.retriesLeft} attempts left)`, + error.name, + ); + }, + }), + ) + .then(() => {}) + .catch(() => {}); + } + + private async sendSms(options: MessageListInstanceCreateOptions) { + return this.twilio.messages.create(options); } }