@onairos/react-native 3.7.1 → 3.7.3
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/commonjs/api/index.js +219 -9
- package/lib/commonjs/assets/icons/spotify.png +0 -0
- package/lib/commonjs/assets/images/spotify.png +0 -0
- package/lib/commonjs/components/BodyText.js +27 -9
- package/lib/commonjs/components/BrandMark.js +111 -10
- package/lib/commonjs/components/CodeInput.js +116 -9
- package/lib/commonjs/components/EmailInput.js +30 -8
- package/lib/commonjs/components/GoogleButton.js +56 -9
- package/lib/commonjs/components/HeadingGroup.js +43 -9
- package/lib/commonjs/components/LLMDataInputModal.js +664 -14
- package/lib/commonjs/components/ModalHeader.js +99 -9
- package/lib/commonjs/components/ModalSheet.js +47 -9
- package/lib/commonjs/components/Onairos.js +380 -14
- package/lib/commonjs/components/OnairosButton.js +313 -13
- package/lib/commonjs/components/OnairosSignInButton.js +130 -12
- package/lib/commonjs/components/Overlay.js +465 -13
- package/lib/commonjs/components/PersonaImage.js +137 -10
- package/lib/commonjs/components/PersonaLoadingScreen.js +318 -12
- package/lib/commonjs/components/PersonalizationConsentScreen.js +467 -13
- package/lib/commonjs/components/PinCreationScreen.js +403 -12
- package/lib/commonjs/components/PinInput.js +464 -9
- package/lib/commonjs/components/PlatformConnectorsStep.js +1311 -23
- package/lib/commonjs/components/PlatformList.js +137 -10
- package/lib/commonjs/components/PlatformToggle.js +180 -9
- package/lib/commonjs/components/PrimaryButton.js +180 -10
- package/lib/commonjs/components/SignInMatchAnimation.js +197 -9
- package/lib/commonjs/components/SignInStep.js +345 -12
- package/lib/commonjs/components/UniversalOnboarding.js +2780 -30
- package/lib/commonjs/components/VerificationStep.js +176 -11
- package/lib/commonjs/components/WelcomeScreen.js +461 -22
- package/lib/commonjs/components/icons/Basicproficon.js +37 -8
- package/lib/commonjs/components/icons/Basicprofile.js +21 -8
- package/lib/commonjs/components/icons/Checkbox.js +21 -8
- package/lib/commonjs/components/icons/Checkmark.js +27 -8
- package/lib/commonjs/components/icons/Contentanalysis.js +21 -8
- package/lib/commonjs/components/icons/Contenticon.js +39 -8
- package/lib/commonjs/components/icons/EnochE.js +41 -8
- package/lib/commonjs/components/icons/Personalityicon.js +30 -8
- package/lib/commonjs/components/icons/Personalityprofile.js +21 -8
- package/lib/commonjs/components/icons/Personalitytraits.js +21 -8
- package/lib/commonjs/components/icons/Userpreferences.js +21 -8
- package/lib/commonjs/components/icons/index.js +84 -17
- package/lib/commonjs/components/onboarding/OAuthWebView.js +1754 -18
- package/lib/commonjs/components/onboarding/OnboardingHeader.js +74 -10
- package/lib/commonjs/components/onboarding/PinInput.js +283 -10
- package/lib/commonjs/components/onboarding/PlatformConnector.js +249 -11
- package/lib/commonjs/config/PLATFORM_APIS.md +849 -0
- package/lib/commonjs/config/api.js +56 -7
- package/lib/commonjs/constants/index.js +120 -7
- package/lib/commonjs/context/AuthContext.js +345 -10
- package/lib/commonjs/hooks/useConnectedAccounts.js +111 -9
- package/lib/commonjs/hooks/useConnections.js +102 -8
- package/lib/commonjs/hooks/useCredentials.js +178 -10
- package/lib/commonjs/hooks/useUserConnections.js +148 -10
- package/lib/commonjs/index.js +439 -34
- package/lib/commonjs/services/apiClient.js +298 -8
- package/lib/commonjs/services/biometricPinService.js +180 -8
- package/lib/commonjs/services/chatGPTConversationExtractor.js +155 -8
- package/lib/commonjs/services/chatGPTConversationService.js +275 -9
- package/lib/commonjs/services/claudeConversationExtractor.js +103 -8
- package/lib/commonjs/services/claudeConversationService.js +158 -9
- package/lib/commonjs/services/connectedAccountsService.js +310 -10
- package/lib/commonjs/services/googleAuthService.js +252 -11
- package/lib/commonjs/services/hingeDataExtractor.js +105 -8
- package/lib/commonjs/services/hingeDataService.js +150 -9
- package/lib/commonjs/services/imageCompressionService.js +260 -7
- package/lib/commonjs/services/instagramDataExtractor.js +126 -8
- package/lib/commonjs/services/instagramDataService.js +163 -9
- package/lib/commonjs/services/jwtStorageService.js +276 -7
- package/lib/commonjs/services/linkedinDOMExtractor.js +245 -7
- package/lib/commonjs/services/linkedinProfileService.js +222 -9
- package/lib/commonjs/services/linkedinScrapingService.js +230 -8
- package/lib/commonjs/services/llmDataStorage.js +294 -8
- package/lib/commonjs/services/mobileTrainingService.js +186 -8
- package/lib/commonjs/services/netflixDataExtractor.js +120 -8
- package/lib/commonjs/services/netflixDataService.js +198 -9
- package/lib/commonjs/services/pinEncryptionService.js +84 -8
- package/lib/commonjs/services/pinStorageUtils.js +105 -7
- package/lib/commonjs/services/platformAuthService.js +1484 -12
- package/lib/commonjs/services/sephoraDataExtractor.js +140 -8
- package/lib/commonjs/services/sephoraDataService.js +200 -9
- package/lib/commonjs/services/spotifyDataExtractor.js +148 -8
- package/lib/commonjs/services/spotifyDataService.js +241 -9
- package/lib/commonjs/services/storageService.js +404 -8
- package/lib/commonjs/services/telegramDataExtractor.js +115 -8
- package/lib/commonjs/services/telegramDataService.js +499 -9
- package/lib/commonjs/services/trainingApiHelpers.js +73 -7
- package/lib/commonjs/services/userConnectionsService.js +340 -10
- package/lib/commonjs/services/youtubeMigrationService.js +416 -10
- package/lib/commonjs/theme/index.js +250 -7
- package/lib/commonjs/types/ambient.d.js +2 -1
- package/lib/commonjs/types/declarations.d.js +2 -1
- package/lib/commonjs/types/index.js +6 -1
- package/lib/commonjs/types/node-fix.d.js +2 -1
- package/lib/commonjs/types/node-override.d.js +2 -1
- package/lib/commonjs/types/opacity.d.js +2 -1
- package/lib/commonjs/types.js +14 -1
- package/lib/commonjs/utils/Portal.js +98 -8
- package/lib/commonjs/utils/api.js +130 -9
- package/lib/commonjs/utils/assetRegistry.js +210 -35
- package/lib/commonjs/utils/auth.js +112 -9
- package/lib/commonjs/utils/connectorTests.js +613 -29
- package/lib/commonjs/utils/crypto.js +62 -8
- package/lib/commonjs/utils/debugHelper.js +64 -1
- package/lib/commonjs/utils/encryption.js +76 -7
- package/lib/commonjs/utils/eventUtils.js +288 -1
- package/lib/commonjs/utils/haptics.js +66 -9
- package/lib/commonjs/utils/imagePreloader.js +6 -1
- package/lib/commonjs/utils/networkDiagnostics.js +226 -8
- package/lib/commonjs/utils/onairosApi.js +350 -9
- package/lib/commonjs/utils/programmaticFlow.js +117 -9
- package/lib/commonjs/utils/retryHelper.js +220 -1
- package/lib/commonjs/utils/secureStorage.js +349 -10
- package/lib/commonjs/utils/webviewScripts/chatgpt.js +551 -1
- package/lib/commonjs/utils/webviewScripts/claude.js +376 -1
- package/lib/commonjs/utils/webviewScripts/hinge.js +411 -1
- package/lib/commonjs/utils/webviewScripts/index.js +698 -15
- package/lib/commonjs/utils/webviewScripts/instagram.js +454 -1
- package/lib/commonjs/utils/webviewScripts/linkedin.js +880 -1
- package/lib/commonjs/utils/webviewScripts/netflix.js +382 -1
- package/lib/commonjs/utils/webviewScripts/sephora.js +516 -1
- package/lib/commonjs/utils/webviewScripts/spotify.js +419 -1
- package/lib/commonjs/utils/webviewScripts/telegram.js +678 -1
- package/lib/module/api/index.js +211 -1
- package/lib/module/assets/icons/spotify.png +0 -0
- package/lib/module/assets/images/spotify.png +0 -0
- package/lib/module/components/BodyText.js +20 -1
- package/lib/module/components/BrandMark.js +104 -1
- package/lib/module/components/CodeInput.js +109 -1
- package/lib/module/components/EmailInput.js +23 -1
- package/lib/module/components/GoogleButton.js +49 -1
- package/lib/module/components/HeadingGroup.js +36 -1
- package/lib/module/components/LLMDataInputModal.js +656 -7
- package/lib/module/components/ModalHeader.js +92 -1
- package/lib/module/components/ModalSheet.js +39 -1
- package/lib/module/components/Onairos.js +373 -1
- package/lib/module/components/OnairosButton.js +305 -1
- package/lib/module/components/OnairosSignInButton.js +121 -1
- package/lib/module/components/Overlay.js +456 -1
- package/lib/module/components/PersonaImage.js +129 -1
- package/lib/module/components/PersonaLoadingScreen.js +310 -1
- package/lib/module/components/PersonalizationConsentScreen.js +460 -1
- package/lib/module/components/PinCreationScreen.js +396 -1
- package/lib/module/components/PinInput.js +456 -1
- package/lib/module/components/PlatformConnectorsStep.js +1302 -6
- package/lib/module/components/PlatformList.js +129 -1
- package/lib/module/components/PlatformToggle.js +173 -1
- package/lib/module/components/PrimaryButton.js +172 -1
- package/lib/module/components/SignInMatchAnimation.js +189 -1
- package/lib/module/components/SignInStep.js +338 -1
- package/lib/module/components/UniversalOnboarding.js +2770 -1
- package/lib/module/components/VerificationStep.js +168 -1
- package/lib/module/components/WelcomeScreen.js +453 -1
- package/lib/module/components/icons/Basicproficon.js +30 -1
- package/lib/module/components/icons/Basicprofile.js +14 -1
- package/lib/module/components/icons/Checkbox.js +14 -1
- package/lib/module/components/icons/Checkmark.js +20 -1
- package/lib/module/components/icons/Contentanalysis.js +14 -1
- package/lib/module/components/icons/Contenticon.js +32 -1
- package/lib/module/components/icons/EnochE.js +34 -1
- package/lib/module/components/icons/Personalityicon.js +23 -1
- package/lib/module/components/icons/Personalityprofile.js +14 -1
- package/lib/module/components/icons/Personalitytraits.js +14 -1
- package/lib/module/components/icons/Userpreferences.js +14 -1
- package/lib/module/components/icons/index.js +13 -1
- package/lib/module/components/onboarding/OAuthWebView.js +1746 -1
- package/lib/module/components/onboarding/OnboardingHeader.js +66 -1
- package/lib/module/components/onboarding/PinInput.js +274 -1
- package/lib/module/components/onboarding/PlatformConnector.js +240 -1
- package/lib/module/config/PLATFORM_APIS.md +849 -0
- package/lib/module/config/api.js +47 -1
- package/lib/module/constants/index.js +114 -1
- package/lib/module/context/AuthContext.js +335 -1
- package/lib/module/hooks/useConnectedAccounts.js +106 -1
- package/lib/module/hooks/useConnections.js +95 -1
- package/lib/module/hooks/useCredentials.js +171 -6
- package/lib/module/hooks/useUserConnections.js +140 -1
- package/lib/module/index.js +172 -1
- package/lib/module/services/apiClient.js +295 -1
- package/lib/module/services/biometricPinService.js +169 -1
- package/lib/module/services/chatGPTConversationExtractor.js +149 -1
- package/lib/module/services/chatGPTConversationService.js +268 -1
- package/lib/module/services/claudeConversationExtractor.js +97 -1
- package/lib/module/services/claudeConversationService.js +151 -1
- package/lib/module/services/connectedAccountsService.js +293 -1
- package/lib/module/services/googleAuthService.js +241 -1
- package/lib/module/services/hingeDataExtractor.js +99 -1
- package/lib/module/services/hingeDataService.js +143 -1
- package/lib/module/services/imageCompressionService.js +250 -1
- package/lib/module/services/instagramDataExtractor.js +120 -1
- package/lib/module/services/instagramDataService.js +156 -1
- package/lib/module/services/jwtStorageService.js +257 -1
- package/lib/module/services/linkedinDOMExtractor.js +234 -1
- package/lib/module/services/linkedinProfileService.js +210 -1
- package/lib/module/services/linkedinScrapingService.js +219 -1
- package/lib/module/services/llmDataStorage.js +277 -1
- package/lib/module/services/mobileTrainingService.js +173 -1
- package/lib/module/services/netflixDataExtractor.js +114 -1
- package/lib/module/services/netflixDataService.js +191 -1
- package/lib/module/services/pinEncryptionService.js +74 -6
- package/lib/module/services/pinStorageUtils.js +93 -1
- package/lib/module/services/platformAuthService.js +1461 -1
- package/lib/module/services/sephoraDataExtractor.js +134 -1
- package/lib/module/services/sephoraDataService.js +193 -1
- package/lib/module/services/spotifyDataExtractor.js +142 -1
- package/lib/module/services/spotifyDataService.js +234 -1
- package/lib/module/services/storageService.js +383 -1
- package/lib/module/services/telegramDataExtractor.js +109 -1
- package/lib/module/services/telegramDataService.js +493 -1
- package/lib/module/services/trainingApiHelpers.js +67 -1
- package/lib/module/services/userConnectionsService.js +329 -1
- package/lib/module/services/youtubeMigrationService.js +405 -1
- package/lib/module/theme/index.js +245 -1
- package/lib/module/types.js +10 -1
- package/lib/module/utils/Portal.js +90 -1
- package/lib/module/utils/api.js +118 -1
- package/lib/module/utils/assetRegistry.js +200 -34
- package/lib/module/utils/auth.js +100 -1
- package/lib/module/utils/connectorTests.js +600 -27
- package/lib/module/utils/crypto.js +54 -1
- package/lib/module/utils/debugHelper.js +54 -1
- package/lib/module/utils/encryption.js +67 -1
- package/lib/module/utils/eventUtils.js +270 -1
- package/lib/module/utils/haptics.js +59 -8
- package/lib/module/utils/imagePreloader.js +3 -1
- package/lib/module/utils/networkDiagnostics.js +217 -1
- package/lib/module/utils/onairosApi.js +333 -1
- package/lib/module/utils/programmaticFlow.js +111 -1
- package/lib/module/utils/retryHelper.js +211 -1
- package/lib/module/utils/secureStorage.js +330 -6
- package/lib/module/utils/webviewScripts/chatgpt.js +545 -1
- package/lib/module/utils/webviewScripts/claude.js +370 -1
- package/lib/module/utils/webviewScripts/hinge.js +405 -1
- package/lib/module/utils/webviewScripts/index.js +434 -1
- package/lib/module/utils/webviewScripts/instagram.js +448 -1
- package/lib/module/utils/webviewScripts/linkedin.js +874 -1
- package/lib/module/utils/webviewScripts/netflix.js +376 -1
- package/lib/module/utils/webviewScripts/sephora.js +510 -1
- package/lib/module/utils/webviewScripts/spotify.js +413 -1
- package/lib/module/utils/webviewScripts/telegram.js +672 -1
- package/package.json +2 -2
|
@@ -1 +1,134 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Sephora Data Extractor
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the Sephora data export flow:
|
|
5
|
+
* 1. Receives extracted shopping data from WebView
|
|
6
|
+
* 2. Validates and formats data
|
|
7
|
+
* 3. Sends to backend via sephoraDataService
|
|
8
|
+
*
|
|
9
|
+
* This acts as the bridge between OAuthWebView and the backend API.
|
|
10
|
+
*
|
|
11
|
+
* @reference ChatGPT implementation: src/services/chatGPTConversationExtractor.ts
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { storeSephoraData } from './sephoraDataService';
|
|
15
|
+
import { Alert } from 'react-native';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Combined Sephora export data from WebView
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hook for Sephora data extraction operations
|
|
23
|
+
*/
|
|
24
|
+
export const useSephoraDataExtractor = () => {
|
|
25
|
+
/**
|
|
26
|
+
* Initiate data export to backend
|
|
27
|
+
*
|
|
28
|
+
* @param username - User identifier
|
|
29
|
+
* @param data - Extracted Sephora data (basket, orders, loves, ratings)
|
|
30
|
+
* @returns true if successful, false otherwise
|
|
31
|
+
*/
|
|
32
|
+
const initiateDataExport = async (username, data) => {
|
|
33
|
+
var _data$basket, _data$orders, _data$loves, _data$ratings, _data$basket2, _data$basket3, _data$orders2, _data$loves2, _data$ratings2;
|
|
34
|
+
console.log('🚀 [SEPHORA_EXTRACTOR] Initiating data export');
|
|
35
|
+
console.log('👤 [SEPHORA_EXTRACTOR] Username:', username);
|
|
36
|
+
console.log('📊 [SEPHORA_EXTRACTOR] Summary:', data.summary);
|
|
37
|
+
|
|
38
|
+
// Validation
|
|
39
|
+
if (!username) {
|
|
40
|
+
console.error('❌ [SEPHORA_EXTRACTOR] Username is required');
|
|
41
|
+
Alert.alert('Error', 'Username is required to export Sephora data.', [{
|
|
42
|
+
text: 'OK',
|
|
43
|
+
style: 'default'
|
|
44
|
+
}]);
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Handle empty data as success - user might be new
|
|
49
|
+
const totalItems = (((_data$basket = data.basket) === null || _data$basket === void 0 || (_data$basket = _data$basket.items) === null || _data$basket === void 0 ? void 0 : _data$basket.length) || 0) + (((_data$orders = data.orders) === null || _data$orders === void 0 ? void 0 : _data$orders.length) || 0) + (((_data$loves = data.loves) === null || _data$loves === void 0 ? void 0 : _data$loves.length) || 0) + (((_data$ratings = data.ratings) === null || _data$ratings === void 0 ? void 0 : _data$ratings.length) || 0);
|
|
50
|
+
if (totalItems === 0) {
|
|
51
|
+
console.log('ℹ️ [SEPHORA_EXTRACTOR] No data to export - treating as success (connected)');
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Validate basket items
|
|
56
|
+
const validBasketItems = (((_data$basket2 = data.basket) === null || _data$basket2 === void 0 ? void 0 : _data$basket2.items) || []).filter(item => {
|
|
57
|
+
const isValid = item.id && item.name;
|
|
58
|
+
if (!isValid) {
|
|
59
|
+
console.warn('⚠️ [SEPHORA_EXTRACTOR] Invalid basket item:', item);
|
|
60
|
+
}
|
|
61
|
+
return isValid;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Validate orders
|
|
65
|
+
const validOrders = (data.orders || []).filter(order => {
|
|
66
|
+
const isValid = order.orderId && order.date;
|
|
67
|
+
if (!isValid) {
|
|
68
|
+
console.warn('⚠️ [SEPHORA_EXTRACTOR] Invalid order:', order);
|
|
69
|
+
}
|
|
70
|
+
return isValid;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Validate loved products
|
|
74
|
+
const validLoves = (data.loves || []).filter(love => {
|
|
75
|
+
const isValid = love.id && love.name;
|
|
76
|
+
if (!isValid) {
|
|
77
|
+
console.warn('⚠️ [SEPHORA_EXTRACTOR] Invalid loved item:', love);
|
|
78
|
+
}
|
|
79
|
+
return isValid;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Validate ratings
|
|
83
|
+
const validRatings = (data.ratings || []).filter(rating => {
|
|
84
|
+
const isValid = rating.productId && typeof rating.rating === 'number';
|
|
85
|
+
if (!isValid) {
|
|
86
|
+
console.warn('⚠️ [SEPHORA_EXTRACTOR] Invalid rating:', rating);
|
|
87
|
+
}
|
|
88
|
+
return isValid;
|
|
89
|
+
});
|
|
90
|
+
const originalCount = (((_data$basket3 = data.basket) === null || _data$basket3 === void 0 || (_data$basket3 = _data$basket3.items) === null || _data$basket3 === void 0 ? void 0 : _data$basket3.length) || 0) + (((_data$orders2 = data.orders) === null || _data$orders2 === void 0 ? void 0 : _data$orders2.length) || 0) + (((_data$loves2 = data.loves) === null || _data$loves2 === void 0 ? void 0 : _data$loves2.length) || 0) + (((_data$ratings2 = data.ratings) === null || _data$ratings2 === void 0 ? void 0 : _data$ratings2.length) || 0);
|
|
91
|
+
const validCount = validBasketItems.length + validOrders.length + validLoves.length + validRatings.length;
|
|
92
|
+
if (validCount < originalCount) {
|
|
93
|
+
console.warn(`⚠️ [SEPHORA_EXTRACTOR] Filtered out ${originalCount - validCount} invalid items`);
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
var _data$basket4;
|
|
97
|
+
console.log('📡 [SEPHORA_EXTRACTOR] Sending to backend...');
|
|
98
|
+
const result = await storeSephoraData(username, {
|
|
99
|
+
basket: {
|
|
100
|
+
items: validBasketItems,
|
|
101
|
+
total: ((_data$basket4 = data.basket) === null || _data$basket4 === void 0 ? void 0 : _data$basket4.total) || 0,
|
|
102
|
+
itemCount: validBasketItems.length
|
|
103
|
+
},
|
|
104
|
+
orders: validOrders,
|
|
105
|
+
loves: validLoves,
|
|
106
|
+
ratings: validRatings,
|
|
107
|
+
userId: data.userId
|
|
108
|
+
});
|
|
109
|
+
if (result.success) {
|
|
110
|
+
console.log('✅ [SEPHORA_EXTRACTOR] Export completed successfully');
|
|
111
|
+
console.log('📊 [SEPHORA_EXTRACTOR] Backend response:', result.data);
|
|
112
|
+
return true;
|
|
113
|
+
} else {
|
|
114
|
+
console.error('❌ [SEPHORA_EXTRACTOR] Backend storage failed:', result.error);
|
|
115
|
+
Alert.alert('Export Failed', result.error || 'An unknown error occurred during data storage.', [{
|
|
116
|
+
text: 'OK',
|
|
117
|
+
style: 'default'
|
|
118
|
+
}]);
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error('❌ [SEPHORA_EXTRACTOR] Unexpected error during export:', error);
|
|
123
|
+
Alert.alert('Export Error', 'Failed to connect to the data storage service. Please check your network connection.', [{
|
|
124
|
+
text: 'OK',
|
|
125
|
+
style: 'default'
|
|
126
|
+
}]);
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
return {
|
|
131
|
+
initiateDataExport
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=sephoraDataExtractor.js.map
|
|
@@ -1 +1,193 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Sephora Data Service
|
|
3
|
+
*
|
|
4
|
+
* API layer for storing Sephora shopping data on backend.
|
|
5
|
+
* Sends extracted basket, orders, loves, and ratings to /platform-data/store endpoint.
|
|
6
|
+
*
|
|
7
|
+
* MATCHES ChatGPT implementation pattern
|
|
8
|
+
* - Uses format: { platform, data, metadata }
|
|
9
|
+
* - Platform: "mobile-sephora"
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { API_CONFIG } from '../config/api';
|
|
13
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
14
|
+
import { Platform } from 'react-native';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Structure of a basket item
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Structure of the shopping basket
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Structure of an order item
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Structure of an order
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Structure of a loved/favorited item
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Structure of a product rating
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Combined Sephora data to store
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Response from backend endpoint
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Store Sephora data on backend
|
|
50
|
+
*
|
|
51
|
+
* @param userId - Username or identifier
|
|
52
|
+
* @param data - Sephora shopping data (basket, orders, loves, ratings)
|
|
53
|
+
* @returns Response indicating success/failure with metadata
|
|
54
|
+
*/
|
|
55
|
+
export const storeSephoraData = async (userId, data) => {
|
|
56
|
+
console.log('🚀 [SEPHORA_SERVICE] Storing Sephora data for:', userId);
|
|
57
|
+
console.log('📊 [SEPHORA_SERVICE] Basket items:', data.basket.items.length);
|
|
58
|
+
console.log('📊 [SEPHORA_SERVICE] Orders:', data.orders.length);
|
|
59
|
+
console.log('📊 [SEPHORA_SERVICE] Loved items:', data.loves.length);
|
|
60
|
+
console.log('📊 [SEPHORA_SERVICE] Ratings:', data.ratings.length);
|
|
61
|
+
|
|
62
|
+
// Input validation
|
|
63
|
+
if (!userId) {
|
|
64
|
+
console.error('❌ [SEPHORA_SERVICE] Invalid input: userId missing');
|
|
65
|
+
return {
|
|
66
|
+
success: false,
|
|
67
|
+
error: 'Invalid input: userId missing.'
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
// Get auth token - check all possible storage keys
|
|
72
|
+
const authToken = (await AsyncStorage.getItem('onairos_jwt_token')) || (await AsyncStorage.getItem('enoch_token')) || (await AsyncStorage.getItem('auth_token'));
|
|
73
|
+
if (!authToken) {
|
|
74
|
+
console.error('❌ [SEPHORA_SERVICE] No auth token found');
|
|
75
|
+
return {
|
|
76
|
+
success: false,
|
|
77
|
+
error: 'Authentication token not found. Please log in again.'
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
console.log('🔑 [SEPHORA_SERVICE] Auth token found');
|
|
81
|
+
|
|
82
|
+
// Mobile metadata
|
|
83
|
+
const mobileMetadata = {
|
|
84
|
+
platform: Platform.OS,
|
|
85
|
+
appVersion: '1.0.0',
|
|
86
|
+
osVersion: Platform.OS === 'ios' ? '17.0' : Platform.OS,
|
|
87
|
+
deviceModel: Platform.OS === 'ios' ? 'iPhone' : 'Android',
|
|
88
|
+
isOfflineSync: false,
|
|
89
|
+
extractedAt: new Date().toISOString()
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Build request body
|
|
93
|
+
const requestBody = {
|
|
94
|
+
platform: 'mobile-sephora',
|
|
95
|
+
dataType: 'ecommerce',
|
|
96
|
+
data: {
|
|
97
|
+
basket: {
|
|
98
|
+
items: data.basket.items.map(item => ({
|
|
99
|
+
productId: item.id,
|
|
100
|
+
name: item.name,
|
|
101
|
+
brand: item.brand,
|
|
102
|
+
price: item.price,
|
|
103
|
+
quantity: item.quantity,
|
|
104
|
+
category: item.category,
|
|
105
|
+
imageUrl: item.imageUrl
|
|
106
|
+
})),
|
|
107
|
+
total: data.basket.total,
|
|
108
|
+
itemCount: data.basket.itemCount
|
|
109
|
+
},
|
|
110
|
+
orders: data.orders.map(order => ({
|
|
111
|
+
orderId: order.orderId,
|
|
112
|
+
date: order.date,
|
|
113
|
+
total: order.total,
|
|
114
|
+
status: order.status,
|
|
115
|
+
items: order.items.map(item => ({
|
|
116
|
+
productId: item.id,
|
|
117
|
+
name: item.name,
|
|
118
|
+
brand: item.brand,
|
|
119
|
+
price: item.price,
|
|
120
|
+
quantity: item.quantity
|
|
121
|
+
}))
|
|
122
|
+
})),
|
|
123
|
+
loves: data.loves.map(love => ({
|
|
124
|
+
productId: love.id,
|
|
125
|
+
name: love.name,
|
|
126
|
+
brand: love.brand,
|
|
127
|
+
category: love.category,
|
|
128
|
+
price: love.price,
|
|
129
|
+
rating: love.rating,
|
|
130
|
+
addedAt: love.addedAt,
|
|
131
|
+
type: 'love'
|
|
132
|
+
})),
|
|
133
|
+
ratings: data.ratings.map(rating => ({
|
|
134
|
+
productId: rating.productId,
|
|
135
|
+
productName: rating.productName,
|
|
136
|
+
score: rating.rating,
|
|
137
|
+
review: rating.review,
|
|
138
|
+
date: rating.date,
|
|
139
|
+
isRecommended: rating.isRecommended,
|
|
140
|
+
sentiment: rating.type
|
|
141
|
+
})),
|
|
142
|
+
sephoraUserId: data.userId
|
|
143
|
+
},
|
|
144
|
+
summary: {
|
|
145
|
+
basketItemCount: data.basket.items.length,
|
|
146
|
+
basketTotal: data.basket.total,
|
|
147
|
+
orderCount: data.orders.length,
|
|
148
|
+
lovedProductCount: data.loves.length,
|
|
149
|
+
ratingCount: data.ratings.length,
|
|
150
|
+
positiveRatings: data.ratings.filter(r => r.type === 'positive').length,
|
|
151
|
+
negativeRatings: data.ratings.filter(r => r.type === 'negative').length
|
|
152
|
+
},
|
|
153
|
+
mobileMetadata: mobileMetadata
|
|
154
|
+
};
|
|
155
|
+
console.log('📡 [SEPHORA_SERVICE] Sending to backend...');
|
|
156
|
+
console.log('📍 [SEPHORA_SERVICE] URL:', `${API_CONFIG.BASE_URL}/platform-data/store`);
|
|
157
|
+
const response = await fetch(`${API_CONFIG.BASE_URL}/platform-data/store`, {
|
|
158
|
+
method: 'POST',
|
|
159
|
+
headers: {
|
|
160
|
+
'Content-Type': 'application/json',
|
|
161
|
+
'Authorization': `Bearer ${authToken}`,
|
|
162
|
+
'User-Agent': `OnairosSDK/1.0.0 (${Platform.OS})`
|
|
163
|
+
},
|
|
164
|
+
body: JSON.stringify(requestBody)
|
|
165
|
+
});
|
|
166
|
+
const responseData = await response.json();
|
|
167
|
+
if (response.ok) {
|
|
168
|
+
console.log('✅ [SEPHORA_SERVICE] Successfully stored Sephora data');
|
|
169
|
+
if (responseData.message) {
|
|
170
|
+
console.log(`📝 [SEPHORA_SERVICE] Backend response: ${responseData.message}`);
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
success: true,
|
|
174
|
+
message: responseData.message || 'Sephora data stored successfully',
|
|
175
|
+
data: responseData.data
|
|
176
|
+
};
|
|
177
|
+
} else {
|
|
178
|
+
console.warn(`⚠️ [SEPHORA_SERVICE] Backend returned status: ${response.status}`);
|
|
179
|
+
console.warn(`⚠️ [SEPHORA_SERVICE] Error: ${responseData.error || 'Unknown error'}`);
|
|
180
|
+
return {
|
|
181
|
+
success: false,
|
|
182
|
+
error: responseData.error || `HTTP ${response.status}`
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error('❌ [SEPHORA_SERVICE] Network error:', error);
|
|
187
|
+
return {
|
|
188
|
+
success: false,
|
|
189
|
+
error: error.message || 'Network error. Please check your connection.'
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
//# sourceMappingURL=sephoraDataService.js.map
|
|
@@ -1 +1,142 @@
|
|
|
1
|
-
import{storeSpotifyData}from'./spotifyDataService';function _0xee64(_0x4455d8,_0xee6422){_0x4455d8=_0x4455d8-0x0;const _0x48c6b9=_0x4455();let _0x2f4684=_0x48c6b9[_0x4455d8];return _0x2f4684;}import{Alert}from'react-native';function _0x4455(){const _0x2ebf14=['NISiF','hoqPw','FMJHH','LWPpO','✅\x20[SPOTIFY_EXTRACTOR]\x20Export\x20completed\x20successfully','gqLEO','❌\x20[SPOTIFY_EXTRACTOR]\x20Backend\x20storage\x20failed:','QnGgT','ℹ️\x20[SPOTIFY_EXTRACTOR]\x20No\x20data\x20to\x20export\x20-\x20treating\x20as\x20success\x20(connected)','🚀\x20[SPOTIFY_EXTRACTOR]\x20Initiating\x20data\x20export','👤\x20[SPOTIFY_EXTRACTOR]\x20Username:','❌\x20[SPOTIFY_EXTRACTOR]\x20Username\x20is\x20required','Error','Natfy','WnvuU','📡\x20[SPOTIFY_EXTRACTOR]\x20Sending\x20to\x20backend...','medium_term','QwLxg','An\x20unknown\x20error\x20occurred\x20during\x20data\x20storage.','❌\x20[SPOTIFY_EXTRACTOR]\x20Unexpected\x20error\x20during\x20export:','Failed\x20to\x20connect\x20to\x20the\x20data\x20storage\x20service.\x20Please\x20check\x20your\x20network\x20connection.','⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20recently\x20played\x20track:','KGAiL','QXCco','JizRr','IIgZE','DdQXI','vplVQ','wAqEN','log','YbaeR','KNMQt','summary','error','jBgMk','Lewns','jJAoL','items','DZpyt','ZqfwH','topItems','wFCEY','aSlZi','tracks','qKPlF','length','FcqPZ','artists','fQkVZ','savedTracks','ECswX','savedAlbums','yvusY','playlistId','name','warn','kOgXj','recentlyPlayed','filter','trackId','uZxGi','eIvmF','iffxi','dGmZU','data','⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20top\x20track:','hSrGr','artistId','jETuq','sbFxY','alert','NPGUl','RxEyV','MvkNP','iopkn','LnZjT','⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20top\x20artist:','xcVbk','aFHlP','⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20playlist:','BNvQr','eAHKf','CEDlu','xMQcX','qnYwQ','neKlh','bUhHO','\x20invalid\x20items','Pqtcc','lhNxs','timeRange','WoiUL','tokenExpiry','userId','success','KKuiU','📊\x20[SPOTIFY_EXTRACTOR]\x20Backend\x20response:','WIXTF','fbEZK','tJTFx','default','Objvy','Export\x20Error','lEaEq'];_0x4455=function(){return _0x2ebf14;};return _0x4455();}export const useSpotifyDataExtractor=()=>{const _0x55391e={'wFCEY':function(_0x1d691c,_0x532b96){return _0x1d691c===_0x532b96;},'hSrGr':_0xee64(0x0),'fQkVZ':function(_0xec2ac4,_0x2f332b){return _0xec2ac4===_0x2f332b;},'jNBHx':_0xee64(0x1),'jETuq':_0xee64(0x2),'vXxCI':'iopkn','LnZjT':'⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20playlist:','kOgXj':function(_0x17ced3,_0x21636d){return _0x17ced3===_0x21636d;},'VQdZu':_0xee64(0x3),'BNvQr':'⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20saved\x20album:','KGAiL':_0xee64(0x4),'QXCco':'📊\x20[SPOTIFY_EXTRACTOR]\x20Backend\x20response:','qKPlF':function(_0xcd28eb,_0x4031c7){return _0xcd28eb===_0x4031c7;},'zmOrq':_0xee64(0x5),'IIgZE':_0xee64(0x6),'DdQXI':'Export\x20Failed','vplVQ':'default','HYHgP':_0xee64(0x7),'wAqEN':'⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20saved\x20track:','UZmlx':_0xee64(0x8),'YbaeR':_0xee64(0x9),'KNMQt':_0xee64(0xa),'jBgMk':_0xee64(0xb),'UMIUj':_0xee64(0xc),'Lewns':'Username\x20is\x20required\x20to\x20export\x20Spotify\x20data.','IFJMp':function(_0x3c32d0,_0x395caf){return _0x3c32d0+_0x395caf;},'jJAoL':function(_0x1d0374,_0x2857f6){return _0x1d0374+_0x2857f6;},'DZpyt':function(_0x29c567,_0x5e2d8a){return _0x29c567===_0x5e2d8a;},'ZqfwH':function(_0x41c8e7,_0x8d6d9a){return _0x41c8e7===_0x8d6d9a;},'aSlZi':function(_0x4cf79e,_0x4c7ad9){return _0x4cf79e===_0x4c7ad9;},'FcqPZ':function(_0x866503,_0x138ab2){return _0x866503===_0x138ab2;},'ECswX':function(_0x2b3e65,_0x1747c5){return _0x2b3e65===_0x1747c5;},'gCLjk':function(_0x281a7a,_0x5030fe){return _0x281a7a===_0x5030fe;},'hLyTJ':function(_0x23dac0,_0xa64cd4){return _0x23dac0!==_0xa64cd4;},'yvusY':_0xee64(0xd),'neXwb':function(_0x576b10,_0x1af82c){return _0x576b10===_0x1af82c;},'lhNxs':function(_0x3567b2,_0x350ef6){return _0x3567b2===_0x350ef6;},'eAHKf':function(_0x230f9c,_0xb4aff5){return _0x230f9c+_0xb4aff5;},'CEDlu':function(_0x4ff7f0,_0x2db455){return _0x4ff7f0+_0x2db455;},'xMQcX':function(_0x188861,_0x1c19c1){return _0x188861+_0x1c19c1;},'SiAnr':function(_0x2e81da,_0xe40a74){return _0x2e81da<_0xe40a74;},'qnYwQ':function(_0x2d2b38,_0x161a6f){return _0x2d2b38!==_0x161a6f;},'IAeqR':'ITNOB','neKlh':_0xee64(0xe),'bUhHO':function(_0x5770e5,_0x287144){return _0x5770e5-_0x287144;},'Pqtcc':_0xee64(0xf),'WoiUL':_0xee64(0x10),'KKuiU':_0xee64(0x11),'WIXTF':'fbEZK','tJTFx':_0xee64(0x12),'Objvy':_0xee64(0x13),'lEaEq':_0xee64(0x14)},_0x19e30c=async(_0x5452af,_0x9c978e)=>{const _0x3ed0b4={'MvkNP':_0xee64(0x15),'iffxi':_0x55391e[_0xee64(0x16)],'dGmZU':_0x55391e[_0xee64(0x17)],'uZxGi':function(_0x5d9316,_0x343616){return _0x55391e['qKPlF'](_0x5d9316,_0x343616);},'YmgtU':_0x55391e['zmOrq'],'eIvmF':_0xee64(0x18),'sbFxY':_0x55391e[_0xee64(0x19)],'NPGUl':_0x55391e[_0xee64(0x1a)],'RxEyV':_0x55391e[_0xee64(0x1b)],'xcVbk':_0x55391e['HYHgP'],'aFHlP':_0x55391e[_0xee64(0x1c)],'sPLzT':_0x55391e['UZmlx']};var _0x4ae95d,_0x364fff,_0x19e7dd,_0x1026b2,_0x27c965,_0x5a4f35,_0x3d0242,_0x296315,_0x4e3ed8;console[_0xee64(0x1d)](_0x55391e[_0xee64(0x1e)]),console['log'](_0x55391e[_0xee64(0x1f)],_0x5452af),console[_0xee64(0x1d)]('📊\x20[SPOTIFY_EXTRACTOR]\x20Summary:',_0x9c978e[_0xee64(0x20)]);if(!_0x5452af)return console[_0xee64(0x21)](_0x55391e[_0xee64(0x22)]),Alert['alert'](_0x55391e['UMIUj'],_0x55391e[_0xee64(0x23)],[{'text':'OK','style':_0x55391e[_0xee64(0x1b)]}]),![];const _0x56ce45=_0x55391e['IFJMp'](_0x55391e[_0xee64(0x24)](_0x55391e['jJAoL']((((_0x4ae95d=_0x9c978e['recentlyPlayed'])===null||_0x4ae95d===void 0x0||_0x55391e['qKPlF'](_0x4ae95d=_0x4ae95d[_0xee64(0x25)],null)||_0x55391e[_0xee64(0x26)](_0x4ae95d,void 0x0)?void 0x0:_0x4ae95d['length'])||0x0)+((_0x55391e[_0xee64(0x27)](_0x364fff=_0x9c978e[_0xee64(0x28)],null)||_0x55391e[_0xee64(0x29)](_0x364fff,void 0x0)||_0x55391e[_0xee64(0x2a)](_0x364fff=_0x364fff[_0xee64(0x2b)],null)||_0x55391e[_0xee64(0x2c)](_0x364fff,void 0x0)?void 0x0:_0x364fff[_0xee64(0x2d)])||0x0),(_0x55391e['aSlZi'](_0x19e7dd=_0x9c978e['topItems'],null)||_0x19e7dd===void 0x0||_0x55391e[_0xee64(0x2e)](_0x19e7dd=_0x19e7dd[_0xee64(0x2f)],null)||_0x55391e[_0xee64(0x30)](_0x19e7dd,void 0x0)?void 0x0:_0x19e7dd[_0xee64(0x2d)])||0x0),(_0x55391e[_0xee64(0x26)](_0x1026b2=_0x9c978e['playlists'],null)||_0x55391e[_0xee64(0x27)](_0x1026b2,void 0x0)?void 0x0:_0x1026b2[_0xee64(0x2d)])||0x0),(_0x55391e[_0xee64(0x30)](_0x27c965=_0x9c978e[_0xee64(0x31)],null)||_0x55391e[_0xee64(0x32)](_0x27c965,void 0x0)?void 0x0:_0x27c965[_0xee64(0x2d)])||0x0)+((_0x55391e[_0xee64(0x2e)](_0x5a4f35=_0x9c978e[_0xee64(0x33)],null)||_0x55391e['gCLjk'](_0x5a4f35,void 0x0)?void 0x0:_0x5a4f35[_0xee64(0x2d)])||0x0);if(_0x56ce45===0x0){if(_0x55391e['hLyTJ'](_0x55391e[_0xee64(0x34)],_0x55391e[_0xee64(0x34)])){const _0x402f11=_0x174b48[_0xee64(0x35)]&&_0x371bee[_0xee64(0x36)];return!_0x402f11&&_0x9ddd26[_0xee64(0x37)]('⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20playlist:',_0x20b5fb),_0x402f11;}else return console['log'](_0x55391e['UZmlx']),!![];}const _0x379aab=((_0x55391e[_0xee64(0x38)](_0x3d0242=_0x9c978e[_0xee64(0x39)],null)||_0x3d0242===void 0x0?void 0x0:_0x3d0242[_0xee64(0x25)])||[])[_0xee64(0x3a)](_0x1bb811=>{const _0x79d3e7=_0x1bb811[_0xee64(0x3b)]&&_0x1bb811[_0xee64(0x36)];return!_0x79d3e7&&console['warn'](_0x3ed0b4['MvkNP'],_0x1bb811),_0x79d3e7;}),_0x1a5970=((_0x55391e['neXwb'](_0x296315=_0x9c978e[_0xee64(0x28)],null)||_0x55391e['ECswX'](_0x296315,void 0x0)?void 0x0:_0x296315[_0xee64(0x2b)])||[])[_0xee64(0x3a)](_0x222564=>{const _0x11c432=_0x222564[_0xee64(0x3b)]&&_0x222564[_0xee64(0x36)];if(!_0x11c432){if(_0x3ed0b4[_0xee64(0x3c)](_0x3ed0b4['YmgtU'],_0x3ed0b4[_0xee64(0x3d)]))return _0x5cb1f3[_0xee64(0x1d)](_0x3ed0b4[_0xee64(0x3e)]),_0x559990[_0xee64(0x1d)](_0x3ed0b4[_0xee64(0x3f)],_0x353abd[_0xee64(0x40)]),!![];else console[_0xee64(0x37)](_0xee64(0x41),_0x222564);}return _0x11c432;}),_0x5e77dc=((_0x55391e['lhNxs'](_0x4e3ed8=_0x9c978e['topItems'],null)||_0x55391e[_0xee64(0x2a)](_0x4e3ed8,void 0x0)?void 0x0:_0x4e3ed8[_0xee64(0x2f)])||[])[_0xee64(0x3a)](_0x2925e0=>{if(_0x55391e['wFCEY'](_0x55391e[_0xee64(0x42)],_0x55391e[_0xee64(0x42)])){const _0x3b7db1=_0x2925e0[_0xee64(0x43)]&&_0x2925e0['name'];if(!_0x3b7db1){if(_0x55391e['fQkVZ'](_0x55391e['jNBHx'],_0x55391e[_0xee64(0x44)]))return _0x1b797f['error'](_0x3ed0b4[_0xee64(0x45)],_0x1bb460[_0xee64(0x21)]),Alert[_0xee64(0x46)](_0x3ed0b4[_0xee64(0x47)],_0xca9696[_0xee64(0x21)]||'An\x20unknown\x20error\x20occurred\x20during\x20data\x20storage.',[{'text':'OK','style':_0x3ed0b4[_0xee64(0x48)]}]),![];else console[_0xee64(0x37)]('⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20top\x20artist:',_0x2925e0);}return _0x3b7db1;}else{const _0x2a456c=_0x1db8b8[_0xee64(0x3b)]&&_0x143fe1[_0xee64(0x36)];return!_0x2a456c&&_0x5b67b9[_0xee64(0x37)](_0x3ed0b4[_0xee64(0x49)],_0x24a0e8),_0x2a456c;}}),_0x53cfb0=(_0x9c978e['playlists']||[])[_0xee64(0x3a)](_0x52b2a7=>{if(_0x55391e['fQkVZ'](_0x55391e['vXxCI'],_0xee64(0x4a))){const _0x364f13=_0x52b2a7['playlistId']&&_0x52b2a7[_0xee64(0x36)];return!_0x364f13&&console[_0xee64(0x37)](_0x55391e[_0xee64(0x4b)],_0x52b2a7),_0x364f13;}else{const _0x5d6565=_0x1ab127[_0xee64(0x43)]&&_0x1cae7c[_0xee64(0x36)];return!_0x5d6565&&_0x3f4f0d['warn'](_0xee64(0x4c),_0x404edc),_0x5d6565;}}),_0x1679ce=(_0x9c978e[_0xee64(0x31)]||[])[_0xee64(0x3a)](_0x209367=>{const _0x172f74=_0x209367[_0xee64(0x3b)]&&_0x209367[_0xee64(0x36)];return!_0x172f74&&(_0x3ed0b4[_0xee64(0x3c)](_0x3ed0b4[_0xee64(0x4d)],_0x3ed0b4[_0xee64(0x4d)])?console['warn'](_0x3ed0b4[_0xee64(0x4e)],_0x209367):_0xde9af5[_0xee64(0x37)](_0xee64(0x4f),_0x5cea05)),_0x172f74;}),_0x21fe8d=(_0x9c978e[_0xee64(0x33)]||[])['filter'](_0x370233=>{if(_0x55391e[_0xee64(0x38)]('vsSoJ',_0x55391e['VQdZu'])){const _0x2b4186=_0xfa78c['albumId']&&_0x3a0794['name'];return!_0x2b4186&&_0x5a7cc3[_0xee64(0x37)]('⚠️\x20[SPOTIFY_EXTRACTOR]\x20Invalid\x20saved\x20album:',_0x36eeb8),_0x2b4186;}else{const _0x457cbb=_0x370233['albumId']&&_0x370233[_0xee64(0x36)];return!_0x457cbb&&console['warn'](_0x55391e[_0xee64(0x50)],_0x370233),_0x457cbb;}}),_0x10f055=_0x56ce45,_0x43c9ce=_0x55391e[_0xee64(0x51)](_0x55391e[_0xee64(0x52)](_0x55391e[_0xee64(0x53)](_0x55391e['jJAoL'](_0x379aab[_0xee64(0x2d)],_0x1a5970[_0xee64(0x2d)]),_0x5e77dc['length']),_0x53cfb0[_0xee64(0x2d)])+_0x1679ce[_0xee64(0x2d)],_0x21fe8d['length']);if(_0x55391e['SiAnr'](_0x43c9ce,_0x10f055)){if(_0x55391e[_0xee64(0x54)](_0x55391e['IAeqR'],_0x55391e[_0xee64(0x55)]))console[_0xee64(0x37)]('⚠️\x20[SPOTIFY_EXTRACTOR]\x20Filtered\x20out\x20'+_0x55391e[_0xee64(0x56)](_0x10f055,_0x43c9ce)+_0xee64(0x57));else return _0x10ae57['log'](_0x3ed0b4['sPLzT']),!![];}try{var _0x2e3984;console[_0xee64(0x1d)](_0x55391e[_0xee64(0x58)]);const _0x1e3123=await storeSpotifyData(_0x5452af,{'recentlyPlayed':{'items':_0x379aab,'totalCount':_0x379aab[_0xee64(0x2d)]},'topItems':{'tracks':_0x1a5970,'artists':_0x5e77dc,'timeRange':(_0x55391e[_0xee64(0x59)](_0x2e3984=_0x9c978e[_0xee64(0x28)],null)||_0x2e3984===void 0x0?void 0x0:_0x2e3984[_0xee64(0x5a)])||_0x55391e[_0xee64(0x5b)]},'playlists':_0x53cfb0,'savedTracks':_0x1679ce,'savedAlbums':_0x21fe8d,'profile':_0x9c978e['profile'],'tokenExpiry':_0x9c978e[_0xee64(0x5c)],'userId':_0x9c978e[_0xee64(0x5d)]});if(_0x1e3123[_0xee64(0x5e)]){if('QwLxg'===_0x55391e[_0xee64(0x5f)])return console['log'](_0x55391e[_0xee64(0x16)]),console[_0xee64(0x1d)](_0xee64(0x60),_0x1e3123[_0xee64(0x40)]),!![];else _0x38c0ba[_0xee64(0x37)](_0xee64(0x41),_0x4a0945);}else{if(_0x55391e[_0xee64(0x26)](_0x55391e[_0xee64(0x61)],_0xee64(0x62)))return console[_0xee64(0x21)](_0x55391e[_0xee64(0x19)],_0x1e3123[_0xee64(0x21)]),Alert[_0xee64(0x46)](_0x55391e[_0xee64(0x1a)],_0x1e3123['error']||_0x55391e[_0xee64(0x63)],[{'text':'OK','style':_0xee64(0x64)}]),![];else _0x5c8199[_0xee64(0x37)](_0xee64(0x4c),_0x283947);}}catch(_0x18c6ba){return console[_0xee64(0x21)](_0x55391e[_0xee64(0x65)],_0x18c6ba),Alert[_0xee64(0x46)](_0xee64(0x66),_0x55391e[_0xee64(0x67)],[{'text':'OK','style':_0x55391e[_0xee64(0x1b)]}]),![];}};return{'initiateDataExport':_0x19e30c};};
|
|
1
|
+
/**
|
|
2
|
+
* Spotify Data Extractor
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the Spotify data export flow:
|
|
5
|
+
* 1. Receives extracted listening data from WebView
|
|
6
|
+
* 2. Validates and formats data
|
|
7
|
+
* 3. Sends to backend via spotifyDataService
|
|
8
|
+
*
|
|
9
|
+
* This acts as the bridge between OAuthWebView and the backend API.
|
|
10
|
+
*
|
|
11
|
+
* @reference Sephora implementation: src/services/sephoraDataExtractor.ts
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { storeSpotifyData } from './spotifyDataService';
|
|
15
|
+
import { Alert } from 'react-native';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Combined Spotify export data from WebView - matches spotify.ts script output
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hook for Spotify data extraction operations
|
|
23
|
+
*/
|
|
24
|
+
export const useSpotifyDataExtractor = () => {
|
|
25
|
+
/**
|
|
26
|
+
* Initiate data export to backend
|
|
27
|
+
*
|
|
28
|
+
* @param username - User identifier
|
|
29
|
+
* @param data - Extracted Spotify data (recentlyPlayed, topItems, playlists, etc.)
|
|
30
|
+
* @returns true if successful, false otherwise
|
|
31
|
+
*/
|
|
32
|
+
const initiateDataExport = async (username, data) => {
|
|
33
|
+
var _data$recentlyPlayed, _data$topItems, _data$topItems2, _data$playlists, _data$savedTracks, _data$savedAlbums, _data$recentlyPlayed2, _data$topItems3, _data$topItems4;
|
|
34
|
+
console.log('🚀 [SPOTIFY_EXTRACTOR] Initiating data export');
|
|
35
|
+
console.log('👤 [SPOTIFY_EXTRACTOR] Username:', username);
|
|
36
|
+
console.log('📊 [SPOTIFY_EXTRACTOR] Summary:', data.summary);
|
|
37
|
+
if (!username) {
|
|
38
|
+
console.error('❌ [SPOTIFY_EXTRACTOR] Username is required');
|
|
39
|
+
Alert.alert('Error', 'Username is required to export Spotify data.', [{
|
|
40
|
+
text: 'OK',
|
|
41
|
+
style: 'default'
|
|
42
|
+
}]);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const totalItems = (((_data$recentlyPlayed = data.recentlyPlayed) === null || _data$recentlyPlayed === void 0 || (_data$recentlyPlayed = _data$recentlyPlayed.items) === null || _data$recentlyPlayed === void 0 ? void 0 : _data$recentlyPlayed.length) || 0) + (((_data$topItems = data.topItems) === null || _data$topItems === void 0 || (_data$topItems = _data$topItems.tracks) === null || _data$topItems === void 0 ? void 0 : _data$topItems.length) || 0) + (((_data$topItems2 = data.topItems) === null || _data$topItems2 === void 0 || (_data$topItems2 = _data$topItems2.artists) === null || _data$topItems2 === void 0 ? void 0 : _data$topItems2.length) || 0) + (((_data$playlists = data.playlists) === null || _data$playlists === void 0 ? void 0 : _data$playlists.length) || 0) + (((_data$savedTracks = data.savedTracks) === null || _data$savedTracks === void 0 ? void 0 : _data$savedTracks.length) || 0) + (((_data$savedAlbums = data.savedAlbums) === null || _data$savedAlbums === void 0 ? void 0 : _data$savedAlbums.length) || 0);
|
|
46
|
+
if (totalItems === 0) {
|
|
47
|
+
console.log('ℹ️ [SPOTIFY_EXTRACTOR] No data to export - treating as success (connected)');
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
const validRecentlyPlayed = (((_data$recentlyPlayed2 = data.recentlyPlayed) === null || _data$recentlyPlayed2 === void 0 ? void 0 : _data$recentlyPlayed2.items) || []).filter(track => {
|
|
51
|
+
const isValid = track.trackId && track.name;
|
|
52
|
+
if (!isValid) {
|
|
53
|
+
console.warn('⚠️ [SPOTIFY_EXTRACTOR] Invalid recently played track:', track);
|
|
54
|
+
}
|
|
55
|
+
return isValid;
|
|
56
|
+
});
|
|
57
|
+
const validTopTracks = (((_data$topItems3 = data.topItems) === null || _data$topItems3 === void 0 ? void 0 : _data$topItems3.tracks) || []).filter(track => {
|
|
58
|
+
const isValid = track.trackId && track.name;
|
|
59
|
+
if (!isValid) {
|
|
60
|
+
console.warn('⚠️ [SPOTIFY_EXTRACTOR] Invalid top track:', track);
|
|
61
|
+
}
|
|
62
|
+
return isValid;
|
|
63
|
+
});
|
|
64
|
+
const validTopArtists = (((_data$topItems4 = data.topItems) === null || _data$topItems4 === void 0 ? void 0 : _data$topItems4.artists) || []).filter(artist => {
|
|
65
|
+
const isValid = artist.artistId && artist.name;
|
|
66
|
+
if (!isValid) {
|
|
67
|
+
console.warn('⚠️ [SPOTIFY_EXTRACTOR] Invalid top artist:', artist);
|
|
68
|
+
}
|
|
69
|
+
return isValid;
|
|
70
|
+
});
|
|
71
|
+
const validPlaylists = (data.playlists || []).filter(playlist => {
|
|
72
|
+
const isValid = playlist.playlistId && playlist.name;
|
|
73
|
+
if (!isValid) {
|
|
74
|
+
console.warn('⚠️ [SPOTIFY_EXTRACTOR] Invalid playlist:', playlist);
|
|
75
|
+
}
|
|
76
|
+
return isValid;
|
|
77
|
+
});
|
|
78
|
+
const validSavedTracks = (data.savedTracks || []).filter(track => {
|
|
79
|
+
const isValid = track.trackId && track.name;
|
|
80
|
+
if (!isValid) {
|
|
81
|
+
console.warn('⚠️ [SPOTIFY_EXTRACTOR] Invalid saved track:', track);
|
|
82
|
+
}
|
|
83
|
+
return isValid;
|
|
84
|
+
});
|
|
85
|
+
const validSavedAlbums = (data.savedAlbums || []).filter(album => {
|
|
86
|
+
const isValid = album.albumId && album.name;
|
|
87
|
+
if (!isValid) {
|
|
88
|
+
console.warn('⚠️ [SPOTIFY_EXTRACTOR] Invalid saved album:', album);
|
|
89
|
+
}
|
|
90
|
+
return isValid;
|
|
91
|
+
});
|
|
92
|
+
const originalCount = totalItems;
|
|
93
|
+
const validCount = validRecentlyPlayed.length + validTopTracks.length + validTopArtists.length + validPlaylists.length + validSavedTracks.length + validSavedAlbums.length;
|
|
94
|
+
if (validCount < originalCount) {
|
|
95
|
+
console.warn(`⚠️ [SPOTIFY_EXTRACTOR] Filtered out ${originalCount - validCount} invalid items`);
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
var _data$topItems5;
|
|
99
|
+
console.log('📡 [SPOTIFY_EXTRACTOR] Sending to backend...');
|
|
100
|
+
const result = await storeSpotifyData(username, {
|
|
101
|
+
recentlyPlayed: {
|
|
102
|
+
items: validRecentlyPlayed,
|
|
103
|
+
totalCount: validRecentlyPlayed.length
|
|
104
|
+
},
|
|
105
|
+
topItems: {
|
|
106
|
+
tracks: validTopTracks,
|
|
107
|
+
artists: validTopArtists,
|
|
108
|
+
timeRange: ((_data$topItems5 = data.topItems) === null || _data$topItems5 === void 0 ? void 0 : _data$topItems5.timeRange) || 'medium_term'
|
|
109
|
+
},
|
|
110
|
+
playlists: validPlaylists,
|
|
111
|
+
savedTracks: validSavedTracks,
|
|
112
|
+
savedAlbums: validSavedAlbums,
|
|
113
|
+
profile: data.profile,
|
|
114
|
+
tokenExpiry: data.tokenExpiry,
|
|
115
|
+
userId: data.userId
|
|
116
|
+
});
|
|
117
|
+
if (result.success) {
|
|
118
|
+
console.log('✅ [SPOTIFY_EXTRACTOR] Export completed successfully');
|
|
119
|
+
console.log('📊 [SPOTIFY_EXTRACTOR] Backend response:', result.data);
|
|
120
|
+
return true;
|
|
121
|
+
} else {
|
|
122
|
+
console.error('❌ [SPOTIFY_EXTRACTOR] Backend storage failed:', result.error);
|
|
123
|
+
Alert.alert('Export Failed', result.error || 'An unknown error occurred during data storage.', [{
|
|
124
|
+
text: 'OK',
|
|
125
|
+
style: 'default'
|
|
126
|
+
}]);
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error('❌ [SPOTIFY_EXTRACTOR] Unexpected error during export:', error);
|
|
131
|
+
Alert.alert('Export Error', 'Failed to connect to the data storage service. Please check your network connection.', [{
|
|
132
|
+
text: 'OK',
|
|
133
|
+
style: 'default'
|
|
134
|
+
}]);
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
initiateDataExport
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
//# sourceMappingURL=spotifyDataExtractor.js.map
|