satyamark-react 0.0.12 → 0.0.14
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/README.md +164 -353
- package/dist/index.d.ts +9 -16
- package/dist/index.js +387 -218
- package/dist/index.mjs +386 -213
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,14 +22,290 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
init: () => init,
|
|
24
24
|
onConnected: () => onConnected,
|
|
25
|
-
|
|
26
|
-
process: () => process,
|
|
27
|
-
receiveData: () => receiveData,
|
|
28
|
-
registerStatus: () => registerStatus,
|
|
29
|
-
sendData: () => sendData
|
|
25
|
+
process: () => process
|
|
30
26
|
});
|
|
31
27
|
module.exports = __toCommonJS(src_exports);
|
|
32
28
|
|
|
29
|
+
// src/core/socketClient.ts
|
|
30
|
+
var SocketClient = class {
|
|
31
|
+
constructor(url, handlers) {
|
|
32
|
+
this.socket = null;
|
|
33
|
+
this.url = url;
|
|
34
|
+
this.handlers = handlers;
|
|
35
|
+
}
|
|
36
|
+
connect() {
|
|
37
|
+
this.socket = new WebSocket(this.url);
|
|
38
|
+
this.socket.onopen = () => this.handlers.onOpen();
|
|
39
|
+
this.socket.onmessage = (event) => this.handlers.onMessage(JSON.parse(event.data));
|
|
40
|
+
this.socket.onclose = () => this.handlers.onClose();
|
|
41
|
+
this.socket.onerror = () => this.handlers.onError();
|
|
42
|
+
}
|
|
43
|
+
send(payload) {
|
|
44
|
+
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
|
|
45
|
+
throw new Error("Socket not ready");
|
|
46
|
+
}
|
|
47
|
+
this.socket.send(JSON.stringify(payload));
|
|
48
|
+
}
|
|
49
|
+
close() {
|
|
50
|
+
var _a;
|
|
51
|
+
(_a = this.socket) == null ? void 0 : _a.close();
|
|
52
|
+
this.socket = null;
|
|
53
|
+
}
|
|
54
|
+
isOpen() {
|
|
55
|
+
var _a;
|
|
56
|
+
return ((_a = this.socket) == null ? void 0 : _a.readyState) === WebSocket.OPEN;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// src/utils/generateIds.ts
|
|
61
|
+
function generateTimestamp() {
|
|
62
|
+
const now = /* @__PURE__ */ new Date();
|
|
63
|
+
return now.getFullYear().toString() + String(now.getMonth() + 1).padStart(2, "0") + String(now.getDate()).padStart(2, "0") + String(now.getHours()).padStart(2, "0") + String(now.getMinutes()).padStart(2, "0") + String(now.getSeconds()).padStart(2, "0") + String(now.getMilliseconds()).padStart(3, "0") + Math.floor(Math.random() * 1e3).toString().padStart(3, "0");
|
|
64
|
+
}
|
|
65
|
+
function generateJobId(app_id, user_id, dataId) {
|
|
66
|
+
const timestamp = generateTimestamp();
|
|
67
|
+
const jobId = `${app_id}_${user_id}_${dataId}_${timestamp}`;
|
|
68
|
+
return jobId;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// src/core/eventBus.ts
|
|
72
|
+
var messageListeners = /* @__PURE__ */ new Set();
|
|
73
|
+
var connectionListeners = /* @__PURE__ */ new Set();
|
|
74
|
+
function onMessage(cb) {
|
|
75
|
+
messageListeners.add(cb);
|
|
76
|
+
return () => messageListeners.delete(cb);
|
|
77
|
+
}
|
|
78
|
+
function emitMessage(data) {
|
|
79
|
+
messageListeners.forEach((cb) => {
|
|
80
|
+
try {
|
|
81
|
+
cb(data);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
console.error("Message listener error:", err);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function onConnected(cb) {
|
|
88
|
+
connectionListeners.add(cb);
|
|
89
|
+
return () => connectionListeners.delete(cb);
|
|
90
|
+
}
|
|
91
|
+
function emitConnection(context2) {
|
|
92
|
+
connectionListeners.forEach((cb) => {
|
|
93
|
+
try {
|
|
94
|
+
cb(context2);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.log("Connection listener error:", err);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/utils/encryption.ts
|
|
102
|
+
var SECRET = "your-strong-secret";
|
|
103
|
+
function strToBuf(str) {
|
|
104
|
+
return new TextEncoder().encode(str);
|
|
105
|
+
}
|
|
106
|
+
function bufToStr(buf) {
|
|
107
|
+
return new TextDecoder().decode(buf);
|
|
108
|
+
}
|
|
109
|
+
function bufToBase64(buf) {
|
|
110
|
+
return btoa(String.fromCharCode(...new Uint8Array(buf)));
|
|
111
|
+
}
|
|
112
|
+
function base64ToBuf(base64) {
|
|
113
|
+
const binary = atob(base64);
|
|
114
|
+
const bytes = new Uint8Array(binary.length);
|
|
115
|
+
for (let i = 0; i < binary.length; i++) {
|
|
116
|
+
bytes[i] = binary.charCodeAt(i);
|
|
117
|
+
}
|
|
118
|
+
return bytes.buffer;
|
|
119
|
+
}
|
|
120
|
+
async function getKey() {
|
|
121
|
+
const keyMaterial = await crypto.subtle.importKey(
|
|
122
|
+
"raw",
|
|
123
|
+
strToBuf(SECRET),
|
|
124
|
+
{ name: "PBKDF2" },
|
|
125
|
+
false,
|
|
126
|
+
["deriveKey"]
|
|
127
|
+
);
|
|
128
|
+
return crypto.subtle.deriveKey(
|
|
129
|
+
{
|
|
130
|
+
name: "PBKDF2",
|
|
131
|
+
salt: strToBuf("satya_salt"),
|
|
132
|
+
iterations: 1e5,
|
|
133
|
+
hash: "SHA-256"
|
|
134
|
+
},
|
|
135
|
+
keyMaterial,
|
|
136
|
+
{ name: "AES-GCM", length: 256 },
|
|
137
|
+
false,
|
|
138
|
+
["encrypt", "decrypt"]
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
async function encrypt(text) {
|
|
142
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
143
|
+
const key = await getKey();
|
|
144
|
+
const encrypted = await crypto.subtle.encrypt(
|
|
145
|
+
{ name: "AES-GCM", iv },
|
|
146
|
+
key,
|
|
147
|
+
strToBuf(text)
|
|
148
|
+
);
|
|
149
|
+
const combined = new Uint8Array(iv.length + encrypted.byteLength);
|
|
150
|
+
combined.set(iv);
|
|
151
|
+
combined.set(new Uint8Array(encrypted), iv.length);
|
|
152
|
+
return bufToBase64(combined.buffer);
|
|
153
|
+
}
|
|
154
|
+
async function decrypt(cipherText) {
|
|
155
|
+
const combined = new Uint8Array(base64ToBuf(cipherText));
|
|
156
|
+
const iv = combined.slice(0, 12);
|
|
157
|
+
const data = combined.slice(12);
|
|
158
|
+
const key = await getKey();
|
|
159
|
+
const decrypted = await crypto.subtle.decrypt(
|
|
160
|
+
{ name: "AES-GCM", iv },
|
|
161
|
+
key,
|
|
162
|
+
data
|
|
163
|
+
);
|
|
164
|
+
return bufToStr(decrypted);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/utils/storage.ts
|
|
168
|
+
function getCookie(name) {
|
|
169
|
+
var _a;
|
|
170
|
+
const value = `; ${document.cookie}`;
|
|
171
|
+
const parts = value.split(`; ${name}=`);
|
|
172
|
+
if (parts.length === 2)
|
|
173
|
+
return (_a = parts.pop()) == null ? void 0 : _a.split(";").shift();
|
|
174
|
+
}
|
|
175
|
+
function setCookie(name, value, days = 7) {
|
|
176
|
+
const expires = new Date(Date.now() + days * 864e5).toUTCString();
|
|
177
|
+
document.cookie = `${name}=${value}; expires=${expires}; path=/; Secure; SameSite=Lax`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/utils/manageSessions.ts
|
|
181
|
+
async function getSessionId() {
|
|
182
|
+
const raw = getCookie("satya_session");
|
|
183
|
+
if (!raw)
|
|
184
|
+
return "";
|
|
185
|
+
try {
|
|
186
|
+
return await decrypt(raw);
|
|
187
|
+
} catch {
|
|
188
|
+
return "";
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function setSessionId(sessionId) {
|
|
192
|
+
const encrypted = await encrypt(sessionId);
|
|
193
|
+
setCookie("satya_session", encrypted);
|
|
194
|
+
}
|
|
195
|
+
function clearSession() {
|
|
196
|
+
setCookie("satya_session", "", -1);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/core/connectionManager.ts
|
|
200
|
+
var isDev = false;
|
|
201
|
+
var context = null;
|
|
202
|
+
var socketClient = null;
|
|
203
|
+
var isConnecting = false;
|
|
204
|
+
var isConnected = false;
|
|
205
|
+
var reconnectTimer = null;
|
|
206
|
+
async function resolveWsUrl() {
|
|
207
|
+
if (isDev) {
|
|
208
|
+
const wsUrl2 = "ws://localhost:1000";
|
|
209
|
+
return wsUrl2;
|
|
210
|
+
}
|
|
211
|
+
const res = await fetch(
|
|
212
|
+
"https://dhirajkarangale.github.io/SatyaMark/ws.json",
|
|
213
|
+
{ cache: "no-store" }
|
|
214
|
+
);
|
|
215
|
+
const data = await res.json();
|
|
216
|
+
const wsUrl = data.wsUrl;
|
|
217
|
+
if (!wsUrl)
|
|
218
|
+
throw new Error("WebSocket URL resolution failed");
|
|
219
|
+
return wsUrl;
|
|
220
|
+
}
|
|
221
|
+
async function init(newContext) {
|
|
222
|
+
if (!(newContext == null ? void 0 : newContext.app_id) || !(newContext == null ? void 0 : newContext.user_id)) {
|
|
223
|
+
throw new Error("init() requires valid app_id and user_id");
|
|
224
|
+
}
|
|
225
|
+
if (isConnecting || isConnected)
|
|
226
|
+
return;
|
|
227
|
+
context = newContext;
|
|
228
|
+
await connect();
|
|
229
|
+
}
|
|
230
|
+
async function connect() {
|
|
231
|
+
if (!context)
|
|
232
|
+
return;
|
|
233
|
+
if (isConnecting || isConnected)
|
|
234
|
+
return;
|
|
235
|
+
isConnecting = true;
|
|
236
|
+
const url = await resolveWsUrl();
|
|
237
|
+
socketClient = new SocketClient(url, {
|
|
238
|
+
onOpen: async () => {
|
|
239
|
+
const sessionId = await getSessionId();
|
|
240
|
+
socketClient == null ? void 0 : socketClient.send({
|
|
241
|
+
type: "handshake",
|
|
242
|
+
clientId: context == null ? void 0 : context.user_id,
|
|
243
|
+
app_id: context == null ? void 0 : context.app_id,
|
|
244
|
+
sessionId
|
|
245
|
+
});
|
|
246
|
+
isConnected = true;
|
|
247
|
+
isConnecting = false;
|
|
248
|
+
emitConnection(context);
|
|
249
|
+
},
|
|
250
|
+
onMessage: async (data) => {
|
|
251
|
+
if (data.type === "session_created" && data.sessionId) {
|
|
252
|
+
await setSessionId(data.sessionId);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (data.type === "RateLimiter") {
|
|
256
|
+
if (data.msg === "Invalid session") {
|
|
257
|
+
clearSession();
|
|
258
|
+
socketClient == null ? void 0 : socketClient.close();
|
|
259
|
+
}
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (data.clientId === (context == null ? void 0 : context.user_id)) {
|
|
263
|
+
emitMessage(data);
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
onClose: () => {
|
|
267
|
+
if (!isConnected && !isConnecting)
|
|
268
|
+
return;
|
|
269
|
+
isConnected = false;
|
|
270
|
+
isConnecting = false;
|
|
271
|
+
emitConnection(null);
|
|
272
|
+
scheduleReconnect();
|
|
273
|
+
},
|
|
274
|
+
onError: () => {
|
|
275
|
+
socketClient == null ? void 0 : socketClient.close();
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
socketClient.connect();
|
|
279
|
+
}
|
|
280
|
+
function scheduleReconnect() {
|
|
281
|
+
if (reconnectTimer || !context)
|
|
282
|
+
return;
|
|
283
|
+
reconnectTimer = setTimeout(() => {
|
|
284
|
+
reconnectTimer = null;
|
|
285
|
+
connect();
|
|
286
|
+
}, 2e3);
|
|
287
|
+
}
|
|
288
|
+
async function sendJob(text, imageUrl, dataId) {
|
|
289
|
+
if (!context)
|
|
290
|
+
throw new Error("Satyamark is not ready Call init() first");
|
|
291
|
+
if (!text && !imageUrl) {
|
|
292
|
+
throw new Error("Provide text or imageUrl");
|
|
293
|
+
}
|
|
294
|
+
if (text && text.trim().length < 3) {
|
|
295
|
+
throw new Error("Text must be at least 3 characters");
|
|
296
|
+
}
|
|
297
|
+
const jobId = generateJobId(context.app_id, context.user_id, dataId);
|
|
298
|
+
const sessionId = await getSessionId();
|
|
299
|
+
socketClient == null ? void 0 : socketClient.send({
|
|
300
|
+
clientId: context.user_id,
|
|
301
|
+
sessionId,
|
|
302
|
+
jobId,
|
|
303
|
+
text,
|
|
304
|
+
image_url: imageUrl
|
|
305
|
+
});
|
|
306
|
+
return jobId;
|
|
307
|
+
}
|
|
308
|
+
|
|
33
309
|
// src/utils/iconRegistry.ts
|
|
34
310
|
var ICON_URLS = {
|
|
35
311
|
correct: "https://res.cloudinary.com/dfamljkyo/image/upload/v1768325442/correct_gjiadc.png",
|
|
@@ -61,218 +337,21 @@ function loadIcon(key) {
|
|
|
61
337
|
iconLoadMap.set(key, promise);
|
|
62
338
|
return promise;
|
|
63
339
|
}
|
|
64
|
-
function preloadIcons() {
|
|
65
|
-
const run = () => {
|
|
66
|
-
Object.keys(ICON_URLS).forEach(loadIcon);
|
|
67
|
-
};
|
|
68
|
-
if ("requestIdleCallback" in window) {
|
|
69
|
-
window.requestIdleCallback(run);
|
|
70
|
-
} else {
|
|
71
|
-
setTimeout(run, 0);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
340
|
function ensureIconLoaded(key) {
|
|
75
341
|
return loadIcon(key).catch(() => {
|
|
76
342
|
});
|
|
77
343
|
}
|
|
78
344
|
|
|
79
|
-
// src/
|
|
80
|
-
var wsUrl = null;
|
|
81
|
-
var socket = null;
|
|
82
|
-
var storedConnectionData = null;
|
|
83
|
-
var listeners = [];
|
|
84
|
-
var onConnectedCb = null;
|
|
85
|
-
async function getWsUrl() {
|
|
86
|
-
if (wsUrl)
|
|
87
|
-
return wsUrl;
|
|
88
|
-
const res = await fetch(
|
|
89
|
-
"https://dhirajkarangale.github.io/SatyaMark/ws.json",
|
|
90
|
-
{ cache: "no-store" }
|
|
91
|
-
);
|
|
92
|
-
const data = await res.json();
|
|
93
|
-
wsUrl = data.wsUrl;
|
|
94
|
-
return wsUrl;
|
|
95
|
-
}
|
|
96
|
-
function onReceive(cb) {
|
|
97
|
-
listeners.push(cb);
|
|
98
|
-
return () => {
|
|
99
|
-
const idx = listeners.indexOf(cb);
|
|
100
|
-
if (idx !== -1)
|
|
101
|
-
listeners.splice(idx, 1);
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
function onConnected(cb) {
|
|
105
|
-
onConnectedCb = cb;
|
|
106
|
-
}
|
|
107
|
-
async function init(connectionData, options) {
|
|
108
|
-
var _a;
|
|
109
|
-
preloadIcons();
|
|
110
|
-
if (socket && socket.readyState == WebSocket.OPEN && storedConnectionData == connectionData) {
|
|
111
|
-
console.log("Already Connected: ", connectionData);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
const url = await getWsUrl();
|
|
115
|
-
if (url) {
|
|
116
|
-
socket = new WebSocket(url);
|
|
117
|
-
} else {
|
|
118
|
-
console.error("WebSocket endpoint resolution failed. Unable to establish connection.");
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
onConnectedCb = (_a = options == null ? void 0 : options.onConnected) != null ? _a : onConnectedCb;
|
|
122
|
-
socket.onopen = () => {
|
|
123
|
-
console.log("Connected to server: ", connectionData.user_id);
|
|
124
|
-
safeSend({
|
|
125
|
-
type: "handshake",
|
|
126
|
-
clientId: connectionData.user_id,
|
|
127
|
-
appId: connectionData.app_id
|
|
128
|
-
});
|
|
129
|
-
onConnectedCb == null ? void 0 : onConnectedCb(connectionData);
|
|
130
|
-
};
|
|
131
|
-
socket.onmessage = (event) => {
|
|
132
|
-
receiveData(JSON.parse(event.data));
|
|
133
|
-
};
|
|
134
|
-
socket.onclose = () => {
|
|
135
|
-
console.log("Server connection closed");
|
|
136
|
-
};
|
|
137
|
-
storedConnectionData = connectionData;
|
|
138
|
-
}
|
|
139
|
-
function isSocketOpen() {
|
|
140
|
-
return socket && socket.readyState === WebSocket.OPEN;
|
|
141
|
-
}
|
|
142
|
-
function assert(condition, message) {
|
|
143
|
-
if (!condition)
|
|
144
|
-
throw new Error(message);
|
|
145
|
-
}
|
|
146
|
-
function safeSend(msg) {
|
|
147
|
-
if (!storedConnectionData) {
|
|
148
|
-
console.warn("No connectionData found. Call connect() first.");
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
if (!socket || socket.readyState !== WebSocket.OPEN) {
|
|
152
|
-
console.warn("Socket not ready");
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
socket.send(JSON.stringify(msg));
|
|
156
|
-
}
|
|
157
|
-
function uniqueTimestamp() {
|
|
158
|
-
const now = /* @__PURE__ */ new Date();
|
|
159
|
-
const yyyy = now.getFullYear();
|
|
160
|
-
const MM = String(now.getMonth() + 1).padStart(2, "0");
|
|
161
|
-
const dd = String(now.getDate()).padStart(2, "0");
|
|
162
|
-
const hh = String(now.getHours()).padStart(2, "0");
|
|
163
|
-
const mm = String(now.getMinutes()).padStart(2, "0");
|
|
164
|
-
const ss = String(now.getSeconds()).padStart(2, "0");
|
|
165
|
-
const ms = String(now.getMilliseconds()).padStart(3, "0");
|
|
166
|
-
const micro = String(Math.floor(Math.random() * 1e3)).padStart(3, "0");
|
|
167
|
-
return `${yyyy}${MM}${dd}${hh}${mm}${ss}${ms}${micro}`;
|
|
168
|
-
}
|
|
169
|
-
function sendData(text, image_url, dataId) {
|
|
170
|
-
if (!storedConnectionData) {
|
|
171
|
-
console.log("No connectionData found. Call connect() first.");
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
if (!socket || socket.readyState !== WebSocket.OPEN) {
|
|
175
|
-
console.log("Socket not ready");
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
assert(storedConnectionData, "Call init() before sendData()");
|
|
179
|
-
assert(isSocketOpen(), "WebSocket is not ready");
|
|
180
|
-
assert(dataId, "dataId is required");
|
|
181
|
-
assert(text || image_url, "Provide text or image_url");
|
|
182
|
-
if (text)
|
|
183
|
-
assert(text.trim().length >= 3, "Text must be at least 3 characters");
|
|
184
|
-
const { app_id, user_id } = storedConnectionData;
|
|
185
|
-
const timestamp = uniqueTimestamp();
|
|
186
|
-
const jobId = `${app_id}_${user_id}_${dataId}_${timestamp}`;
|
|
187
|
-
const data = {
|
|
188
|
-
clientId: user_id,
|
|
189
|
-
jobId,
|
|
190
|
-
text,
|
|
191
|
-
image_url
|
|
192
|
-
};
|
|
193
|
-
socket.send(JSON.stringify(data));
|
|
194
|
-
return jobId;
|
|
195
|
-
}
|
|
196
|
-
function receiveData(data) {
|
|
197
|
-
if (!storedConnectionData || data.clientId != storedConnectionData.user_id)
|
|
198
|
-
return;
|
|
199
|
-
for (const cb of Array.from(listeners)) {
|
|
200
|
-
try {
|
|
201
|
-
cb(data);
|
|
202
|
-
} catch (err) {
|
|
203
|
-
console.log("listener error", err);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// src/satyamark_process.ts
|
|
209
|
-
var mergeText = (texts) => texts.join(", ");
|
|
210
|
-
var isValidImageUrl = (url) => {
|
|
211
|
-
return new Promise((resolve) => {
|
|
212
|
-
const img = new Image();
|
|
213
|
-
img.onload = () => resolve(true);
|
|
214
|
-
img.onerror = () => resolve(false);
|
|
215
|
-
img.src = url;
|
|
216
|
-
});
|
|
217
|
-
};
|
|
218
|
-
var getFirstValidImage = async (urls) => {
|
|
219
|
-
for (const url of urls) {
|
|
220
|
-
if (await isValidImageUrl(url))
|
|
221
|
-
return url;
|
|
222
|
-
}
|
|
223
|
-
return null;
|
|
224
|
-
};
|
|
225
|
-
var extractFromDiv = (root) => {
|
|
226
|
-
var _a;
|
|
227
|
-
const images = Array.from(root.querySelectorAll("img")).map((img) => img.src);
|
|
228
|
-
const text = [];
|
|
229
|
-
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
230
|
-
let node;
|
|
231
|
-
while (node = walker.nextNode()) {
|
|
232
|
-
const trimmed = (_a = node.textContent) == null ? void 0 : _a.trim();
|
|
233
|
-
if (trimmed)
|
|
234
|
-
text.push(trimmed);
|
|
235
|
-
}
|
|
236
|
-
return { text, images };
|
|
237
|
-
};
|
|
238
|
-
async function process(divRef, dataId) {
|
|
239
|
-
if (!divRef) {
|
|
240
|
-
throw new Error("Invalid root element");
|
|
241
|
-
}
|
|
242
|
-
if (!dataId) {
|
|
243
|
-
throw new Error("dataId is required");
|
|
244
|
-
}
|
|
245
|
-
const { text, images } = extractFromDiv(divRef);
|
|
246
|
-
const mergedText = mergeText(text);
|
|
247
|
-
const validImage = await getFirstValidImage(images);
|
|
248
|
-
if (!mergedText && !validImage) {
|
|
249
|
-
throw new Error("No valid text or image found in the element");
|
|
250
|
-
}
|
|
251
|
-
if (mergedText && mergedText.length < 3) {
|
|
252
|
-
throw new Error("Extracted text is too short");
|
|
253
|
-
}
|
|
254
|
-
const jobId = sendData(mergedText, validImage != null ? validImage : "", dataId);
|
|
255
|
-
return jobId;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// src/satyamark_status_controller.ts
|
|
259
|
-
var jobMap = {};
|
|
345
|
+
// src/core/status_controller.ts
|
|
260
346
|
var DEFAULT_ICON_SIZE = 20;
|
|
261
347
|
var satyamark_url = "https://satyamark.vercel.app/chat";
|
|
262
|
-
function
|
|
348
|
+
function updateIcon(containerRef, data) {
|
|
263
349
|
var _a;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
function updateIcon(jobId, rawMark, data) {
|
|
271
|
-
const entry = jobMap[jobId];
|
|
272
|
-
if (!entry)
|
|
273
|
-
return;
|
|
274
|
-
const { root, iconSize } = entry;
|
|
275
|
-
const mark = rawMark in ICON_URLS ? rawMark : "pending";
|
|
350
|
+
const root = containerRef;
|
|
351
|
+
const iconSize = DEFAULT_ICON_SIZE;
|
|
352
|
+
let mark = "pending";
|
|
353
|
+
if (data && data.mark)
|
|
354
|
+
mark = (_a = data.mark) == null ? void 0 : _a.toLowerCase();
|
|
276
355
|
ensureIconLoaded(mark);
|
|
277
356
|
const container = root.querySelector("[data-satyamark-status-container]");
|
|
278
357
|
if (!container)
|
|
@@ -328,19 +407,109 @@ function updateIcon(jobId, rawMark, data) {
|
|
|
328
407
|
icon.onclick = null;
|
|
329
408
|
}
|
|
330
409
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
410
|
+
|
|
411
|
+
// src/utils/process_data.ts
|
|
412
|
+
var mergeText = (texts) => texts.join(" |#| ");
|
|
413
|
+
var isValidImageUrl = (url) => {
|
|
414
|
+
return new Promise((resolve) => {
|
|
415
|
+
const img = new Image();
|
|
416
|
+
img.onload = () => resolve(true);
|
|
417
|
+
img.onerror = () => resolve(false);
|
|
418
|
+
img.src = url;
|
|
419
|
+
});
|
|
420
|
+
};
|
|
421
|
+
var getFirstValidImage = async (urls) => {
|
|
422
|
+
for (const url of urls) {
|
|
423
|
+
if (await isValidImageUrl(url))
|
|
424
|
+
return url;
|
|
425
|
+
}
|
|
426
|
+
return null;
|
|
427
|
+
};
|
|
428
|
+
var extractFromDiv = (root) => {
|
|
429
|
+
var _a;
|
|
430
|
+
const images = Array.from(root.querySelectorAll("img")).map((img) => img.src);
|
|
431
|
+
const text = [];
|
|
432
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
433
|
+
let node;
|
|
434
|
+
while (node = walker.nextNode()) {
|
|
435
|
+
const trimmed = (_a = node.textContent) == null ? void 0 : _a.trim();
|
|
436
|
+
if (trimmed)
|
|
437
|
+
text.push(trimmed);
|
|
438
|
+
}
|
|
439
|
+
return { text, images };
|
|
440
|
+
};
|
|
441
|
+
async function process_data(divRef, dataId) {
|
|
442
|
+
if (!divRef) {
|
|
443
|
+
throw new Error("Invalid root element");
|
|
444
|
+
}
|
|
445
|
+
if (!dataId) {
|
|
446
|
+
throw new Error("dataId is required");
|
|
447
|
+
}
|
|
448
|
+
const { text, images } = extractFromDiv(divRef);
|
|
449
|
+
const mergedText = mergeText(text);
|
|
450
|
+
const validImage = await getFirstValidImage(images);
|
|
451
|
+
if (!mergedText && !validImage) {
|
|
452
|
+
throw new Error("No valid text or image found in the element");
|
|
453
|
+
}
|
|
454
|
+
if (mergedText && mergedText.length < 3) {
|
|
455
|
+
throw new Error("Extracted text is too short");
|
|
456
|
+
}
|
|
457
|
+
const image_url = validImage ? validImage : "";
|
|
458
|
+
return { text: mergedText, image_url };
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// src/core/process.ts
|
|
462
|
+
var isConnected2 = false;
|
|
463
|
+
var isSendingJobs = false;
|
|
464
|
+
var jobMap = /* @__PURE__ */ new Map();
|
|
465
|
+
var process_queue = [];
|
|
466
|
+
function process(containerRef, dataId) {
|
|
467
|
+
process_queue.push({ containerRef, dataId });
|
|
468
|
+
void sendJobs();
|
|
469
|
+
}
|
|
470
|
+
async function sendJobs() {
|
|
471
|
+
if (isSendingJobs || !isConnected2)
|
|
472
|
+
return;
|
|
473
|
+
isSendingJobs = true;
|
|
474
|
+
while (process_queue.length > 0) {
|
|
475
|
+
const item = process_queue[0];
|
|
476
|
+
if (!item)
|
|
477
|
+
break;
|
|
478
|
+
const { containerRef, dataId } = item;
|
|
479
|
+
try {
|
|
480
|
+
const { text, image_url } = await process_data(containerRef, dataId);
|
|
481
|
+
const jobId = await sendJob(text, image_url, dataId);
|
|
482
|
+
jobMap.set(jobId, containerRef);
|
|
483
|
+
process_queue.shift();
|
|
484
|
+
updateIcon(containerRef, null);
|
|
485
|
+
} catch (error) {
|
|
486
|
+
isSendingJobs = false;
|
|
487
|
+
setTimeout(() => {
|
|
488
|
+
void sendJobs();
|
|
489
|
+
}, 1e3);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
isSendingJobs = false;
|
|
494
|
+
}
|
|
495
|
+
onMessage((data) => {
|
|
496
|
+
if (!data || !data.jobId)
|
|
334
497
|
return;
|
|
335
|
-
|
|
498
|
+
const containerRef = jobMap.get(data.jobId);
|
|
499
|
+
if (!containerRef)
|
|
500
|
+
return;
|
|
501
|
+
jobMap.delete(data.jobId);
|
|
502
|
+
updateIcon(containerRef, data);
|
|
503
|
+
});
|
|
504
|
+
onConnected((data) => {
|
|
505
|
+
isConnected2 = !!data;
|
|
506
|
+
if (isConnected2) {
|
|
507
|
+
void sendJobs();
|
|
508
|
+
}
|
|
336
509
|
});
|
|
337
510
|
// Annotate the CommonJS export names for ESM import in node:
|
|
338
511
|
0 && (module.exports = {
|
|
339
512
|
init,
|
|
340
513
|
onConnected,
|
|
341
|
-
|
|
342
|
-
process,
|
|
343
|
-
receiveData,
|
|
344
|
-
registerStatus,
|
|
345
|
-
sendData
|
|
514
|
+
process
|
|
346
515
|
});
|