notifly-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # notifly-node-package
package/index.js ADDED
@@ -0,0 +1,279 @@
1
+ import messaging from "@react-native-firebase/messaging";
2
+ import notifee, { AndroidImportance } from "@notifee/react-native";
3
+ import { Linking, Platform } from 'react-native';
4
+ import AsyncStorage from '@react-native-async-storage/async-storage';
5
+ import rnDeviceInfo from 'react-native-device-info';
6
+ import { v5 } from 'uuid';
7
+ import { NAMESPACE } from './namespace';
8
+
9
+ exports.trackEvent = logEvent;
10
+
11
+ exports.setUserProperties = _setUserProperties
12
+
13
+ exports.setUserId = async userId => await _setUserProperties({
14
+ external_user_id: userId,
15
+ })
16
+
17
+ exports.sessionStart = async function () {
18
+ const apiLevel = rnDeviceInfo.getApiLevel(); // only android
19
+ const brand = rnDeviceInfo.getBrand(); // apple samsung
20
+ const model = rnDeviceInfo.getModel(); // 기종 SM-G960N or iPhone 8
21
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
22
+ const platform = Platform.OS;
23
+ const deviceInfo = await Promise.all([model, brand, apiLevel]);
24
+ const openAppEventParams = {
25
+ "timezone": timezone,
26
+ "app_id": 'test_app',
27
+ "platform": platform,
28
+ "device_model": deviceInfo[0],
29
+ "properties": {
30
+ "device_brand": deviceInfo[1],
31
+ "api_level": deviceInfo[2],
32
+ },
33
+ }
34
+ await logEvent("session_start", openAppEventParams, true)
35
+
36
+ }
37
+
38
+ exports.initialize = async function (prjId, userName, password) {
39
+ try {
40
+ messaging().onNotificationOpenedApp(async (remoteMessage) => {
41
+ await logEvent("push_click", { "campaign_id": remoteMessage.data.campaign_id, "status": "background" }, true);
42
+ });
43
+
44
+ messaging().getToken()
45
+
46
+ messaging()
47
+ .getInitialNotification()
48
+ .then(async (remoteMessage) => {
49
+ if (remoteMessage) {
50
+ const link = remoteMessage.notification?.android?.link;
51
+ if (link) {
52
+ Linking.openURL(remoteMessage.notification?.android?.link);
53
+ }
54
+ await logEvent("push_click", { "campaign_id": remoteMessage.data.campaign_id, "status": "quit" }, true);
55
+ await logEvent("push_delivered", { "campaign_id": remoteMessage.data.campaign_id, "status": "quit" }, true);
56
+
57
+ }
58
+ });
59
+
60
+ messaging().setBackgroundMessageHandler(async (remoteMessage) => {
61
+ await logEvent("push_delivered", { "campaign_id": remoteMessage.data.campaign_id, "status": "background" }, true);
62
+ return
63
+ })
64
+
65
+ await Promise.all([
66
+ AsyncStorage.setItem('notiflyProjectId', prjId),
67
+ AsyncStorage.setItem('notiflyUserName', userName),
68
+ AsyncStorage.setItem('notiflyUserPassword', password),
69
+ ])
70
+
71
+ notifee.requestPermission()
72
+ if (Platform.OS === 'android') {
73
+ notifee.createChannel({
74
+ id: "foreground",
75
+ name: "foreground",
76
+ importance: AndroidImportance.HIGH,
77
+ })
78
+ }
79
+ notifee.onBackgroundEvent(async ({ type, detail }) => {
80
+ const { notification } = detail;
81
+ const campaign_id = notification.data.campaign_id;
82
+ if (!campaign_id) {
83
+ return
84
+ }
85
+ switch (type) {
86
+ case 3:
87
+ try {
88
+ await logEvent("push_delivered", { "campaign_id": campaign_id, "status": "background-notifee" }, true);
89
+ } catch (err) {
90
+ console.error('[Notifly]: ', err);
91
+ }
92
+ break;
93
+ }
94
+ });
95
+ } catch (err) {
96
+ console.error("[Notifly]: ", err);
97
+ }
98
+ }
99
+
100
+ exports.foregroundSetting = function () {
101
+ messaging().onMessage(async remoteMessage => {
102
+ await notifee.displayNotification({
103
+ title: remoteMessage.notification.title,
104
+ body: remoteMessage.notification.body,
105
+ data: remoteMessage.data,
106
+ android: {
107
+ channelId: "foreground",
108
+ },
109
+ });
110
+ await logEvent("push_delivered", { "campaign_id": remoteMessage.data.campaign_id, "status": "foreground" }, true);
111
+ });
112
+ notifee.onForegroundEvent(async ({ type, detail }) => {
113
+ const { notification } = detail;
114
+ const campaign_id = notification.data.campaign_id;
115
+ if (!campaign_id) {
116
+ return
117
+ }
118
+ if (type == 1) {
119
+ try {
120
+ if (notification.data.link) {
121
+ Linking.openURL(notification.data.link)
122
+ await logEvent("push_click", { "campaign_id": campaign_id, "status": "foreground" }, true);
123
+ } else {
124
+ await logEvent("push_click", { "campaign_id": campaign_id, "status": "foreground" }, true);
125
+ }
126
+ } catch (err) {
127
+ console.error('[Notifly]: ', err);
128
+ }
129
+ }
130
+ });
131
+ }
132
+
133
+ async function getCognitoIdToken(userName, password) {
134
+ const myHeaders = new Headers();
135
+ myHeaders.append("X-Amz-Target", "AWSCognitoIdentityProviderService.InitiateAuth");
136
+ myHeaders.append("Content-Type", "application/x-amz-json-1.1");
137
+
138
+ const raw = `{\n \"AuthFlow\":\"USER_PASSWORD_AUTH\",\n \"AuthParameters\": {\n \"PASSWORD\": \"${password}\",\n \"USERNAME\":\"${userName}\"\n },\n \"ClientId\":\"2pc5pce21ec53csf8chafknqve\"\n}`;
139
+
140
+ const requestOptions = {
141
+ method: 'POST',
142
+ headers: myHeaders,
143
+ body: raw,
144
+ redirect: 'follow'
145
+ };
146
+
147
+ const token = fetch("https://cognito-idp.ap-northeast-2.amazonaws.com/", requestOptions)
148
+ .then(response => response.text())
149
+ .then(result => {
150
+ const tokens = JSON.parse(result).AuthenticationResult.IdToken
151
+ return tokens;
152
+ })
153
+ .catch(error => console.error('[Notifly]: ', error));
154
+
155
+ return token;
156
+ }
157
+
158
+ async function _getNotiflyUserId() {
159
+ const encodedUserId = await AsyncStorage.getItem('notiflyUserId');
160
+ if (encodedUserId) {
161
+ return encodedUserId;
162
+ }
163
+ const [prjId, externalUserId] = await Promise.all([AsyncStorage.getItem('notiflyProjectId'), AsyncStorage.getItem('notiflyExternalUserId')])
164
+ let notiflyUserId
165
+ if (externalUserId) {
166
+ notiflyUserId = v5(`${prjId}${externalUserId}`, NAMESPACE.REGISTERED_USERID).replace(/-/g, '');
167
+ } else {
168
+ notiflyUserId = v5(`${prjId}${await messaging().getToken()}`, NAMESPACE.UNREGISTERED_USERID).replace(/-/g, '');
169
+ }
170
+ return notiflyUserId;
171
+ }
172
+
173
+ async function _setUserProperties(params) {
174
+ if (params.external_user_id) {
175
+ await Promise.all([
176
+ AsyncStorage.setItem('notiflyExternalUserId', params.external_user_id),
177
+ AsyncStorage.removeItem('notiflyUserId'),
178
+ ]);
179
+ }
180
+ return await logEvent("set_user_properties", params, true);
181
+ }
182
+
183
+ async function logEvent(eventName, eventParams, isInternalEvent = false) {
184
+ try {
185
+ let token;
186
+ const [savedCognitoToken, notiflyUserId, externalUserId, prjId, externalDeviceId, osVersion, appVersion] = await Promise.all([
187
+ AsyncStorage.getItem('notiflyCognitoIdToken'),
188
+ _getNotiflyUserId(),
189
+ AsyncStorage.getItem('notiflyExternalUserId'),
190
+ AsyncStorage.getItem('notiflyProjectId'),
191
+ rnDeviceInfo.getUniqueId(),
192
+ rnDeviceInfo.getSystemVersion(),
193
+ rnDeviceInfo.getVersion(),
194
+ ]);
195
+
196
+ const [eventId, notiflyDeviceId, deviceToken] = await Promise.all([
197
+ v5(`${notiflyUserId}${eventName}${new Date().valueOf()}`, NAMESPACE.EVENTID).replace(/-/g, ''),
198
+ v5(externalDeviceId, NAMESPACE.DEVICEID).replace(/-/g, ''),
199
+ messaging().getToken(),
200
+ ]);
201
+
202
+ if (!savedCognitoToken) {
203
+ const [userName, password] = await Promise.all([AsyncStorage.getItem('notiflyUserName'), AsyncStorage.getItem('notiflyUserPassword')])
204
+ newToken = await getCognitoIdToken(userName, password);
205
+ await AsyncStorage.setItem("notiflyCognitoIdToken", newToken);
206
+ token = newToken;
207
+ } else {
208
+ token = savedCognitoToken;
209
+ }
210
+
211
+ if (!token || !notiflyUserId || !prjId || !eventId || !externalDeviceId || !notiflyDeviceId || !deviceToken) {
212
+ throw new Error("null value");
213
+ }
214
+ const myHeaders = new Headers();
215
+ myHeaders.append("Authorization", token);
216
+ myHeaders.append("Content-Type", "application/json");
217
+
218
+ const eventDataWithoutExternalUserId = {
219
+ "event_params": eventParams,
220
+ "id": eventId,
221
+ "name": eventName,
222
+ "notifly_user_id": notiflyUserId,
223
+ "time": parseInt(new Date().valueOf() / 1000),
224
+ "notifly_device_id": notiflyDeviceId,
225
+ "external_device_id": externalDeviceId,
226
+ "device_token": deviceToken,
227
+ "is_internal_event": isInternalEvent,
228
+ "project_id": prjId,
229
+ "platform": Platform.OS,
230
+ "os_version": osVersion,
231
+ "app_version": appVersion,
232
+ }
233
+ const eventData = JSON.stringify(
234
+ externalUserId ?
235
+ {
236
+ ...eventDataWithoutExternalUserId,
237
+ "external_user_id": externalUserId,
238
+ }
239
+ :
240
+ eventDataWithoutExternalUserId
241
+ );
242
+
243
+ const body = JSON.stringify({
244
+ "records": [{
245
+ "data": eventData,
246
+ "partitionKey": notiflyUserId,
247
+ }]
248
+ })
249
+
250
+ const requestOptions = {
251
+ method: 'POST',
252
+ headers: myHeaders,
253
+ body: body,
254
+ redirect: 'follow'
255
+ };
256
+
257
+ const response = await _apiCall("https://12lnng07q2.execute-api.ap-northeast-2.amazonaws.com/prod/records", requestOptions);
258
+ const result = JSON.parse(response)
259
+ console.log(result)
260
+ if (result.message == "The incoming token has expired") {
261
+ const [userName, password] = await Promise.all([AsyncStorage.getItem('notiflyUserName'), AsyncStorage.getItem('notiflyUserPassword')])
262
+ const newToken = await getCognitoIdToken(userName, password);
263
+ await AsyncStorage.setItem("notiflyCognitoIdToken", newToken);
264
+ await logEvent(eventName, eventParams)
265
+ }
266
+
267
+ } catch (err) {
268
+ console.log(err)
269
+ if (err == 'Error: null value') {
270
+ throw new Error("[Notifly] Fail to log the event.");
271
+ }
272
+ }
273
+ }
274
+
275
+ async function _apiCall(apiUrl, requestOptions) {
276
+ const result = fetch(apiUrl, requestOptions)
277
+ .then(response => response.text());
278
+ return result;
279
+ }
package/namespace.js ADDED
@@ -0,0 +1,6 @@
1
+ export const NAMESPACE = {
2
+ "EVENTID": "830b5f7b-e392-43db-a17b-d835f0bcab2b",
3
+ "REGISTERED_USERID": "ce7c62f9-e8ae-4009-8fd6-468e9581fa21",
4
+ "UNREGISTERED_USERID": "a6446dcf-c057-4de7-a360-56af8659d52f",
5
+ "DEVICEID": "830848b3-2444-467d-9cd8-3430d2738c57",
6
+ }
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "notifly-sdk",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "peerDependencies": {
10
+ "@notifee/react-native": "^7.3.0",
11
+ "@react-native-async-storage/async-storage": "^1.17.11",
12
+ "@react-native-firebase/app": "^16.5.0",
13
+ "@react-native-firebase/messaging": "^16.5.0",
14
+ "react-native-device-info": "^10.3.0",
15
+ "uuid": "^9.0.0"
16
+ },
17
+ "author": "daeseongKim",
18
+ "license": "ISC",
19
+ "type": "module"
20
+ }