playov2-js-utilities 0.3.0 → 0.3.1-6.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/lib/constants.js CHANGED
@@ -12,7 +12,10 @@ const RATINGS_WEIGHTAGE = Object.freeze({
12
12
  'old': 0.1
13
13
  });
14
14
 
15
+ const DEFAULT_TIME_ZONE = 'Asia/Kolkata';
16
+
15
17
  module.exports = {
16
18
  USER_INDIVIDUAL_RATINGS,
17
- RATINGS_WEIGHTAGE
19
+ RATINGS_WEIGHTAGE,
20
+ DEFAULT_TIME_ZONE
18
21
  }
package/lib/cron.js ADDED
@@ -0,0 +1,43 @@
1
+ /**
2
+ * This file will have all cron related utilities - (e.g. - schedulers etc.).
3
+ * Try to contain service common utilities here.
4
+ */
5
+ const Constants = require('./constants');
6
+ const { CronJob } = require('cron');
7
+ const Utils = require('./util')
8
+
9
+ const cronner = (
10
+ cronTime,
11
+ onTime = Utils.noop,
12
+ onComplete = Utils.noop,
13
+ timeZone = Constants.DEFAULT_TIME_ZONE,
14
+ context = this,
15
+ runOnInit,
16
+ utcOffset,
17
+ ) => {
18
+ const job = new CronJob({
19
+ cronTime,
20
+ // when the time specified by pattern is matched
21
+ onTick: onTime,
22
+ // onComplete
23
+ onComplete,
24
+ // whether the cron should start on constructor invoke (or whether .start() needs to be called)
25
+ start: false,
26
+ // timezone -> defaults to Asia/Kolkata
27
+ timeZone,
28
+ // the context to bind the onTime method to
29
+ context,
30
+ // flat to start cron on invocation of the module
31
+ runOnInit,
32
+ // the utc offset to run the cron at
33
+ utcOffset
34
+ });
35
+ job.start();
36
+ return job;
37
+ };
38
+
39
+ module.exports = {
40
+ cronner
41
+ };
42
+
43
+
package/lib/index.js CHANGED
@@ -1,9 +1,14 @@
1
1
 
2
- //Naming terminology - While exporting constants use PascalCase while exporting functions/methods use camelCase
2
+ /*
3
+ * Naming terminology - While exporting constants use PascalCase while exporting functions/methods use camelCase
4
+ */
3
5
  module.exports = {
4
- ratings : require('./ratings/index'),
5
- Constants : require('./constants'),
6
- playoUtils : require('./util'),
7
- NotificationTemplates : require('./notification-templates'),
8
- NotificationConfig: require('./notification.config')
6
+ ratings: require('./ratings/index'),
7
+ Constants: require('./constants'),
8
+ playoUtils: require('./util'),
9
+ NotificationTemplates: require('./notification-templates'),
10
+ NotificationConfig: require('./notification.config'),
11
+ httpRequest: require('./request'),
12
+ Cron: require('./cron'),
13
+ MessagePublisher: require('./message_publisher')
9
14
  };
@@ -0,0 +1,93 @@
1
+ /*
2
+ Read this and associated queue configs before deploying a new queue
3
+ https://cloud.google.com/tasks/docs/reference/rest/v2beta3/projects.locations.queues.tasks#resource:-task
4
+ */
5
+
6
+ const { CloudTasksClient } = require('@google-cloud/tasks');
7
+ const { v4: uuidv4 } = require('uuid');
8
+
9
+ const PLAYO_LOGGER = require("@playo/logger");
10
+ const LOGGER = new PLAYO_LOGGER("playo-message-publisher");
11
+
12
+ const client = new CloudTasksClient();
13
+
14
+ const PROJECT = process.env.GCP_PROJECT;
15
+ const LOCATION = process.env.GCP_LOCATION;
16
+
17
+ if (!PROJECT || !LOCATION) {
18
+ console.warn('You need to pass - GCP_PROJECT, GCP_LOCATION in env for message queue to work!');
19
+ }
20
+ /**
21
+ *
22
+ * @param {String} queueId - Name of the queue being targeted
23
+ * @param {Object} payload - {
24
+ * httpMethod: String <POST, GET, PUT>
25
+ * url: String,
26
+ * headers: Object,
27
+ * body: Object, // not needed if GET request
28
+ * ttl: Optional, date in utc format, consumer will check if the ttl has been exceeded or not and then will respond accordingly
29
+ * ...
30
+ *
31
+ * }
32
+ * @param {Object} messageProcessingProperties - {
33
+ * delay
34
+ * }
35
+ * @param {String} taskId -used as de-duplication key
36
+ * @param {String} requestId
37
+ */
38
+ async function createHttpTask(queueId, payload, messageProcessingProperties, taskId, requestId) {
39
+
40
+ try {
41
+ const project = PROJECT;
42
+ const queue = queueId;
43
+ const location = LOCATION;
44
+
45
+ const { delay = 0 } = messageProcessingProperties
46
+
47
+ const parent = client.queuePath(project, location, queue);
48
+
49
+ const task = {
50
+ httpRequest: payload,
51
+ name: ''
52
+ };
53
+
54
+ task.name = getTaskId(project, location, queue, taskId);
55
+
56
+ if (payload.body) {
57
+ task.httpRequest.body = Buffer.from(payload.body).toString('base64');
58
+ }
59
+
60
+ if (delay) {
61
+ // The time when the task is scheduled to be attempted.
62
+ task.scheduleTime = {
63
+ seconds: delay + Date.now() / 1000,
64
+ };
65
+ };
66
+
67
+ LOGGER.info(requestId, task, `Sending task to queue ${queueId}}`)
68
+
69
+ const request = { parent: parent, task: task };
70
+ const [response] = await client.createTask(request);
71
+
72
+ LOGGER.info(requestId, { name: response.name, response }, `Added task to queue ${queueId}}`)
73
+ } catch (err) {
74
+ LOGGER.error(requestId, err, err.message)
75
+ }
76
+ };
77
+
78
+ /**
79
+ * Returns a unique string for name of a task in task queues, to be used for task de-duplication purpose.
80
+ * @param {String} projectId
81
+ * @param {String} locationId
82
+ * @param {String} queueId
83
+ * @param {String} taskId
84
+ * @returns {String}
85
+ */
86
+ const getTaskId = (projectId, locationId, queueId, taskId = uuidv4()) => {
87
+ return `projects/${projectId}/locations/${locationId}/queues/${queueId}/tasks/${taskId}`;
88
+ };
89
+
90
+ module.exports = {
91
+ createHttpTask,
92
+ getTaskId
93
+ };
@@ -39,10 +39,10 @@ const host_response_to_query = {
39
39
  * @param {String} date - Activity's date
40
40
  */
41
41
  const activity_join_request = {
42
- heading: 'You have a new game request! 🙌',
42
+ heading: 'New game request! 🙌',
43
43
  text: '{{user_first_name}} has requested to join your {{sport_name}} game happening on {{date}}.',
44
44
  additional_message_text: {
45
- text: 'They have a message for you! Tap to read',
45
+ text: 'They have a message for you! Tap to read.',
46
46
  default: 'Let them know if you\'re game.'
47
47
  },
48
48
  buttons: [],
@@ -58,7 +58,7 @@ const activity_join_request = {
58
58
  * @param {String} date - Activity's date
59
59
  */
60
60
  const activity_request_accepted = {
61
- heading: '{{host_first_name}} has accepted your request! 🥳',
61
+ heading: 'Request accepted! 🥳',
62
62
  text: 'You\'re on for the {{sport_name}} game on {{date}}. You can now chat with your game squad.',
63
63
  buttons: [],
64
64
  notificationId: notificationIds.ACTIVITY_REQUEST_RESPONSE
@@ -73,11 +73,11 @@ const activity_request_accepted = {
73
73
  * @param {String} date - Activity's date
74
74
  */
75
75
  const activity_request_declined = {
76
- heading: 'Your request has been declined. 😟',
76
+ heading: 'Request declined. 😟',
77
77
  text: '{{host_first_name}} declined your request to join the {{sport_name}} game on {{date}}.',
78
78
  additional_message_text: {
79
- text: 'They have a message for you! Tap to read',
80
- default: 'No worries, other games are waiting for you to join! Join them now. 😀'
79
+ text: 'They have a message for you! Tap to read.',
80
+ default: 'No worries, other games are waiting for you! Join them now. 😀'
81
81
  },
82
82
  buttons: [],
83
83
  notificationId: notificationIds.HOST_RETIRED
@@ -92,7 +92,7 @@ const activity_request_declined = {
92
92
  * @param {String} date - Activity's date
93
93
  */
94
94
  const user_invited_by_host = {
95
- heading: 'You have a new invite! 📩',
95
+ heading: 'New game invite! 📩',
96
96
  text: '{{host_first_name}} has invited you to the {{sport_name}} game on {{date}}. Are you game? 💪',
97
97
  buttons: [],
98
98
  notificationId: notificationIds.ACTIVITY_INVITATION
@@ -107,8 +107,8 @@ const user_invited_by_host = {
107
107
  * @param {String} date - Activity's date
108
108
  */
109
109
  const user_accepted_invite = {
110
- heading: 'Your invite has been accepted! 🤝',
111
- text: '{{user_first_name}} has accepted your request for the {{sport_name}} game on {{date}}.',
110
+ heading: 'Game invite accepted! 🤝',
111
+ text: '{{user_first_name}} has accepted your invite for the {{sport_name}} game on {{date}}.',
112
112
  buttons: [],
113
113
  notificationId: notificationIds.ACTIVITY_INVITATION_RESPONSE
114
114
  };
@@ -122,11 +122,11 @@ const user_accepted_invite = {
122
122
  * @param {String} date - Activity's date
123
123
  */
124
124
  const user_declined_invite = {
125
- heading: 'Your invite has been declined. 😟',
126
- text: '{{user_first_name}} has declined your request for the {{sport_name}} game on {{date}}.',
125
+ heading: 'Game invite declined. 😟',
126
+ text: '{{user_first_name}} has declined your invite for the {{sport_name}} game on {{date}}.',
127
127
  additional_message_text: {
128
- text: 'They have a message for you! Tap to read',
129
- default: ''
128
+ text: 'They have a message for you! Tap to read.',
129
+ default: 'Tap to invite other players.'
130
130
  },
131
131
  buttons: [],
132
132
  notificationId: notificationIds.HOST_RETIRED
@@ -141,10 +141,10 @@ const user_declined_invite = {
141
141
  * @param {String} date - Activity's date
142
142
  */
143
143
  const host_revoked_invite = {
144
- heading: 'Your invite has been cancelled 😕 ',
144
+ heading: 'Game invite cancelled 😕',
145
145
  text: '{{host_first_name}} has cancelled your invitation to the {{sport_name}} game on {{date}}.',
146
146
  additional_message_text: {
147
- text: 'They have a message for you! Tap to read',
147
+ text: 'They have a message for you! Tap to read.',
148
148
  default: 'But, you can always join another game!'
149
149
  },
150
150
  buttons: [],
@@ -160,7 +160,7 @@ const host_revoked_invite = {
160
160
  * @param {String} date - Activity's date
161
161
  */
162
162
  const host_retired_user = {
163
- heading: 'You have been made to retire. 😕 ',
163
+ heading: 'You have been made to retire.😕',
164
164
  text: 'You are no longer a part of {{sport_name}} game on {{date}}.',
165
165
  additional_message_text: {
166
166
  text: '{{host_first_name}} has a message for you! Tap to read',
@@ -182,8 +182,8 @@ const user_left_game = {
182
182
  heading: 'Player has left the game.',
183
183
  text: '{{user_first_name}} has left {{date}}\'s {{sport_name}} game.',
184
184
  additional_message_text: {
185
- text: '{{user_first_name}} has a message for you! Tap to read',
186
- default: ''
185
+ text: 'They have a message for you! Tap to read.',
186
+ default: 'Tap to invite other players.'
187
187
  },
188
188
  buttons: [],
189
189
  notificationId: notificationIds.HOST_RETIRED
@@ -204,6 +204,20 @@ const host_cancelled_activity = {
204
204
  notificationId: notificationIds.ACTIVITY_CANCEL
205
205
  };
206
206
 
207
+ /**
208
+ * Template for sending activity reminder.
209
+ * Notification is received by all the players of the activity.
210
+ * Text render only
211
+ * @param {String} sport_name
212
+ * @param {String} date
213
+ */
214
+ const activity_reminder = {
215
+ heading: 'Activity Reminder',
216
+ text: 'You have a {{sport_name}} game coming up at {{date}}. Gear up for some fun!',
217
+ buttons: [],
218
+ notificationId: notificationIds.ACTIVITY_REMINDER
219
+ };
220
+
207
221
  const host_updated_activity_details = {
208
222
  // ??
209
223
  };
@@ -228,5 +242,6 @@ module.exports = {
228
242
  host_revoked_invite,
229
243
  host_retired_user,
230
244
  user_left_game,
231
- host_cancelled_activity
245
+ host_cancelled_activity,
246
+ activity_reminder
232
247
  }
@@ -17,28 +17,36 @@ const notificationChannels = {
17
17
  'activity_suggestions': '3ab98c37-b93c-4d39-ab55-bb2cc6279cb8', // done - 1 notifications tagged
18
18
  'expenses': '1eb30f33-2b3b-40ce-8798-fce55c1275e2', // done - 6 notifications tagged
19
19
  'groups_manage_requests': '83c024d1-2cb7-47fa-989d-1d8ef343a51c', // done - 6 notifications tagged
20
- 'group_updates': '9e023a20-deab-4bc4-bd33-08a8d9316322' // done - 3 notifications tagged
20
+ 'group_updates': '9e023a20-deab-4bc4-bd33-08a8d9316322', // done - 3 notifications tagged
21
+ 'activity_reminders': '53c55399-a73c-4800-b824-3c750ac57b98'
21
22
  };
22
23
 
23
24
  // ------------------------------------------ Exported (public) -----------------------------------------//
24
25
 
25
26
  const notificationIds = {
26
- ACTIVITY_NOTIFY_PUSH: 'activity-notify-push',
27
- ACTIVITY_NOTIFY_DRAWER: 'activity-notify-drawer',
27
+ ACTIVITY_NOTIFY_PUSH: 'activity-notify-push', // > DEPRECATED
28
+ ACTIVITY_NOTIFY_DRAWER: 'activity-notify-drawer', // > DEPRECATED
29
+ ACTIVITY_NOTIFY: 'activity-notify',
28
30
  GROUP_INVITATION: 'group-invitation',
29
- GROUP_INVITATION_RESPONSE_PUSH: 'group-invitation-response-push',
30
- GROUP_INVITATION_RESPONSE_DRAWER: 'group-invitation-response-drawer',
31
- GROUP_REQUEST_PUSH: 'group-request-push',
32
- GROUP_REQUEST_DRAWER: 'group-request-drawer',
31
+ GROUP_INVITATION_RESPONSE: 'group-invitation-response',
32
+ GROUP_INVITATION_RESPONSE_PUSH: 'group-invitation-response-push', // > DEPRECATED
33
+ GROUP_INVITATION_RESPONSE_DRAWER: 'group-invitation-response-drawer', // > DEPRECATED
34
+ GROUP_REQUEST_PUSH: 'group-request-push', // > DEPRECATED
35
+ GROUP_REQUEST_DRAWER: 'group-request-drawer', // > DEPRECATED
36
+ GROUP_REQUEST: 'group-request',
33
37
  GROUP_REQUEST_RESPONSE: 'group-request-response',
34
- GROUP_NAME_PUSH: 'group-name-push',
35
- GROUP_NAME_DRAWER: 'group-name-drawer',
36
- ADMIN_STATUS_PUSH: 'admin-status-push',
37
- ADMIN_STATUS_DRAWER: 'admin-status-drawer',
38
- NEW_MESSAGE_PUSH: 'new-message-push',
39
- NEW_MESSAGE_DRAWER: 'new-message-drawer',
40
- NEW_COMMENT_PUSH: 'new-comment-push',
41
- NEW_COMMENT_DRAWER: 'new-comment-drawer',
38
+ GROUP_NAME: 'group-name',
39
+ GROUP_NAME_PUSH: 'group-name-push', // > DEPRECATED
40
+ GROUP_NAME_DRAWER: 'group-name-drawer', // > DEPRECATED
41
+ ADMIN_STATUS: 'admin-status',
42
+ ADMIN_STATUS_PUSH: 'admin-status-push', // > DEPRECATED
43
+ ADMIN_STATUS_DRAWER: 'admin-status-drawer',// > DEPRECATED
44
+ NEW_MESSAGE_PUSH: 'new-message-push', // > DEPRECATED
45
+ NEW_MESSAGE_DRAWER: 'new-message-drawer', // > DEPRECATED
46
+ NEW_MESSAGE: 'new-message',
47
+ NEW_COMMENT_PUSH: 'new-comment-push', // > DEPRECATED
48
+ NEW_COMMENT_DRAWER: 'new-comment-drawer', // > DEPRECATED
49
+ NEW_COMMENT: 'new-comment',
42
50
  ACTIVITY_INVITATION: 'activity-invitation',
43
51
  ACTIVITY_INVITATION_RESPONSE: 'activity-invitation-response',
44
52
  ACTIVITY_REQUEST: 'activity-request',
@@ -71,29 +79,21 @@ const notificationIds = {
71
79
  SPLIT_EXPENSE_DELETED: 'split-expense-deleted',
72
80
  HOST_ACTIVITY_PAYOUT: 'host-activity-payout',
73
81
  KARMA_CASHBACK: 'karma-cashback',
74
- ACTIVITY_QUERY_ANSWERED: 'activity-query-answered'
82
+ ACTIVITY_QUERY_ANSWERED: 'activity-query-answered',
83
+ ACTIVITY_REMINDER: 'activity-reminder'
75
84
  };
76
85
 
77
86
  // TODO - Check targets against current value
78
87
 
79
88
  const config = {
80
- [notificationIds.ACTIVITY_NOTIFY_PUSH]: {
81
- category: notificationCategories,
82
- target: "group",
83
- path: "timeline",
84
- title: "Group Update",
85
- type: ["push"],
86
- buttons: [],
87
- android_channel_id: ''
88
- },
89
- [notificationIds.ACTIVITY_NOTIFY_DRAWER]: {
89
+ [notificationIds.ACTIVITY_NOTIFY]: {
90
90
  category: notificationCategories.GROUP,
91
91
  target: "group",
92
92
  path: "timeline",
93
93
  title: "Group Update",
94
- type: ["drawer"],
94
+ type: ["drawer", "push"],
95
95
  buttons: [],
96
- android_channel_id: ''
96
+ android_channel_id: notificationChannels.activity_suggestions
97
97
  },
98
98
  [notificationIds.GROUP_INVITATION]: {
99
99
  category: notificationCategories.GROUP,
@@ -104,39 +104,21 @@ const config = {
104
104
  buttons: [],
105
105
  android_channel_id: notificationChannels.groups_manage_requests
106
106
  },
107
- [notificationIds.GROUP_INVITATION_RESPONSE_PUSH]: {
107
+ [notificationIds.GROUP_INVITATION_RESPONSE]: {
108
108
  category: notificationCategories.GROUP,
109
109
  target: "group",
110
110
  path: "manage",
111
111
  title: "Group Update",
112
- type: ["push"],
113
- buttons: [],
114
- android_channel_id: notificationChannels.groups_manage_requests
115
- },
116
- [notificationIds.GROUP_INVITATION_RESPONSE_DRAWER]: {
117
- category: notificationCategories.GROUP,
118
- target: "group",
119
- path: "manage",
120
- title: "Group Update",
121
- type: ["drawer"],
122
- buttons: [],
123
- android_channel_id: notificationChannels.groups_manage_requests
124
- },
125
- [notificationIds.GROUP_REQUEST_PUSH]: {
126
- category: notificationCategories.GROUP,
127
- target: "group",
128
- path: "manage",
129
- title: "Group Update",
130
- type: ["push"],
112
+ type: ["push", "drawer"],
131
113
  buttons: [],
132
114
  android_channel_id: notificationChannels.groups_manage_requests
133
115
  },
134
- [notificationIds.GROUP_REQUEST_DRAWER]: {
116
+ [notificationIds.GROUP_REQUEST]: {
135
117
  category: notificationCategories.GROUP,
136
118
  target: "group",
137
119
  path: "manage",
138
120
  title: "Group Update",
139
- type: ["drawer"],
121
+ type: ["push", "drawer"],
140
122
  buttons: [],
141
123
  android_channel_id: notificationChannels.groups_manage_requests
142
124
  },
@@ -149,77 +131,41 @@ const config = {
149
131
  buttons: [],
150
132
  android_channel_id: notificationChannels.groups_manage_requests
151
133
  },
152
- [notificationIds.GROUP_NAME_PUSH]: {
153
- category: notificationCategories.GROUP,
154
- target: "group",
155
- path: "manage",
156
- title: "Group Update",
157
- type: ["push"],
158
- buttons: [],
159
- android_channel_id: notificationChannels.group_updates
160
- },
161
- [notificationIds.GROUP_NAME_DRAWER]: {
134
+ [notificationIds.GROUP_NAME]: {
162
135
  category: notificationCategories.GROUP,
163
136
  target: "group",
164
137
  path: "manage",
165
138
  title: "Group Update",
166
- type: ["drawer"],
139
+ type: ["push", "drawer"],
167
140
  buttons: [],
168
141
  android_channel_id: notificationChannels.group_updates
169
142
  },
170
- [notificationIds.ADMIN_STATUS_PUSH]: {
143
+ [notificationIds.ADMIN_STATUS]: {
171
144
  category: notificationCategories.GROUP,
172
145
  target: "group",
173
146
  path: "manage",
174
147
  title: "Group Update",
175
- type: ["push"],
148
+ type: ["drawer", "push"],
176
149
  buttons: [],
177
150
  android_channel_id: notificationChannels.group_updates
178
151
  },
179
- [notificationIds.ADMIN_STATUS_DRAWER]: {
180
- category: notificationCategories.GROUP,
181
- target: "group",
182
- path: "manage",
183
- title: "Group Update",
184
- type: ["drawer"],
185
- buttons: [],
186
- android_channel_id: ''
187
- },
188
- [notificationIds.NEW_MESSAGE_PUSH]: {
152
+ [notificationIds.NEW_MESSAGE]: {
189
153
  category: notificationCategories.GROUP,
190
154
  target: "group",
191
155
  path: "board",
192
156
  title: "Group Update",
193
- type: ["push"],
157
+ type: ["push", "drawer"],
194
158
  buttons: [],
195
- android_channel_id: ''
159
+ android_channel_id: notificationChannels.group_updates
196
160
  },
197
- [notificationIds.NEW_COMMENT_DRAWER]: {
161
+ [notificationIds.NEW_COMMENT]: {
198
162
  category: notificationCategories.GROUP,
199
163
  target: "group",
200
164
  path: "board",
201
165
  title: "Group Update",
202
- type: ["drawer"],
203
- buttons: [],
204
- android_channel_id: ''
205
- },
206
- [notificationIds.NEW_COMMENT_PUSH]: {
207
- category: notificationCategories.GROUP,
208
- target: "group",
209
- path: "message",
210
- title: "Group Update",
211
- type: ["push"],
212
- buttons: [],
213
- android_channel_id: ''
214
- },
215
- [notificationIds.NEW_COMMENT_DRAWER]: {
216
- category: notificationCategories.GROUP,
217
- target: "group",
218
- path: "message",
219
- title: "Group Update",
220
- type: ["drawer"],
166
+ type: ["drawer","push"],
221
167
  buttons: [],
222
- android_channel_id: ''
168
+ android_channel_id: notificationChannels.group_updates
223
169
  },
224
170
  [notificationIds.ACTIVITY_INVITATION]: {
225
171
  category: notificationCategories.ACTIVITY,
@@ -488,6 +434,14 @@ const config = {
488
434
  type: ["push", "drawer"],
489
435
  buttons: [],
490
436
  android_channel_id: notificationChannels.activity_query
437
+ },
438
+ [notificationIds.ACTIVITY_REMINDER] : {
439
+ category: notificationCategories.ACTIVITY,
440
+ target: "match",
441
+ title: "Activity Reminder",
442
+ type: ["push"],
443
+ buttons: [],
444
+ android_channel_id: notificationChannels.activity_reminders
491
445
  }
492
446
  };
493
447
 
@@ -77,7 +77,7 @@ const getUserAverageRatingForASport = (currentAvg, prevAvg) => {
77
77
  let oldAvg = prevAvg ? prevAvg * Constants.RATINGS_WEIGHTAGE.old : 0;
78
78
 
79
79
  // If for any reason any player doesn't have any old rating/ new rating, send back both ratings with 100% weightage (as one of them will be zero)
80
- if (!prevAvg || !currentAvg) {
80
+ if (!prevAvg || !currentAvg) {
81
81
  latest25Avg = currentAvg;
82
82
  oldAvg = prevAvg;
83
83
  }
package/lib/request.js ADDED
@@ -0,0 +1,136 @@
1
+ const Axios = require('axios');
2
+ const TIMEOUT_DURATION = 10 * 1000 // milliseconds, used as default
3
+ const PLAYO_LOGGER = require("@playo/logger");
4
+
5
+ const LOGGER = new PLAYO_LOGGER("playo-http-request-handler");
6
+
7
+ /**
8
+ * This function assumes the external api being called gives response,
9
+ * following same structure as being used in playo currently for showing success/failure , i.e. -
10
+ * for successful http request, { requestStatus : 1 } & http failure/ error would be recorded otherwise
11
+ * the responses for external services should be logged for requestId tracing , and analytics purpose later on
12
+ * @param {*} resp
13
+ */
14
+ const playoResponseHandler = (resp, requestId) => {
15
+ const { status, data, config } = resp;
16
+ const { url } = config;
17
+ if (status === 200) {
18
+ const { requestStatus } = data;
19
+ LOGGER.info(requestId, data, `Api call to url to ${url} succeeded with status ${status}`);
20
+ if (!requestStatus) {
21
+ data['requestStatus'] = 1; // assume request status of 1 if any service doesn't provide requestStatus.
22
+ }
23
+ return data;
24
+ } else {
25
+ LOGGER.error(requestId, data, `Api call to url to ${url} failed with status : ${status}`);
26
+ data['requestStatus'] = 0;
27
+ return Promise.reject(data);
28
+ }
29
+ };
30
+
31
+ /**
32
+ * Makes a get http request - throws error to be handled by calling function
33
+ * @param {String} url
34
+ * @param {Object} headers
35
+ * @param {Object} query
36
+ * @param {String} requestId
37
+ * @param {Boolean} shouldTimeOut - Defaults to false
38
+ * @param {Number} timeout - in seconds, Defaults to 10 seconds
39
+ * @param {Function} responseHandler - Caller should pass it's own http response handler. Defaults to playo's response function handler
40
+ */
41
+ const get = async (url, headers = {}, query = {}, requestId = '', responseHandler = playoResponseHandler, shouldTimeOut = false, timeout = TIMEOUT_DURATION) => {
42
+ try {
43
+ if (!shouldTimeOut) {
44
+ timeout = 0; // no timeout
45
+ }
46
+ const resp = await Axios.get(url, { headers, params: query, timeout });
47
+ return responseHandler(resp, requestId);
48
+ } catch (error) {
49
+ LOGGER.error(requestId, error, `Api call to url to ${url} failed due to ${error.message}`);
50
+ return Promise.reject(error);
51
+ }
52
+ };
53
+
54
+ /**
55
+ * Makes a POST http request - throws error to be handled by calling function
56
+ * @param {String} url
57
+ * @param {Object} headers
58
+ * @param {Object} query
59
+ * @param {Object} body
60
+ * @param {String} requestId
61
+ * @param {Boolean} shouldTimeOut - Defaults to false
62
+ * @param {Number} timeout - in seconds, Defaults to 10 seconds
63
+ * @param {Function} responseHandler - Caller should pass it's own http response handler. Defaults to playo's response function handler
64
+ */
65
+ const post = async (url, headers = {}, query = {}, body = {}, requestId = '', responseHandler = playoResponseHandler, shouldTimeOut = false, timeout = TIMEOUT_DURATION) => {
66
+ try {
67
+ if (!shouldTimeOut) {
68
+ timeout = 0; // no timeout
69
+ }
70
+ const options = { headers, query, timeout };
71
+ const resp = await Axios.post(url, body, options);
72
+ return responseHandler(resp, requestId);
73
+ } catch (err) {
74
+ LOGGER.error(requestId, err, `Api call to url to ${url} failed due to ${err.message}`);
75
+ return Promise.reject(err);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Makes a PUT http request - throws error to be handled by calling function
81
+ * @param {String} url
82
+ * @param {Object} headers
83
+ * @param {Object} query
84
+ * @param {Object} body
85
+ * @param {String} requestId
86
+ * @param {Boolean} shouldTimeOut - Defaults to false
87
+ * @param {Number} timeout - in seconds, Defaults to 10 seconds
88
+ * @param {Function} responseHandler - Caller should pass it's own http response handler. Defaults to playo's response function handler
89
+ */
90
+ const put = async (url, headers = {}, query = {}, body = {}, requestId = '', responseHandler = playoResponseHandler, shouldTimeOut = false, timeout = TIMEOUT_DURATION) => {
91
+ try {
92
+ if (!shouldTimeOut) {
93
+ timeout = 0; // no timeout
94
+ }
95
+ const options = { headers, query, timeout };
96
+ const resp = await Axios.put(url, body, options);
97
+
98
+ return responseHandler(resp, requestId);
99
+ } catch (error) {
100
+ LOGGER.error(requestId, error, `Api call to url to ${url} failed due to ${error.message}`);
101
+ return Promise.reject(error);
102
+ }
103
+ };
104
+
105
+ /**
106
+ * Makes a DELETE http request - throws error to be handled by calling function
107
+ * @param {String} url
108
+ * @param {Object} headers
109
+ * @param {Object} query
110
+ * @param {Object} body
111
+ * @param {String} requestId
112
+ * @param {Boolean} shouldTimeOut - Defaults to false
113
+ * @param {Number} timeout - in seconds, Defaults to 10 seconds
114
+ * @param {Function} responseHandler - Caller should pass it's own http response handler. Defaults to playo's response function handler
115
+ */
116
+ const remove = async (url, headers = {}, query = {}, body, requestId = '', responseHandler = playoResponseHandler, shouldTimeOut = false, timeout = TIMEOUT_DURATION) => {
117
+ try {
118
+ if (!shouldTimeOut) {
119
+ timeout = 0; // no timeout
120
+ }
121
+ const options = { headers, params: query, data: body, timeout };
122
+ const resp = await Axios.delete(url, options);
123
+ return responseHandler(resp, requestId);
124
+ } catch (error) {
125
+ LOGGER.error(requestId, error, `Api call to url to ${url} failed due to ${error.message}`);
126
+ return Promise.reject(error);
127
+ }
128
+ };
129
+
130
+
131
+ module.exports = {
132
+ get,
133
+ post,
134
+ put,
135
+ remove
136
+ }
package/lib/util.js CHANGED
@@ -1,9 +1,11 @@
1
1
  /**\
2
2
  * This module is not imported in PlayoLib directly as there are already many imports in individual repositories
3
3
  * named util/utils and importing this alongside might cause unforeseen errors or poor readability
4
- * Ideally new repositories should import utils from here only. Todo- look for a workaround
4
+ * Ideally new repositories should import utils from here only. Todo- look for a workaround - named imports
5
5
  */
6
6
 
7
+ const hbs = require('handlebars');
8
+
7
9
  /**
8
10
  * Finds rating given to a user for a sport by playpals <Assumes playpalDocs supplied are already filtered for a user>
9
11
  * @param {Array} playpalDocs
@@ -70,6 +72,9 @@ const getRecentRatingDictOfPals = (postActivityDocs) => {
70
72
  // pals array contains ratings object as per given by other playpals for a particular activity, check schema for further details
71
73
  const { pals = [] } = postActivityDoc;
72
74
 
75
+ /**
76
+ * Description for code below we are try to get a dictionary of latest non-zero rating the user has received to be processed later
77
+ */
73
78
  if (Array.isArray(pals)) {
74
79
  pals.forEach((palRating) => {
75
80
  const { palId = '', rating = 0, timestamp } = palRating;
@@ -78,7 +83,7 @@ const getRecentRatingDictOfPals = (postActivityDocs) => {
78
83
  rating: rating,
79
84
  timestamp: timestamp
80
85
  }
81
- } else if (palRatingDict[palId] && timestamp >= palRatingDict[palId]["timestamp"]) {
86
+ } else if (palRatingDict[palId] && timestamp >= palRatingDict[palId]["timestamp"] && rating > 0) {
82
87
  // If user received any rating more recent then consider that instead
83
88
  palRatingDict[palId]["rating"] = rating;
84
89
  }
@@ -118,11 +123,30 @@ const getCategoricalBreakUpFromRecentUserRatings = (palRatingDict, levelCategori
118
123
  }
119
124
 
120
125
  return categoricalBreakUp;
121
- }
126
+ };
127
+
128
+ const noop = () => {
129
+ return undefined;
130
+ };
131
+
132
+ /**
133
+ *
134
+ * @param {String} template - Handlebars compatible template
135
+ * @param {Object} data - Data points containing key value pairs of data required in template supplied
136
+ * @returns {String}
137
+ */
138
+ const renderTemplate = (template, data) => {
139
+
140
+ const temp = hbs.compile(template);
141
+
142
+ return temp(data);
143
+ };
122
144
 
123
145
  module.exports = {
124
146
  getRatingsFromPlaypalDocs,
125
147
  findAverage,
126
148
  getRecentRatingDictOfPals,
127
- getCategoricalBreakUpFromRecentUserRatings
128
- }
149
+ getCategoricalBreakUpFromRecentUserRatings,
150
+ noop,
151
+ renderTemplate
152
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playov2-js-utilities",
3
- "version": "0.3.0",
3
+ "version": "0.3.16.0",
4
4
  "description": "Private package for JS utility functions",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -16,9 +16,16 @@
16
16
  "author": "Saurabh Agrawal",
17
17
  "license": "ISC",
18
18
  "homepage": "https://bitbucket.org/techmash/playov2-js-utilities#readme",
19
-
20
19
  "devDependencies": {
21
20
  "faker": "^5.5.3",
22
21
  "jest": "^27.1.0"
22
+ },
23
+ "dependencies": {
24
+ "@google-cloud/tasks": "^2.5.0",
25
+ "@playo/logger": "^0.9.18",
26
+ "axios": "^0.24.0",
27
+ "cron": "^1.8.2",
28
+ "handlebars": "^4.7.7",
29
+ "uuid": "^8.3.2"
23
30
  }
24
31
  }