Skip to content

Commit

Permalink
refactor(settings): Adds sending of user's address as an SMS with a t…
Browse files Browse the repository at this point in the history
…hreshold of 5 SMSes per day.
  • Loading branch information
mango-habanero committed Oct 28, 2023
1 parent 9c4ea92 commit 3b50754
Showing 1 changed file with 82 additions and 17 deletions.
99 changes: 82 additions & 17 deletions src/machines/settings.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import { createMachine } from 'xstate';
import { L } from '@i18n/i18n-node';
import {PostgresDb} from "@fastify/postgres";
import { Redis as RedisClient } from 'ioredis';
import {
intermediateMachineTranslations,
isOption1,
isOption2,
isOption3,
isOption4,
isOption5,
isOption6,
MachineEvent,
MachineId,
MachineInterface,
UserContext
intermediateMachineTranslations,
isOption1,
isOption2,
isOption3,
isOption4,
isOption5,
isOption6,
isSuccess,
MachineEvent,
MachineId,
MachineInterface, NotifierContext
} from '@machines/utils';
import {translate} from "@i18n/translators";
import {sendSMS} from "@lib/ussd";
import {AccountService} from "@services/account";
import {config} from "@/config";

const stateMachine = createMachine<UserContext, MachineEvent>({

export interface SettingsContext extends NotifierContext {}

const stateMachine = createMachine<SettingsContext, MachineEvent>({
id: MachineId.SETTINGS,
initial: "settingsMenu",
states: {
Expand All @@ -23,9 +33,8 @@ const stateMachine = createMachine<UserContext, MachineEvent>({
},
displayAddress: {
description: 'Displays the address of the current user.',
on: {
BACK: 'settingsMenu'
}
type: 'final',
tags: 'resolved'
},
language: {
description: 'Transitions to language machine',
Expand All @@ -43,6 +52,16 @@ const stateMachine = createMachine<UserContext, MachineEvent>({
description: 'Transitions to profile machine',
type: 'final'
},
sendingAddress: {
description: 'Sends user address to the user via SMS.',
invoke: {
id: 'sendingAddress',
src: 'smsAddress',
onDone: { target: 'displayAddress', cond: 'isSuccess' },
onError: { target: 'displayAddress' }
},
tags: 'invoked'
},
settingsMenu: {
description: 'Displays account management menu.',
on: {
Expand All @@ -53,7 +72,7 @@ const stateMachine = createMachine<UserContext, MachineEvent>({
{ target: 'balances', cond: 'isOption3' },
{ target: 'statement', cond: 'isOption4' },
{ target: 'pinManagement', cond: 'isOption5' },
{ target: 'displayAddress', cond: 'isOption6'}
{ target: 'sendingAddress', cond: 'isOption6'}
]
}
},
Expand All @@ -69,11 +88,57 @@ const stateMachine = createMachine<UserContext, MachineEvent>({
isOption3,
isOption4,
isOption5,
isOption6
isOption6,
isSuccess
},
services: {
smsAddress
}
})

export const settingsMachine: MachineInterface = {
stateMachine,
translate: intermediateMachineTranslations
}


async function updateAddressSmsThreshold(db: PostgresDb, redis: RedisClient, phoneNumber: string, threshold: number) {
const thresholdKey = `address-sms-threshold-reset-${phoneNumber}`;
const lastReset = await redis.get(thresholdKey);
const thresholdResetTime = lastReset ? parseInt(lastReset, 10) : Date.now();

if (Date.now() - thresholdResetTime > 86400000 || !lastReset) {
threshold = 1;
await redis.set(thresholdKey, Date.now().toString());
}

await new AccountService(db, redis).updateAddressSmsThreshold(threshold, phoneNumber);
}


async function smsAddress(context: SettingsContext) {
const {
connections: { db, redis},
notifier,
user: { account: { address, address_sms_threshold, language, phone_number }
} } = context;

if (address_sms_threshold && address_sms_threshold >= config.ADDRESS_SMS_THRESHOLD){
console.warn(`SMS address threshold reached for ${phone_number}`);
return { success: true };
}

const translator = L[language][MachineId.SETTINGS];
let message: string = await translate('displayAddress', translator, { address });

// remove END from message.
message = message.replace(/END /g, '')

// replace new line with space for SMS.
message = message.replace(/\n/g, ' ');

await sendSMS(message, notifier, [phone_number]);
const threshold = address_sms_threshold ? address_sms_threshold + 1 : 1;
await updateAddressSmsThreshold(db, redis.persistent, phone_number, threshold);
return { success: true };
}

0 comments on commit 3b50754

Please sign in to comment.