@kelvdra/baileys 1.0.5-rc.1 → 1.0.5-rc.2
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/Socket/groups.js +193 -23
- package/lib/Socket/hydra.js +477 -0
- package/lib/Socket/messages-send.js +32 -0
- package/lib/Types/GroupMetadata.d.ts +16 -0
- package/lib/WAUSync/Protocols/index.d.ts +1 -0
- package/lib/WAUSync/Protocols/index.js +1 -0
- package/lib/WAUSync/USyncQuery.js +5 -1
- package/package.json +1 -1
package/lib/Socket/groups.js
CHANGED
|
@@ -2,12 +2,195 @@ import { proto } from '../../WAProto/index.js';
|
|
|
2
2
|
import { WAMessageAddressingMode, WAMessageStubType } from '../Types/index.js';
|
|
3
3
|
import { generateMessageIDV2, unixTimestampSeconds } from '../Utils/index.js';
|
|
4
4
|
import { getBinaryNodeChild, getBinaryNodeChildren, getBinaryNodeChildString, isLidUser, isPnUser, jidEncode, jidNormalizedUser } from '../WABinary/index.js';
|
|
5
|
+
import { USyncQuery, USyncUser } from '../WAUSync/index.js';
|
|
5
6
|
import { makeChatsSocket } from './chats.js';
|
|
7
|
+
const pickFirst = (...values) => values.find(v => typeof v === 'string' && v.length > 0);
|
|
8
|
+
const preferPnJid = (primary, pn) => {
|
|
9
|
+
const normalizedPrimary = primary ? jidNormalizedUser(primary) : undefined;
|
|
10
|
+
const normalizedPn = pn ? jidNormalizedUser(pn) : undefined;
|
|
11
|
+
if (isLidUser(normalizedPrimary) && isPnUser(normalizedPn)) return normalizedPn;
|
|
12
|
+
return normalizedPrimary;
|
|
13
|
+
};
|
|
14
|
+
const getParticipantUsername = (attrs = {}) => pickFirst(
|
|
15
|
+
attrs.notify,
|
|
16
|
+
attrs.name,
|
|
17
|
+
attrs.short_name,
|
|
18
|
+
attrs.shortName,
|
|
19
|
+
attrs.pushname,
|
|
20
|
+
attrs.verified_name,
|
|
21
|
+
attrs.verifiedName,
|
|
22
|
+
attrs.vname
|
|
23
|
+
);
|
|
24
|
+
const getJidUser = (jid) => typeof jid === 'string' ? jid.split('@')[0] : undefined;
|
|
25
|
+
const getContactDisplayName = (contact = {}) => pickFirst(
|
|
26
|
+
contact.name,
|
|
27
|
+
contact.notify,
|
|
28
|
+
contact.verifiedName,
|
|
29
|
+
contact.verified_name,
|
|
30
|
+
contact.pushname,
|
|
31
|
+
contact.shortName,
|
|
32
|
+
contact.short_name
|
|
33
|
+
);
|
|
34
|
+
const participantNameFallback = (participant = {}) => getJidUser(participant.phoneNumber || participant.jid || participant.id || participant.lid);
|
|
35
|
+
const buildGroupParticipant = (attrs = {}) => {
|
|
36
|
+
const rawJid = attrs.jid ? jidNormalizedUser(attrs.jid) : undefined;
|
|
37
|
+
const rawLid = attrs.lid ? jidNormalizedUser(attrs.lid) : undefined;
|
|
38
|
+
const rawPn = pickFirst(attrs.phone_number, attrs.phoneNumber, attrs.jid_pn, attrs.participant_pn, attrs.pn);
|
|
39
|
+
const pnJid = rawPn ? jidNormalizedUser(rawPn) : undefined;
|
|
40
|
+
const id = preferPnJid(rawJid, pnJid) || pnJid || rawJid;
|
|
41
|
+
const lid = isLidUser(rawJid) ? rawJid : (isLidUser(rawLid) ? rawLid : undefined);
|
|
42
|
+
const username = getParticipantUsername(attrs);
|
|
43
|
+
const participant = {
|
|
44
|
+
id,
|
|
45
|
+
jid: id,
|
|
46
|
+
phoneNumber: isPnUser(id) ? id : undefined,
|
|
47
|
+
lid,
|
|
48
|
+
username,
|
|
49
|
+
name: username,
|
|
50
|
+
notify: attrs.notify,
|
|
51
|
+
admin: (attrs.type || null)
|
|
52
|
+
};
|
|
53
|
+
const fallback = participantNameFallback(participant);
|
|
54
|
+
return {
|
|
55
|
+
...participant,
|
|
56
|
+
username: username || fallback,
|
|
57
|
+
name: username || fallback,
|
|
58
|
+
notify: attrs.notify || username || fallback,
|
|
59
|
+
displayName: username || fallback
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
const normalizeGroupMetadataJids = (metadata) => ({
|
|
63
|
+
...metadata,
|
|
64
|
+
owner: preferPnJid(metadata.owner, metadata.ownerPn),
|
|
65
|
+
ownerLid: isLidUser(metadata.owner) ? metadata.owner : undefined,
|
|
66
|
+
subjectOwner: preferPnJid(metadata.subjectOwner, metadata.subjectOwnerPn),
|
|
67
|
+
subjectOwnerLid: isLidUser(metadata.subjectOwner) ? metadata.subjectOwner : undefined,
|
|
68
|
+
descOwner: preferPnJid(metadata.descOwner, metadata.descOwnerPn),
|
|
69
|
+
descOwnerLid: isLidUser(metadata.descOwner) ? metadata.descOwner : undefined,
|
|
70
|
+
participants: Array.isArray(metadata.participants)
|
|
71
|
+
? metadata.participants.map(p => ({ ...p, id: preferPnJid(p.id, p.phoneNumber) || p.id, jid: preferPnJid(p.jid || p.id, p.phoneNumber) || p.jid || p.id }))
|
|
72
|
+
: []
|
|
73
|
+
});
|
|
6
74
|
export const makeGroupsSocket = (config) => {
|
|
7
75
|
const sock = makeChatsSocket(config);
|
|
8
|
-
const { authState, ev, query, upsertMessage } = sock;
|
|
76
|
+
const { authState, ev, query, upsertMessage, executeUSyncQuery } = sock;
|
|
9
77
|
const { cachedGroupMetadata } = config;
|
|
78
|
+
// Cache nama kontak dari history/contact/message event.
|
|
79
|
+
// Catatan: metadata grup dari WA sering hanya mengirim jid/lid/phone_number,
|
|
80
|
+
// jadi nama member harus diperkaya dari cache kontak lokal jika tersedia.
|
|
81
|
+
const contactNameCache = new Map();
|
|
82
|
+
const putContactName = (contact = {}) => {
|
|
83
|
+
const ids = [contact.id, contact.jid, contact.phoneNumber, contact.lid]
|
|
84
|
+
.filter(Boolean)
|
|
85
|
+
.map(jid => {
|
|
86
|
+
try { return jidNormalizedUser(jid); } catch { return jid; }
|
|
87
|
+
});
|
|
88
|
+
if (!ids.length) return;
|
|
89
|
+
const displayName = getContactDisplayName(contact);
|
|
90
|
+
const cached = {
|
|
91
|
+
...contact,
|
|
92
|
+
displayName,
|
|
93
|
+
username: displayName || contact.username,
|
|
94
|
+
name: contact.name || displayName,
|
|
95
|
+
notify: contact.notify || displayName
|
|
96
|
+
};
|
|
97
|
+
for (const id of ids) contactNameCache.set(id, cached);
|
|
98
|
+
};
|
|
99
|
+
const getCachedContactName = (participant = {}) => {
|
|
100
|
+
const ids = [participant.id, participant.jid, participant.phoneNumber, participant.lid].filter(Boolean);
|
|
101
|
+
for (const id of ids) {
|
|
102
|
+
const normalized = (() => { try { return jidNormalizedUser(id); } catch { return id; } })();
|
|
103
|
+
const contact = contactNameCache.get(normalized);
|
|
104
|
+
const name = getContactDisplayName(contact);
|
|
105
|
+
if (name) return name;
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
};
|
|
109
|
+
const enrichGroupMetadataNames = (metadata = {}) => ({
|
|
110
|
+
...metadata,
|
|
111
|
+
participants: Array.isArray(metadata.participants)
|
|
112
|
+
? metadata.participants.map(participant => {
|
|
113
|
+
const cachedName = getCachedContactName(participant);
|
|
114
|
+
const displayName = pickFirst(participant.username, participant.name, participant.notify, cachedName, participantNameFallback(participant));
|
|
115
|
+
return {
|
|
116
|
+
...participant,
|
|
117
|
+
username: displayName,
|
|
118
|
+
name: displayName,
|
|
119
|
+
notify: pickFirst(participant.notify, displayName),
|
|
120
|
+
displayName
|
|
121
|
+
};
|
|
122
|
+
})
|
|
123
|
+
: []
|
|
124
|
+
});
|
|
125
|
+
ev.on('contacts.upsert', contacts => contacts?.forEach?.(putContactName));
|
|
126
|
+
ev.on('contacts.update', contacts => contacts?.forEach?.(putContactName));
|
|
127
|
+
ev.on('messaging-history.set', ({ contacts }) => contacts?.forEach?.(putContactName));
|
|
128
|
+
ev.on('messages.upsert', ({ messages }) => {
|
|
129
|
+
for (const msg of messages || []) {
|
|
130
|
+
const remoteJid = msg?.key?.remoteJid;
|
|
131
|
+
const participant = msg?.key?.participant;
|
|
132
|
+
const id = participant || (remoteJid && !remoteJid.endsWith('@g.us') ? remoteJid : undefined);
|
|
133
|
+
if (id && msg?.pushName) putContactName({ id, notify: msg.pushName });
|
|
134
|
+
}
|
|
135
|
+
});
|
|
10
136
|
// ── Built-in group metadata cache ─────────────────────────────────────────
|
|
137
|
+
|
|
138
|
+
const fetchParticipantUsernames = async (participants = []) => {
|
|
139
|
+
// WA username (@username) beda dengan pushName/kontak.
|
|
140
|
+
// groupMetadata biasanya tidak membawa username, jadi kita query USync username.
|
|
141
|
+
// Jika akun belum punya username atau server tidak mengizinkan, hasilnya kosong.
|
|
142
|
+
const entries = participants
|
|
143
|
+
.map(p => ({ participant: p, jid: p.jid || p.id || p.phoneNumber || p.lid }))
|
|
144
|
+
.filter(({ jid }) => typeof jid === 'string' && jid.length > 0);
|
|
145
|
+
const result = new Map();
|
|
146
|
+
const chunkSize = config.groupUsernameQueryChunkSize || 50;
|
|
147
|
+
for (let i = 0; i < entries.length; i += chunkSize) {
|
|
148
|
+
const chunk = entries.slice(i, i + chunkSize);
|
|
149
|
+
try {
|
|
150
|
+
const usync = new USyncQuery().withContext('interactive').withUsernameProtocol();
|
|
151
|
+
for (const { jid } of chunk) {
|
|
152
|
+
const normalized = (() => { try { return jidNormalizedUser(jid); } catch { return jid; } })();
|
|
153
|
+
usync.withUser(new USyncUser().withId(normalized));
|
|
154
|
+
}
|
|
155
|
+
const res = await executeUSyncQuery(usync);
|
|
156
|
+
for (const item of res?.list || []) {
|
|
157
|
+
const username = typeof item.username === 'string' && item.username.length > 0 ? item.username : undefined;
|
|
158
|
+
if (username) result.set(jidNormalizedUser(item.id), username);
|
|
159
|
+
}
|
|
160
|
+
} catch (err) {
|
|
161
|
+
config.logger?.debug?.({ err }, 'failed to fetch group participant usernames');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
};
|
|
166
|
+
const enrichGroupMetadataUsernames = async (metadata = {}) => {
|
|
167
|
+
const normalized = normalizeGroupMetadataJids(metadata);
|
|
168
|
+
const shouldQueryUsername = config.fetchGroupParticipantsUsername !== false;
|
|
169
|
+
const usernameMap = shouldQueryUsername ? await fetchParticipantUsernames(normalized.participants) : new Map();
|
|
170
|
+
const withNames = enrichGroupMetadataNames(normalized);
|
|
171
|
+
return {
|
|
172
|
+
...withNames,
|
|
173
|
+
participants: withNames.participants.map(participant => {
|
|
174
|
+
const keys = [participant.jid, participant.id, participant.phoneNumber, participant.lid].filter(Boolean);
|
|
175
|
+
let waUsername;
|
|
176
|
+
for (const key of keys) {
|
|
177
|
+
const normalizedKey = (() => { try { return jidNormalizedUser(key); } catch { return key; } })();
|
|
178
|
+
waUsername = usernameMap.get(normalizedKey);
|
|
179
|
+
if (waUsername) break;
|
|
180
|
+
}
|
|
181
|
+
return waUsername
|
|
182
|
+
? {
|
|
183
|
+
...participant,
|
|
184
|
+
username: waUsername,
|
|
185
|
+
waUsername,
|
|
186
|
+
displayName: waUsername,
|
|
187
|
+
name: participant.name,
|
|
188
|
+
notify: participant.notify
|
|
189
|
+
}
|
|
190
|
+
: participant;
|
|
191
|
+
})
|
|
192
|
+
};
|
|
193
|
+
};
|
|
11
194
|
const groupMetadataCache = new Map();
|
|
12
195
|
const GROUP_CACHE_TTL = (config.groupCacheTTL || 5) * 60 * 1000; // default 5 menit
|
|
13
196
|
const getCachedGroupMetadata = async (jid) => {
|
|
@@ -97,13 +280,13 @@ export const makeGroupsSocket = (config) => {
|
|
|
97
280
|
const groupMetadata = async (jid) => {
|
|
98
281
|
// Cek cache dulu sebelum hit network
|
|
99
282
|
const cached = await getCachedGroupMetadata(jid);
|
|
100
|
-
if (cached) return cached;
|
|
283
|
+
if (cached) return await enrichGroupMetadataUsernames(cached);
|
|
101
284
|
// Fetch dari WA
|
|
102
285
|
const result = await groupQuery(jid, 'get', [{ tag: 'query', attrs: { request: 'interactive' } }]);
|
|
103
286
|
const meta = extractGroupMetadata(result);
|
|
104
287
|
// Simpan ke cache
|
|
105
288
|
setCachedGroupMetadata(jid, meta);
|
|
106
|
-
return meta;
|
|
289
|
+
return await enrichGroupMetadataUsernames(meta);
|
|
107
290
|
};
|
|
108
291
|
const groupFetchAllParticipating = async () => {
|
|
109
292
|
const result = await query({
|
|
@@ -134,7 +317,7 @@ export const makeGroupsSocket = (config) => {
|
|
|
134
317
|
attrs: {},
|
|
135
318
|
content: [groupNode]
|
|
136
319
|
});
|
|
137
|
-
data[meta.id] = meta;
|
|
320
|
+
data[meta.id] = enrichGroupMetadataNames(normalizeGroupMetadataJids(meta));
|
|
138
321
|
}
|
|
139
322
|
}
|
|
140
323
|
// TODO: properly parse LID / PN DATA
|
|
@@ -167,7 +350,7 @@ export const makeGroupsSocket = (config) => {
|
|
|
167
350
|
}))
|
|
168
351
|
}
|
|
169
352
|
]);
|
|
170
|
-
return extractGroupMetadata(result);
|
|
353
|
+
return enrichGroupMetadataNames(extractGroupMetadata(result));
|
|
171
354
|
},
|
|
172
355
|
groupLeave: async (id) => {
|
|
173
356
|
await groupQuery('@g.us', 'set', [
|
|
@@ -417,8 +600,9 @@ export const extractGroupMetadata = (result) => {
|
|
|
417
600
|
notify: group.attrs.notify,
|
|
418
601
|
addressingMode: group.attrs.addressing_mode === 'lid' ? WAMessageAddressingMode.LID : WAMessageAddressingMode.PN,
|
|
419
602
|
subject: group.attrs.subject,
|
|
420
|
-
subjectOwner: group.attrs.s_o,
|
|
421
|
-
subjectOwnerPn: group.attrs.s_o_pn,
|
|
603
|
+
subjectOwner: preferPnJid(group.attrs.s_o, group.attrs.s_o_pn),
|
|
604
|
+
subjectOwnerPn: group.attrs.s_o_pn ? jidNormalizedUser(group.attrs.s_o_pn) : undefined,
|
|
605
|
+
subjectOwnerLid: isLidUser(group.attrs.s_o) ? jidNormalizedUser(group.attrs.s_o) : undefined,
|
|
422
606
|
subjectTime: +group.attrs.s_t,
|
|
423
607
|
size: group.attrs.size ? +group.attrs.size : getBinaryNodeChildren(group, 'participant').length,
|
|
424
608
|
creation: +group.attrs.creation,
|
|
@@ -437,23 +621,9 @@ export const extractGroupMetadata = (result) => {
|
|
|
437
621
|
isCommunityAnnounce: !!getBinaryNodeChild(group, 'default_sub_group'),
|
|
438
622
|
joinApprovalMode: !!getBinaryNodeChild(group, 'membership_approval_mode'),
|
|
439
623
|
memberAddMode,
|
|
440
|
-
participants: getBinaryNodeChildren(group, 'participant').map(({ attrs }) =>
|
|
441
|
-
const isLid = isLidUser(attrs.jid);
|
|
442
|
-
const pn = attrs.phone_number;
|
|
443
|
-
const hasPn = isPnUser(pn);
|
|
444
|
-
// Jika grup pakai LID addressing:
|
|
445
|
-
// - id → pakai phoneNumber (PN) agar bisa dicompare dengan m.sender
|
|
446
|
-
// - lid → simpan LID asli
|
|
447
|
-
// Jika grup pakai PN addressing: id tetap PN
|
|
448
|
-
return {
|
|
449
|
-
id: isLid && hasPn ? pn : attrs.jid,
|
|
450
|
-
phoneNumber: isLid && hasPn ? pn : undefined,
|
|
451
|
-
lid: isLid ? attrs.jid : (isPnUser(attrs.jid) && isLidUser(attrs.lid) ? attrs.lid : undefined),
|
|
452
|
-
admin: (attrs.type || null)
|
|
453
|
-
};
|
|
454
|
-
}),
|
|
624
|
+
participants: getBinaryNodeChildren(group, 'participant').map(({ attrs }) => buildGroupParticipant(attrs)),
|
|
455
625
|
ephemeralDuration: eph ? +eph : undefined
|
|
456
626
|
};
|
|
457
|
-
return metadata;
|
|
627
|
+
return normalizeGroupMetadataJids(metadata);
|
|
458
628
|
};
|
|
459
629
|
//# sourceMappingURL=groups.js.map
|
package/lib/Socket/hydra.js
CHANGED
|
@@ -4,6 +4,183 @@ const WAProto = WaProto.proto
|
|
|
4
4
|
import axios from "axios"
|
|
5
5
|
import crypto from 'crypto'
|
|
6
6
|
|
|
7
|
+
function hydraExtractHyperlink(text = '') {
|
|
8
|
+
const hyperlink = [];
|
|
9
|
+
const stack = [];
|
|
10
|
+
let result = '';
|
|
11
|
+
let last = 0;
|
|
12
|
+
let index = 1;
|
|
13
|
+
let entity = 0;
|
|
14
|
+
|
|
15
|
+
for (let i = 0; i < text.length; i++) {
|
|
16
|
+
if (text[i] === '[' && text[i - 1] !== '\\') {
|
|
17
|
+
stack.push(i);
|
|
18
|
+
} else if (text[i] === ']' && text[i + 1] === '(') {
|
|
19
|
+
const start = stack.pop();
|
|
20
|
+
if (start == null) continue;
|
|
21
|
+
|
|
22
|
+
let end = i + 2;
|
|
23
|
+
let depth = 1;
|
|
24
|
+
|
|
25
|
+
while (end < text.length && depth) {
|
|
26
|
+
if (text[end] === '(' && text[end - 1] !== '\\') depth++;
|
|
27
|
+
else if (text[end] === ')' && text[end - 1] !== '\\') depth--;
|
|
28
|
+
end++;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (depth) continue;
|
|
32
|
+
|
|
33
|
+
const txt = text.slice(start + 1, i).trim();
|
|
34
|
+
const url = text.slice(i + 2, end - 1);
|
|
35
|
+
const reference_id = txt ? 0 : index++;
|
|
36
|
+
const key = `HYDRA_IE_${entity++}`;
|
|
37
|
+
const tag = `{{${key}}}${txt || url || 'Link'}{{/${key}}}`;
|
|
38
|
+
|
|
39
|
+
result += text.slice(last, start) + tag;
|
|
40
|
+
last = end;
|
|
41
|
+
|
|
42
|
+
hyperlink.push({ reference_id, key, text: txt, url });
|
|
43
|
+
i = end - 1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
result += text.slice(last);
|
|
48
|
+
return { text: result, hyperlink };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function hydraToTableMetadata(arr = []) {
|
|
52
|
+
if (!Array.isArray(arr) || arr.length < 1) {
|
|
53
|
+
return { title: '', rows: [], unified_rows: [] };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const [header = [], ...rows] = arr;
|
|
57
|
+
const maxLen = Math.max(header.length || 0, ...rows.map((r) => Array.isArray(r) ? r.length : 0), 1);
|
|
58
|
+
const normalize = (r = []) => [...r, ...Array(maxLen - r.length).fill('')].map((x) => String(x ?? ''));
|
|
59
|
+
|
|
60
|
+
const unified_rows = [
|
|
61
|
+
{ is_header: true, cells: normalize(header) },
|
|
62
|
+
...rows.map((r) => ({ is_header: false, cells: normalize(Array.isArray(r) ? r : [r]) }))
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
title: '',
|
|
67
|
+
rows: unified_rows.map((r) => ({
|
|
68
|
+
items: r.cells,
|
|
69
|
+
...(r.is_header ? { isHeading: true } : {})
|
|
70
|
+
})),
|
|
71
|
+
unified_rows
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function hydraTokenizeCode(code = '', lang = 'javascript') {
|
|
76
|
+
const keywordsMap = {
|
|
77
|
+
javascript: new Set([
|
|
78
|
+
'break', 'case', 'catch', 'continue', 'debugger', 'delete', 'do', 'else',
|
|
79
|
+
'finally', 'for', 'function', 'if', 'in', 'instanceof', 'new', 'return',
|
|
80
|
+
'switch', 'this', 'throw', 'try', 'typeof', 'var', 'void', 'while', 'with',
|
|
81
|
+
'true', 'false', 'null', 'undefined', 'class', 'const', 'let', 'super',
|
|
82
|
+
'extends', 'export', 'import', 'yield', 'static', 'constructor', 'async',
|
|
83
|
+
'await', 'get', 'set'
|
|
84
|
+
]),
|
|
85
|
+
python: new Set([
|
|
86
|
+
'False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break',
|
|
87
|
+
'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally',
|
|
88
|
+
'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal',
|
|
89
|
+
'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'
|
|
90
|
+
])
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const TYPE_MAP = {
|
|
94
|
+
0: 'DEFAULT',
|
|
95
|
+
1: 'KEYWORD',
|
|
96
|
+
2: 'METHOD',
|
|
97
|
+
3: 'STR',
|
|
98
|
+
4: 'NUMBER',
|
|
99
|
+
5: 'COMMENT'
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const keywords = keywordsMap[lang] || keywordsMap.javascript;
|
|
103
|
+
const tokens = [];
|
|
104
|
+
let i = 0;
|
|
105
|
+
|
|
106
|
+
const push = (content, type) => {
|
|
107
|
+
if (!content) return;
|
|
108
|
+
const last = tokens[tokens.length - 1];
|
|
109
|
+
if (last && last.highlightType === type) last.codeContent += content;
|
|
110
|
+
else tokens.push({ codeContent: content, highlightType: type });
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
while (i < code.length) {
|
|
114
|
+
const c = code[i];
|
|
115
|
+
|
|
116
|
+
if (/\s/.test(c)) {
|
|
117
|
+
const s = i;
|
|
118
|
+
while (i < code.length && /\s/.test(code[i])) i++;
|
|
119
|
+
push(code.slice(s, i), 0);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if ((c === '/' && code[i + 1] === '/') || (c === '#' && lang === 'python')) {
|
|
124
|
+
const s = i;
|
|
125
|
+
i += c === '#' ? 1 : 2;
|
|
126
|
+
while (i < code.length && code[i] !== '\n') i++;
|
|
127
|
+
push(code.slice(s, i), 5);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (c === '"' || c === "'" || c === '`') {
|
|
132
|
+
const s = i;
|
|
133
|
+
const q = c;
|
|
134
|
+
i++;
|
|
135
|
+
while (i < code.length) {
|
|
136
|
+
if (code[i] === '\\' && i + 1 < code.length) i += 2;
|
|
137
|
+
else if (code[i] === q) {
|
|
138
|
+
i++;
|
|
139
|
+
break;
|
|
140
|
+
} else i++;
|
|
141
|
+
}
|
|
142
|
+
push(code.slice(s, i), 3);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (/[0-9]/.test(c)) {
|
|
147
|
+
const s = i;
|
|
148
|
+
while (i < code.length && /[0-9.]/.test(code[i])) i++;
|
|
149
|
+
push(code.slice(s, i), 4);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (/[a-zA-Z_$]/.test(c)) {
|
|
154
|
+
const s = i;
|
|
155
|
+
while (i < code.length && /[a-zA-Z0-9_$]/.test(code[i])) i++;
|
|
156
|
+
const word = code.slice(s, i);
|
|
157
|
+
|
|
158
|
+
let type = 0;
|
|
159
|
+
if (keywords.has(word)) type = 1;
|
|
160
|
+
else {
|
|
161
|
+
let j = i;
|
|
162
|
+
while (j < code.length && /\s/.test(code[j])) j++;
|
|
163
|
+
if (code[j] === '(') type = 2;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
push(word, type);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
push(c, 0);
|
|
171
|
+
i++;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
codeBlock: tokens,
|
|
176
|
+
unified_codeBlock: tokens.map((t) => ({
|
|
177
|
+
content: t.codeContent,
|
|
178
|
+
type: TYPE_MAP[t.highlightType] || 'DEFAULT'
|
|
179
|
+
}))
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
|
|
7
184
|
class hydra {
|
|
8
185
|
constructor(utils, waUploadToServer, relayMessageFn) {
|
|
9
186
|
this.utils = utils;
|
|
@@ -23,6 +200,7 @@ class hydra {
|
|
|
23
200
|
if (content.groupStatus) return 'GROUP_STATUS';
|
|
24
201
|
if (content.carouselMessage || content.carousel) return 'CAROUSEL';
|
|
25
202
|
if (content.stickerPack) return "STICKER_PACK";
|
|
203
|
+
if (content.aiRich || content.airich || content.richResponse || content.richResponseMessage || content.AIRich) return 'AI_RICH';
|
|
26
204
|
return null;
|
|
27
205
|
}
|
|
28
206
|
|
|
@@ -753,6 +931,305 @@ class hydra {
|
|
|
753
931
|
messageId: this.utils.generateMessageID()
|
|
754
932
|
});
|
|
755
933
|
}
|
|
934
|
+
|
|
935
|
+
buildAIRichPayload(data = {}) {
|
|
936
|
+
const submessages = [];
|
|
937
|
+
const sections = [];
|
|
938
|
+
const richResponseSources = [];
|
|
939
|
+
|
|
940
|
+
const addText = (text = '', { hyperlink = true } = {}) => {
|
|
941
|
+
const extracted = hyperlink ? hydraExtractHyperlink(String(text ?? '')) : { text: String(text ?? ''), hyperlink: [] };
|
|
942
|
+
|
|
943
|
+
submessages.push({
|
|
944
|
+
messageType: 2,
|
|
945
|
+
messageText: extracted.text
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
sections.push({
|
|
949
|
+
view_model: {
|
|
950
|
+
primitive: extracted.hyperlink.length
|
|
951
|
+
? {
|
|
952
|
+
text: extracted.text,
|
|
953
|
+
inline_entities: extracted.hyperlink.map(({ reference_id, key, text, url }) => ({
|
|
954
|
+
key,
|
|
955
|
+
metadata: text?.trim()
|
|
956
|
+
? {
|
|
957
|
+
display_name: text,
|
|
958
|
+
is_trusted: true,
|
|
959
|
+
url,
|
|
960
|
+
__typename: 'GenAIInlineLinkItem'
|
|
961
|
+
}
|
|
962
|
+
: {
|
|
963
|
+
reference_id,
|
|
964
|
+
reference_url: url,
|
|
965
|
+
reference_title: url,
|
|
966
|
+
reference_display_name: url,
|
|
967
|
+
sources: [],
|
|
968
|
+
__typename: 'GenAISearchCitationItem'
|
|
969
|
+
}
|
|
970
|
+
})),
|
|
971
|
+
__typename: 'GenAIMarkdownTextUXPrimitive'
|
|
972
|
+
}
|
|
973
|
+
: {
|
|
974
|
+
text: String(text ?? ''),
|
|
975
|
+
__typename: 'GenAIMarkdownTextUXPrimitive'
|
|
976
|
+
},
|
|
977
|
+
__typename: 'GenAISingleLayoutViewModel'
|
|
978
|
+
}
|
|
979
|
+
});
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
const addCode = (language = 'javascript', code = '') => {
|
|
983
|
+
const meta = hydraTokenizeCode(String(code ?? ''), language);
|
|
984
|
+
|
|
985
|
+
submessages.push({
|
|
986
|
+
messageType: 5,
|
|
987
|
+
codeMetadata: {
|
|
988
|
+
codeLanguage: language,
|
|
989
|
+
codeBlocks: meta.codeBlock
|
|
990
|
+
}
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
sections.push({
|
|
994
|
+
view_model: {
|
|
995
|
+
primitive: {
|
|
996
|
+
language,
|
|
997
|
+
code_blocks: meta.unified_codeBlock,
|
|
998
|
+
__typename: 'GenAICodeUXPrimitive'
|
|
999
|
+
},
|
|
1000
|
+
__typename: 'GenAISingleLayoutViewModel'
|
|
1001
|
+
}
|
|
1002
|
+
});
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
const addTable = (table = []) => {
|
|
1006
|
+
const meta = hydraToTableMetadata(table);
|
|
1007
|
+
|
|
1008
|
+
submessages.push({
|
|
1009
|
+
messageType: 4,
|
|
1010
|
+
tableMetadata: {
|
|
1011
|
+
title: meta.title,
|
|
1012
|
+
rows: meta.rows
|
|
1013
|
+
}
|
|
1014
|
+
});
|
|
1015
|
+
|
|
1016
|
+
sections.push({
|
|
1017
|
+
view_model: {
|
|
1018
|
+
primitive: {
|
|
1019
|
+
rows: meta.unified_rows,
|
|
1020
|
+
__typename: 'GenATableUXPrimitive'
|
|
1021
|
+
},
|
|
1022
|
+
__typename: 'GenAISingleLayoutViewModel'
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
1025
|
+
};
|
|
1026
|
+
|
|
1027
|
+
const addImages = (images = []) => {
|
|
1028
|
+
const list = Array.isArray(images) ? images : [images];
|
|
1029
|
+
const imageUrls = list
|
|
1030
|
+
.filter(Boolean)
|
|
1031
|
+
.map((item) => {
|
|
1032
|
+
const url = typeof item === 'string' ? item : item.url || item.imageUrl || item.imagePreviewUrl;
|
|
1033
|
+
return {
|
|
1034
|
+
imagePreviewUrl: url,
|
|
1035
|
+
imageHighResUrl: item.imageHighResUrl || item.highResUrl || url,
|
|
1036
|
+
sourceUrl: item.sourceUrl || data.sourceUrl || 'https://google.com'
|
|
1037
|
+
};
|
|
1038
|
+
})
|
|
1039
|
+
.filter((x) => x.imagePreviewUrl);
|
|
1040
|
+
|
|
1041
|
+
if (!imageUrls.length) return;
|
|
1042
|
+
|
|
1043
|
+
submessages.push({
|
|
1044
|
+
messageType: 1,
|
|
1045
|
+
gridImageMetadata: {
|
|
1046
|
+
gridImageUrl: {
|
|
1047
|
+
imagePreviewUrl: imageUrls[0].imagePreviewUrl
|
|
1048
|
+
},
|
|
1049
|
+
imageUrls
|
|
1050
|
+
}
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
imageUrls.forEach(({ imagePreviewUrl }) => {
|
|
1054
|
+
sections.push({
|
|
1055
|
+
view_model: {
|
|
1056
|
+
primitive: {
|
|
1057
|
+
media: {
|
|
1058
|
+
url: imagePreviewUrl,
|
|
1059
|
+
mime_type: 'image/jpeg'
|
|
1060
|
+
},
|
|
1061
|
+
imagine_type: 3,
|
|
1062
|
+
status: {
|
|
1063
|
+
status: 'READY'
|
|
1064
|
+
},
|
|
1065
|
+
__typename: 'GenAIImaginePrimitive'
|
|
1066
|
+
},
|
|
1067
|
+
__typename: 'GenAISingleLayoutViewModel'
|
|
1068
|
+
}
|
|
1069
|
+
});
|
|
1070
|
+
});
|
|
1071
|
+
};
|
|
1072
|
+
|
|
1073
|
+
const addSources = (sources = []) => {
|
|
1074
|
+
if (!Array.isArray(sources) || !sources.length) return;
|
|
1075
|
+
|
|
1076
|
+
sections.push({
|
|
1077
|
+
view_model: {
|
|
1078
|
+
primitive: {
|
|
1079
|
+
sources: sources.map((source) => {
|
|
1080
|
+
const arr = Array.isArray(source) ? source : null;
|
|
1081
|
+
const profileUrl = arr ? arr[0] : source.profileIconUrl || source.faviconUrl || source.thumbnailUrl || '';
|
|
1082
|
+
const url = arr ? arr[1] : source.url || source.sourceUrl || source.sourceProviderURL || '';
|
|
1083
|
+
const text = arr ? arr[2] : source.title || source.sourceTitle || source.provider || 'Source';
|
|
1084
|
+
|
|
1085
|
+
return {
|
|
1086
|
+
source_type: 'THIRD_PARTY',
|
|
1087
|
+
source_display_name: text,
|
|
1088
|
+
source_subtitle: source.subtitle || 'AI',
|
|
1089
|
+
source_url: url,
|
|
1090
|
+
favicon: {
|
|
1091
|
+
url: profileUrl,
|
|
1092
|
+
mime_type: 'image/jpeg',
|
|
1093
|
+
width: 16,
|
|
1094
|
+
height: 16
|
|
1095
|
+
}
|
|
1096
|
+
};
|
|
1097
|
+
}),
|
|
1098
|
+
__typename: 'GenAISearchResultPrimitive'
|
|
1099
|
+
},
|
|
1100
|
+
__typename: 'GenAISingleLayoutViewModel'
|
|
1101
|
+
}
|
|
1102
|
+
});
|
|
1103
|
+
};
|
|
1104
|
+
|
|
1105
|
+
const addReels = (reelsItems = []) => {
|
|
1106
|
+
if (!Array.isArray(reelsItems) || !reelsItems.length) return;
|
|
1107
|
+
|
|
1108
|
+
submessages.push({
|
|
1109
|
+
messageType: 9,
|
|
1110
|
+
contentItemsMetadata: {
|
|
1111
|
+
contentType: 1,
|
|
1112
|
+
itemsMetadata: reelsItems.map((item) => ({
|
|
1113
|
+
reelItem: {
|
|
1114
|
+
title: item.title || item.creator || '',
|
|
1115
|
+
profileIconUrl: item.profileIconUrl || item.avatar_url || '',
|
|
1116
|
+
thumbnailUrl: item.thumbnailUrl || item.thumbnail_url || '',
|
|
1117
|
+
videoUrl: item.videoUrl || item.reels_url || item.url || '',
|
|
1118
|
+
}
|
|
1119
|
+
}))
|
|
1120
|
+
}
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
reelsItems.forEach((item, idx) => {
|
|
1124
|
+
richResponseSources.push({
|
|
1125
|
+
provider: item.provider || 'UNKNOWN',
|
|
1126
|
+
thumbnailCDNURL: item.thumbnailUrl || item.thumbnail_url || '',
|
|
1127
|
+
sourceProviderURL: item.videoUrl || item.reels_url || item.url || '',
|
|
1128
|
+
sourceQuery: '',
|
|
1129
|
+
faviconCDNURL: item.profileIconUrl || item.avatar_url || '',
|
|
1130
|
+
citationNumber: idx + 1,
|
|
1131
|
+
sourceTitle: item.title || item.creator || `Reel ${idx + 1}`
|
|
1132
|
+
});
|
|
1133
|
+
});
|
|
1134
|
+
|
|
1135
|
+
sections.push({
|
|
1136
|
+
view_model: {
|
|
1137
|
+
primitives: reelsItems.map((item) => ({
|
|
1138
|
+
reels_url: item.videoUrl || item.reels_url || item.url || '',
|
|
1139
|
+
thumbnail_url: item.thumbnailUrl || item.thumbnail_url || '',
|
|
1140
|
+
creator: item.title || item.creator || '',
|
|
1141
|
+
avatar_url: item.profileIconUrl || item.avatar_url || '',
|
|
1142
|
+
reels_title: item.reels_title || item.reelsTitle || item.title || '',
|
|
1143
|
+
likes_count: item.likes_count || item.likesCount || 0,
|
|
1144
|
+
shares_count: item.shares_count || item.sharesCount || 0,
|
|
1145
|
+
view_count: item.view_count || item.viewCount || 0,
|
|
1146
|
+
reel_source: item.reel_source || item.reelSource || 'IG',
|
|
1147
|
+
is_verified: !!(item.is_verified ?? item.isVerified),
|
|
1148
|
+
__typename: 'GenAIReelPrimitive'
|
|
1149
|
+
})),
|
|
1150
|
+
__typename: 'GenAIHScrollLayoutViewModel'
|
|
1151
|
+
}
|
|
1152
|
+
});
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
if (data.text) addText(data.text, { hyperlink: data.hyperlink !== false });
|
|
1156
|
+
if (Array.isArray(data.texts)) data.texts.forEach((text) => addText(text, { hyperlink: data.hyperlink !== false }));
|
|
1157
|
+
|
|
1158
|
+
if (data.code) {
|
|
1159
|
+
if (typeof data.code === 'string') addCode(data.language || 'javascript', data.code);
|
|
1160
|
+
else addCode(data.code.language || data.language || 'javascript', data.code.content || data.code.code || '');
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
if (Array.isArray(data.codes)) {
|
|
1164
|
+
data.codes.forEach((item) => {
|
|
1165
|
+
if (typeof item === 'string') addCode(data.language || 'javascript', item);
|
|
1166
|
+
else addCode(item.language || data.language || 'javascript', item.content || item.code || '');
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
if (data.table) addTable(data.table);
|
|
1171
|
+
if (data.image || data.images || data.gridImage) addImages(data.images || data.gridImage || data.image);
|
|
1172
|
+
if (data.sources) addSources(data.sources);
|
|
1173
|
+
if (data.reels || data.reel) addReels(data.reels || data.reel);
|
|
1174
|
+
|
|
1175
|
+
const forwarded = data.forwarded !== false;
|
|
1176
|
+
const includesUnifiedResponse = data.includesUnifiedResponse !== false;
|
|
1177
|
+
|
|
1178
|
+
return {
|
|
1179
|
+
messageContextInfo: {
|
|
1180
|
+
deviceListMetadata: {},
|
|
1181
|
+
deviceListMetadataVersion: 2,
|
|
1182
|
+
botMetadata: {
|
|
1183
|
+
messageDisclaimerText: data.disclaimerText || data.messageDisclaimerText || '',
|
|
1184
|
+
pluginMetadata: {},
|
|
1185
|
+
richResponseSourcesMetadata: {
|
|
1186
|
+
sources: data.richResponseSources || richResponseSources
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
},
|
|
1190
|
+
botForwardedMessage: {
|
|
1191
|
+
message: {
|
|
1192
|
+
richResponseMessage: {
|
|
1193
|
+
messageType: data.messageType || 1,
|
|
1194
|
+
submessages,
|
|
1195
|
+
unifiedResponse: {
|
|
1196
|
+
data: includesUnifiedResponse
|
|
1197
|
+
? Buffer.from(JSON.stringify({
|
|
1198
|
+
response_id: data.responseId || crypto.randomUUID(),
|
|
1199
|
+
sections
|
|
1200
|
+
})).toString('base64')
|
|
1201
|
+
: ''
|
|
1202
|
+
},
|
|
1203
|
+
contextInfo: forwarded
|
|
1204
|
+
? {
|
|
1205
|
+
forwardingScore: data.forwardingScore || 1,
|
|
1206
|
+
isForwarded: true,
|
|
1207
|
+
forwardedAiBotMessageInfo: {
|
|
1208
|
+
botJid: data.botJid || '0@bot'
|
|
1209
|
+
},
|
|
1210
|
+
forwardOrigin: data.forwardOrigin || 4,
|
|
1211
|
+
...(data.contextInfo || {})
|
|
1212
|
+
}
|
|
1213
|
+
: (data.contextInfo || {})
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
async handleAIRich(content, jid, quoted, options = {}) {
|
|
1221
|
+
const data = content.aiRich || content.airich || content.richResponse || content.AIRich || content;
|
|
1222
|
+
|
|
1223
|
+
const msg = this.buildAIRichPayload(data);
|
|
1224
|
+
|
|
1225
|
+
return await this.relayMessage(jid, msg, {
|
|
1226
|
+
messageId: data.messageId || this.utils.generateMessageID?.() || crypto.randomBytes(10).toString('hex').toUpperCase(),
|
|
1227
|
+
...(quoted ? { quoted } : {}),
|
|
1228
|
+
...options
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
|
|
756
1233
|
}
|
|
757
1234
|
|
|
758
1235
|
export default hydra
|
|
@@ -1270,8 +1270,35 @@ export const makeMessagesSocket = (config) => {
|
|
|
1270
1270
|
}
|
|
1271
1271
|
return album
|
|
1272
1272
|
},
|
|
1273
|
+
sendAIRich: async (jid, content = {}, options = {}) => {
|
|
1274
|
+
const { quoted, filter = false } = options;
|
|
1275
|
+
const getParticipantAttr = () => filter ? { participant: { jid } } : {};
|
|
1276
|
+
return await kelvdra.handleAIRich({ aiRich: content }, jid, quoted, {
|
|
1277
|
+
...getParticipantAttr()
|
|
1278
|
+
});
|
|
1279
|
+
},
|
|
1273
1280
|
sendMessage: async (jid, content, options = {}) => {
|
|
1274
1281
|
const userJid = authState.creds.me.id;
|
|
1282
|
+
const normalizeDeleteKey = async (key = {}) => {
|
|
1283
|
+
const normalized = { ...key };
|
|
1284
|
+
const resolveLid = async (value) => {
|
|
1285
|
+
if (!value || !isLidUser(value)) return value;
|
|
1286
|
+
try {
|
|
1287
|
+
return (await signalRepository?.lidMapping?.getPNForLID(value)) || value;
|
|
1288
|
+
} catch {
|
|
1289
|
+
return value;
|
|
1290
|
+
}
|
|
1291
|
+
};
|
|
1292
|
+
normalized.remoteJid = await resolveLid(normalized.remoteJid || jid);
|
|
1293
|
+
normalized.participant = await resolveLid(normalized.participant);
|
|
1294
|
+
if (isJidGroup(normalized.remoteJid || jid) && !normalized.participant) {
|
|
1295
|
+
normalized.participant = normalized.fromMe ? userJid : undefined;
|
|
1296
|
+
}
|
|
1297
|
+
return normalized;
|
|
1298
|
+
};
|
|
1299
|
+
if (content?.delete) {
|
|
1300
|
+
content = { ...content, delete: await normalizeDeleteKey(content.delete) };
|
|
1301
|
+
}
|
|
1275
1302
|
const additionalAttributes = {}
|
|
1276
1303
|
const { filter = false, quoted } = options;
|
|
1277
1304
|
const getParticipantAttr = () => filter ? { participant: { jid } } : {};
|
|
@@ -1314,6 +1341,11 @@ export const makeMessagesSocket = (config) => {
|
|
|
1314
1341
|
|
|
1315
1342
|
case 'CAROUSEL':
|
|
1316
1343
|
return await kelvdra.handleCarousel(content, jid, quoted);
|
|
1344
|
+
|
|
1345
|
+
case 'AI_RICH':
|
|
1346
|
+
return await kelvdra.handleAIRich(content, jid, quoted, {
|
|
1347
|
+
...getParticipantAttr()
|
|
1348
|
+
});
|
|
1317
1349
|
}
|
|
1318
1350
|
}
|
|
1319
1351
|
if (typeof content === 'object' &&
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import type { Contact } from './Contact.js';
|
|
2
2
|
import type { WAMessageAddressingMode } from './Message.js';
|
|
3
3
|
export type GroupParticipant = Contact & {
|
|
4
|
+
/** PN/JID result. If WA returns @lid with phone_number, this is normalized to @s.whatsapp.net */
|
|
5
|
+
jid?: string;
|
|
6
|
+
/** display/notify name returned by WhatsApp participant node */
|
|
7
|
+
username?: string;
|
|
8
|
+
waUsername?: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
notify?: string;
|
|
11
|
+
/** best display name after metadata/contact-cache enrichment */
|
|
12
|
+
displayName?: string;
|
|
13
|
+
/** original LID when WhatsApp returns LID addressing */
|
|
14
|
+
lid?: string;
|
|
15
|
+
/** PN JID when available */
|
|
16
|
+
phoneNumber?: string;
|
|
4
17
|
isAdmin?: boolean;
|
|
5
18
|
isSuperAdmin?: boolean;
|
|
6
19
|
admin?: 'admin' | 'superadmin' | null;
|
|
@@ -15,17 +28,20 @@ export interface GroupMetadata {
|
|
|
15
28
|
addressingMode?: WAMessageAddressingMode;
|
|
16
29
|
owner: string | undefined;
|
|
17
30
|
ownerPn?: string | undefined;
|
|
31
|
+
ownerLid?: string | undefined;
|
|
18
32
|
owner_country_code?: string | undefined;
|
|
19
33
|
subject: string;
|
|
20
34
|
/** group subject owner */
|
|
21
35
|
subjectOwner?: string;
|
|
22
36
|
subjectOwnerPn?: string;
|
|
37
|
+
subjectOwnerLid?: string;
|
|
23
38
|
/** group subject modification date */
|
|
24
39
|
subjectTime?: number;
|
|
25
40
|
creation?: number;
|
|
26
41
|
desc?: string;
|
|
27
42
|
descOwner?: string;
|
|
28
43
|
descOwnerPn?: string;
|
|
44
|
+
descOwnerLid?: string;
|
|
29
45
|
descId?: string;
|
|
30
46
|
descTime?: number;
|
|
31
47
|
/** if this group is part of a community, it returns the jid of the community to which it belongs */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getBinaryNodeChild } from '../WABinary/index.js';
|
|
2
2
|
import { USyncBotProfileProtocol } from './Protocols/UsyncBotProfileProtocol.js';
|
|
3
3
|
import { USyncLIDProtocol } from './Protocols/UsyncLIDProtocol.js';
|
|
4
|
-
import { USyncContactProtocol, USyncDeviceProtocol, USyncDisappearingModeProtocol, USyncStatusProtocol } from './Protocols/index.js';
|
|
4
|
+
import { USyncContactProtocol, USyncDeviceProtocol, USyncDisappearingModeProtocol, USyncStatusProtocol, USyncUsernameProtocol } from './Protocols/index.js';
|
|
5
5
|
import { USyncUser } from './USyncUser.js';
|
|
6
6
|
export class USyncQuery {
|
|
7
7
|
constructor() {
|
|
@@ -90,5 +90,9 @@ export class USyncQuery {
|
|
|
90
90
|
this.protocols.push(new USyncLIDProtocol());
|
|
91
91
|
return this;
|
|
92
92
|
}
|
|
93
|
+
withUsernameProtocol() {
|
|
94
|
+
this.protocols.push(new USyncUsernameProtocol());
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
93
97
|
}
|
|
94
98
|
//# sourceMappingURL=USyncQuery.js.map
|