Browse Source

FEATURE | alpha sms library

merge-requests/236/head
Vitalik 2 years ago
parent
commit
0c919acbcb
  1. 79
      package-lock.json
  2. 1
      package.json
  3. 6
      src/app.module.ts
  4. 2
      src/core/namespaces/tasks.namespace.ts
  5. 22
      src/domain/old-database-seed/services/tasks.service.ts
  6. 2
      src/domain/sms/const/index.ts
  7. 3
      src/domain/sms/interfaces/sms-module-options.interface.ts
  8. 45
      src/domain/sms/services/alphasms.service.ts
  9. 46
      src/domain/sms/sms.module.ts
  10. 11
      src/domain/tasks/services/tasks-events.service.ts
  11. 3
      src/domain/users/users.module.ts
  12. 5
      src/shared/helpers/get-env.helpers.ts

79
package-lock.json generated

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
"license": "UNLICENSED",
"dependencies": {
"@nestjs-modules/mailer": "^1.6.0",
"@nestjs/axios": "^1.0.1",
"@nestjs/common": "^8.4.4",
"@nestjs/core": "^8.4.4",
"@nestjs/event-emitter": "^1.0.0",
@ -2656,6 +2657,42 @@ @@ -2656,6 +2657,42 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@nestjs/axios": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-1.0.1.tgz",
"integrity": "sha512-TpoZM/0ZJ9xiC04qkRDFod93LCZ12TQARRU3ejDvBK2E8emvzM4HThOs5ePklVxce4Q1ZsnrIWqnImvoDmJYnQ==",
"dependencies": {
"axios": "1.2.1"
},
"peerDependencies": {
"@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0 || ^7.0.0"
}
},
"node_modules/@nestjs/axios/node_modules/axios": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/@nestjs/axios/node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/@nestjs/cli": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-7.6.0.tgz",
@ -8142,9 +8179,9 @@ @@ -8142,9 +8179,9 @@
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==",
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"funding": [
{
"type": "individual",
@ -19095,6 +19132,36 @@ @@ -19095,6 +19132,36 @@
}
}
},
"@nestjs/axios": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-1.0.1.tgz",
"integrity": "sha512-TpoZM/0ZJ9xiC04qkRDFod93LCZ12TQARRU3ejDvBK2E8emvzM4HThOs5ePklVxce4Q1ZsnrIWqnImvoDmJYnQ==",
"requires": {
"axios": "1.2.1"
},
"dependencies": {
"axios": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
}
}
},
"@nestjs/cli": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-7.6.0.tgz",
@ -23434,9 +23501,9 @@ @@ -23434,9 +23501,9 @@
"dev": true
},
"follow-redirects": {
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
"integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w=="
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
},
"foreach": {
"version": "2.0.5",

1
package.json

@ -26,6 +26,7 @@ @@ -26,6 +26,7 @@
},
"dependencies": {
"@nestjs-modules/mailer": "^1.6.0",
"@nestjs/axios": "^1.0.1",
"@nestjs/common": "^8.4.4",
"@nestjs/core": "^8.4.4",
"@nestjs/event-emitter": "^1.0.0",

6
src/app.module.ts

@ -43,7 +43,11 @@ const imports = [ @@ -43,7 +43,11 @@ const imports = [
PushNotificationsModule.forRoot($config.getPushNotificationsConfig()),
ScheduleModule.forRoot(),
FilesStorageModule.forRoot($config.getFilesStorageConfig()),
SmsModule.forRoot({ test: stringToBoolean(getEnv('SMS_TEST_MODE')) }),
SmsModule.forRoot({
test: stringToBoolean(getEnv('SMS_TEST_MODE')),
alphasmsApiKey: getEnv('SMS_ALPHASMS_API_KEY', true),
alphasmsFrom: getEnv('SMS_ALPHASMS_FROM', true),
}),
MailerModule.forRoot($config.getMailerConfig()),
UsersModule.forRoot({ passwordHashSalt: getEnv('LOCAL_HASH_SALT') }),
SessionsModule.forRoot(),

2
src/core/namespaces/tasks.namespace.ts

@ -616,6 +616,6 @@ export namespace Tasks { @@ -616,6 +616,6 @@ export namespace Tasks {
* @param {payload} AddTaskEventPayload
*/
export interface ITasksEventsService {
addEvent(payload: AddTaskEventPayload): Promise<void>
addEvent(payload: AddTaskEventPayload, isSystemCreated?: boolean): Promise<void>
}
}

22
src/domain/old-database-seed/services/tasks.service.ts

@ -189,14 +189,20 @@ export class OldDBTasksService { @@ -189,14 +189,20 @@ export class OldDBTasksService {
const tasksIds = await this.getNewEntitiesIds(OldDbRelationType.Tasks)
for (const taskId of tasksIds) {
for (const userId of usersIds) {
await this.tasksEventsService.addEvent({
taskId,
userId,
event: Tasks.Event.Read,
allowDuplicate: false,
})
}
await Promise.all(
usersIds.map(async userId => {
await this.tasksEventsService.addEvent(
{
taskId,
userId,
event: Tasks.Event.Read,
allowDuplicate: false,
},
true,
)
}),
)
console.log('Added events ', taskId)
}
}
}

2
src/domain/sms/const/index.ts

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
export const ALPHASMS_API_KEY = Symbol('ALPHASMS_API_KEY')
export const ALPHASMS_FROM = Symbol('ALPHASMS_FROM')

3
src/domain/sms/interfaces/sms-module-options.interface.ts

@ -1,3 +1,6 @@ @@ -1,3 +1,6 @@
export interface ISmsModuleOptions {
test: boolean
alphasmsApiKey?: string
alphasmsFrom?: string
}

45
src/domain/sms/services/alphasms.service.ts

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
import { HttpService } from '@nestjs/axios'
import { Inject, Injectable } from '@nestjs/common'
import { AxiosError } from 'axios'
import { catchError, firstValueFrom } from 'rxjs'
import { Sms } from 'src/core'
import { ALPHASMS_API_KEY, ALPHASMS_FROM } from '../const'
@Injectable()
export class AlphaSmsService implements Sms.ISmsService {
@Inject(ALPHASMS_API_KEY)
private readonly alphasmsApiKey: string
@Inject(ALPHASMS_FROM)
private readonly alphasmsFrom: string
constructor(private readonly httpService: HttpService) {}
onModuleInit() {
if (!this.alphasmsApiKey || !this.alphasmsFrom) throw new Error('AlphaSms not config')
}
public async send(payload: Sms.ISendPayload): Promise<void> {
const result = await firstValueFrom(
this.httpService
.get('https://alphasms.ua/api/http.php', {
params: {
version: 'http',
key: this.alphasmsApiKey,
from: this.alphasmsFrom,
to: payload.to,
message: payload.text,
command: 'send',
},
timeout: 36000,
})
.pipe(
catchError((error: AxiosError) => {
console.log('error', error)
throw 'An error happened!'
}),
),
)
console.log(result)
}
}

46
src/domain/sms/sms.module.ts

@ -1,8 +1,10 @@ @@ -1,8 +1,10 @@
import { HttpModule } from '@nestjs/axios'
import { DynamicModule, Module } from '@nestjs/common'
import { SMS_SERVICE } from 'src/core/consts'
import { provideClass } from 'src/shared'
import { ALPHASMS_API_KEY, ALPHASMS_FROM } from './const'
import { ISmsModuleOptions } from './interfaces'
import { OneSignalSmsService } from './services/one-signal-sms.service'
import { AlphaSmsService } from './services/alphasms.service'
import { TelegramSmsService } from './services/telegram-sms.service'
@Module({})
@ -18,19 +20,51 @@ export class SmsModule { @@ -18,19 +20,51 @@ export class SmsModule {
return {
module: SmsModule,
imports: [
HttpModule.register({
timeout: 5000,
maxRedirects: 3,
baseURL: 'https://alphasms.ua/api/http.php',
}),
],
providers: [
provideClass(
SMS_SERVICE,
SmsModule.options.test ? TelegramSmsService : AlphaSmsService,
),
{
provide: ALPHASMS_API_KEY,
useValue: SmsModule.options.alphasmsApiKey,
},
{
provide: ALPHASMS_FROM,
useValue: SmsModule.options.alphasmsFrom,
},
],
}
}
static forFeature(): DynamicModule {
console.log('SmsModule.options.test', SmsModule.options.test)
return {
module: SmsModule,
providers: [
provideClass(
SMS_SERVICE,
SmsModule.options.test ? TelegramSmsService : OneSignalSmsService,
),
provideClass(SMS_SERVICE, true ? TelegramSmsService : AlphaSmsService),
// {
// provide: ALPHASMS_API_KEY,
// useValue: SmsModule.options.alphasmsApiKey,
// },
// {
// provide: ALPHASMS_FROM,
// useValue: SmsModule.options.alphasmsFrom,
// },
],
imports: [
HttpModule.register({
timeout: 36000,
maxRedirects: 3,
}),
],
imports: [],
exports: SmsModule.getExports(),
}
}

11
src/domain/tasks/services/tasks-events.service.ts

@ -16,7 +16,7 @@ export class TasksEventsService implements Tasks.ITasksEventsService { @@ -16,7 +16,7 @@ export class TasksEventsService implements Tasks.ITasksEventsService {
constructor(private readonly eventEmitter: EventEmitter2) {}
public async addEvent(payload: Tasks.AddTaskEventPayload) {
public async addEvent(payload: Tasks.AddTaskEventPayload, isSystemCreated = false) {
const isExistEvent = await this.checkExistEvent(
payload.taskId,
payload.userId,
@ -31,10 +31,11 @@ export class TasksEventsService implements Tasks.ITasksEventsService { @@ -31,10 +31,11 @@ export class TasksEventsService implements Tasks.ITasksEventsService {
payload: payload.payload,
})
this.eventEmitter.emit(Events.OnUpdateEntity, {
type: Versions.EntityType.Task,
entityId: payload.taskId,
})
if (!isSystemCreated)
this.eventEmitter.emit(Events.OnUpdateEntity, {
type: Versions.EntityType.Task,
entityId: payload.taskId,
})
}
}

3
src/domain/users/users.module.ts

@ -37,7 +37,6 @@ export class UsersModule { @@ -37,7 +37,6 @@ export class UsersModule {
provideEntity(USERS_INFOS_REPOSITORY, UserInfo),
provideEntity(USERS_FACTORIES_RELATIONS_REPOSITORY, UserFactoriesRelations),
provideEntity(USERS_FACTORIES_DIRECTORS_REPOSITORY, UserFactoriesDirector),
...USERS_SEEDERS,
]
}
@ -66,7 +65,7 @@ export class UsersModule { @@ -66,7 +65,7 @@ export class UsersModule {
return {
module: UsersModule,
providers: UsersModule.getProviders(),
providers: [...UsersModule.getProviders(), ...USERS_SEEDERS],
imports: UsersModule.getImports(),
exports: UsersModule.getExports(),
}

5
src/shared/helpers/get-env.helpers.ts

@ -4,10 +4,11 @@ const testEnv = { @@ -4,10 +4,11 @@ const testEnv = {
const isTest = process.env.NODE_ENV === 'test'
export const getEnv = (name: string): string => {
export const getEnv = (name: string, optional = false): string => {
const value = isTest ? testEnv[name] : process.env[name]
if (value === undefined || value === null) throw new Error('Not found env var: ' + name)
if (!optional && (value === undefined || value === null))
throw new Error('Not found env var: ' + name)
return value
}

Loading…
Cancel
Save