Skip to content

Commit ec2aedb

Browse files
committed
fix: Notification event mutation
1 parent 522814d commit ec2aedb

File tree

3 files changed

+235
-57
lines changed

3 files changed

+235
-57
lines changed

packages/restapi/src/lib/pushstream/DataModifier.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import {
1212
JoinGroupEvent,
1313
RequestEvent,
1414
RemoveEvent,
15+
NotificationEvent,
16+
NotificationEventType,
17+
NotificationType,
18+
NOTIFICATION,
1519
} from './pushStreamTypes';
1620

1721
export class DataModifier {
@@ -301,4 +305,75 @@ export class DataModifier {
301305
return data;
302306
}
303307
}
308+
309+
public static mapToNotificationEvent(
310+
data: any,
311+
notificationEventType: NotificationEventType,
312+
origin: 'other' | 'self',
313+
includeRaw = false
314+
): NotificationEvent {
315+
const notificationType =
316+
(Object.keys(NOTIFICATION.TYPE) as NotificationType[]).find(
317+
(key) => NOTIFICATION.TYPE[key] === data.payload.data.type
318+
) || 'BROADCAST'; // Assuming 'BROADCAST' as the default
319+
320+
321+
let recipients: string[];
322+
323+
if (Array.isArray(data.payload.recipients)) {
324+
recipients = data.payload.recipients;
325+
} else if (typeof data.payload.recipients === 'string') {
326+
recipients = [data.payload.recipients];
327+
} else {
328+
recipients = Object.keys(data.payload.recipients);
329+
}
330+
331+
const notificationEvent: NotificationEvent = {
332+
event: notificationEventType,
333+
origin: origin,
334+
timestamp: data.epoch,
335+
from: data.sender,
336+
to: recipients,
337+
notifID: data.payload_id.toString(),
338+
channel: {
339+
name: data.payload.data.app,
340+
icon: data.payload.data.icon,
341+
url: data.payload.data.url,
342+
},
343+
meta: {
344+
type: 'NOTIFICATION.' + notificationType,
345+
},
346+
message: {
347+
notification: {
348+
title: data.payload.notification.title,
349+
body: data.payload.notification.body,
350+
},
351+
payload: {
352+
title: data.payload.data.asub,
353+
body: data.payload.data.amsg,
354+
cta: data.payload.data.acta,
355+
embed: data.payload.data.aimg,
356+
meta: {
357+
domain: data.payload.data.additionalMeta?.domain || 'push.org',
358+
type: data.payload.data.additionalMeta?.type,
359+
data: data.payload.data.additionalMeta?.data,
360+
},
361+
},
362+
},
363+
config: {
364+
expiry: data.payload.data.etime,
365+
silent: data.payload.data.silent === '1',
366+
hidden: data.payload.data.hidden === '1',
367+
},
368+
source: data.source,
369+
};
370+
371+
if (includeRaw) {
372+
notificationEvent.raw = {
373+
verificationProof: data.payload.verificationProof,
374+
};
375+
}
376+
377+
return notificationEvent;
378+
}
304379
}

packages/restapi/src/lib/pushstream/PushStream.ts

Lines changed: 96 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ENV } from '../constants';
44
import {
55
GroupEventType,
66
MessageEventType,
7+
NotificationEventType,
78
ProposedEventNames,
89
PushStreamInitializeProps,
910
STREAM,
@@ -53,11 +54,11 @@ export class PushStream extends EventEmitter {
5354

5455
if (!this.pushNotificationSocket) {
5556
throw new Error('Push notification socket not connected');
56-
}
57+
}
5758

5859
if (!this.pushChatSocket) {
5960
throw new Error('Push chat socket not connected');
60-
}
61+
}
6162

6263
this.raw = options.raw ?? false;
6364
this.options = options;
@@ -155,6 +156,16 @@ export class PushStream extends EventEmitter {
155156
return this.options.filter.chats.includes(dataChatId);
156157
}
157158

159+
private shouldEmitChannel(dataChannelId: string): boolean {
160+
if (
161+
!this.options.filter?.channels ||
162+
this.options.filter.channels.length === 0
163+
) {
164+
return true;
165+
}
166+
return this.options.filter.channels.includes(dataChannelId);
167+
}
168+
158169
public async init(): Promise<void> {
159170
const shouldEmit = (eventType: STREAM): boolean => {
160171
if (!this.options.listen || this.options.listen.length === 0) {
@@ -164,78 +175,106 @@ export class PushStream extends EventEmitter {
164175
};
165176

166177
this.pushChatSocket.on(EVENTS.CHAT_GROUPS, (data: any) => {
167-
try {
168-
const modifiedData = DataModifier.handleChatGroupEvent(data, this.raw);
169-
modifiedData.event = this.convertToProposedName(modifiedData.event);
170-
this.handleToField(modifiedData);
171-
if (this.shouldEmitChat(data.chatId)) {
172-
if (
173-
data.eventType === GroupEventType.JoinGroup ||
174-
data.eventType === GroupEventType.LeaveGroup ||
175-
data.eventType === MessageEventType.Request ||
176-
data.eventType === GroupEventType.Remove
177-
) {
178-
if (shouldEmit(STREAM.CHAT)) {
179-
this.emit(STREAM.CHAT, modifiedData);
180-
}
181-
} else {
182-
if (shouldEmit(STREAM.CHAT_OPS)) {
183-
this.emit(STREAM.CHAT_OPS, modifiedData);
184-
}
185-
}
186-
}
187-
} catch (error) {
188-
console.error('Error handling CHAT_GROUPS event:', error, 'Data:', data);
189-
}
190-
});
191-
192-
this.pushChatSocket.on(EVENTS.CHAT_RECEIVED_MESSAGE, async (data: any) => {
193-
try {
178+
try {
179+
const modifiedData = DataModifier.handleChatGroupEvent(data, this.raw);
180+
modifiedData.event = this.convertToProposedName(modifiedData.event);
181+
this.handleToField(modifiedData);
182+
if (this.shouldEmitChat(data.chatId)) {
194183
if (
195-
data.messageCategory == 'Chat' ||
196-
data.messageCategory == 'Request'
184+
data.eventType === GroupEventType.JoinGroup ||
185+
data.eventType === GroupEventType.LeaveGroup ||
186+
data.eventType === MessageEventType.Request ||
187+
data.eventType === GroupEventType.Remove
197188
) {
198-
data = await this.chatInstance.decrypt([data]);
199-
data = data[0]
200-
}
201-
202-
const modifiedData = DataModifier.handleChatEvent(data, this.raw);
203-
modifiedData.event = this.convertToProposedName(modifiedData.event);
204-
this.handleToField(modifiedData);
205-
if (this.shouldEmitChat(data.chatId)) {
206189
if (shouldEmit(STREAM.CHAT)) {
207190
this.emit(STREAM.CHAT, modifiedData);
208191
}
192+
} else {
193+
if (shouldEmit(STREAM.CHAT_OPS)) {
194+
this.emit(STREAM.CHAT_OPS, modifiedData);
195+
}
209196
}
210-
} catch (error) {
211-
console.error(
212-
'Error handling CHAT_RECEIVED_MESSAGE event:',
213-
error,
214-
'Data:',
215-
data
216-
);
217197
}
198+
} catch (error) {
199+
console.error(
200+
'Error handling CHAT_GROUPS event:',
201+
error,
202+
'Data:',
203+
data
204+
);
205+
}
206+
});
207+
208+
this.pushChatSocket.on(EVENTS.CHAT_RECEIVED_MESSAGE, async (data: any) => {
209+
try {
210+
if (
211+
data.messageCategory == 'Chat' ||
212+
data.messageCategory == 'Request'
213+
) {
214+
data = await this.chatInstance.decrypt([data]);
215+
data = data[0];
216+
}
217+
218+
const modifiedData = DataModifier.handleChatEvent(data, this.raw);
219+
modifiedData.event = this.convertToProposedName(modifiedData.event);
220+
this.handleToField(modifiedData);
221+
if (this.shouldEmitChat(data.chatId)) {
222+
if (shouldEmit(STREAM.CHAT)) {
223+
this.emit(STREAM.CHAT, modifiedData);
224+
}
225+
}
226+
} catch (error) {
227+
console.error(
228+
'Error handling CHAT_RECEIVED_MESSAGE event:',
229+
error,
230+
'Data:',
231+
data
232+
);
233+
}
218234
});
219235

220236
this.pushNotificationSocket.on(EVENTS.USER_FEEDS, (data: any) => {
221237
try {
222-
this.emit(STREAM.NOTIF, data);
238+
const modifiedData = DataModifier.mapToNotificationEvent(
239+
data,
240+
NotificationEventType.INBOX,
241+
this.account === data.sender ? 'self' : 'other',
242+
this.raw
243+
);
244+
245+
if (this.shouldEmitChannel(modifiedData.from)) {
246+
if (shouldEmit(STREAM.NOTIF)) {
247+
this.emit(STREAM.NOTIF, modifiedData);
248+
}
249+
}
223250
} catch (error) {
224251
console.error('Error handling USER_FEEDS event:', error, 'Data:', data);
225252
}
226253
});
227254

228255
this.pushNotificationSocket.on(EVENTS.USER_SPAM_FEEDS, (data: any) => {
229-
try {
230-
this.emit(STREAM.NOTIF, data);
231-
} catch (error) {
232-
console.error(
233-
'Error handling USER_SPAM_FEEDS event:',
234-
error,
235-
'Data:',
236-
data
237-
);
238-
}
256+
try {
257+
const modifiedData = DataModifier.mapToNotificationEvent(
258+
data,
259+
NotificationEventType.SPAM,
260+
this.account === data.sender ? 'self' : 'other',
261+
this.raw
262+
);
263+
modifiedData.origin =
264+
this.account === modifiedData.from ? 'self' : 'other';
265+
if (this.shouldEmitChannel(modifiedData.from)) {
266+
if (shouldEmit(STREAM.NOTIF)) {
267+
this.emit(STREAM.NOTIF, modifiedData);
268+
}
269+
}
270+
} catch (error) {
271+
console.error(
272+
'Error handling USER_SPAM_FEEDS event:',
273+
error,
274+
'Data:',
275+
data
276+
);
277+
}
239278
});
240279
}
241280
}

packages/restapi/src/lib/pushstream/pushStreamTypes.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ export enum STREAM {
2525
CHAT_OPS = 'STREAM.CHAT_OPS',
2626
}
2727

28+
export enum NotificationEventType {
29+
INBOX = 'notification.inbox',
30+
SPAM = 'notification.spam',
31+
}
32+
33+
2834
export enum MessageOrigin {
2935
Other = 'other',
3036
Self = 'self',
@@ -155,6 +161,64 @@ export interface MessageEvent {
155161
raw?: MessageRawData;
156162
}
157163

164+
export const NOTIFICATION = {
165+
TYPE: {
166+
BROADCAST: 1,
167+
TARGETTED: 3,
168+
SUBSET: 4,
169+
},
170+
} as const;
171+
172+
export type NotificationType = keyof typeof NOTIFICATION.TYPE;
173+
174+
175+
176+
export interface NotificationEvent {
177+
event: NotificationEventType;
178+
origin: 'other' | 'self';
179+
timestamp: string;
180+
from: string;
181+
to: string[];
182+
notifID: string;
183+
channel: {
184+
name: string;
185+
icon: string;
186+
url: string;
187+
};
188+
meta: {
189+
type: string;
190+
};
191+
message: {
192+
notification: {
193+
title: string;
194+
body: string;
195+
};
196+
payload?: {
197+
title?: string;
198+
body?: string;
199+
cta?: string;
200+
embed?: string;
201+
meta?: {
202+
domain?: string;
203+
type: string;
204+
data: string;
205+
};
206+
};
207+
};
208+
config?: {
209+
expiry?: number;
210+
silent?: boolean;
211+
hidden?: boolean;
212+
};
213+
advanced?: {
214+
chatid?: string;
215+
};
216+
source: string;
217+
raw?: {
218+
verificationProof: string;
219+
};
220+
}
221+
158222
export interface MessageRawData {
159223
fromCAIP10: string;
160224
toCAIP10: string;

0 commit comments

Comments
 (0)