UNPKG

@benshi.ai/js-sdk

Version:

Benshi SDK

118 lines (96 loc) 4.16 kB
import { CTAType, INudgesRepository, Nudge } from './repositories/nudges/typings' import { EventEmitter } from 'events'; import { NotificationAction, NotificationDispatcher } from '../drivers/notifications/typings' import { IStorage } from '../drivers/storage/typings' import { DateTime } from 'luxon' import { INudgeManager, NudgeManagerAction } from './BsNudgeManager.typings'; interface IndexedNudge { [key: string]: Nudge } export default class NudgeManager extends EventEmitter implements INudgeManager { private timersId = [] private notificationDispatcher private nudgesRepository private refreshInterval = 5 * 60 * 1000 private indexedNudges: IndexedNudge = {} public constructor( userId: string, notificationDispacher: NotificationDispatcher, nudgesRepository: INudgesRepository, refreshInterval = 5 * 60 * 1000 ) { super() this.notificationDispatcher = notificationDispacher this.nudgesRepository = nudgesRepository this.refreshInterval = refreshInterval /* - nudges are retrieved periodically, each 5min. - in the future this timeout will be configurable - dispatched_at will be: - current time less 1 hour the first time - time of last shown nudge, if exists, or current time next times */ this.notificationDispatcher.on(NotificationAction.Open, (id) => { this.emit(NudgeManagerAction.Open, id, this.indexedNudges[id]) const hasActions = () => { return (this.indexedNudges[id].action.call_to_action.type !== CTAType.None && this.indexedNudges[id].action.call_to_action.cta_resource.id !== "") } if (!this.indexedNudges[id]) { return } if (!hasActions()) { return } this.emit( NudgeManagerAction.Action, this.indexedNudges[id].action.call_to_action) }) this.notificationDispatcher.on(NotificationAction.Discard, id => { this.emit(NudgeManagerAction.Discard, id, this.indexedNudges[id]) }) this.notificationDispatcher.on(NotificationAction.Block, id => { this.emit(NudgeManagerAction.Block, id, this.indexedNudges[id]) }) const oneHourAgo = new Date() oneHourAgo.setHours(oneHourAgo.getHours() - 1) // get storaged item: this.fetchNudges(userId) setInterval(() => { this.fetchNudges(userId) }, this.refreshInterval) } private async fetchNudges(userId: string) { let nudges; try { nudges = await this.nudgesRepository.getNudges(userId) } catch (e) { console.error('Error fetching nudges: ', e) return } const nudgeExpiryDate = DateTime.local().plus({ seconds: 3600 }).toJSDate().toISOString() nudges .filter(({ id }) => { const alreadyShown = this.nudgesRepository.haveBeenAlreadyShown(id) return !alreadyShown }) .forEach(nudge => { const { action: { definition: { title, body } }, id, dispatched_at, expire_at } = nudge this.indexedNudges[id] = nudge this.processNudge(id, dispatched_at, expire_at, title, body) }) } private processNudge(id: string, dispatched_at: string, expire_at: string, title: string, body: string) { const dispatched_at_date = new Date(dispatched_at) const expirationNotDefined = expire_at === "0001-01-01T00:00:00Z" const notExpired = expire_at > new Date().toISOString() if (notExpired || expirationNotDefined) { const timeout = dispatched_at_date.getTime() - Date.now() const timeoutId = setTimeout(() => { this.nudgesRepository.markNudgeAsShown(id) this.notificationDispatcher.show(title, body, id) }, timeout) this.timersId.push(timeoutId) } } }