Skip to content

Commit

Permalink
feat: added fcm notification module
Browse files Browse the repository at this point in the history
Signed-off-by: KulkarniShashank <[email protected]>
  • Loading branch information
KulkarniShashank committed Feb 6, 2024
1 parent bedb00f commit ecf3c15
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 47 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ FIREBASE_PROJECT_ID=
FIREBASE_PRIVATE_KEY=
FIREBASE_CLIENT_EMAIL=
FIREBASE_NOTIFICATION_TITLE=You have message from your contacts
FIREBASE_NOTIFICATION_BODY=Please open your app to read the message
FIREBASE_NOTIFICATION_BODY=Please open your app to read the message
NOTIFICATION_WEBHOOK_URL=
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@
"postinstall": "patch-package"
},
"dependencies": {
"@aries-framework/askar": "^0.4.1",
"@aries-framework/core": "^0.4.1",
"@aries-framework/node": "^0.4.1",
"@hyperledger/aries-askar-nodejs": "^0.1.0",
"@aries-framework/askar": "0.4.2",
"@aries-framework/core": "0.4.2",
"@aries-framework/node": "0.4.2",
"@hyperledger/aries-askar-nodejs": "^0.1.1",
"axios": "^1.6.5",
"express": "^4.18.1",
"firebase-admin": "^11.10.1",
"prettier": "^2.8.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.d.ts b/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.d.ts
index 578a26f..3cb7221 100644
index 578a26f..ba1796a 100644
--- a/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.d.ts
+++ b/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.d.ts
@@ -2,11 +2,12 @@ import type { KeylistUpdate } from './messages/KeylistUpdateMessage';
Expand All @@ -17,14 +17,16 @@ index 578a26f..3cb7221 100644
}
export interface RoutingCreatedEvent extends BaseEvent {
type: typeof RoutingEventTypes.RoutingCreatedEvent;
@@ -28,3 +29,9 @@ export interface KeylistUpdatedEvent extends BaseEvent {
@@ -28,3 +29,11 @@ export interface KeylistUpdatedEvent extends BaseEvent {
keylist: KeylistUpdate[];
};
}
+
+export interface ForwardMessageEvent extends BaseEvent {
+ type: typeof RoutingEventTypes.ForwardMessageEvent;
+ payload: {
+ connectionRecord: ConnectionRecord;
+ messageType: string;
+ };
+}
diff --git a/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.js b/node_modules/@aries-framework/core/build/modules/routing/RoutingEvents.js
Expand All @@ -40,30 +42,34 @@ index ad9e68b..1aa5cb6 100644
//# sourceMappingURL=RoutingEvents.js.map
\ No newline at end of file
diff --git a/node_modules/@aries-framework/core/build/modules/routing/handlers/ForwardHandler.js b/node_modules/@aries-framework/core/build/modules/routing/handlers/ForwardHandler.js
index bb61eee..8e2069b 100644
index bb61eee..e96615e 100644
--- a/node_modules/@aries-framework/core/build/modules/routing/handlers/ForwardHandler.js
+++ b/node_modules/@aries-framework/core/build/modules/routing/handlers/ForwardHandler.js
@@ -12,6 +12,8 @@ class ForwardHandler {
@@ -12,6 +12,12 @@ class ForwardHandler {
async handle(messageContext) {
const { encryptedMessage, mediationRecord } = await this.mediatorService.processForwardMessage(messageContext);
const connectionRecord = await this.connectionService.getById(messageContext.agentContext, mediationRecord.connectionId);
+
+ console.log("messageContext.message ------", messageContext.message)
+ console.log("messageType ------", messageContext.message?.messageType)
+
+ // Send forward message to the event emitter so that it can be picked up events
+ await this.mediatorService.emitForwardEvent(messageContext.agentContext, connectionRecord);
+ await this.mediatorService.emitForwardEvent(messageContext.agentContext, connectionRecord, messageContext.message?.messageType);
// The message inside the forward message is packed so we just send the packed
// message to the connection associated with it
await this.messageSender.sendPackage(messageContext.agentContext, {
diff --git a/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.d.ts b/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.d.ts
index e02dbab..ec9ba0d 100644
index e02dbab..d007d8e 100644
--- a/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.d.ts
+++ b/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.d.ts
@@ -2,6 +2,7 @@ import type { AgentContext } from '../../../agent';
import type { InboundMessageContext } from '../../../agent/models/InboundMessageContext';
import type { Query } from '../../../storage/StorageService';
import type { EncryptedMessage } from '../../../types';
@@ -11,6 +11,7 @@ import { MediatorRoutingRecord } from '../repository';
import { MediationRecord } from '../repository/MediationRecord';
import { MediationRepository } from '../repository/MediationRepository';
import { MediatorRoutingRepository } from '../repository/MediatorRoutingRepository';
+import type { ConnectionRecord } from '../../connections';
import type { ForwardMessage, MediationRequestMessage } from '../messages';
import { EventEmitter } from '../../../agent/EventEmitter';
import { Logger } from '../../../logger';
export declare class MediatorService {
private logger;
private mediationRepository;
@@ -23,6 +24,7 @@ export declare class MediatorService {
mediationRecord: MediationRecord;
encryptedMessage: EncryptedMessage;
Expand All @@ -73,21 +79,34 @@ index e02dbab..ec9ba0d 100644
createGrantMediationMessage(agentContext: AgentContext, mediationRecord: MediationRecord): Promise<{
mediationRecord: MediationRecord;
diff --git a/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.js b/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.js
index ec8cd1b..2118939 100644
index ec8cd1b..de911d5 100644
--- a/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.js
+++ b/node_modules/@aries-framework/core/build/modules/routing/services/MediatorService.js
@@ -61,6 +61,14 @@ let MediatorService = class MediatorService {
@@ -61,6 +61,15 @@ let MediatorService = class MediatorService {
mediationRecord,
};
}
+ async emitForwardEvent(agentContext, connectionRecord) {
+ async emitForwardEvent(agentContext, connectionRecord, messageType) {
+ this.eventEmitter.emit(agentContext, {
+ type: RoutingEvents_1.RoutingEventTypes.ForwardMessageEvent,
+ payload: {
+ connectionRecord,
+ messageType
+ },
+ });
+ }
async processKeylistUpdateRequest(messageContext) {
// Assert Ready connection
const connection = messageContext.assertReadyConnection();
@@ -204,8 +213,8 @@ MediatorService = __decorate([
(0, plugins_1.injectable)(),
__param(3, (0, plugins_1.inject)(constants_1.InjectionSymbols.Logger)),
__metadata("design:paramtypes", [MediationRepository_1.MediationRepository,
- MediatorRoutingRepository_1.MediatorRoutingRepository,
- EventEmitter_1.EventEmitter, Object, connections_1.ConnectionService])
+ MediatorRoutingRepository_1.MediatorRoutingRepository,
+ EventEmitter_1.EventEmitter, Object, connections_1.ConnectionService])
], MediatorService);
exports.MediatorService = MediatorService;
//# sourceMappingURL=MediatorService.js.map
\ No newline at end of file
16 changes: 8 additions & 8 deletions src/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,16 @@ export async function createAgent() {

// Register all event handlers and initialize fcm module
if (USE_PUSH_NOTIFICATIONS) {
initializeApp({
credential: credential.cert({
projectId: FIREBASE_PROJECT_ID,
clientEmail: FIREBASE_CLIENT_EMAIL,
privateKey: FIREBASE_PRIVATE_KEY,
}),
})
// initializeApp({
// credential: credential.cert({
// projectId: FIREBASE_PROJECT_ID,
// clientEmail: FIREBASE_CLIENT_EMAIL,
// privateKey: FIREBASE_PRIVATE_KEY,
// }),
// })
routingEvents(agent)
}

// When an 'upgrade' to WS is made on our http server, we forward the
// request to the WS server
httpInboundTransport.server?.on('upgrade', (request, socket, head) => {
Expand Down
6 changes: 5 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { LogLevel } from '@aries-framework/core'
import * as dotenv from 'dotenv';
dotenv.config();

export const AGENT_PORT = process.env.AGENT_PORT ? Number(process.env.AGENT_PORT) : 3000
export const AGENT_NAME = process.env.AGENT_NAME || 'Animo Mediator'
Expand All @@ -22,7 +24,6 @@ export const LOG_LEVEL = LogLevel.debug
export const IS_DEV = process.env.NODE_ENV === 'development'

export const USE_PUSH_NOTIFICATIONS = process.env.USE_PUSH_NOTIFICATIONS === 'true'

export const FIREBASE_PROJECT_ID = process.env.FIREBASE_PROJECT_ID
export const FIREBASE_PRIVATE_KEY = process.env.FIREBASE_PRIVATE_KEY
? process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n')
Expand All @@ -31,3 +32,6 @@ export const FIREBASE_CLIENT_EMAIL = process.env.FIREBASE_CLIENT_EMAIL

export const FIREBASE_NOTIFICATION_TITLE = process.env.FIREBASE_NOTIFICATION_TITLE
export const FIREBASE_NOTIFICATION_BODY = process.env.FIREBASE_NOTIFICATION_BODY

export const NOTIFICATION_WEBHOOK_URL = process.env.NOTIFICATION_WEBHOOK_URL

5 changes: 3 additions & 2 deletions src/events/RoutingEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { MediatorAgent } from '../agent'
export const routingEvents = async (agent: MediatorAgent) => {
agent.events.on(RoutingEventTypes.ForwardMessageEvent, async (event: ForwardMessageEvent) => {
try {
const record = event.payload.connectionRecord
const connectionRecord = event.payload?.connectionRecord;
const messageType = event.payload?.messageType;
await agent.modules.pushNotificationsFcm.sendNotification(connectionRecord.id, messageType);

await agent.modules.pushNotificationsFcm.sendNotification(record.id)
} catch (error) {
agent.config.logger.error(`Error sending notification`, {
cause: error,
Expand Down
4 changes: 2 additions & 2 deletions src/push-notifications/fcm/PushNotificationsFcmApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class PushNotificationsFcmApi {
* @param connectionId The connection ID string
* @returns Promise<void>
*/
public async sendNotification(connectionId: string) {
return this.pushNotificationsService.sendNotification(this.agentContext, connectionId)
public async sendNotification(connectionId: string, messageType: string) {
return this.pushNotificationsService.sendNotification(this.agentContext, connectionId, messageType)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class PushNotificationsFcmSetDeviceInfoMessage extends AgentMessage {
this.id = options.id ?? this.generateId()
this.deviceToken = options.deviceToken
this.devicePlatform = options.devicePlatform
this.clientCode = options.clientCode
}
}

Expand All @@ -34,6 +35,11 @@ export class PushNotificationsFcmSetDeviceInfoMessage extends AgentMessage {
@ValidateIf((object, value) => value !== null)
public devicePlatform!: string | null

@Expose({ name: 'client_code' })
@IsString()
@ValidateIf((object, value) => value !== null)
public clientCode!: string | null

@IsValidMessageType(PushNotificationsFcmSetDeviceInfoMessage.type)
public readonly type = PushNotificationsFcmSetDeviceInfoMessage.type.messageTypeUri
public static readonly type = parseMessageType('https://didcomm.org/push-notifications-fcm/1.0/set-device-info')
Expand Down
1 change: 1 addition & 0 deletions src/push-notifications/fcm/models/FcmDeviceInfo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type FcmDeviceInfo = {
deviceToken: string | null
devicePlatform: string | null
clientCode: string | null
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface PushNotificationsFcmStorageProps {
id?: string
deviceToken: string | null
devicePlatform: string | null
clientCode: string | null
connectionId: string
tags?: CustomPushNotificationsFcmTags
}
Expand All @@ -23,6 +24,7 @@ export class PushNotificationsFcmRecord extends BaseRecord<
public deviceToken!: string | null
public devicePlatform!: string | null
public connectionId!: string
public clientCode!: string | null

public static readonly type = 'PushNotificationsFcmRecord'
public readonly type = PushNotificationsFcmRecord.type
Expand All @@ -36,6 +38,7 @@ export class PushNotificationsFcmRecord extends BaseRecord<
this.deviceToken = props.deviceToken
this.connectionId = props.connectionId
this._tags = props.tags ?? {}
this.clientCode = props.clientCode
}
}

Expand Down
73 changes: 60 additions & 13 deletions src/push-notifications/fcm/services/PushNotificationsFcmService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,30 @@ import { PushNotificationsFcmSetDeviceInfoMessage, PushNotificationsFcmDeviceInf
import { PushNotificationsFcmRecord, PushNotificationsFcmRepository } from '../repository'

import * as admin from 'firebase-admin'
import { FIREBASE_NOTIFICATION_BODY, FIREBASE_NOTIFICATION_TITLE } from '../../../constants'
import { FIREBASE_NOTIFICATION_TITLE, NOTIFICATION_WEBHOOK_URL } from '../../../constants'
import axios from 'axios';

interface NotificationBody {
title?: string;
body?: string;
}

interface ApsPayload {
aps: {
sound: string;
};
}

interface Apns {
payload: ApsPayload;
}

interface NotificationMessage {
notification: NotificationBody;
apns: Apns;
token: string;
clientCode: string;
}

@injectable()
export class PushNotificationsFcmService {
Expand Down Expand Up @@ -45,6 +68,7 @@ export class PushNotificationsFcmService {
threadId,
deviceToken: deviceInfo.deviceToken,
devicePlatform: deviceInfo.devicePlatform,
clientCode: deviceInfo.clientCode
})
}

Expand Down Expand Up @@ -83,21 +107,22 @@ export class PushNotificationsFcmService {
connectionId: connection.id,
deviceToken: message.deviceToken,
devicePlatform: message.devicePlatform,
clientCode: message.clientCode
})

await this.pushNotificationsFcmRepository.save(agentContext, pushNotificationsFcmRecord)
}
}

public async sendNotification(agentContext: AgentContext, connectionId: string) {
public async sendNotification(agentContext: AgentContext, connectionId: string, messageType: string) {
try {
// Get the session for the connection
const session = await this.transportService.findSessionByConnectionId(connectionId)

if (session) {
this.logger.info(`Connection ${connectionId} is active. So skip sending notification`)
return
}
// const session = await this.transportService.findSessionByConnectionId(connectionId)
// if (session) {
// this.logger.info(`Connection ${connectionId} is active. So skip sending notification`)
// return
// }

// Get the device token for the connection
const pushNotificationFcmRecord = await this.pushNotificationsFcmRepository.findSingleByQuery(agentContext, {
Expand All @@ -109,11 +134,12 @@ export class PushNotificationsFcmService {
return
}


// Prepare a message to be sent to the device
const message = {
const message: NotificationMessage = {
notification: {
title: FIREBASE_NOTIFICATION_TITLE,
body: FIREBASE_NOTIFICATION_BODY,
body: messageType,
},
apns: {
payload: {
Expand All @@ -122,12 +148,14 @@ export class PushNotificationsFcmService {
},
},
},
token: pushNotificationFcmRecord.deviceToken,
token: pushNotificationFcmRecord?.deviceToken || '',
clientCode: pushNotificationFcmRecord?.clientCode || ''
}

this.logger.info(`Sending notification to ${pushNotificationFcmRecord?.connectionId}`)
await admin.messaging().send(message)
this.logger.info(`Notification sent successfully to ${pushNotificationFcmRecord.connectionId}`)
await this.processNotification(message);
// await admin.messaging().send(message)
this.logger.info(`Notification sent successfully to ${connectionId}`)
} catch (error) {
if (error instanceof RecordDuplicateError) {
this.logger.error(`Multiple device info found for connectionId ${connectionId}`)
Expand All @@ -138,4 +166,23 @@ export class PushNotificationsFcmService {
}
}
}

public async processNotification(message: NotificationMessage) {
try {
if (NOTIFICATION_WEBHOOK_URL) {
const payload = {
fcmToken: message.token || '',
'@type': message.notification.body,
clientCode: message.clientCode || '5b4d6bc6-362e-4f53-bdad-ee2742bc0de3'
}
await axios.post(NOTIFICATION_WEBHOOK_URL, payload);
} else {
this.logger.error("Notification webhook URL not found");
}
} catch (error) {
this.logger.error(`Error sending notification`, {
cause: error,
})
}
}
}

0 comments on commit ecf3c15

Please sign in to comment.