openzca 0.1.15 → 0.1.16
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 +3 -0
- package/dist/cli.js +104 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -206,7 +206,10 @@ It also includes stable routing fields for downstream tools:
|
|
|
206
206
|
|
|
207
207
|
- `threadId`, `targetId`, `conversationId`
|
|
208
208
|
- `senderId`, `toId`, `chatType`, `msgType`, `timestamp`
|
|
209
|
+
- `mentions` (normalized mention entities: `uid`, `pos`, `len`, `type`, optional `text`)
|
|
210
|
+
- `mentionIds` (flattened mention user IDs)
|
|
209
211
|
- `metadata.threadId`, `metadata.targetId`, `metadata.senderId`, `metadata.toId`
|
|
212
|
+
- `metadata.mentions`, `metadata.mentionIds`, `metadata.mentionCount`
|
|
210
213
|
- `quote` and `metadata.quote` when the inbound message is a reply to a previous message
|
|
211
214
|
- Includes parsed `quote.attach` and extracted `quote.mediaUrls` when attachment URLs are present.
|
|
212
215
|
- `quoteMediaPath`, `quoteMediaPaths`, `quoteMediaUrl`, `quoteMediaUrls`, `quoteMediaType`, `quoteMediaTypes`
|
package/dist/cli.js
CHANGED
|
@@ -1459,6 +1459,98 @@ function buildReplyMediaAttachedText(params) {
|
|
|
1459
1459
|
}
|
|
1460
1460
|
return lines.join("\n");
|
|
1461
1461
|
}
|
|
1462
|
+
function parseOptionalInt(value) {
|
|
1463
|
+
const numeric = typeof value === "number" ? value : typeof value === "string" ? Number(value) : Number.NaN;
|
|
1464
|
+
if (!Number.isFinite(numeric)) return void 0;
|
|
1465
|
+
return Math.trunc(numeric);
|
|
1466
|
+
}
|
|
1467
|
+
function buildInboundMention(record, rawText) {
|
|
1468
|
+
const uid = getStringCandidate(record, ["uid", "userId", "user_id", "id"]);
|
|
1469
|
+
if (!uid) return null;
|
|
1470
|
+
const pos = parseOptionalInt(record.pos ?? record.offset ?? record.start ?? record.index);
|
|
1471
|
+
const len = parseOptionalInt(record.len ?? record.length);
|
|
1472
|
+
const type = parseOptionalInt(record.type ?? record.kind);
|
|
1473
|
+
let text = getStringCandidate(record, ["text", "label", "name"]) || (typeof pos === "number" && typeof len === "number" && len > 0 && pos >= 0 && pos < rawText.length ? rawText.slice(pos, Math.min(rawText.length, pos + len)) : "");
|
|
1474
|
+
if (!text.trim()) {
|
|
1475
|
+
text = "";
|
|
1476
|
+
}
|
|
1477
|
+
return {
|
|
1478
|
+
uid,
|
|
1479
|
+
...typeof pos === "number" ? { pos } : {},
|
|
1480
|
+
...typeof len === "number" ? { len } : {},
|
|
1481
|
+
...typeof type === "number" ? { type } : {},
|
|
1482
|
+
...text ? { text } : {}
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
function collectInboundMentions(value, sink, rawText, depth = 0) {
|
|
1486
|
+
if (depth > 6 || sink.size >= 64 || value === null || value === void 0) {
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
if (typeof value === "string") {
|
|
1490
|
+
if (!looksLikeStructuredJsonString(value)) return;
|
|
1491
|
+
try {
|
|
1492
|
+
const parsed = JSON.parse(value);
|
|
1493
|
+
collectInboundMentions(parsed, sink, rawText, depth + 1);
|
|
1494
|
+
} catch {
|
|
1495
|
+
}
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
if (Array.isArray(value)) {
|
|
1499
|
+
for (const item of value) {
|
|
1500
|
+
const mention = asObject(item) ? buildInboundMention(item, rawText) : null;
|
|
1501
|
+
if (mention) {
|
|
1502
|
+
const key = `${mention.uid}|${mention.pos ?? ""}|${mention.len ?? ""}|${mention.type ?? ""}`;
|
|
1503
|
+
sink.set(key, mention);
|
|
1504
|
+
continue;
|
|
1505
|
+
}
|
|
1506
|
+
collectInboundMentions(item, sink, rawText, depth + 1);
|
|
1507
|
+
if (sink.size >= 64) return;
|
|
1508
|
+
}
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
const record = asObject(value);
|
|
1512
|
+
if (!record) return;
|
|
1513
|
+
const direct = buildInboundMention(record, rawText);
|
|
1514
|
+
if (direct) {
|
|
1515
|
+
const key = `${direct.uid}|${direct.pos ?? ""}|${direct.len ?? ""}|${direct.type ?? ""}`;
|
|
1516
|
+
sink.set(key, direct);
|
|
1517
|
+
}
|
|
1518
|
+
const mentionKeys = [
|
|
1519
|
+
"mentions",
|
|
1520
|
+
"mentionInfo",
|
|
1521
|
+
"mention_info",
|
|
1522
|
+
"mentionList",
|
|
1523
|
+
"mention_list",
|
|
1524
|
+
"mention"
|
|
1525
|
+
];
|
|
1526
|
+
for (const key of mentionKeys) {
|
|
1527
|
+
if (!(key in record)) continue;
|
|
1528
|
+
collectInboundMentions(record[key], sink, rawText, depth + 1);
|
|
1529
|
+
if (sink.size >= 64) return;
|
|
1530
|
+
}
|
|
1531
|
+
for (const nested of Object.values(record)) {
|
|
1532
|
+
collectInboundMentions(nested, sink, rawText, depth + 1);
|
|
1533
|
+
if (sink.size >= 64) return;
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
function extractInboundMentions(params) {
|
|
1537
|
+
const sink = /* @__PURE__ */ new Map();
|
|
1538
|
+
const candidates = [
|
|
1539
|
+
params.messageData.mentions,
|
|
1540
|
+
params.messageData.mentionInfo,
|
|
1541
|
+
params.messageData.mention_info,
|
|
1542
|
+
params.messageData.mentionList,
|
|
1543
|
+
params.messageData.mention_list,
|
|
1544
|
+
params.messageData.mention,
|
|
1545
|
+
params.messageData.content,
|
|
1546
|
+
params.parsedContent
|
|
1547
|
+
];
|
|
1548
|
+
for (const candidate of candidates) {
|
|
1549
|
+
collectInboundMentions(candidate, sink, params.rawText);
|
|
1550
|
+
if (sink.size >= 64) break;
|
|
1551
|
+
}
|
|
1552
|
+
return [...sink.values()];
|
|
1553
|
+
}
|
|
1462
1554
|
function normalizeFriendLookupRows(value) {
|
|
1463
1555
|
const queue = [value];
|
|
1464
1556
|
const rows = [];
|
|
@@ -2791,6 +2883,12 @@ ${replyContextText}` : replyContextText;
|
|
|
2791
2883
|
const senderNameForMetadata = message.type === ThreadType.Group ? senderDisplayName : void 0;
|
|
2792
2884
|
const toId = getStringCandidate(messageData, ["idTo"]) || void 0;
|
|
2793
2885
|
const threadName = typeof messageData.threadName === "string" ? messageData.threadName : typeof messageData.tName === "string" ? messageData.tName : void 0;
|
|
2886
|
+
const mentions = extractInboundMentions({
|
|
2887
|
+
messageData,
|
|
2888
|
+
parsedContent,
|
|
2889
|
+
rawText
|
|
2890
|
+
});
|
|
2891
|
+
const mentionIds = mentions.map((item) => item.uid);
|
|
2794
2892
|
const timestamp = toEpochSeconds(message.data.ts);
|
|
2795
2893
|
const payload = {
|
|
2796
2894
|
threadId: message.threadId,
|
|
@@ -2816,6 +2914,8 @@ ${replyContextText}` : replyContextText;
|
|
|
2816
2914
|
mediaType,
|
|
2817
2915
|
mediaTypes: mediaTypes.length > 0 ? mediaTypes : void 0,
|
|
2818
2916
|
mediaKind: mediaKind ?? void 0,
|
|
2917
|
+
mentions: mentions.length > 0 ? mentions : void 0,
|
|
2918
|
+
mentionIds: mentionIds.length > 0 ? mentionIds : void 0,
|
|
2819
2919
|
metadata: {
|
|
2820
2920
|
isGroup: message.type === ThreadType.Group,
|
|
2821
2921
|
chatType,
|
|
@@ -2842,7 +2942,10 @@ ${replyContextText}` : replyContextText;
|
|
|
2842
2942
|
mediaUrls: mediaUrls.length > 0 ? mediaUrls : void 0,
|
|
2843
2943
|
mediaType,
|
|
2844
2944
|
mediaTypes: mediaTypes.length > 0 ? mediaTypes : void 0,
|
|
2845
|
-
mediaKind: mediaKind ?? void 0
|
|
2945
|
+
mediaKind: mediaKind ?? void 0,
|
|
2946
|
+
mentions: mentions.length > 0 ? mentions : void 0,
|
|
2947
|
+
mentionIds: mentionIds.length > 0 ? mentionIds : void 0,
|
|
2948
|
+
mentionCount: mentions.length > 0 ? mentions.length : void 0
|
|
2846
2949
|
},
|
|
2847
2950
|
// Backward-compatible convenience fields.
|
|
2848
2951
|
chatType,
|