@baileys-md/baileys 10.0.7
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/LICENSE +21 -0
- package/README.md +2 -0
- package/WAProto/index.js +155693 -0
- package/WASignalGroup/GroupProtocol.js +1697 -0
- package/WASignalGroup/ciphertext_message.js +16 -0
- package/WASignalGroup/group_cipher.js +120 -0
- package/WASignalGroup/group_session_builder.js +46 -0
- package/WASignalGroup/index.js +5 -0
- package/WASignalGroup/keyhelper.js +21 -0
- package/WASignalGroup/protobufs.js +3 -0
- package/WASignalGroup/queue_job.js +69 -0
- package/WASignalGroup/sender_chain_key.js +50 -0
- package/WASignalGroup/sender_key_distribution_message.js +78 -0
- package/WASignalGroup/sender_key_message.js +92 -0
- package/WASignalGroup/sender_key_name.js +70 -0
- package/WASignalGroup/sender_key_record.js +56 -0
- package/WASignalGroup/sender_key_state.js +129 -0
- package/WASignalGroup/sender_message_key.js +39 -0
- package/lib/Defaults/baileys-version.json +3 -0
- package/lib/Defaults/index.js +122 -0
- package/lib/Defaults/phonenumber-mcc.json +223 -0
- package/lib/Signal/libsignal.js +161 -0
- package/lib/Socket/Client/abstract-socket-client.js +13 -0
- package/lib/Socket/Client/index.js +19 -0
- package/lib/Socket/Client/mobile-socket-client.js +65 -0
- package/lib/Socket/Client/web-socket-client.js +62 -0
- package/lib/Socket/business.js +260 -0
- package/lib/Socket/chats.js +882 -0
- package/lib/Socket/groups.js +327 -0
- package/lib/Socket/index.js +10 -0
- package/lib/Socket/messages-recv.js +1043 -0
- package/lib/Socket/messages-send.js +836 -0
- package/lib/Socket/newsletter.js +248 -0
- package/lib/Socket/registration.js +166 -0
- package/lib/Socket/socket.js +640 -0
- package/lib/Socket/usync.js +70 -0
- package/lib/Store/index.js +8 -0
- package/lib/Store/make-cache-manager-store.js +83 -0
- package/lib/Store/make-in-memory-store.js +431 -0
- package/lib/Store/make-mongo-store.js +567 -0
- package/lib/Store/make-ordered-dictionary.js +81 -0
- package/lib/Store/object-repository.js +27 -0
- package/lib/Types/Auth.js +2 -0
- package/lib/Types/Call.js +2 -0
- package/lib/Types/Chat.js +4 -0
- package/lib/Types/Contact.js +2 -0
- package/lib/Types/Events.js +2 -0
- package/lib/Types/GroupMetadata.js +2 -0
- package/lib/Types/Label.js +27 -0
- package/lib/Types/LabelAssociation.js +9 -0
- package/lib/Types/Message.js +7 -0
- package/lib/Types/Newsletter.js +18 -0
- package/lib/Types/Product.js +2 -0
- package/lib/Types/Signal.js +2 -0
- package/lib/Types/Socket.js +2 -0
- package/lib/Types/State.js +2 -0
- package/lib/Types/USync.js +2 -0
- package/lib/Types/index.js +42 -0
- package/lib/Utils/auth-utils.js +206 -0
- package/lib/Utils/baileys-event-stream.js +63 -0
- package/lib/Utils/business.js +234 -0
- package/lib/Utils/chat-utils.js +730 -0
- package/lib/Utils/crypto.js +151 -0
- package/lib/Utils/decode-wa-message.js +198 -0
- package/lib/Utils/event-buffer.js +520 -0
- package/lib/Utils/generics.js +445 -0
- package/lib/Utils/history.js +94 -0
- package/lib/Utils/index.js +33 -0
- package/lib/Utils/link-preview.js +126 -0
- package/lib/Utils/logger.js +7 -0
- package/lib/Utils/lt-hash.js +51 -0
- package/lib/Utils/make-mutex.js +43 -0
- package/lib/Utils/messages-media.js +724 -0
- package/lib/Utils/messages.js +1018 -0
- package/lib/Utils/noise-handler.js +155 -0
- package/lib/Utils/process-message.js +372 -0
- package/lib/Utils/signal.js +143 -0
- package/lib/Utils/use-multi-file-auth-state.js +93 -0
- package/lib/Utils/validate-connection.js +207 -0
- package/lib/WABinary/constants.js +40 -0
- package/lib/WABinary/decode.js +265 -0
- package/lib/WABinary/encode.js +250 -0
- package/lib/WABinary/generic-utils.js +110 -0
- package/lib/WABinary/index.js +21 -0
- package/lib/WABinary/jid-utils.js +69 -0
- package/lib/WABinary/types.js +2 -0
- package/lib/WAM/BinaryInfo.js +13 -0
- package/lib/WAM/constants.js +15350 -0
- package/lib/WAM/encode.js +155 -0
- package/lib/WAM/index.js +19 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +32 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +57 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +30 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +42 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +53 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +24 -0
- package/lib/WAUSync/Protocols/index.js +20 -0
- package/lib/WAUSync/USyncQuery.js +89 -0
- package/lib/WAUSync/USyncUser.js +26 -0
- package/lib/WAUSync/index.js +19 -0
- package/lib/index.js +33 -0
- package/package.json +84 -0
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.waLabelAssociationKey = exports.waMessageID = exports.waChatKey = void 0;
|
|
7
|
+
const cron_1 = require("cron");
|
|
8
|
+
const moment_timezone_1 = __importDefault(require("moment-timezone"));
|
|
9
|
+
const WAProto_1 = require("../../WAProto");
|
|
10
|
+
const Defaults_1 = require("../Defaults");
|
|
11
|
+
const LabelAssociation_1 = require("../Types/LabelAssociation");
|
|
12
|
+
const Utils_1 = require("../Utils");
|
|
13
|
+
const WABinary_1 = require("../WABinary");
|
|
14
|
+
const make_ordered_dictionary_1 = __importDefault(require("./make-ordered-dictionary"));
|
|
15
|
+
const object_repository_1 = require("./object-repository");
|
|
16
|
+
const waChatKey = (pin) => ({
|
|
17
|
+
key: (c) => (pin ? (c.pinned ? "1" : "0") : "") +
|
|
18
|
+
(c.archived ? "0" : "1") +
|
|
19
|
+
(c.conversationTimestamp
|
|
20
|
+
? c.conversationTimestamp.toString(16).padStart(8, "0")
|
|
21
|
+
: "") +
|
|
22
|
+
c.id,
|
|
23
|
+
compare: (k1, k2) => k2.localeCompare(k1),
|
|
24
|
+
});
|
|
25
|
+
exports.waChatKey = waChatKey;
|
|
26
|
+
const waMessageID = (m) => m.key.id || "";
|
|
27
|
+
exports.waMessageID = waMessageID;
|
|
28
|
+
exports.waLabelAssociationKey = {
|
|
29
|
+
key: (la) => la.type === LabelAssociation_1.LabelAssociationType.Chat
|
|
30
|
+
? la.chatId + la.labelId
|
|
31
|
+
: la.chatId + la.messageId + la.labelId,
|
|
32
|
+
compare: (k1, k2) => k2.localeCompare(k1),
|
|
33
|
+
};
|
|
34
|
+
const makeMessagesDictionary = () => (0, make_ordered_dictionary_1.default)(exports.waMessageID);
|
|
35
|
+
const predefinedLabels = Object.freeze({
|
|
36
|
+
"0": {
|
|
37
|
+
id: "0",
|
|
38
|
+
name: "New customer",
|
|
39
|
+
predefinedId: "0",
|
|
40
|
+
color: 0,
|
|
41
|
+
deleted: false,
|
|
42
|
+
},
|
|
43
|
+
"1": {
|
|
44
|
+
id: "1",
|
|
45
|
+
name: "New order",
|
|
46
|
+
predefinedId: "1",
|
|
47
|
+
color: 1,
|
|
48
|
+
deleted: false,
|
|
49
|
+
},
|
|
50
|
+
"2": {
|
|
51
|
+
id: "2",
|
|
52
|
+
name: "Pending payment",
|
|
53
|
+
predefinedId: "2",
|
|
54
|
+
color: 2,
|
|
55
|
+
deleted: false,
|
|
56
|
+
},
|
|
57
|
+
"3": {
|
|
58
|
+
id: "3",
|
|
59
|
+
name: "Paid",
|
|
60
|
+
predefinedId: "3",
|
|
61
|
+
color: 3,
|
|
62
|
+
deleted: false,
|
|
63
|
+
},
|
|
64
|
+
"4": {
|
|
65
|
+
id: "4",
|
|
66
|
+
name: "Order completed",
|
|
67
|
+
predefinedId: "4",
|
|
68
|
+
color: 4,
|
|
69
|
+
deleted: false,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
exports.default = ({ logger: _logger, socket, db, filterChats, autoDeleteStatusMessage, }) => {
|
|
73
|
+
const isOlderThan24Hours = (timestamp) => {
|
|
74
|
+
const currentTime = (0, moment_timezone_1.default)(new Date()).tz("Asia/Jakarta");
|
|
75
|
+
const hoursDifference = currentTime.diff((0, moment_timezone_1.default)(timestamp * 1000).tz("Asia/Jakarta"), "hours");
|
|
76
|
+
return hoursDifference > 24;
|
|
77
|
+
};
|
|
78
|
+
if (autoDeleteStatusMessage) {
|
|
79
|
+
if (typeof autoDeleteStatusMessage === "boolean") {
|
|
80
|
+
autoDeleteStatusMessage = {
|
|
81
|
+
cronTime: "0 0 * * *",
|
|
82
|
+
timeZone: "Asia/Jakarta",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const update = {
|
|
86
|
+
$set: {
|
|
87
|
+
messages: {
|
|
88
|
+
$filter: {
|
|
89
|
+
input: "$messages",
|
|
90
|
+
cond: {
|
|
91
|
+
$not: {
|
|
92
|
+
$or: [],
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
new cron_1.CronJob(autoDeleteStatusMessage.cronTime, // cronTime
|
|
100
|
+
async () => {
|
|
101
|
+
var _a, _b, _c, _d, _e;
|
|
102
|
+
const statusMesasges = await chats.findOne({ id: "status@broadcast" }, { projection: { _id: 0 } });
|
|
103
|
+
if (statusMesasges) {
|
|
104
|
+
for (const m of statusMesasges === null || statusMesasges === void 0 ? void 0 : statusMesasges.messages) {
|
|
105
|
+
if (isOlderThan24Hours(typeof ((_a = m.message) === null || _a === void 0 ? void 0 : _a.messageTimestamp) === "number"
|
|
106
|
+
? (_b = m.message) === null || _b === void 0 ? void 0 : _b.messageTimestamp
|
|
107
|
+
: (_d = (_c = m.message) === null || _c === void 0 ? void 0 : _c.messageTimestamp) === null || _d === void 0 ? void 0 : _d.low)) {
|
|
108
|
+
update.$set.messages.$filter.cond.$not.$or.push({
|
|
109
|
+
$eq: ["$$this.message.key.id", (_e = m.message) === null || _e === void 0 ? void 0 : _e.key.id],
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (update.$set.messages.$filter.cond.$not.$or.length > 0) {
|
|
114
|
+
const updateResult = await chats.updateOne({ id: "status@broadcast" }, [update]);
|
|
115
|
+
logger === null || logger === void 0 ? void 0 : logger.debug(updateResult, "updated statusMessages");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}, () => {
|
|
119
|
+
logger === null || logger === void 0 ? void 0 : logger.debug("cleared statusMessages");
|
|
120
|
+
}, true, // start
|
|
121
|
+
autoDeleteStatusMessage === null || autoDeleteStatusMessage === void 0 ? void 0 : autoDeleteStatusMessage.timeZone);
|
|
122
|
+
}
|
|
123
|
+
const logger = _logger ||
|
|
124
|
+
Defaults_1.DEFAULT_CONNECTION_CONFIG.logger.child({ stream: "mongo-store" });
|
|
125
|
+
const chats = db.collection("chats");
|
|
126
|
+
const messages = {};
|
|
127
|
+
const contacts = db.collection("contacts");
|
|
128
|
+
const groupMetadata = {};
|
|
129
|
+
const presences = {};
|
|
130
|
+
const state = { connection: "close" };
|
|
131
|
+
const labels = new object_repository_1.ObjectRepository(predefinedLabels);
|
|
132
|
+
const labelAssociations = db.collection("labelAssociations");
|
|
133
|
+
const assertMessageList = (jid) => {
|
|
134
|
+
if (!messages[jid]) {
|
|
135
|
+
messages[jid] = makeMessagesDictionary();
|
|
136
|
+
}
|
|
137
|
+
return messages[jid];
|
|
138
|
+
};
|
|
139
|
+
const labelsUpsert = (newLabels) => {
|
|
140
|
+
for (const label of newLabels) {
|
|
141
|
+
labels.upsertById(label.id, label);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
// const contactsUpsert = async (newContacts: Contact[]) => {
|
|
145
|
+
// const oldContacts = new Set(await contacts
|
|
146
|
+
// .find({}, { projection: { _id: 0 } })
|
|
147
|
+
// .toArray());
|
|
148
|
+
// for (const contact of newContacts) {
|
|
149
|
+
// }
|
|
150
|
+
// };
|
|
151
|
+
const bind = (ev) => {
|
|
152
|
+
ev.on("connection.update", (update) => {
|
|
153
|
+
Object.assign(state, update);
|
|
154
|
+
});
|
|
155
|
+
ev.on("messaging-history.set", async ({ chats: newChats, contacts: newContacts, messages: newMessages, isLatest }) => {
|
|
156
|
+
var _a;
|
|
157
|
+
if (isLatest) {
|
|
158
|
+
await chats.drop();
|
|
159
|
+
await contacts.drop();
|
|
160
|
+
for (const id in messages) {
|
|
161
|
+
delete messages[id];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (filterChats) {
|
|
165
|
+
newChats = newChats
|
|
166
|
+
.map((chat) => {
|
|
167
|
+
var _a;
|
|
168
|
+
if ((_a = chat.messages) === null || _a === void 0 ? void 0 : _a.some((m) => { var _a, _b; return !((_a = m.message) === null || _a === void 0 ? void 0 : _a.message) && ((_b = m.message) === null || _b === void 0 ? void 0 : _b.messageStubType); })) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
return chat;
|
|
172
|
+
})
|
|
173
|
+
.filter(Boolean);
|
|
174
|
+
}
|
|
175
|
+
if (newChats.length) {
|
|
176
|
+
const chatsAdded = await chats.bulkWrite(newChats.map((chat) => {
|
|
177
|
+
return {
|
|
178
|
+
insertOne: {
|
|
179
|
+
document: chat,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}));
|
|
183
|
+
logger.debug({ chatsAdded: chatsAdded.insertedCount }, "synced chats");
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
logger.debug("no chats added");
|
|
187
|
+
}
|
|
188
|
+
const oldContacts = await contacts.bulkWrite(newContacts.map((contact) => {
|
|
189
|
+
return {
|
|
190
|
+
insertOne: {
|
|
191
|
+
document: contact,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}));
|
|
195
|
+
logger.debug({ insertedContacts: oldContacts.insertedCount }, "synced contacts");
|
|
196
|
+
if (!oldContacts.insertedCount) {
|
|
197
|
+
throw new Error("no contacts added");
|
|
198
|
+
}
|
|
199
|
+
for (const msg of newMessages) {
|
|
200
|
+
const jid = msg.key.remoteJid;
|
|
201
|
+
const list = assertMessageList(jid);
|
|
202
|
+
list.upsert(msg, "prepend");
|
|
203
|
+
const chat = await chats.findOne({ id: jid }, { projection: { _id: 0 } });
|
|
204
|
+
if (chat) {
|
|
205
|
+
((_a = chat.messages) === null || _a === void 0 ? void 0 : _a.push({ message: msg })) ||
|
|
206
|
+
(chat.messages = [{ message: msg }]);
|
|
207
|
+
await chats.findOneAndUpdate({ id: jid }, { $set: chat }, { upsert: true });
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
logger.debug({ jid }, "chat not found");
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
logger.debug({ messages: newMessages.length }, "synced messages");
|
|
214
|
+
});
|
|
215
|
+
ev.on("contacts.upsert", async (Contacts) => {
|
|
216
|
+
for (const contact of Contacts) {
|
|
217
|
+
await contacts.updateOne({ id: contact.id }, { $set: contact }, { upsert: true });
|
|
218
|
+
}
|
|
219
|
+
logger === null || logger === void 0 ? void 0 : logger.debug({ contactsUpserted: Contacts.length }, "contacts upserted");
|
|
220
|
+
});
|
|
221
|
+
ev.on("contacts.update", async (updates) => {
|
|
222
|
+
for (const update of updates) {
|
|
223
|
+
const contact = await contacts.findOne({ id: update.id }, { projection: { _id: 0 } });
|
|
224
|
+
if (contact) {
|
|
225
|
+
Object.assign(contact, update);
|
|
226
|
+
await contacts.updateOne({ id: update.id }, { $set: contact }, { upsert: true });
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
logger.debug("got update for non-existent contact");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
ev.on("chats.upsert", async (newChats) => {
|
|
234
|
+
await chats.bulkWrite(newChats.map((chat) => {
|
|
235
|
+
return {
|
|
236
|
+
updateOne: {
|
|
237
|
+
filter: { id: chat.id },
|
|
238
|
+
update: { $set: chat },
|
|
239
|
+
upsert: true,
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
}));
|
|
243
|
+
});
|
|
244
|
+
ev.on("chats.update", async (updates) => {
|
|
245
|
+
// try {
|
|
246
|
+
for (const update of updates) {
|
|
247
|
+
const chat = await chats.findOneAndUpdate({ id: update.id }, {
|
|
248
|
+
$set: update,
|
|
249
|
+
}, { upsert: true });
|
|
250
|
+
if (!chat) {
|
|
251
|
+
logger.debug("got update for non-existant chat");
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
ev.on("labels.edit", (label) => {
|
|
256
|
+
if (label.deleted) {
|
|
257
|
+
return labels.deleteById(label.id);
|
|
258
|
+
}
|
|
259
|
+
// WhatsApp can store only up to 20 labels
|
|
260
|
+
if (labels.count() < 20) {
|
|
261
|
+
return labels.upsertById(label.id, label);
|
|
262
|
+
}
|
|
263
|
+
logger.error("Labels count exceed");
|
|
264
|
+
});
|
|
265
|
+
ev.on("labels.association", async ({ type, association }) => {
|
|
266
|
+
switch (type) {
|
|
267
|
+
case "add":
|
|
268
|
+
await labelAssociations.updateOne({ id: (association === null || association === void 0 ? void 0 : association.chatId) || (association === null || association === void 0 ? void 0 : association.labelId) }, { $set: association }, { upsert: true });
|
|
269
|
+
break;
|
|
270
|
+
case "remove":
|
|
271
|
+
await labelAssociations.deleteOne({
|
|
272
|
+
id: (association === null || association === void 0 ? void 0 : association.chatId) || (association === null || association === void 0 ? void 0 : association.labelId),
|
|
273
|
+
});
|
|
274
|
+
break;
|
|
275
|
+
default:
|
|
276
|
+
logger.error(`unknown operation type [${type}]`);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
ev.on("presence.update", ({ id, presences: update }) => {
|
|
280
|
+
presences[id] = presences[id] || {};
|
|
281
|
+
Object.assign(presences[id], update);
|
|
282
|
+
});
|
|
283
|
+
ev.on("chats.delete", async (deletions) => {
|
|
284
|
+
for (const item of deletions) {
|
|
285
|
+
await chats.deleteOne({ id: item });
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
ev.on("messages.upsert", async ({ messages: newMessages, type }) => {
|
|
289
|
+
// try {
|
|
290
|
+
switch (type) {
|
|
291
|
+
case "append":
|
|
292
|
+
case "notify":
|
|
293
|
+
for (const msg of newMessages) {
|
|
294
|
+
const jid = (0, WABinary_1.jidNormalizedUser)(msg.key.remoteJid);
|
|
295
|
+
const list = assertMessageList(jid);
|
|
296
|
+
list.upsert(msg, "append");
|
|
297
|
+
const chat = await chats.findOne({ id: jid });
|
|
298
|
+
if (type === "notify") {
|
|
299
|
+
if (!chat) {
|
|
300
|
+
ev.emit("chats.upsert", [
|
|
301
|
+
{
|
|
302
|
+
id: jid,
|
|
303
|
+
conversationTimestamp: (0, Utils_1.toNumber)(msg.messageTimestamp),
|
|
304
|
+
unreadCount: 1,
|
|
305
|
+
},
|
|
306
|
+
]);
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
chat.messages
|
|
310
|
+
? chat.messages.push({ message: msg })
|
|
311
|
+
: (chat.messages = [{ message: msg }]);
|
|
312
|
+
await chats.updateOne({ id: jid }, { $set: chat }, { upsert: true });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
ev.on("messages.update", (updates) => {
|
|
320
|
+
var _a;
|
|
321
|
+
for (const { update, key } of updates) {
|
|
322
|
+
const list = assertMessageList((0, WABinary_1.jidNormalizedUser)(key.remoteJid));
|
|
323
|
+
if (update === null || update === void 0 ? void 0 : update.status) {
|
|
324
|
+
const listStatus = (_a = list.get(key.id)) === null || _a === void 0 ? void 0 : _a.status;
|
|
325
|
+
if (listStatus && (update === null || update === void 0 ? void 0 : update.status) <= listStatus) {
|
|
326
|
+
logger.debug({ update, storedStatus: listStatus }, "status stored newer then update");
|
|
327
|
+
delete update.status;
|
|
328
|
+
logger.debug({ update }, "new update object");
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
const result = list.updateAssign(key.id, update);
|
|
332
|
+
if (!result) {
|
|
333
|
+
logger.debug("got update for non-existent message");
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
ev.on("messages.delete", (item) => {
|
|
338
|
+
if ("all" in item) {
|
|
339
|
+
const list = messages[item.jid];
|
|
340
|
+
list === null || list === void 0 ? void 0 : list.clear();
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
const jid = item.keys[0].remoteJid;
|
|
344
|
+
const list = messages[jid];
|
|
345
|
+
if (list) {
|
|
346
|
+
const idSet = new Set(item.keys.map((k) => k.id));
|
|
347
|
+
list.filter((m) => !idSet.has(m.key.id));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
ev.on("groups.update", (updates) => {
|
|
352
|
+
for (const update of updates) {
|
|
353
|
+
const id = update.id;
|
|
354
|
+
if (groupMetadata[id]) {
|
|
355
|
+
Object.assign(groupMetadata[id], update);
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
logger.debug({ update }, "got update for non-existant group metadata");
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
ev.on("group-participants.update", ({ id, participants, action }) => {
|
|
363
|
+
const metadata = groupMetadata[id];
|
|
364
|
+
if (metadata) {
|
|
365
|
+
switch (action) {
|
|
366
|
+
case "add":
|
|
367
|
+
metadata.participants.push(...participants.map((id) => ({
|
|
368
|
+
id,
|
|
369
|
+
isAdmin: false,
|
|
370
|
+
isSuperAdmin: false,
|
|
371
|
+
})));
|
|
372
|
+
break;
|
|
373
|
+
case "demote":
|
|
374
|
+
case "promote":
|
|
375
|
+
for (const participant of metadata.participants) {
|
|
376
|
+
if (participants.includes(participant.id)) {
|
|
377
|
+
participant.isAdmin = action === "promote";
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
break;
|
|
381
|
+
case "remove":
|
|
382
|
+
metadata.participants = metadata.participants.filter((p) => !participants.includes(p.id));
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
ev.on("message-receipt.update", (updates) => {
|
|
388
|
+
for (const { key, receipt } of updates) {
|
|
389
|
+
const obj = messages[key.remoteJid];
|
|
390
|
+
const msg = obj === null || obj === void 0 ? void 0 : obj.get(key.id);
|
|
391
|
+
if (msg) {
|
|
392
|
+
(0, Utils_1.updateMessageWithReceipt)(msg, receipt);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
ev.on("messages.reaction", (reactions) => {
|
|
397
|
+
for (const { key, reaction } of reactions) {
|
|
398
|
+
const obj = messages[key.remoteJid];
|
|
399
|
+
const msg = obj === null || obj === void 0 ? void 0 : obj.get(key.id);
|
|
400
|
+
if (msg) {
|
|
401
|
+
(0, Utils_1.updateMessageWithReaction)(msg, reaction);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
};
|
|
406
|
+
const toJSON = () => ({
|
|
407
|
+
chats,
|
|
408
|
+
contacts,
|
|
409
|
+
messages,
|
|
410
|
+
labels,
|
|
411
|
+
labelAssociations,
|
|
412
|
+
});
|
|
413
|
+
// TODO: replace upsert logic by corresponding mongodb collection methods
|
|
414
|
+
const fromJSON = async (json) => {
|
|
415
|
+
await chats.updateMany({}, { $set: { ...json.chats } }, { upsert: true });
|
|
416
|
+
await labelAssociations.updateMany({}, { $set: { ...(json.labelAssociations || []) } }, { upsert: true });
|
|
417
|
+
const contactsCollection = db.collection("contacts");
|
|
418
|
+
await contactsCollection.updateMany({}, { $set: { ...Object.values(json.contacts) } }, { upsert: true });
|
|
419
|
+
//
|
|
420
|
+
// contactsUpsert(Object.values(json.contacts))
|
|
421
|
+
labelsUpsert(Object.values(json.labels || {}));
|
|
422
|
+
for (const jid in json.messages) {
|
|
423
|
+
const list = assertMessageList(jid);
|
|
424
|
+
for (const msg of json.messages[jid]) {
|
|
425
|
+
list.upsert(WAProto_1.proto.WebMessageInfo.fromObject(msg), "append");
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
/**
|
|
430
|
+
* Retrieves a chat object by its ID.
|
|
431
|
+
*
|
|
432
|
+
* @param {string} jid - The ID of the chat.
|
|
433
|
+
* @return {Promise<Chat|null>} A promise that resolves to the chat object if found, or null if not found.
|
|
434
|
+
*/
|
|
435
|
+
const getChatById = async (jid) => {
|
|
436
|
+
return await chats.findOne({ id: jid }, { projection: { _id: 0 } });
|
|
437
|
+
};
|
|
438
|
+
return {
|
|
439
|
+
chats,
|
|
440
|
+
contacts,
|
|
441
|
+
messages,
|
|
442
|
+
groupMetadata,
|
|
443
|
+
state,
|
|
444
|
+
presences,
|
|
445
|
+
labels,
|
|
446
|
+
labelAssociations,
|
|
447
|
+
bind,
|
|
448
|
+
/** loads messages from the store, if not found -- uses the legacy connection */
|
|
449
|
+
loadMessages: async (jid, count, cursor) => {
|
|
450
|
+
const list = assertMessageList(jid);
|
|
451
|
+
const mode = !cursor || "before" in cursor ? "before" : "after";
|
|
452
|
+
const cursorKey = !!cursor
|
|
453
|
+
? "before" in cursor
|
|
454
|
+
? cursor.before
|
|
455
|
+
: cursor.after
|
|
456
|
+
: undefined;
|
|
457
|
+
const cursorValue = cursorKey ? list.get(cursorKey.id) : undefined;
|
|
458
|
+
let messages;
|
|
459
|
+
if (list && mode === "before" && (!cursorKey || cursorValue)) {
|
|
460
|
+
if (cursorValue) {
|
|
461
|
+
const msgIdx = list.array.findIndex((m) => m.key.id === (cursorKey === null || cursorKey === void 0 ? void 0 : cursorKey.id));
|
|
462
|
+
messages = list.array.slice(0, msgIdx);
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
messages = list.array;
|
|
466
|
+
}
|
|
467
|
+
const diff = count - messages.length;
|
|
468
|
+
if (diff < 0) {
|
|
469
|
+
messages = messages.slice(-count); // get the last X messages
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
messages = [];
|
|
474
|
+
}
|
|
475
|
+
return messages;
|
|
476
|
+
},
|
|
477
|
+
/**
|
|
478
|
+
* Get all available labels for profile
|
|
479
|
+
*
|
|
480
|
+
* Keep in mind that the list is formed from predefined tags and tags
|
|
481
|
+
* that were "caught" during their editing.
|
|
482
|
+
*/
|
|
483
|
+
getLabels: () => {
|
|
484
|
+
return labels;
|
|
485
|
+
},
|
|
486
|
+
/**
|
|
487
|
+
* Get labels for chat
|
|
488
|
+
*
|
|
489
|
+
* @returns Label IDs
|
|
490
|
+
**/
|
|
491
|
+
getChatLabels: (chatId) => {
|
|
492
|
+
return labelAssociations.findOne((la) => la.chatId === chatId);
|
|
493
|
+
},
|
|
494
|
+
/**
|
|
495
|
+
* Get labels for message
|
|
496
|
+
*
|
|
497
|
+
* @returns Label IDs
|
|
498
|
+
**/
|
|
499
|
+
getMessageLabels: async (messageId) => {
|
|
500
|
+
const associations = labelAssociations.find((la) => la.messageId === messageId);
|
|
501
|
+
return associations === null || associations === void 0 ? void 0 : associations.map(({ labelId }) => labelId);
|
|
502
|
+
},
|
|
503
|
+
loadMessage: async (jid, id) => {
|
|
504
|
+
var _a, _b;
|
|
505
|
+
if (messages[jid]) {
|
|
506
|
+
return messages[jid].get(id);
|
|
507
|
+
}
|
|
508
|
+
const chat = await chats.findOne({ id: jid }, { projection: { _id: 0 } });
|
|
509
|
+
for (const m of (_a = chat === null || chat === void 0 ? void 0 : chat.messages) !== null && _a !== void 0 ? _a : []) {
|
|
510
|
+
if (((_b = m === null || m === void 0 ? void 0 : m.message) === null || _b === void 0 ? void 0 : _b.key.id) === id) {
|
|
511
|
+
return m.message;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
},
|
|
515
|
+
mostRecentMessage: async (jid) => {
|
|
516
|
+
var _a, _b, _c;
|
|
517
|
+
const message = ((_a = messages[jid]) === null || _a === void 0 ? void 0 : _a.array.slice(-1)[0]) ||
|
|
518
|
+
((_c = (_b = (await chats.findOne({ id: jid }, { projection: { _id: 0 } }))) === null || _b === void 0 ? void 0 : _b.messages) === null || _c === void 0 ? void 0 : _c.slice(-1)[0].message) ||
|
|
519
|
+
undefined;
|
|
520
|
+
return message;
|
|
521
|
+
},
|
|
522
|
+
fetchImageUrl: async (jid, sock) => {
|
|
523
|
+
const contact = await contacts.findOne({ id: jid }, { projection: { _id: 0 } });
|
|
524
|
+
if (!contact) {
|
|
525
|
+
return sock === null || sock === void 0 ? void 0 : sock.profilePictureUrl(jid);
|
|
526
|
+
}
|
|
527
|
+
if (typeof contact.imgUrl === "undefined") {
|
|
528
|
+
contact.imgUrl = await (sock === null || sock === void 0 ? void 0 : sock.profilePictureUrl(jid));
|
|
529
|
+
await contacts.updateOne({ id: jid }, { $set: contact }, { upsert: true });
|
|
530
|
+
}
|
|
531
|
+
return contact.imgUrl;
|
|
532
|
+
},
|
|
533
|
+
getContactInfo: async (jid, socket) => {
|
|
534
|
+
const contact = await contacts.findOne({ id: jid }, { projection: { _id: 0 } });
|
|
535
|
+
if (!contact) {
|
|
536
|
+
return {
|
|
537
|
+
id: jid,
|
|
538
|
+
imgUrl: await (socket === null || socket === void 0 ? void 0 : socket.profilePictureUrl(jid)),
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
// fetch image if required
|
|
542
|
+
if (typeof contact.imgUrl === "undefined" ||
|
|
543
|
+
contact.imgUrl === "changed") {
|
|
544
|
+
contact.imgUrl = await (socket === null || socket === void 0 ? void 0 : socket.profilePictureUrl(contact.id, "image"));
|
|
545
|
+
await contacts.updateOne({ id: jid }, { $set: { ...contact } }, { upsert: true });
|
|
546
|
+
}
|
|
547
|
+
return contact;
|
|
548
|
+
},
|
|
549
|
+
fetchGroupMetadata: async (jid, sock) => {
|
|
550
|
+
if (!groupMetadata[jid]) {
|
|
551
|
+
const metadata = await (sock === null || sock === void 0 ? void 0 : sock.groupMetadata(jid));
|
|
552
|
+
if (metadata) {
|
|
553
|
+
groupMetadata[jid] = metadata;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return groupMetadata[jid];
|
|
557
|
+
},
|
|
558
|
+
fetchMessageReceipts: async ({ remoteJid, id }) => {
|
|
559
|
+
const list = messages[remoteJid];
|
|
560
|
+
const msg = list === null || list === void 0 ? void 0 : list.get(id);
|
|
561
|
+
return msg === null || msg === void 0 ? void 0 : msg.userReceipt;
|
|
562
|
+
},
|
|
563
|
+
getChatById,
|
|
564
|
+
toJSON,
|
|
565
|
+
fromJSON,
|
|
566
|
+
};
|
|
567
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function makeOrderedDictionary(idGetter) {
|
|
4
|
+
const array = [];
|
|
5
|
+
const dict = {};
|
|
6
|
+
const get = (id) => dict[id];
|
|
7
|
+
const update = (item) => {
|
|
8
|
+
const id = idGetter(item);
|
|
9
|
+
const idx = array.findIndex(i => idGetter(i) === id);
|
|
10
|
+
if (idx >= 0) {
|
|
11
|
+
array[idx] = item;
|
|
12
|
+
dict[id] = item;
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
};
|
|
16
|
+
const upsert = (item, mode) => {
|
|
17
|
+
const id = idGetter(item);
|
|
18
|
+
if (get(id)) {
|
|
19
|
+
update(item);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
if (mode === 'append') {
|
|
23
|
+
array.push(item);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
array.splice(0, 0, item);
|
|
27
|
+
}
|
|
28
|
+
dict[id] = item;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const remove = (item) => {
|
|
32
|
+
const id = idGetter(item);
|
|
33
|
+
const idx = array.findIndex(i => idGetter(i) === id);
|
|
34
|
+
if (idx >= 0) {
|
|
35
|
+
array.splice(idx, 1);
|
|
36
|
+
delete dict[id];
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
array,
|
|
43
|
+
get,
|
|
44
|
+
upsert,
|
|
45
|
+
update,
|
|
46
|
+
remove,
|
|
47
|
+
updateAssign: (id, update) => {
|
|
48
|
+
const item = get(id);
|
|
49
|
+
if (item) {
|
|
50
|
+
Object.assign(item, update);
|
|
51
|
+
delete dict[id];
|
|
52
|
+
dict[idGetter(item)] = item;
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
},
|
|
57
|
+
clear: () => {
|
|
58
|
+
array.splice(0, array.length);
|
|
59
|
+
for (const key of Object.keys(dict)) {
|
|
60
|
+
delete dict[key];
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
filter: (contain) => {
|
|
64
|
+
let i = 0;
|
|
65
|
+
while (i < array.length) {
|
|
66
|
+
if (!contain(array[i])) {
|
|
67
|
+
delete dict[idGetter(array[i])];
|
|
68
|
+
array.splice(i, 1);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
i += 1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
toJSON: () => array,
|
|
76
|
+
fromJSON: (newItems) => {
|
|
77
|
+
array.splice(0, array.length, ...newItems);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
exports.default = makeOrderedDictionary;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ObjectRepository = void 0;
|
|
4
|
+
class ObjectRepository {
|
|
5
|
+
constructor(entities = {}) {
|
|
6
|
+
this.entityMap = new Map(Object.entries(entities));
|
|
7
|
+
}
|
|
8
|
+
findById(id) {
|
|
9
|
+
return this.entityMap.get(id);
|
|
10
|
+
}
|
|
11
|
+
findAll() {
|
|
12
|
+
return Array.from(this.entityMap.values());
|
|
13
|
+
}
|
|
14
|
+
upsertById(id, entity) {
|
|
15
|
+
return this.entityMap.set(id, { ...entity });
|
|
16
|
+
}
|
|
17
|
+
deleteById(id) {
|
|
18
|
+
return this.entityMap.delete(id);
|
|
19
|
+
}
|
|
20
|
+
count() {
|
|
21
|
+
return this.entityMap.size;
|
|
22
|
+
}
|
|
23
|
+
toJSON() {
|
|
24
|
+
return this.findAll();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.ObjectRepository = ObjectRepository;
|