/
notificationservice.ts
125 lines (115 loc) · 3.28 KB
/
notificationservice.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { Ident } from "../models/ident";
import { User } from "../models/user";
import { Service, ServiceParameters } from "./service";
/**
* Define a service that can notify a user based on his info
* It can use email or SMS or any other media
*/
export interface NotificationService {
/**
* Check if this type of notification is available
*/
hasNotification(notification: string): Promise<boolean>;
/**
* Check if the service can deliver notification to this user
* @param user
*/
handleNotificationFor(userOrIdent: User | Ident): Promise<boolean>;
/**
* Send the notification to the user
* @param user
* @param notification
* @param replacements
*/
sendNotification(user: User | Ident, notification: string, replacements: any): Promise<void>;
}
/**
* Parameters for multi notification service
*/
export class MultiNotificationParameters extends ServiceParameters {
/**
* Notification service that will send
* The order of the array is important if multiple is false
* When multiple is `false` the first available NotificationService will
* be used, otherwise every available NotificationService will be used
*/
senders: string[];
/**
* Define if it sends one or several notification per user
* @default false
*/
multiple?: boolean;
/**
* @override
*/
constructor(params: any) {
super(params);
this.senders ??= [];
}
}
/**
* Allow an aggregation of Notification to send via multiple media
* like SMS and Email
*
* @WebdaModda
*/
export default class MultiNotificationService<T extends MultiNotificationParameters = MultiNotificationParameters>
extends Service<T>
implements NotificationService
{
senders: NotificationService[];
/**
* @override
*/
loadParameters(params: any): MultiNotificationParameters {
return new MultiNotificationParameters(params);
}
/**
* @override
*/
resolve(): this {
super.resolve();
this.senders = this.parameters.senders.map(s => {
let service = <NotificationService>(<unknown>this.getService(s));
if (!service) {
throw new Error(`Unknown service '${s}'`);
}
return service;
});
return this;
}
/**
* @override
*/
async sendNotification(user: User | Ident, notification: string, replacements: any): Promise<void> {
const selectedSenders = (
await Promise.all(
this.senders.map(async s => {
if ((await s.hasNotification(notification)) && (await s.handleNotificationFor(user))) {
return s;
}
})
)
).filter(s => s !== undefined);
if (!selectedSenders.length) {
return;
}
if (!this.parameters.multiple) {
return selectedSenders.shift().sendNotification(user, notification, replacements);
}
await Promise.all(selectedSenders.map(s => s.sendNotification(user, notification, replacements)));
}
/**
* @override
*/
async handleNotificationFor(user: User | Ident): Promise<boolean> {
return (await Promise.all(this.senders.map(s => s.handleNotificationFor(user)))).some(s => s);
}
/**
* @override
*/
async hasNotification(notification: string): Promise<boolean> {
return (await Promise.all(this.senders.map(s => s.hasNotification(notification)))).some(s => s);
}
}
export { MultiNotificationService };