UNPKG

simple-sms-sender

Version:

Simple SMS sender to multiple recipients using Twilio

138 lines (137 loc) 4.26 kB
// src/SmsSender.ts import twilio from "twilio"; var SmsSender = class { /** Twilio Account SID */ accountSid; /** Twilio client instance */ client; /** Sender's phone number */ fromNumber; /** Logger for logging messages and errors */ logger; /** Twilio SID */ sid; /** Twilio secret */ secret; /** * Creates an instance of SmsSender. * @param accountSid - Twilio Account SID. * @param fromNumber - Sender's phone number. * @param logger - Logger for logging messages and errors. * @param sid - Twilio SID. * @param secret - Twilio secret. */ constructor({ accountSid, fromNumber, logger, sid, secret }) { this.accountSid = accountSid; this.logger = logger || { error: console.error.bind(console), info: console.log.bind(console) }; this.fromNumber = fromNumber; this.sid = sid; this.secret = secret; this.client = twilio(this.sid, this.secret, { accountSid: this.accountSid }); } /** * Sends an SMS message to a list of recipients. * @param body - The content of the SMS message. * @param recipients - Array of recipient phone numbers. * @param scheduledTime - Optional ISO 8601 formatted date/time to schedule the message. * @throws Will throw an error if the body or recipients are empty. * @returns A promise that resolves to an array of sent message objects. */ async sendSms({ body, recipients, scheduledTime }) { if (!body || body.length === 0) { throw new Error("No body to send SMS"); } if (!recipients || recipients.length === 0) { throw new Error("No recipients to send SMS"); } if (scheduledTime) { this.validateScheduledTime(scheduledTime); } const sendSmsToNumber = async (phoneNumber) => { const to = phoneNumber?.trim(); if (!to) { this.logger.error("Not a valid phone number to send SMS"); return; } this.logger.info(`Trying to send SMS to number ${phoneNumber}`); try { const message = await this.client.messages.create({ body, to, from: this.fromNumber, ...scheduledTime && { sendAt: new Date(scheduledTime) } }); const { errorCode, errorMessage, status } = message; if (errorCode) { this.logger.error( `There was an error sending SMS to number ${phoneNumber} (${errorCode} - ${errorMessage})` ); } else { this.logger.info( `Sent SMS to number ${phoneNumber} successful (status ${status})` ); } return message; } catch (error) { this.logger.error( `Could not send SMS to number '${phoneNumber}'`, error ); } return; }; return Promise.all(recipients.map(sendSmsToNumber)); } /** * Sends multiple SMS messages. * @param messages - Array of messages to send. * @returns A promise that resolves to an array of sent message objects. */ async sendMultipleSms(messages) { return Promise.all(messages.map((message) => this.sendSms(message))); } /** * Validates the scheduled time format and ensures it's in the future. * @param scheduledTime - ISO 8601 formatted date/time string. * @throws Will throw an error if the format is invalid or time is in the past. */ validateScheduledTime(scheduledTime) { try { const scheduledDate = new Date(scheduledTime); if (isNaN(scheduledDate.getTime())) { throw new Error("Invalid date format"); } const now = /* @__PURE__ */ new Date(); if (scheduledDate <= now) { throw new Error("Scheduled time must be in the future"); } const maxFutureDate = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1e3); if (scheduledDate > maxFutureDate) { throw new Error( "Scheduled time cannot be more than 7 days in the future" ); } } catch (error) { if (error instanceof Error) { throw new Error(`Invalid scheduledTime: ${error.message}`); } throw new Error( "Invalid scheduledTime format. Please use ISO 8601 format (e.g., 2024-01-01T12:00:00Z)" ); } } }; export { SmsSender };