bulltrackers-module 1.0.494 → 1.0.495

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.
@@ -29,15 +29,41 @@ async function processAlertForPI(db, logger, piCid, alertType, computationMetada
29
29
  // 3. Generate alert message
30
30
  const alertMessage = generateAlertMessage(alertType, piUsername, computationMetadata);
31
31
 
32
+ // Helper function to get Firebase UID from eToro CID
33
+ async function getFirebaseUidFromCid(etoroCid) {
34
+ const signedInUsersSnapshot = await db.collection('signedInUsers')
35
+ .where('etoroCID', '==', Number(etoroCid))
36
+ .limit(1)
37
+ .get();
38
+
39
+ if (!signedInUsersSnapshot.empty) {
40
+ return signedInUsersSnapshot.docs[0].id; // Firebase UID is the document ID
41
+ }
42
+ return null;
43
+ }
44
+
32
45
  // 4. Create notifications for each subscribed user (using user_notifications collection)
46
+ // Convert eToro CIDs to Firebase UIDs first
33
47
  const batch = db.batch();
34
48
  const notificationRefs = [];
35
49
  const counterUpdates = {};
50
+ const uidMapping = {}; // Cache for CID -> UID mappings
36
51
 
37
52
  for (const subscription of subscriptions) {
53
+ // Get Firebase UID for this user's eToro CID
54
+ let firebaseUid = uidMapping[subscription.userCid];
55
+ if (!firebaseUid) {
56
+ firebaseUid = await getFirebaseUidFromCid(subscription.userCid);
57
+ if (!firebaseUid) {
58
+ logger.log('WARN', `[processAlertForPI] Could not find Firebase UID for user CID ${subscription.userCid}, skipping notification`);
59
+ continue; // Skip this user if we can't find their Firebase UID
60
+ }
61
+ uidMapping[subscription.userCid] = firebaseUid;
62
+ }
63
+
38
64
  const notificationId = `alert_${Date.now()}_${subscription.userCid}_${piCid}_${Math.random().toString(36).substring(2, 9)}`;
39
65
  const notificationRef = db.collection('user_notifications')
40
- .doc(String(subscription.userCid))
66
+ .doc(firebaseUid) // Use Firebase UID, not eToro CID
41
67
  .collection('notifications')
42
68
  .doc(notificationId);
43
69
 
@@ -48,6 +74,7 @@ async function processAlertForPI(db, logger, piCid, alertType, computationMetada
48
74
  message: alertMessage,
49
75
  read: false,
50
76
  createdAt: FieldValue.serverTimestamp(),
77
+ timestamp: FieldValue.serverTimestamp(), // Also include timestamp for ordering
51
78
  metadata: {
52
79
  piCid: Number(piCid),
53
80
  piUsername: piUsername,
@@ -65,26 +92,26 @@ async function processAlertForPI(db, logger, piCid, alertType, computationMetada
65
92
  batch.set(notificationRef, notificationData);
66
93
  notificationRefs.push(notificationRef);
67
94
 
68
- // Track counter updates
95
+ // Track counter updates (using Firebase UID as key)
69
96
  const dateKey = computationDate || new Date().toISOString().split('T')[0];
70
- if (!counterUpdates[subscription.userCid]) {
71
- counterUpdates[subscription.userCid] = {
97
+ if (!counterUpdates[firebaseUid]) {
98
+ counterUpdates[firebaseUid] = {
72
99
  date: dateKey,
73
100
  unreadCount: 0,
74
101
  totalCount: 0,
75
102
  byType: {}
76
103
  };
77
104
  }
78
- counterUpdates[subscription.userCid].unreadCount += 1;
79
- counterUpdates[subscription.userCid].totalCount += 1;
80
- counterUpdates[subscription.userCid].byType[alertType.id] =
81
- (counterUpdates[subscription.userCid].byType[alertType.id] || 0) + 1;
105
+ counterUpdates[firebaseUid].unreadCount += 1;
106
+ counterUpdates[firebaseUid].totalCount += 1;
107
+ counterUpdates[firebaseUid].byType[alertType.id] =
108
+ (counterUpdates[firebaseUid].byType[alertType.id] || 0) + 1;
82
109
  }
83
110
 
84
- // 5. Update notification counters
85
- for (const [userCid, counter] of Object.entries(counterUpdates)) {
111
+ // 5. Update notification counters (using Firebase UIDs)
112
+ for (const [firebaseUid, counter] of Object.entries(counterUpdates)) {
86
113
  const counterRef = db.collection('user_notifications')
87
- .doc(String(userCid))
114
+ .doc(firebaseUid) // Use Firebase UID, not eToro CID
88
115
  .collection('counters')
89
116
  .doc(counter.date);
90
117
 
@@ -59,36 +59,73 @@ async function sendTestAlert(req, res, dependencies, config) {
59
59
  logger.log('INFO', `[sendTestAlert] Using default alert type: ${alertType.id}`);
60
60
  }
61
61
 
62
- // Determine target user CIDs
63
- let targetCids = [];
62
+ // Helper function to get Firebase UID from eToro CID
63
+ async function getFirebaseUidFromCid(etoroCid) {
64
+ const signedInUsersSnapshot = await db.collection('signedInUsers')
65
+ .where('etoroCID', '==', Number(etoroCid))
66
+ .limit(1)
67
+ .get();
68
+
69
+ if (!signedInUsersSnapshot.empty) {
70
+ return signedInUsersSnapshot.docs[0].id; // Firebase UID is the document ID
71
+ }
72
+ return null;
73
+ }
74
+
75
+ // Determine target users (as Firebase UIDs)
76
+ let targetFirebaseUids = [];
64
77
 
65
78
  if (targetUsers === 'all') {
66
- // Get all users from user_notifications collection
67
- const notificationsSnapshot = await db.collection('user_notifications').get();
68
- targetCids = notificationsSnapshot.docs.map(doc => Number(doc.id));
69
- logger.log('INFO', `[sendTestAlert] Sending to all ${targetCids.length} users`);
79
+ // Get all users from signedInUsers collection (who have etoroCID)
80
+ const signedInUsersSnapshot = await db.collection('signedInUsers')
81
+ .where('etoroCID', '!=', null)
82
+ .get();
83
+
84
+ targetFirebaseUids = signedInUsersSnapshot.docs.map(doc => doc.id);
85
+ logger.log('INFO', `[sendTestAlert] Sending to all ${targetFirebaseUids.length} users`);
70
86
  } else if (targetUsers === 'dev') {
71
87
  // Get all developer accounts with dev override enabled
72
88
  const devOverridesCollection = config.devOverridesCollection || 'dev_overrides';
73
89
  const devOverridesSnapshot = await db.collection(devOverridesCollection).get();
74
90
 
91
+ const devCids = [];
75
92
  for (const doc of devOverridesSnapshot.docs) {
76
93
  const data = doc.data();
77
94
  if (data.enabled === true) {
78
- targetCids.push(Number(doc.id));
95
+ devCids.push(Number(doc.id));
79
96
  }
80
97
  }
81
98
 
82
99
  // Also include the requesting developer
83
- if (!targetCids.includes(Number(userCid))) {
84
- targetCids.push(Number(userCid));
100
+ if (!devCids.includes(Number(userCid))) {
101
+ devCids.push(Number(userCid));
102
+ }
103
+
104
+ // Convert eToro CIDs to Firebase UIDs
105
+ for (const cid of devCids) {
106
+ const firebaseUid = await getFirebaseUidFromCid(cid);
107
+ if (firebaseUid) {
108
+ targetFirebaseUids.push(firebaseUid);
109
+ } else {
110
+ logger.log('WARN', `[sendTestAlert] Could not find Firebase UID for developer CID ${cid}`);
111
+ }
85
112
  }
86
113
 
87
- logger.log('INFO', `[sendTestAlert] Sending to ${targetCids.length} developer accounts`);
114
+ logger.log('INFO', `[sendTestAlert] Sending to ${targetFirebaseUids.length} developer accounts`);
88
115
  } else if (Array.isArray(targetUsers)) {
89
- // Specific user CIDs
90
- targetCids = targetUsers.map(cid => Number(cid)).filter(cid => !isNaN(cid) && cid > 0);
91
- logger.log('INFO', `[sendTestAlert] Sending to ${targetCids.length} specific users`);
116
+ // Specific user CIDs - convert to Firebase UIDs
117
+ const specificCids = targetUsers.map(cid => Number(cid)).filter(cid => !isNaN(cid) && cid > 0);
118
+
119
+ for (const cid of specificCids) {
120
+ const firebaseUid = await getFirebaseUidFromCid(cid);
121
+ if (firebaseUid) {
122
+ targetFirebaseUids.push(firebaseUid);
123
+ } else {
124
+ logger.log('WARN', `[sendTestAlert] Could not find Firebase UID for CID ${cid}`);
125
+ }
126
+ }
127
+
128
+ logger.log('INFO', `[sendTestAlert] Sending to ${targetFirebaseUids.length} specific users (from ${specificCids.length} CIDs)`);
92
129
  } else {
93
130
  return res.status(400).json({
94
131
  error: "Invalid targetUsers",
@@ -96,7 +133,7 @@ async function sendTestAlert(req, res, dependencies, config) {
96
133
  });
97
134
  }
98
135
 
99
- if (targetCids.length === 0) {
136
+ if (targetFirebaseUids.length === 0) {
100
137
  return res.status(400).json({
101
138
  error: "No target users",
102
139
  message: "No users found matching the target criteria"
@@ -112,16 +149,16 @@ async function sendTestAlert(req, res, dependencies, config) {
112
149
  testSentAt: new Date().toISOString()
113
150
  });
114
151
 
115
- // Create notifications for each target user
152
+ // Create notifications for each target user (using Firebase UIDs)
116
153
  const batch = db.batch();
117
154
  const notificationRefs = [];
118
155
  const counterUpdates = {};
119
156
  const today = new Date().toISOString().split('T')[0];
120
157
 
121
- for (const targetCid of targetCids) {
122
- const notificationId = `test_alert_${Date.now()}_${targetCid}_${piCid}_${Math.random().toString(36).substring(2, 9)}`;
158
+ for (const firebaseUid of targetFirebaseUids) {
159
+ const notificationId = `test_alert_${Date.now()}_${firebaseUid}_${piCid}_${Math.random().toString(36).substring(2, 9)}`;
123
160
  const notificationRef = db.collection('user_notifications')
124
- .doc(String(targetCid))
161
+ .doc(firebaseUid) // Use Firebase UID, not eToro CID
125
162
  .collection('notifications')
126
163
  .doc(notificationId);
127
164
 
@@ -132,6 +169,7 @@ async function sendTestAlert(req, res, dependencies, config) {
132
169
  message: alertMessage,
133
170
  read: false,
134
171
  createdAt: FieldValue.serverTimestamp(),
172
+ timestamp: FieldValue.serverTimestamp(), // Also include timestamp for ordering
135
173
  metadata: {
136
174
  piCid: Number(piCid),
137
175
  piUsername: piUsername,
@@ -150,25 +188,25 @@ async function sendTestAlert(req, res, dependencies, config) {
150
188
  batch.set(notificationRef, notificationData);
151
189
  notificationRefs.push(notificationRef);
152
190
 
153
- // Track counter updates
154
- if (!counterUpdates[targetCid]) {
155
- counterUpdates[targetCid] = {
191
+ // Track counter updates (using Firebase UID as key)
192
+ if (!counterUpdates[firebaseUid]) {
193
+ counterUpdates[firebaseUid] = {
156
194
  date: today,
157
195
  unreadCount: 0,
158
196
  totalCount: 0,
159
197
  byType: {}
160
198
  };
161
199
  }
162
- counterUpdates[targetCid].unreadCount += 1;
163
- counterUpdates[targetCid].totalCount += 1;
164
- counterUpdates[targetCid].byType[alertType.id] =
165
- (counterUpdates[targetCid].byType[alertType.id] || 0) + 1;
200
+ counterUpdates[firebaseUid].unreadCount += 1;
201
+ counterUpdates[firebaseUid].totalCount += 1;
202
+ counterUpdates[firebaseUid].byType[alertType.id] =
203
+ (counterUpdates[firebaseUid].byType[alertType.id] || 0) + 1;
166
204
  }
167
205
 
168
- // Update notification counters
169
- for (const [targetCid, counter] of Object.entries(counterUpdates)) {
206
+ // Update notification counters (using Firebase UIDs)
207
+ for (const [firebaseUid, counter] of Object.entries(counterUpdates)) {
170
208
  const counterRef = db.collection('user_notifications')
171
- .doc(String(targetCid))
209
+ .doc(firebaseUid) // Use Firebase UID, not eToro CID
172
210
  .collection('counters')
173
211
  .doc(counter.date);
174
212
 
@@ -188,15 +226,15 @@ async function sendTestAlert(req, res, dependencies, config) {
188
226
 
189
227
  return res.status(200).json({
190
228
  success: true,
191
- message: `Test alert sent to ${targetCids.length} users`,
229
+ message: `Test alert sent to ${targetFirebaseUids.length} users`,
192
230
  alertType: {
193
231
  id: alertType.id,
194
232
  name: alertType.name,
195
233
  computationName: alertType.computationName
196
234
  },
197
235
  targetUsers: {
198
- count: targetCids.length,
199
- cids: targetCids
236
+ count: targetFirebaseUids.length,
237
+ firebaseUids: targetFirebaseUids
200
238
  },
201
239
  piCid: Number(piCid),
202
240
  piUsername: piUsername,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.494",
3
+ "version": "1.0.495",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [