mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-07-09 22:57:26 +00:00
feat: sms using twillio
This commit is contained in:
74
package-lock.json
generated
74
package-lock.json
generated
@ -40,6 +40,7 @@
|
||||
"moment": "^2.30.1",
|
||||
"nestjs-i18n": "^10.4.9",
|
||||
"nestjs-pino": "^4.1.0",
|
||||
"nestjs-twilio": "^4.4.0",
|
||||
"nodemailer": "^6.9.16",
|
||||
"oci-common": "^2.99.0",
|
||||
"oci-sdk": "^2.99.0",
|
||||
@ -3808,7 +3809,6 @@
|
||||
"node_modules/axios": {
|
||||
"version": "1.7.7",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
@ -6350,7 +6350,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
@ -10036,6 +10035,19 @@
|
||||
"pino-http": "^6.4.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nestjs-twilio": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/nestjs-twilio/-/nestjs-twilio-4.4.0.tgz",
|
||||
"integrity": "sha512-TtT+mgVaIsiGNX1J8zkjVhIBxJPsChfU8gfu6dbPyEtde9ewgb5sxhAreOE6STT5U95OiSAlFcqKoqlARCIFxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"twilio": "^5.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": ">=9.0.0",
|
||||
"@nestjs/core": ">=9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nice-try": {
|
||||
"version": "1.0.5",
|
||||
"license": "MIT",
|
||||
@ -15120,8 +15132,7 @@
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pug": {
|
||||
"version": "3.0.3",
|
||||
@ -16020,6 +16031,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/scmp": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz",
|
||||
"integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/secure-json-parse": {
|
||||
"version": "2.7.0",
|
||||
"license": "BSD-3-Clause"
|
||||
@ -17032,6 +17049,46 @@
|
||||
"version": "0.14.5",
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/twilio": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/twilio/-/twilio-5.4.0.tgz",
|
||||
"integrity": "sha512-kEmxzdOLTzXzUEXIkBVwT1Itxlbp+rtGrQogNfPtSE3EjoEsxrxB/9tdMIEbrsioL8CzTk/+fiKNJekAyHxjuQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.4",
|
||||
"dayjs": "^1.11.9",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"qs": "^6.9.4",
|
||||
"scmp": "^2.1.0",
|
||||
"xmlbuilder": "^13.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/twilio/node_modules/jsonwebtoken": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
||||
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jws": "^3.2.2",
|
||||
"lodash.includes": "^4.3.0",
|
||||
"lodash.isboolean": "^3.0.3",
|
||||
"lodash.isinteger": "^4.0.4",
|
||||
"lodash.isnumber": "^3.0.3",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.isstring": "^4.0.1",
|
||||
"lodash.once": "^4.0.0",
|
||||
"ms": "^2.1.1",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12",
|
||||
"npm": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"dev": true,
|
||||
@ -17800,6 +17857,15 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "13.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz",
|
||||
"integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"license": "MIT",
|
||||
|
@ -57,6 +57,7 @@
|
||||
"moment": "^2.30.1",
|
||||
"nestjs-i18n": "^10.4.9",
|
||||
"nestjs-pino": "^4.1.0",
|
||||
"nestjs-twilio": "^4.4.0",
|
||||
"nodemailer": "^6.9.16",
|
||||
"oci-common": "^2.99.0",
|
||||
"oci-sdk": "^2.99.0",
|
||||
|
@ -26,6 +26,7 @@ import { JuniorModule } from './junior/junior.module';
|
||||
import { MoneyRequestModule } from './money-request/money-request.module';
|
||||
import { SavingGoalsModule } from './saving-goals/saving-goals.module';
|
||||
import { TaskModule } from './task/task.module';
|
||||
|
||||
@Module({
|
||||
controllers: [],
|
||||
imports: [
|
||||
|
@ -1,15 +1,25 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { TwilioModule } from 'nestjs-twilio';
|
||||
import { AuthModule } from '~/auth/auth.module';
|
||||
import { buildTwilioOptions } from '~/core/module-options';
|
||||
import { NotificationsController } from './controllers';
|
||||
import { Notification } from './entities';
|
||||
import { NotificationsRepository } from './repositories';
|
||||
import { FirebaseService } from './services/firebase.service';
|
||||
import { NotificationsService } from './services/notifications.service';
|
||||
|
||||
import { TwilioService } from './services/twilio.service';
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Notification]), AuthModule],
|
||||
providers: [NotificationsService, FirebaseService, NotificationsRepository],
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Notification]),
|
||||
AuthModule,
|
||||
TwilioModule.forRootAsync({
|
||||
useFactory: buildTwilioOptions,
|
||||
inject: [ConfigService],
|
||||
}),
|
||||
],
|
||||
providers: [NotificationsService, FirebaseService, NotificationsRepository, TwilioService],
|
||||
exports: [NotificationsService],
|
||||
controllers: [NotificationsController],
|
||||
})
|
||||
|
@ -4,6 +4,7 @@ import { PageOptionsRequestDto } from '~/core/dtos';
|
||||
import { Notification } from '../entities';
|
||||
import { NotificationsRepository } from '../repositories';
|
||||
import { FirebaseService } from './firebase.service';
|
||||
import { TwilioService } from './twilio.service';
|
||||
|
||||
@Injectable()
|
||||
export class NotificationsService {
|
||||
@ -11,6 +12,7 @@ export class NotificationsService {
|
||||
private readonly deviceService: DeviceService,
|
||||
private readonly firebaseService: FirebaseService,
|
||||
private readonly notificationRepository: NotificationsRepository,
|
||||
private readonly twilioService: TwilioService,
|
||||
) {}
|
||||
|
||||
async sendPushNotification(userId: string, title: string, body: string) {
|
||||
@ -25,6 +27,10 @@ export class NotificationsService {
|
||||
return this.firebaseService.sendNotification(tokens, title, body);
|
||||
}
|
||||
|
||||
async sendSMS(to: string, body: string) {
|
||||
await this.twilioService.sendSMS(to, body);
|
||||
}
|
||||
|
||||
async getNotifications(userId: string, pageOptionsDto: PageOptionsRequestDto) {
|
||||
const [[notifications, count], unreadCount] = await Promise.all([
|
||||
this.notificationRepository.getNotifications(userId, pageOptionsDto),
|
||||
|
21
src/common/modules/notification/services/twilio.service.ts
Normal file
21
src/common/modules/notification/services/twilio.service.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { TwilioService as TwilioApiService } from 'nestjs-twilio';
|
||||
import { Environment } from '~/core/enums';
|
||||
@Injectable()
|
||||
export class TwilioService {
|
||||
private logger = new Logger(TwilioService.name);
|
||||
constructor(private readonly twilioService: TwilioApiService, private readonly configService: ConfigService) {}
|
||||
private from = this.configService.getOrThrow('TWILIO_PHONE_NUMBER');
|
||||
sendSMS(to: string, body: string) {
|
||||
if (this.configService.get('NODE_ENV') === Environment.DEV) {
|
||||
this.logger.log(`Skipping SMS sending in DEV environment. Message: ${body} to: ${to}`);
|
||||
return;
|
||||
}
|
||||
return this.twilioService.client.messages.create({
|
||||
body,
|
||||
to,
|
||||
from: this.from,
|
||||
});
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
export * from '././keyv-options';
|
||||
export * from './config-options';
|
||||
export * from './logger-options';
|
||||
export * from './twilio-options';
|
||||
export * from './typeorm-options';
|
||||
|
9
src/core/module-options/twilio-options.ts
Normal file
9
src/core/module-options/twilio-options.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { TwilioModuleOptions } from 'nestjs-twilio';
|
||||
|
||||
export function buildTwilioOptions(config: ConfigService): TwilioModuleOptions {
|
||||
return {
|
||||
accountSid: config.get('TWILIO_ACCOUNT_SID'),
|
||||
authToken: config.get('TWILIO_AUTH_TOKEN'),
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user