releasebird-javascript-sdk 1.0.90 → 1.0.92
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/build/index.js +1 -1
- package/package.json +2 -1
- package/published/1.0.90/index.js +1 -1
- package/published/1.0.91/index.js +1 -0
- package/published/1.0.92/index.js +1 -0
- package/published/latest/index.js +1 -1
- package/src/RbirdAutomationManager.js +206 -253
- package/src/RbirdBookingManager.js +251 -0
- package/src/RbirdWebsiteWidget.js +1 -5
- package/src/index.js +20 -0
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import RbirdSessionManager from "./RbirdSessionManager";
|
|
2
|
+
import RbirdWebsiteWidget from "./RbirdWebsiteWidget";
|
|
2
3
|
import { RbirdBannerManager } from "./RbirdBannerManager";
|
|
3
4
|
import { RbirdFormManager } from "./RbirdFormManager";
|
|
4
5
|
import { RbirdSurveyManager } from "./RbirdSurveyManager";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
* Manages automations
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Manages automations by sending events to the backend and executing commands.
|
|
9
|
+
* The actual workflow execution happens on the backend - this manager handles:
|
|
10
|
+
* - Sending events to the backend
|
|
11
|
+
* - Polling for pending commands
|
|
12
|
+
* - Executing UI commands (show banner, form, survey, send chat)
|
|
10
13
|
*/
|
|
11
14
|
export class RbirdAutomationManager {
|
|
12
15
|
static instance = null;
|
|
13
|
-
automations = [];
|
|
14
16
|
apiKey = null;
|
|
15
17
|
firstSeenTimestamp = null;
|
|
16
|
-
|
|
18
|
+
pollingInterval = null;
|
|
19
|
+
isPolling = false;
|
|
17
20
|
|
|
18
21
|
static getInstance() {
|
|
19
22
|
if (!this.instance) {
|
|
@@ -30,14 +33,36 @@ export class RbirdAutomationManager {
|
|
|
30
33
|
this.apiKey = apiKey;
|
|
31
34
|
this.firstSeenTimestamp = this.getFirstSeenTimestamp();
|
|
32
35
|
|
|
33
|
-
// Load automations from backend
|
|
34
|
-
await this.loadAutomations();
|
|
35
|
-
|
|
36
36
|
// Register event handlers
|
|
37
37
|
this.registerEventHandlers();
|
|
38
38
|
|
|
39
|
-
//
|
|
40
|
-
this.
|
|
39
|
+
// Listen for WebSocket notifications from widget iframe
|
|
40
|
+
this.setupWebSocketListener();
|
|
41
|
+
|
|
42
|
+
// Start command polling (reduced frequency - WebSocket is primary)
|
|
43
|
+
this.startCommandPolling();
|
|
44
|
+
|
|
45
|
+
// Send first_seen event
|
|
46
|
+
await this.sendEvent('first_seen', {
|
|
47
|
+
timeSinceFirstSeen: (Date.now() - this.firstSeenTimestamp) / 1000
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log('[Rbird] Automation manager initialized');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Setup listener for WebSocket notifications from widget iframe.
|
|
55
|
+
* This allows instant command execution when the backend pushes a notification.
|
|
56
|
+
*/
|
|
57
|
+
setupWebSocketListener() {
|
|
58
|
+
window.addEventListener('message', (event) => {
|
|
59
|
+
// Handle automation command notification from widget
|
|
60
|
+
if (event.data === 'automationCommand') {
|
|
61
|
+
console.log('[Rbird] Received WebSocket automation notification');
|
|
62
|
+
// Immediately fetch and execute pending commands
|
|
63
|
+
this.pollCommands();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
41
66
|
}
|
|
42
67
|
|
|
43
68
|
/**
|
|
@@ -53,297 +78,253 @@ export class RbirdAutomationManager {
|
|
|
53
78
|
return now;
|
|
54
79
|
}
|
|
55
80
|
|
|
56
|
-
/**
|
|
57
|
-
* Load active automations from the backend
|
|
58
|
-
*/
|
|
59
|
-
async loadAutomations() {
|
|
60
|
-
try {
|
|
61
|
-
const sessionManager = RbirdSessionManager.getInstance();
|
|
62
|
-
const baseUrl = sessionManager.apiUrl || 'https://api.releasebird.com';
|
|
63
|
-
|
|
64
|
-
const response = await fetch(`${baseUrl}/papi/ewidget/automations`, {
|
|
65
|
-
method: 'GET',
|
|
66
|
-
headers: {
|
|
67
|
-
'Content-Type': 'application/json',
|
|
68
|
-
'apiKey': this.apiKey,
|
|
69
|
-
'languageCode': navigator.language?.split('-')[0] || 'en',
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
if (response.ok) {
|
|
74
|
-
this.automations = await response.json();
|
|
75
|
-
console.log('[Rbird] Loaded automations:', this.automations.length);
|
|
76
|
-
}
|
|
77
|
-
} catch (error) {
|
|
78
|
-
console.error('[Rbird] Error loading automations:', error);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
81
|
/**
|
|
83
82
|
* Register event handlers for automation triggers
|
|
84
83
|
*/
|
|
85
84
|
registerEventHandlers() {
|
|
86
|
-
// Listen for page visits
|
|
87
|
-
window.addEventListener('popstate', () => this.
|
|
85
|
+
// Listen for page visits (navigation)
|
|
86
|
+
window.addEventListener('popstate', () => this.sendPageVisitEvents());
|
|
87
|
+
|
|
88
|
+
// Also track initial page load
|
|
89
|
+
this.sendPageVisitEvents();
|
|
88
90
|
|
|
89
91
|
// Listen for identify events
|
|
90
92
|
document.addEventListener('rbird:identify', (e) => {
|
|
91
|
-
this.
|
|
93
|
+
this.sendEvent('user_identified', e.detail);
|
|
94
|
+
// Also send user_page_visit when user is identified
|
|
95
|
+
this.sendEvent('user_page_visit');
|
|
92
96
|
});
|
|
93
97
|
|
|
94
98
|
// Listen for form submissions
|
|
95
99
|
document.addEventListener('rbird:form_submitted', (e) => {
|
|
96
|
-
this.
|
|
100
|
+
this.sendEvent('form_submitted', e.detail);
|
|
97
101
|
});
|
|
98
102
|
|
|
99
103
|
// Listen for survey completions
|
|
100
104
|
document.addEventListener('rbird:survey_completed', (e) => {
|
|
101
|
-
this.
|
|
105
|
+
this.sendEvent('survey_completed', e.detail);
|
|
102
106
|
});
|
|
103
107
|
|
|
104
108
|
// Listen for custom events
|
|
105
109
|
document.addEventListener('rbird:track', (e) => {
|
|
106
|
-
this.
|
|
110
|
+
this.sendEvent(e.detail?.eventName, e.detail?.data);
|
|
107
111
|
});
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
/**
|
|
111
|
-
*
|
|
115
|
+
* Send page visit events based on user identification status.
|
|
116
|
+
* Sends:
|
|
117
|
+
* - page_visit: always (for backward compatibility)
|
|
118
|
+
* - visitor_page_visit: if user is NOT identified (anonymous)
|
|
119
|
+
* - user_page_visit: if user IS identified
|
|
112
120
|
*/
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
121
|
+
sendPageVisitEvents() {
|
|
122
|
+
// Always send generic page_visit for backward compatibility
|
|
123
|
+
this.sendEvent('page_visit');
|
|
124
|
+
|
|
125
|
+
// Send specific event based on identification status
|
|
126
|
+
const peopleId = this.getPeopleId();
|
|
127
|
+
if (peopleId) {
|
|
128
|
+
this.sendEvent('user_page_visit');
|
|
129
|
+
} else {
|
|
130
|
+
this.sendEvent('visitor_page_visit');
|
|
131
|
+
}
|
|
122
132
|
}
|
|
123
133
|
|
|
124
134
|
/**
|
|
125
|
-
*
|
|
135
|
+
* Send an event to the backend
|
|
126
136
|
* @param {string} eventType - The type of event
|
|
127
137
|
* @param {Object} eventData - Additional event data
|
|
128
138
|
*/
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
async sendEvent(eventType, eventData = {}) {
|
|
140
|
+
if (!eventType) return;
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
const response = await fetch(`${API}/ewidget/events`, {
|
|
144
|
+
method: 'POST',
|
|
145
|
+
headers: {
|
|
146
|
+
'Content-Type': 'application/json',
|
|
147
|
+
'apiKey': this.apiKey,
|
|
148
|
+
'peopleId': this.getPeopleId() || '',
|
|
149
|
+
'anonymousId': this.getAnonymousId() || ''
|
|
150
|
+
},
|
|
151
|
+
body: JSON.stringify({
|
|
152
|
+
eventType,
|
|
153
|
+
context: {
|
|
154
|
+
...eventData,
|
|
155
|
+
pageUrl: window.location.href,
|
|
156
|
+
pagePath: window.location.pathname
|
|
157
|
+
},
|
|
158
|
+
firstSeenTimestamp: this.firstSeenTimestamp
|
|
159
|
+
})
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
console.warn('[Rbird] Failed to send event:', response.status);
|
|
164
|
+
} else {
|
|
165
|
+
console.log('[Rbird] Event sent:', eventType);
|
|
134
166
|
}
|
|
135
|
-
})
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error('[Rbird] Error sending event:', error);
|
|
169
|
+
}
|
|
136
170
|
}
|
|
137
171
|
|
|
138
172
|
/**
|
|
139
|
-
*
|
|
140
|
-
* @param {Object} automation - The automation object
|
|
141
|
-
* @returns {Object|null} The trigger node or null
|
|
173
|
+
* Get the current people ID from session
|
|
142
174
|
*/
|
|
143
|
-
|
|
144
|
-
return
|
|
175
|
+
getPeopleId() {
|
|
176
|
+
return RbirdSessionManager.getInstance().getState()?.identify?.peopleId;
|
|
145
177
|
}
|
|
146
178
|
|
|
147
179
|
/**
|
|
148
|
-
*
|
|
149
|
-
* @param {Object} automation - The automation object
|
|
150
|
-
* @param {Object} triggerNode - The trigger node
|
|
151
|
-
* @param {Object} context - The event context
|
|
180
|
+
* Get the anonymous ID from session
|
|
152
181
|
*/
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Evaluate trigger conditions
|
|
160
|
-
if (!this.evaluateTriggerConditions(triggerNode, context)) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Mark as executed
|
|
165
|
-
this.executedAutomations.add(automation.id);
|
|
166
|
-
|
|
167
|
-
// Execute the workflow starting from the trigger node
|
|
168
|
-
this.executeWorkflow(automation, triggerNode.id, context);
|
|
182
|
+
getAnonymousId() {
|
|
183
|
+
return RbirdSessionManager.getInstance().getState()?.identify?.anonymousId ||
|
|
184
|
+
localStorage.getItem('rbird_anonymous_id') ||
|
|
185
|
+
this.generateAnonymousId();
|
|
169
186
|
}
|
|
170
187
|
|
|
171
188
|
/**
|
|
172
|
-
*
|
|
173
|
-
* @param {Object} triggerNode - The trigger node
|
|
174
|
-
* @param {Object} context - The event context
|
|
175
|
-
* @returns {boolean} Whether conditions are met
|
|
189
|
+
* Generate and store an anonymous ID
|
|
176
190
|
*/
|
|
177
|
-
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const value = this.getContextValue(condition.property, context);
|
|
182
|
-
|
|
183
|
-
switch (condition.operator) {
|
|
184
|
-
case 'less_than':
|
|
185
|
-
if (!(parseFloat(value) < parseFloat(condition.value))) return false;
|
|
186
|
-
break;
|
|
187
|
-
case 'greater_than':
|
|
188
|
-
if (!(parseFloat(value) > parseFloat(condition.value))) return false;
|
|
189
|
-
break;
|
|
190
|
-
case 'equals':
|
|
191
|
-
if (value !== condition.value) return false;
|
|
192
|
-
break;
|
|
193
|
-
case 'contains':
|
|
194
|
-
if (!String(value).includes(condition.value)) return false;
|
|
195
|
-
break;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return true;
|
|
191
|
+
generateAnonymousId() {
|
|
192
|
+
const id = 'anon_' + Math.random().toString(36).substr(2, 9);
|
|
193
|
+
localStorage.setItem('rbird_anonymous_id', id);
|
|
194
|
+
return id;
|
|
200
195
|
}
|
|
201
196
|
|
|
202
197
|
/**
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
* @returns {any} The value
|
|
198
|
+
* Start polling for pending commands.
|
|
199
|
+
* Polling is now a fallback mechanism - WebSocket is the primary delivery method.
|
|
200
|
+
* The interval is set to 60 seconds to catch any missed commands.
|
|
207
201
|
*/
|
|
208
|
-
|
|
209
|
-
if (
|
|
210
|
-
return
|
|
202
|
+
startCommandPolling() {
|
|
203
|
+
if (this.pollingInterval) {
|
|
204
|
+
return; // Already polling
|
|
211
205
|
}
|
|
212
206
|
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
return value;
|
|
207
|
+
// Poll immediately once
|
|
208
|
+
this.pollCommands();
|
|
209
|
+
|
|
210
|
+
// Poll every 60 seconds as fallback (WebSocket handles instant delivery)
|
|
211
|
+
this.pollingInterval = setInterval(() => this.pollCommands(), 60000);
|
|
220
212
|
}
|
|
221
213
|
|
|
222
214
|
/**
|
|
223
|
-
*
|
|
224
|
-
* @param {Object} automation - The automation object
|
|
225
|
-
* @param {string} startNodeId - The ID of the starting node
|
|
226
|
-
* @param {Object} context - The execution context
|
|
215
|
+
* Stop command polling
|
|
227
216
|
*/
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
for (const edge of nextEdges) {
|
|
233
|
-
const targetNode = automation.nodes?.find((node) => node.id === edge.target);
|
|
234
|
-
if (!targetNode) continue;
|
|
235
|
-
|
|
236
|
-
if (targetNode.type === 'condition') {
|
|
237
|
-
// Evaluate condition and follow appropriate path
|
|
238
|
-
const conditionResult = this.evaluateCondition(targetNode, context);
|
|
239
|
-
const handleToFollow = conditionResult ? 'true' : 'false';
|
|
240
|
-
|
|
241
|
-
// Find edges from this condition with matching handle
|
|
242
|
-
const conditionEdges = automation.edges?.filter(
|
|
243
|
-
(e) => e.source === targetNode.id && e.sourceHandle === handleToFollow
|
|
244
|
-
) || [];
|
|
245
|
-
|
|
246
|
-
for (const condEdge of conditionEdges) {
|
|
247
|
-
this.executeWorkflow(automation, condEdge.source, context);
|
|
248
|
-
}
|
|
249
|
-
} else if (targetNode.type === 'action') {
|
|
250
|
-
// Execute the action
|
|
251
|
-
this.executeAction(targetNode, context);
|
|
252
|
-
|
|
253
|
-
// Continue to next nodes if any
|
|
254
|
-
this.executeWorkflow(automation, targetNode.id, context);
|
|
255
|
-
}
|
|
217
|
+
stopCommandPolling() {
|
|
218
|
+
if (this.pollingInterval) {
|
|
219
|
+
clearInterval(this.pollingInterval);
|
|
220
|
+
this.pollingInterval = null;
|
|
256
221
|
}
|
|
257
222
|
}
|
|
258
223
|
|
|
259
224
|
/**
|
|
260
|
-
*
|
|
261
|
-
* @param {Object} conditionNode - The condition node
|
|
262
|
-
* @param {Object} context - The execution context
|
|
263
|
-
* @returns {boolean} The result of the condition
|
|
225
|
+
* Poll for pending commands from the backend
|
|
264
226
|
*/
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
227
|
+
async pollCommands() {
|
|
228
|
+
if (this.isPolling) return; // Prevent concurrent polls
|
|
229
|
+
this.isPolling = true;
|
|
230
|
+
|
|
231
|
+
try {
|
|
232
|
+
const response = await fetch(`${API}/ewidget/commands`, {
|
|
233
|
+
method: 'GET',
|
|
234
|
+
headers: {
|
|
235
|
+
'Content-Type': 'application/json',
|
|
236
|
+
'apiKey': this.apiKey,
|
|
237
|
+
'peopleId': this.getPeopleId() || '',
|
|
238
|
+
'anonymousId': this.getAnonymousId() || ''
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
if (!response.ok) {
|
|
243
|
+
return;
|
|
280
244
|
}
|
|
281
|
-
} else {
|
|
282
|
-
actualValue = context[property];
|
|
283
|
-
}
|
|
284
245
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
246
|
+
const commands = await response.json();
|
|
247
|
+
|
|
248
|
+
// Execute each command
|
|
249
|
+
for (const cmd of commands) {
|
|
250
|
+
await this.executeCommand(cmd);
|
|
251
|
+
await this.markDelivered(cmd.id);
|
|
252
|
+
}
|
|
253
|
+
} catch (error) {
|
|
254
|
+
// Silently fail - polling will retry
|
|
255
|
+
} finally {
|
|
256
|
+
this.isPolling = false;
|
|
296
257
|
}
|
|
297
258
|
}
|
|
298
259
|
|
|
299
260
|
/**
|
|
300
|
-
* Execute
|
|
301
|
-
* @param {Object}
|
|
302
|
-
* @param {Object} context - The execution context
|
|
261
|
+
* Execute a command from the backend
|
|
262
|
+
* @param {Object} cmd - The command to execute
|
|
303
263
|
*/
|
|
304
|
-
|
|
305
|
-
|
|
264
|
+
async executeCommand(cmd) {
|
|
265
|
+
console.log('[Rbird] Executing command:', cmd.type);
|
|
306
266
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
switch (actionType) {
|
|
310
|
-
case 'send_chat':
|
|
311
|
-
this.executeSendChat(config?.message, context);
|
|
312
|
-
break;
|
|
267
|
+
switch (cmd.type) {
|
|
313
268
|
case 'show_banner':
|
|
314
|
-
this.executeShowBanner(
|
|
269
|
+
this.executeShowBanner(cmd.targetId);
|
|
315
270
|
break;
|
|
316
271
|
case 'show_form':
|
|
317
|
-
this.executeShowForm(
|
|
272
|
+
this.executeShowForm(cmd.targetId);
|
|
318
273
|
break;
|
|
319
274
|
case 'show_survey':
|
|
320
|
-
this.executeShowSurvey(
|
|
275
|
+
this.executeShowSurvey(cmd.targetId);
|
|
321
276
|
break;
|
|
322
|
-
case '
|
|
323
|
-
this.
|
|
277
|
+
case 'send_chat':
|
|
278
|
+
this.executeSendChat(cmd.message, cmd.config);
|
|
324
279
|
break;
|
|
280
|
+
default:
|
|
281
|
+
console.warn('[Rbird] Unknown command type:', cmd.type);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Mark a command as delivered
|
|
287
|
+
* @param {string} commandId - The command ID
|
|
288
|
+
*/
|
|
289
|
+
async markDelivered(commandId) {
|
|
290
|
+
try {
|
|
291
|
+
await fetch(`${API}/ewidget/commands/${commandId}/delivered`, {
|
|
292
|
+
method: 'POST',
|
|
293
|
+
headers: {
|
|
294
|
+
'Content-Type': 'application/json',
|
|
295
|
+
'apiKey': this.apiKey
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
} catch (error) {
|
|
299
|
+
console.warn('[Rbird] Failed to mark command as delivered:', error);
|
|
325
300
|
}
|
|
326
301
|
}
|
|
327
302
|
|
|
328
303
|
/**
|
|
329
|
-
* Execute send_chat
|
|
304
|
+
* Execute send_chat command
|
|
330
305
|
*/
|
|
331
|
-
executeSendChat(message,
|
|
306
|
+
executeSendChat(message, config) {
|
|
332
307
|
if (!message) return;
|
|
333
308
|
|
|
334
|
-
|
|
335
|
-
const processedMessage = this.processMessage(message, context);
|
|
309
|
+
console.log('[Rbird] Chat message triggered:', message);
|
|
336
310
|
|
|
337
|
-
//
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
}));
|
|
311
|
+
// Open the widget and send the message
|
|
312
|
+
const widget = RbirdWebsiteWidget.getInstance();
|
|
313
|
+
widget.openWebsiteWidget();
|
|
341
314
|
|
|
342
|
-
|
|
315
|
+
// Send message to iframe to display automation message
|
|
316
|
+
setTimeout(() => {
|
|
317
|
+
if (widget.iframe) {
|
|
318
|
+
widget.iframe.contentWindow?.postMessage({
|
|
319
|
+
type: 'automationMessage',
|
|
320
|
+
message: message
|
|
321
|
+
}, '*');
|
|
322
|
+
}
|
|
323
|
+
}, 500); // Small delay to ensure iframe is ready
|
|
343
324
|
}
|
|
344
325
|
|
|
345
326
|
/**
|
|
346
|
-
* Execute show_banner
|
|
327
|
+
* Execute show_banner command
|
|
347
328
|
*/
|
|
348
329
|
executeShowBanner(bannerId) {
|
|
349
330
|
if (!bannerId) return;
|
|
@@ -351,7 +332,7 @@ export class RbirdAutomationManager {
|
|
|
351
332
|
}
|
|
352
333
|
|
|
353
334
|
/**
|
|
354
|
-
* Execute show_form
|
|
335
|
+
* Execute show_form command
|
|
355
336
|
*/
|
|
356
337
|
executeShowForm(formId) {
|
|
357
338
|
if (!formId) return;
|
|
@@ -359,48 +340,13 @@ export class RbirdAutomationManager {
|
|
|
359
340
|
}
|
|
360
341
|
|
|
361
342
|
/**
|
|
362
|
-
* Execute show_survey
|
|
343
|
+
* Execute show_survey command
|
|
363
344
|
*/
|
|
364
345
|
executeShowSurvey(surveyId) {
|
|
365
346
|
if (!surveyId) return;
|
|
366
347
|
RbirdSurveyManager.getInstance().showSurvey(surveyId, {});
|
|
367
348
|
}
|
|
368
349
|
|
|
369
|
-
/**
|
|
370
|
-
* Execute webhook action
|
|
371
|
-
*/
|
|
372
|
-
async executeWebhook(url, method, context) {
|
|
373
|
-
if (!url) return;
|
|
374
|
-
|
|
375
|
-
try {
|
|
376
|
-
const options = {
|
|
377
|
-
method: method,
|
|
378
|
-
headers: {
|
|
379
|
-
'Content-Type': 'application/json',
|
|
380
|
-
},
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
if (method === 'POST') {
|
|
384
|
-
options.body = JSON.stringify(context);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
await fetch(url, options);
|
|
388
|
-
console.log('[Rbird] Webhook executed:', url);
|
|
389
|
-
} catch (error) {
|
|
390
|
-
console.error('[Rbird] Webhook error:', error);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
/**
|
|
395
|
-
* Process message placeholders
|
|
396
|
-
*/
|
|
397
|
-
processMessage(message, context) {
|
|
398
|
-
return message
|
|
399
|
-
.replace(/\{\{user\.name\}\}/g, RbirdSessionManager.getInstance().getUser()?.name || '')
|
|
400
|
-
.replace(/\{\{user\.email\}\}/g, RbirdSessionManager.getInstance().getUser()?.email || '')
|
|
401
|
-
.replace(/\{\{page\.url\}\}/g, window.location.href);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
350
|
/**
|
|
405
351
|
* Track a custom event
|
|
406
352
|
* @param {string} eventName - The name of the event
|
|
@@ -411,6 +357,13 @@ export class RbirdAutomationManager {
|
|
|
411
357
|
detail: { eventName, data }
|
|
412
358
|
}));
|
|
413
359
|
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Cleanup when manager is destroyed
|
|
363
|
+
*/
|
|
364
|
+
destroy() {
|
|
365
|
+
this.stopCommandPolling();
|
|
366
|
+
}
|
|
414
367
|
}
|
|
415
368
|
|
|
416
369
|
export default RbirdAutomationManager;
|