bulltrackers-module 1.0.629 → 1.0.631
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/functions/alert-system/helpers/alert_helpers.js +69 -77
- package/functions/alert-system/index.js +19 -29
- package/functions/api-v2/helpers/notification_helpers.js +187 -0
- package/functions/computation-system/helpers/computation_worker.js +1 -1
- package/functions/task-engine/helpers/popular_investor_helpers.js +11 -7
- package/index.js +0 -5
- package/package.json +1 -2
- package/functions/old-generic-api/admin-api/index.js +0 -895
- package/functions/old-generic-api/helpers/api_helpers.js +0 -457
- package/functions/old-generic-api/index.js +0 -204
- package/functions/old-generic-api/user-api/helpers/alerts/alert_helpers.js +0 -355
- package/functions/old-generic-api/user-api/helpers/alerts/subscription_helpers.js +0 -327
- package/functions/old-generic-api/user-api/helpers/alerts/test_alert_helpers.js +0 -212
- package/functions/old-generic-api/user-api/helpers/collection_helpers.js +0 -193
- package/functions/old-generic-api/user-api/helpers/core/compression_helpers.js +0 -68
- package/functions/old-generic-api/user-api/helpers/core/data_lookup_helpers.js +0 -256
- package/functions/old-generic-api/user-api/helpers/core/path_resolution_helpers.js +0 -640
- package/functions/old-generic-api/user-api/helpers/core/user_status_helpers.js +0 -195
- package/functions/old-generic-api/user-api/helpers/data/computation_helpers.js +0 -503
- package/functions/old-generic-api/user-api/helpers/data/instrument_helpers.js +0 -55
- package/functions/old-generic-api/user-api/helpers/data/portfolio_helpers.js +0 -245
- package/functions/old-generic-api/user-api/helpers/data/social_helpers.js +0 -174
- package/functions/old-generic-api/user-api/helpers/data_helpers.js +0 -87
- package/functions/old-generic-api/user-api/helpers/dev/dev_helpers.js +0 -336
- package/functions/old-generic-api/user-api/helpers/fetch/on_demand_fetch_helpers.js +0 -615
- package/functions/old-generic-api/user-api/helpers/metrics/personalized_metrics_helpers.js +0 -231
- package/functions/old-generic-api/user-api/helpers/notifications/notification_helpers.js +0 -641
- package/functions/old-generic-api/user-api/helpers/profile/pi_profile_helpers.js +0 -182
- package/functions/old-generic-api/user-api/helpers/profile/profile_view_helpers.js +0 -137
- package/functions/old-generic-api/user-api/helpers/profile/user_profile_helpers.js +0 -190
- package/functions/old-generic-api/user-api/helpers/recommendations/recommendation_helpers.js +0 -66
- package/functions/old-generic-api/user-api/helpers/reviews/review_helpers.js +0 -550
- package/functions/old-generic-api/user-api/helpers/rootdata/rootdata_aggregation_helpers.js +0 -378
- package/functions/old-generic-api/user-api/helpers/search/pi_request_helpers.js +0 -295
- package/functions/old-generic-api/user-api/helpers/search/pi_search_helpers.js +0 -162
- package/functions/old-generic-api/user-api/helpers/sync/user_sync_helpers.js +0 -677
- package/functions/old-generic-api/user-api/helpers/verification/verification_helpers.js +0 -323
- package/functions/old-generic-api/user-api/helpers/watchlist/watchlist_analytics_helpers.js +0 -96
- package/functions/old-generic-api/user-api/helpers/watchlist/watchlist_data_helpers.js +0 -141
- package/functions/old-generic-api/user-api/helpers/watchlist/watchlist_generation_helpers.js +0 -310
- package/functions/old-generic-api/user-api/helpers/watchlist/watchlist_management_helpers.js +0 -829
- package/functions/old-generic-api/user-api/index.js +0 -109
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Portfolio Data Helpers
|
|
3
|
-
* Handles user portfolio data endpoints with migration support
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const { findLatestPortfolioDate, findLatestComputationDate } = require('../core/data_lookup_helpers');
|
|
7
|
-
const { checkIfUserIsPI } = require('../core/user_status_helpers');
|
|
8
|
-
const { getEffectiveCid, getDevOverride } = require('../dev/dev_helpers');
|
|
9
|
-
const { checkPiInComputationDate } = require('./computation_helpers');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* GET /user/me/portfolio
|
|
13
|
-
* Fetches the signed-in user's portfolio data
|
|
14
|
-
*/
|
|
15
|
-
async function getUserPortfolio(req, res, dependencies, config) {
|
|
16
|
-
const { db, logger } = dependencies;
|
|
17
|
-
const { userCid } = req.query;
|
|
18
|
-
|
|
19
|
-
if (!userCid) {
|
|
20
|
-
return res.status(400).json({ error: "Missing userCid" });
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
// Check for dev override impersonation
|
|
25
|
-
const effectiveCid = await getEffectiveCid(db, userCid, config, logger);
|
|
26
|
-
const devOverride = await getDevOverride(db, userCid, config, logger);
|
|
27
|
-
const isImpersonating = devOverride && devOverride.enabled && devOverride.impersonateCid && effectiveCid !== Number(userCid);
|
|
28
|
-
|
|
29
|
-
// If impersonating, check if the effective CID is a Popular Investor
|
|
30
|
-
if (isImpersonating) {
|
|
31
|
-
const rankEntry = await checkIfUserIsPI(db, effectiveCid, config, logger);
|
|
32
|
-
if (rankEntry) {
|
|
33
|
-
return res.status(404).json({
|
|
34
|
-
error: "Popular Investor account",
|
|
35
|
-
message: `CID ${effectiveCid} is a Popular Investor. Use /user/me/pi-personalized-metrics or /user/pi/${effectiveCid}/profile instead.`,
|
|
36
|
-
effectiveCid: effectiveCid,
|
|
37
|
-
isImpersonating: true,
|
|
38
|
-
isPopularInvestor: true,
|
|
39
|
-
suggestedEndpoint: `/user/me/pi-personalized-metrics?userCid=${userCid}`
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const { signedInUsersCollection } = config;
|
|
45
|
-
const CANARY_BLOCK_ID = '19M';
|
|
46
|
-
const today = new Date().toISOString().split('T')[0];
|
|
47
|
-
|
|
48
|
-
// Use effective CID for portfolio lookup
|
|
49
|
-
const dataDate = await findLatestPortfolioDate(db, signedInUsersCollection, effectiveCid, 30);
|
|
50
|
-
|
|
51
|
-
if (!dataDate) {
|
|
52
|
-
return res.status(404).json({
|
|
53
|
-
error: "Portfolio data not found for this user (checked last 30 days)",
|
|
54
|
-
effectiveCid: effectiveCid,
|
|
55
|
-
isImpersonating: isImpersonating || false
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const isFallback = dataDate !== today;
|
|
60
|
-
if (isFallback) {
|
|
61
|
-
logger.log('INFO', `[getUserPortfolio] Using fallback date ${dataDate} for effective CID ${effectiveCid} (today: ${today})`);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Fetch portfolio from signed_in_users/19M/snapshots/{date}/parts/part_X
|
|
65
|
-
const partsRef = db.collection(signedInUsersCollection)
|
|
66
|
-
.doc(CANARY_BLOCK_ID)
|
|
67
|
-
.collection('snapshots')
|
|
68
|
-
.doc(dataDate)
|
|
69
|
-
.collection('parts');
|
|
70
|
-
|
|
71
|
-
const partsSnapshot = await partsRef.get();
|
|
72
|
-
|
|
73
|
-
let portfolioData = null;
|
|
74
|
-
|
|
75
|
-
// Search through all parts to find the user's portfolio (use effective CID)
|
|
76
|
-
for (const partDoc of partsSnapshot.docs) {
|
|
77
|
-
const partData = partDoc.data();
|
|
78
|
-
if (partData && partData[String(effectiveCid)]) {
|
|
79
|
-
portfolioData = partData[String(effectiveCid)];
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (!portfolioData) {
|
|
85
|
-
return res.status(404).json({
|
|
86
|
-
error: "Portfolio data not found in any part document",
|
|
87
|
-
effectiveCid: effectiveCid,
|
|
88
|
-
isImpersonating: isImpersonating || false
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Apply dev override to AggregatedMirrors if dev override is active
|
|
93
|
-
if (devOverride && devOverride.enabled && devOverride.fakeCopiedPIs.length > 0 && portfolioData.AggregatedMirrors) {
|
|
94
|
-
logger.log('INFO', `[getUserPortfolio] Applying DEV OVERRIDE to AggregatedMirrors for user ${userCid}`);
|
|
95
|
-
|
|
96
|
-
portfolioData.AggregatedMirrors = devOverride.fakeCopiedPIs.map(cid => ({
|
|
97
|
-
ParentCID: Number(cid),
|
|
98
|
-
ParentUsername: `PI-${cid}`,
|
|
99
|
-
Invested: 0,
|
|
100
|
-
NetProfit: 0,
|
|
101
|
-
Value: 0,
|
|
102
|
-
PendingForClosure: false
|
|
103
|
-
}));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return res.status(200).json({
|
|
107
|
-
portfolio: portfolioData,
|
|
108
|
-
date: dataDate,
|
|
109
|
-
isFallback: isFallback,
|
|
110
|
-
requestedDate: today,
|
|
111
|
-
userCid: String(userCid),
|
|
112
|
-
devOverrideActive: devOverride && devOverride.enabled
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
} catch (error) {
|
|
116
|
-
logger.log('ERROR', `[getUserPortfolio] Error fetching portfolio for ${userCid}`, error);
|
|
117
|
-
return res.status(500).json({ error: error.message });
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* GET /user/me/data-status
|
|
123
|
-
* Checks if signed-in user's profile page computation is available.
|
|
124
|
-
* The profile page uses SignedInUserProfileMetrics computation, not raw portfolio/history data.
|
|
125
|
-
* If computation exists, the profile page can be rendered. If not, user should sync.
|
|
126
|
-
*/
|
|
127
|
-
async function getUserDataStatus(req, res, dependencies, config) {
|
|
128
|
-
const { db, logger } = dependencies;
|
|
129
|
-
const { userCid } = req.query;
|
|
130
|
-
|
|
131
|
-
if (!userCid) {
|
|
132
|
-
return res.status(400).json({ error: "Missing userCid" });
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
try {
|
|
136
|
-
const today = new Date().toISOString().split('T')[0];
|
|
137
|
-
|
|
138
|
-
logger.log('INFO', `[getUserDataStatus] Checking computation for CID: ${userCid}, Date: ${today}`);
|
|
139
|
-
|
|
140
|
-
// Check for dev override impersonation
|
|
141
|
-
const effectiveCid = await getEffectiveCid(db, userCid, config, logger);
|
|
142
|
-
|
|
143
|
-
// Primary check: Does SignedInUserProfileMetrics computation exist for this user?
|
|
144
|
-
// This is what the profile page actually uses to render
|
|
145
|
-
const insightsCollection = config.unifiedInsightsCollection || 'unified_insights';
|
|
146
|
-
const resultsSub = config.resultsSubcollection || 'results';
|
|
147
|
-
const compsSub = config.computationsSubcollection || 'computations';
|
|
148
|
-
const category = 'popular-investor';
|
|
149
|
-
const computationName = 'SignedInUserProfileMetrics';
|
|
150
|
-
|
|
151
|
-
let computationAvailable = false;
|
|
152
|
-
let computationDate = null;
|
|
153
|
-
let isComputationFallback = false;
|
|
154
|
-
|
|
155
|
-
// Search backwards from today to find the latest date where user exists in computation
|
|
156
|
-
// Priority: Today (T) -> Yesterday (T-1) -> Continue backwards up to 30 days
|
|
157
|
-
const maxDaysBack = 30;
|
|
158
|
-
let foundDate = null;
|
|
159
|
-
|
|
160
|
-
for (let daysBack = 0; daysBack < maxDaysBack; daysBack++) {
|
|
161
|
-
const checkDate = new Date();
|
|
162
|
-
checkDate.setDate(checkDate.getDate() - daysBack);
|
|
163
|
-
const dateStr = checkDate.toISOString().split('T')[0];
|
|
164
|
-
|
|
165
|
-
try {
|
|
166
|
-
// Check if page document exists for this user and date (new pages subcollection structure)
|
|
167
|
-
const { found } = await checkPiInComputationDate(
|
|
168
|
-
db,
|
|
169
|
-
insightsCollection,
|
|
170
|
-
resultsSub,
|
|
171
|
-
compsSub,
|
|
172
|
-
category,
|
|
173
|
-
computationName,
|
|
174
|
-
dateStr,
|
|
175
|
-
String(effectiveCid),
|
|
176
|
-
logger
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
if (found) {
|
|
180
|
-
foundDate = dateStr;
|
|
181
|
-
computationAvailable = true;
|
|
182
|
-
computationDate = dateStr;
|
|
183
|
-
isComputationFallback = daysBack > 0;
|
|
184
|
-
|
|
185
|
-
if (isComputationFallback) {
|
|
186
|
-
logger.log('INFO', `[getUserDataStatus] Found computation for user ${userCid} on date ${computationDate} (${daysBack} days back from today: ${today})`);
|
|
187
|
-
} else {
|
|
188
|
-
logger.log('INFO', `[getUserDataStatus] Found computation for user ${userCid} on today's date`);
|
|
189
|
-
}
|
|
190
|
-
break; // Found user, stop searching
|
|
191
|
-
} else {
|
|
192
|
-
logger.log('DEBUG', `[getUserDataStatus] Page document not found for user ${userCid} on date ${dateStr}, continuing search...`);
|
|
193
|
-
}
|
|
194
|
-
} catch (error) {
|
|
195
|
-
// Continue to next date if error
|
|
196
|
-
logger.log('DEBUG', `[getUserDataStatus] Error checking date ${dateStr}:`, error.message);
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Check if we've exhausted the fallback window
|
|
202
|
-
const fallbackWindowExhausted = !foundDate;
|
|
203
|
-
|
|
204
|
-
if (!foundDate) {
|
|
205
|
-
logger.log('INFO', `[getUserDataStatus] No computation found for user ${userCid} in last ${maxDaysBack} days - fallback window exhausted`);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// For backward compatibility, keep portfolioAvailable and historyAvailable
|
|
209
|
-
// but they should match computationAvailable (computation is the source of truth)
|
|
210
|
-
const result = {
|
|
211
|
-
portfolioAvailable: computationAvailable, // Profile page uses computation, not raw portfolio
|
|
212
|
-
historyAvailable: computationAvailable, // Profile page uses computation, not raw history
|
|
213
|
-
computationAvailable: computationAvailable, // Explicit computation check
|
|
214
|
-
date: computationDate || today, // Use found date or today as fallback
|
|
215
|
-
computationDate: computationDate, // The actual date where computation was found
|
|
216
|
-
isComputationFallback: isComputationFallback, // True if using T-1 or older date
|
|
217
|
-
requestedDate: today, // What date was requested (today)
|
|
218
|
-
fallbackWindowExhausted: fallbackWindowExhausted, // True if checked all dates in fallback window and found nothing
|
|
219
|
-
userCid: String(userCid),
|
|
220
|
-
effectiveCid: String(effectiveCid)
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
if (computationAvailable && isComputationFallback) {
|
|
224
|
-
logger.log('INFO', `[getUserDataStatus] Using fallback date ${computationDate} for CID ${userCid} (requested: ${today})`);
|
|
225
|
-
} else if (computationAvailable) {
|
|
226
|
-
logger.log('INFO', `[getUserDataStatus] Using today's date ${computationDate} for CID ${userCid}`);
|
|
227
|
-
} else {
|
|
228
|
-
logger.log('WARN', `[getUserDataStatus] No computation found for CID ${userCid} in last ${maxDaysBack} days`);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
logger.log('INFO', `[getUserDataStatus] Result for CID ${userCid}:`, result);
|
|
232
|
-
|
|
233
|
-
return res.status(200).json(result);
|
|
234
|
-
|
|
235
|
-
} catch (error) {
|
|
236
|
-
logger.log('ERROR', `[getUserDataStatus] Error checking data status`, error);
|
|
237
|
-
return res.status(500).json({ error: error.message });
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
module.exports = {
|
|
242
|
-
getUserPortfolio,
|
|
243
|
-
getUserDataStatus
|
|
244
|
-
};
|
|
245
|
-
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Social Posts Data Helpers
|
|
3
|
-
* Handles user social posts endpoints
|
|
4
|
-
* UPDATED: Uses collection registry to read from root data collection
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const { findLatestRankingsDate } = require('../core/data_lookup_helpers');
|
|
8
|
-
const { getEffectiveCid, getDevOverride } = require('../dev/dev_helpers');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Find the latest available date for signed-in user social posts
|
|
12
|
-
* Searches backwards from today up to maxDaysBack days
|
|
13
|
-
* @param {Firestore} db - Firestore instance
|
|
14
|
-
* @param {string|number} userCid - User CID
|
|
15
|
-
* @param {object} collectionRegistry - Collection registry (injected at runtime)
|
|
16
|
-
* @param {number} maxDaysBack - Maximum days to search backwards (default: 30)
|
|
17
|
-
* @returns {Promise<string|null>} - Date string (YYYY-MM-DD) or null if not found
|
|
18
|
-
*/
|
|
19
|
-
async function findLatestSocialDate(db, userCid, collectionRegistry, maxDaysBack = 30) {
|
|
20
|
-
const today = new Date();
|
|
21
|
-
|
|
22
|
-
// Get collection name from registry
|
|
23
|
-
let collectionName = 'SignedInUserSocialPostData'; // Default fallback
|
|
24
|
-
if (collectionRegistry && collectionRegistry.getCollectionPath) {
|
|
25
|
-
try {
|
|
26
|
-
// Extract collection name from registry path template
|
|
27
|
-
const samplePath = collectionRegistry.getCollectionPath('rootData', 'signedInUserSocial', {
|
|
28
|
-
date: '2025-01-01',
|
|
29
|
-
cid: '123'
|
|
30
|
-
});
|
|
31
|
-
collectionName = samplePath.split('/')[0]; // Extract collection name
|
|
32
|
-
} catch (e) {
|
|
33
|
-
// Use default collection name
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
for (let i = 0; i < maxDaysBack; i++) {
|
|
38
|
-
const checkDate = new Date(today);
|
|
39
|
-
checkDate.setDate(checkDate.getDate() - i);
|
|
40
|
-
const dateStr = checkDate.toISOString().split('T')[0];
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
// Construct path: SignedInUserSocialPostData/{date}/{cid}/{cid}
|
|
44
|
-
const socialDocRef = db.collection(collectionName)
|
|
45
|
-
.doc(dateStr)
|
|
46
|
-
.collection(String(userCid))
|
|
47
|
-
.doc(String(userCid));
|
|
48
|
-
|
|
49
|
-
const socialDoc = await socialDocRef.get();
|
|
50
|
-
|
|
51
|
-
if (socialDoc.exists) {
|
|
52
|
-
const data = socialDoc.data();
|
|
53
|
-
if (data.posts && Object.keys(data.posts).length > 0) {
|
|
54
|
-
return dateStr; // Found social posts for this date
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
} catch (error) {
|
|
58
|
-
// Continue to next date if error
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return null; // No social posts found in the last maxDaysBack days
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* GET /user/me/social-posts
|
|
68
|
-
* Fetches the signed-in user's social posts from root data collection
|
|
69
|
-
*/
|
|
70
|
-
async function getUserSocialPosts(req, res, dependencies, config) {
|
|
71
|
-
const { db, logger, collectionRegistry } = dependencies;
|
|
72
|
-
const { userCid, date } = req.query;
|
|
73
|
-
|
|
74
|
-
if (!userCid) {
|
|
75
|
-
return res.status(400).json({ error: "Missing userCid" });
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
// Check for dev override impersonation
|
|
80
|
-
const effectiveCid = await getEffectiveCid(db, userCid, config, logger);
|
|
81
|
-
const devOverride = await getDevOverride(db, userCid, config, logger);
|
|
82
|
-
const isImpersonating = devOverride && devOverride.enabled && devOverride.impersonateCid && effectiveCid !== Number(userCid);
|
|
83
|
-
|
|
84
|
-
const today = new Date().toISOString().split('T')[0];
|
|
85
|
-
|
|
86
|
-
// Determine which date to use
|
|
87
|
-
let dataDate = date || today;
|
|
88
|
-
let isFallback = false;
|
|
89
|
-
|
|
90
|
-
// If no specific date requested, find latest available date
|
|
91
|
-
if (!date) {
|
|
92
|
-
dataDate = await findLatestSocialDate(db, effectiveCid, collectionRegistry, 30);
|
|
93
|
-
if (!dataDate) {
|
|
94
|
-
return res.status(404).json({
|
|
95
|
-
error: "Social posts not found for this user (checked last 30 days)",
|
|
96
|
-
effectiveCid: effectiveCid,
|
|
97
|
-
isImpersonating: isImpersonating || false
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
isFallback = dataDate !== today;
|
|
101
|
-
if (isFallback) {
|
|
102
|
-
logger.log('INFO', `[getUserSocialPosts] Using fallback date ${dataDate} for effective CID ${effectiveCid} (today: ${today})`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Get collection name from registry
|
|
107
|
-
let collectionName = 'SignedInUserSocialPostData'; // Default fallback
|
|
108
|
-
if (collectionRegistry && collectionRegistry.getCollectionPath) {
|
|
109
|
-
try {
|
|
110
|
-
// Extract collection name from registry path template
|
|
111
|
-
const samplePath = collectionRegistry.getCollectionPath('rootData', 'signedInUserSocial', {
|
|
112
|
-
date: '2025-01-01',
|
|
113
|
-
cid: '123'
|
|
114
|
-
});
|
|
115
|
-
collectionName = samplePath.split('/')[0]; // Extract collection name
|
|
116
|
-
} catch (e) {
|
|
117
|
-
logger.log('WARN', `[getUserSocialPosts] Failed to get collection name from registry, using default: ${e.message}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Construct path: SignedInUserSocialPostData/{date}/{cid}/{cid}
|
|
122
|
-
const socialDocRef = db.collection(collectionName)
|
|
123
|
-
.doc(dataDate)
|
|
124
|
-
.collection(String(effectiveCid))
|
|
125
|
-
.doc(String(effectiveCid));
|
|
126
|
-
|
|
127
|
-
const socialDoc = await socialDocRef.get();
|
|
128
|
-
|
|
129
|
-
if (!socialDoc.exists) {
|
|
130
|
-
return res.status(404).json({
|
|
131
|
-
error: "Social posts not found",
|
|
132
|
-
date: dataDate,
|
|
133
|
-
effectiveCid: effectiveCid,
|
|
134
|
-
isImpersonating: isImpersonating || false
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const socialData = socialDoc.data();
|
|
139
|
-
const postsMap = socialData.posts || {};
|
|
140
|
-
|
|
141
|
-
// Convert posts map to array and sort by createdAt (descending)
|
|
142
|
-
const posts = Object.entries(postsMap)
|
|
143
|
-
.map(([postId, postData]) => ({
|
|
144
|
-
id: postId,
|
|
145
|
-
...postData
|
|
146
|
-
}))
|
|
147
|
-
.sort((a, b) => {
|
|
148
|
-
const dateA = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
149
|
-
const dateB = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
150
|
-
return dateB - dateA; // Descending order
|
|
151
|
-
})
|
|
152
|
-
.slice(0, 50); // Limit to 50 most recent posts
|
|
153
|
-
|
|
154
|
-
return res.status(200).json({
|
|
155
|
-
posts,
|
|
156
|
-
count: posts.length,
|
|
157
|
-
date: dataDate,
|
|
158
|
-
isFallback: isFallback,
|
|
159
|
-
requestedDate: date || today,
|
|
160
|
-
userCid: String(userCid),
|
|
161
|
-
effectiveCid: effectiveCid,
|
|
162
|
-
isImpersonating: isImpersonating || false
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
} catch (error) {
|
|
166
|
-
logger.log('ERROR', `[getUserSocialPosts] Error fetching social posts for ${userCid}`, error);
|
|
167
|
-
return res.status(500).json({ error: error.message });
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
module.exports = {
|
|
172
|
-
getUserSocialPosts
|
|
173
|
-
};
|
|
174
|
-
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Data Helpers - Re-export Hub
|
|
3
|
-
* This file re-exports all helper functions from organized modules for backward compatibility.
|
|
4
|
-
* All functions have been refactored into organized modules with migration support.
|
|
5
|
-
*
|
|
6
|
-
* New code should import directly from the organized modules:
|
|
7
|
-
* - core/ - Core utilities (compression, data lookup, user status, path resolution)
|
|
8
|
-
* - data/ - Data endpoints (portfolio, social, computation, instrument)
|
|
9
|
-
* - profile/ - Profile endpoints (PI profile, user profile, profile views)
|
|
10
|
-
* - watchlist/ - Watchlist endpoints (legacy, generation, analytics)
|
|
11
|
-
* - search/ - Search endpoints (PI search, PI requests)
|
|
12
|
-
* - recommendations/ - Recommendation endpoints
|
|
13
|
-
* - metrics/ - Metrics endpoints
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
// Import from organized modules
|
|
17
|
-
const portfolioHelpers = require('./data/portfolio_helpers');
|
|
18
|
-
const socialHelpers = require('./data/social_helpers');
|
|
19
|
-
const computationHelpers = require('./data/computation_helpers');
|
|
20
|
-
const instrumentHelpers = require('./data/instrument_helpers');
|
|
21
|
-
const piProfileHelpers = require('./profile/pi_profile_helpers');
|
|
22
|
-
const userProfileHelpers = require('./profile/user_profile_helpers');
|
|
23
|
-
const profileViewHelpers = require('./profile/profile_view_helpers');
|
|
24
|
-
const watchlistDataHelpers = require('./watchlist/watchlist_data_helpers');
|
|
25
|
-
const watchlistGenerationHelpers = require('./watchlist/watchlist_generation_helpers');
|
|
26
|
-
const watchlistAnalyticsHelpers = require('./watchlist/watchlist_analytics_helpers');
|
|
27
|
-
const piSearchHelpers = require('./search/pi_search_helpers');
|
|
28
|
-
const piRequestHelpers = require('./search/pi_request_helpers');
|
|
29
|
-
const recommendationHelpers = require('./recommendations/recommendation_helpers');
|
|
30
|
-
const metricsHelpers = require('./metrics/personalized_metrics_helpers');
|
|
31
|
-
|
|
32
|
-
// Import core helpers
|
|
33
|
-
const { tryDecompress } = require('./core/compression_helpers');
|
|
34
|
-
const {
|
|
35
|
-
findLatestRankingsDate,
|
|
36
|
-
findLatestPortfolioDate,
|
|
37
|
-
findLatestComputationDate,
|
|
38
|
-
findLatestPiPortfolioDate,
|
|
39
|
-
findLatestPiHistoryDate
|
|
40
|
-
} = require('./core/data_lookup_helpers');
|
|
41
|
-
const { checkIfUserIsPI } = require('./core/user_status_helpers');
|
|
42
|
-
const { checkPiInComputationDate } = require('./data/computation_helpers');
|
|
43
|
-
|
|
44
|
-
// Re-export all functions for backward compatibility
|
|
45
|
-
module.exports = {
|
|
46
|
-
// Data helpers
|
|
47
|
-
getUserPortfolio: portfolioHelpers.getUserPortfolio,
|
|
48
|
-
getUserDataStatus: portfolioHelpers.getUserDataStatus,
|
|
49
|
-
getUserSocialPosts: socialHelpers.getUserSocialPosts,
|
|
50
|
-
getUserComputations: computationHelpers.getUserComputations,
|
|
51
|
-
getInstrumentMappings: instrumentHelpers.getInstrumentMappings,
|
|
52
|
-
checkPiInComputationDate,
|
|
53
|
-
|
|
54
|
-
// Profile helpers
|
|
55
|
-
getPiAnalytics: piProfileHelpers.getPiAnalytics,
|
|
56
|
-
getPiProfile: piProfileHelpers.getPiProfile,
|
|
57
|
-
getUserVerification: userProfileHelpers.getUserVerification,
|
|
58
|
-
checkIfUserIsPopularInvestor: userProfileHelpers.checkIfUserIsPopularInvestor,
|
|
59
|
-
trackProfileView: profileViewHelpers.trackProfileView,
|
|
60
|
-
|
|
61
|
-
// Watchlist helpers
|
|
62
|
-
getWatchlist: watchlistDataHelpers.getWatchlist,
|
|
63
|
-
updateWatchlist: watchlistDataHelpers.updateWatchlist,
|
|
64
|
-
autoGenerateWatchlist: watchlistGenerationHelpers.autoGenerateWatchlist,
|
|
65
|
-
getWatchlistTriggerCounts: watchlistAnalyticsHelpers.getWatchlistTriggerCounts,
|
|
66
|
-
|
|
67
|
-
// Search helpers
|
|
68
|
-
searchPopularInvestors: piSearchHelpers.searchPopularInvestors,
|
|
69
|
-
requestPiAddition: piRequestHelpers.requestPiAddition,
|
|
70
|
-
checkPisInRankings: piRequestHelpers.checkPisInRankings,
|
|
71
|
-
|
|
72
|
-
// Recommendations helpers
|
|
73
|
-
getUserRecommendations: recommendationHelpers.getUserRecommendations,
|
|
74
|
-
|
|
75
|
-
// Metrics helpers
|
|
76
|
-
getSignedInUserPIPersonalizedMetrics: metricsHelpers.getSignedInUserPIPersonalizedMetrics,
|
|
77
|
-
generateSamplePIPersonalizedMetrics: metricsHelpers.generateSamplePIPersonalizedMetrics,
|
|
78
|
-
|
|
79
|
-
// Core utilities (for use in other helpers)
|
|
80
|
-
tryDecompress,
|
|
81
|
-
findLatestRankingsDate,
|
|
82
|
-
findLatestPortfolioDate,
|
|
83
|
-
findLatestComputationDate,
|
|
84
|
-
findLatestPiPortfolioDate,
|
|
85
|
-
findLatestPiHistoryDate,
|
|
86
|
-
checkIfUserIsPI
|
|
87
|
-
};
|