baileys-bottle-devstroupe
Version:
A little package made by deadlinecode and updated by vspok for storing all the data from baileys in whatever database you want to use by using typeorm
637 lines • 29.5 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const baileys_1 = require("baileys");
const Chat_1 = require("../entity/Chat");
const Contact_1 = require("../entity/Contact");
const Message_1 = require("../entity/Message");
const MessageDic_1 = require("../entity/MessageDic");
const PresenceDic_1 = require("../entity/PresenceDic");
const GroupMetadata_1 = require("../entity/GroupMetadata");
const typeorm_1 = require("typeorm");
const lodash_1 = require("lodash");
const moment_1 = __importDefault(require("moment"));
class StoreHandle {
constructor(ds, auth, options) {
this.ds = ds;
this.auth = auth;
this.options = options;
this.repos = {
contacts: this.ds.getRepository(Contact_1.Contact),
chats: this.ds.getRepository(Chat_1.Chat),
messageDics: this.ds.getRepository(MessageDic_1.MessageDic),
messages: this.ds.getRepository(Message_1.Message),
presenceDics: this.ds.getRepository(PresenceDic_1.PresenceDic),
groups: this.ds.getRepository(GroupMetadata_1.GroupMetadata),
};
this.state = { connection: "close" };
this.chats = {
all: () => this.repos.chats.findBy({
DBAuth: {
id: this.auth.id,
},
}),
id: (id) => this.repos.chats.findOneBy({
id,
DBAuth: {
id: this.auth.id,
},
}),
};
this.contacts = {
all: () => this.repos.contacts.findBy({
DBAuth: {
id: this.auth.id,
},
}),
id: (id) => this.repos.contacts.findOneBy({
id,
DBAuth: {
id: this.auth.id,
},
}),
};
this.messages = {
all: (jid) => __awaiter(this, void 0, void 0, function* () {
var _a;
return (_a = (yield this.repos.messageDics.findOne({
where: {
jid,
DBAuth: {
id: this.auth.id,
},
},
relations: ["messages"],
}))) === null || _a === void 0 ? void 0 : _a.messages;
}),
id: (jid, msgId) => __awaiter(this, void 0, void 0, function* () {
var _a;
return (_a = (yield this.repos.messageDics.findOne({
where: {
jid,
DBAuth: {
id: this.auth.id,
},
},
relations: ["messages"],
}))) === null || _a === void 0 ? void 0 : _a.messages.find((x) => x.msgId === msgId);
}),
};
this.groupMetadata = {
all: () => this.repos.groups.findBy({
DBAuth: {
id: this.auth.id,
},
}),
id: (id) => this.repos.groups.findOneBy({
id,
DBAuth: {
id: this.auth.id,
},
}),
};
this.presence = {
all: (id) => __awaiter(this, void 0, void 0, function* () {
var _a;
return (_a = (yield this.repos.presenceDics.findOne({
where: {
id,
DBAuth: {
id: this.auth.id,
},
},
relations: ["presences"],
}))) === null || _a === void 0 ? void 0 : _a.presences;
}),
id: (id, participant) => __awaiter(this, void 0, void 0, function* () {
var _a;
return (_a = (yield this.repos.presenceDics.findOne({
where: {
id,
DBAuth: {
id: this.auth.id,
},
},
relations: ["presences"],
}))) === null || _a === void 0 ? void 0 : _a.presences.find((x) => x.participant === participant);
}),
};
this.contactsUpsert = (newContacts) => __awaiter(this, void 0, void 0, function* () {
// Atualiza os contatos existentes com os novos dados ou adiciona novos contatos
// for (const contact of newContacts) {
// const contactsOld = await this.repos.contacts.findOneBy({
// DBAuth: {
// id: this.auth.id,
// },
// id: contact.id
// });
// // Se o contato já existe, atualiza-o
// if (contactsOld) {
// this.repos.contacts.update(contactsOld.DBId, Object.assign(contactsOld, contact))
// } else {
// // Se não existe, adiciona-o
// this.repos.contacts.save(Object.assign({ DBAuth: { id: this.auth.id } } as DBContact, contact));
// }
// }
const entities = newContacts.map(c => ({
id: c.id,
name: c.name,
notify: c.notify,
verifiedName: c.verifiedName,
imgUrl: c.imgUrl,
status: c.status,
authId: this.auth.id,
}));
yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
return yield this.repos.contacts.upsert(entities, ["id", "authId"] // chave composta que você definiu no @Unique
);
}));
});
this.assertMessageList = (jid) => __awaiter(this, void 0, void 0, function* () {
// return this.ds.transaction(async (manager) => {
let messageDic = yield this.repos.messageDics.findOne({
where: {
jid,
DBAuth: { id: this.auth.id }
},
});
if (!messageDic) {
messageDic = yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
return yield this.repos.messageDics.save({
jid,
DBAuth: { id: this.auth.id }
});
}));
}
return messageDic;
// });
});
this.bind = (ev) => {
ev.on("connection.update", (update) => Object.assign(this.state, update));
ev.on("messaging-history.set", (_a) => __awaiter(this, [_a], void 0, function* ({ chats: newChats, contacts: newContacts, messages: newMessages, isLatest, }) {
var _b;
// if(isLatest) {
try {
let messages = (0, lodash_1.cloneDeep)(newMessages);
if (!isLatest) {
messages = messages.filter(message => ((typeof message.messageTimestamp == 'number' ? message.messageTimestamp : message.messageTimestamp.low) * 1000) >
(0, moment_1.default)().subtract(1, 'days').valueOf());
}
yield this.contactsUpsert(newContacts);
// console.log(messages.length, 'count');
for (let index = 0; index < messages.length; index++) {
const msg = messages[index];
// }
// for (const msg of newMessages) {
const jid = msg.key.remoteJid;
// Realiza a consulta diretamente no banco de dados para verificar se a mensagem já existe
const existingMessage = yield this.repos.messages.findOne({
where: {
msgId: msg.key.id,
dictionary: {
jid,
DBAuth: { id: this.auth.id }
},
},
});
if (!existingMessage) {
// Se a mensagem não existir, salva-a no banco de dados
yield this.repos.messages.save(Object.assign(Object.assign({}, msg), { msgId: (_b = msg.key) === null || _b === void 0 ? void 0 : _b.id, dictionary: yield this.assertMessageList(jid) }));
continue;
}
// Se a mensagem já existir, atualiza-a
Object.assign(existingMessage, msg);
yield this.repos.messages.save(existingMessage);
}
}
catch (error) {
console.error(error);
}
// }
}));
ev.on("contacts.upsert", (contacts) => __awaiter(this, void 0, void 0, function* () {
this.contactsUpsert(contacts);
}));
ev.on("contacts.update", (contacts) => __awaiter(this, void 0, void 0, function* () {
this.contactsUpsert(contacts);
}));
ev.on("chats.upsert", (newChats) => __awaiter(this, void 0, void 0, function* () {
try {
// for (const chat of newChats) {
// let chat_db = await this.repos.chats.findOne({
// where: {
// id: chat.id,
// DBAuth: { id: this.auth.id },
// },
// });
// if (!chat_db) {
// this.repos.chats.save({
// ...chat,
// DBAuth: { id: this.auth.id },
// })
// }
// }
const entities = newChats.map(c => ({
id: c.id,
conversationTimestamp: c.conversationTimestamp,
unreadCount: c.unreadCount,
authId: this.auth.id,
}));
// insere ou atualiza em lote
yield this.repos.chats.upsert(entities, ["id", "authId"]);
}
catch (_a) { }
}));
ev.on("chats.update", (updates) => __awaiter(this, void 0, void 0, function* () {
for (let update of updates) {
var chat = yield this.repos.chats.findOneBy({
id: update.id,
DBAuth: { id: this.auth.id },
});
if (!chat)
return;
if (update.unreadCount > 0) {
update = Object.assign({}, update);
update.unreadCount = (chat.unreadCount || 0) + update.unreadCount;
}
Object.assign(chat, update);
yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
yield this.repos.chats.save(chat);
}));
}
}));
ev.on("presence.update", (_a) => __awaiter(this, [_a], void 0, function* ({ id, presences: update }) {
var chat = (yield this.repos.presenceDics.findOne({
where: {
id,
DBAuth: { id: this.auth.id },
},
relations: ["presences"],
})) ||
{
id,
presences: [],
DBAuth: { id: this.auth.id },
};
Object.entries(update).forEach(([id, presence]) => {
var participant = chat.presences.find((x) => x.participant === id);
participant
? Object.assign(participant, presence)
: chat.presences.push(Object.assign(Object.assign({}, presence), { participant: id }));
});
try {
yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
yield this.repos.presenceDics.save(chat);
}));
}
catch (_b) { }
}));
ev.on("chats.delete", (deletions) => __awaiter(this, void 0, void 0, function* () {
return !this.options.disableDelete.includes("chats") &&
Promise.all(deletions.map((id) => this.repos.chats.delete({
id,
DBAuth: { id: this.auth.id },
})));
}));
ev.on("messages.upsert", (_a) => __awaiter(this, [_a], void 0, function* ({ messages: newMessages, type }) {
if (type !== "append" && type !== "notify") {
return;
}
for (const msg of newMessages) {
const jid = (0, baileys_1.jidNormalizedUser)(msg.key.remoteJid);
// Verifica se a mensagem já existe no dicionário
const existingMessage = yield this.repos.messages.findOne({
where: {
msgId: msg.key.id,
dictionary: {
jid,
DBAuth: { id: this.auth.id }
},
},
});
if (!existingMessage) {
// Se a mensagem não existir, salva-a no banco de dados
yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
var _a;
yield this.repos.messages.save(Object.assign(Object.assign({}, msg), { msgId: (_a = msg.key) === null || _a === void 0 ? void 0 : _a.id, dictionary: yield this.assertMessageList(jid) }));
}));
// Emite um evento de atualização do chat se for uma notificação
if (type === "notify") {
const chat = yield this.repos.chats.findOneBy({
id: jid,
DBAuth: { id: this.auth.id },
});
if (!chat) {
ev.emit("chats.upsert", [
{
id: jid,
conversationTimestamp: (0, baileys_1.toNumber)(msg.messageTimestamp),
unreadCount: 1,
},
]);
}
}
}
else {
// Se a mensagem já existir, atualiza-a
Object.assign(existingMessage, msg);
yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
yield this.repos.messages.save(existingMessage);
}));
}
}
}));
ev.on("messages.update", (updates) => __awaiter(this, void 0, void 0, function* () {
for (const { update, key } of updates) {
const jid = key.remoteJid;
// Verifica se a mensagem existe no dicionário
const message = yield this.repos.messages.findOne({
where: {
msgId: key.id,
dictionary: {
jid,
DBAuth: { id: this.auth.id }
},
},
});
if (message) {
// Se a mensagem existir, atualiza-a
Object.assign(message, update);
yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
yield this.repos.messages.save(message);
}));
}
}
}));
ev.on("messages.delete", (item) => __awaiter(this, void 0, void 0, function* () {
if (this.options.disableDelete.includes("messages"))
return;
if ("all" in item) {
const dictionary = yield this.repos.messageDics.findOne({
where: {
jid: item.jid,
DBAuth: { id: this.auth.id },
},
relations: ["messages"],
});
if (!dictionary)
return;
this.repos.messages.remove(dictionary.messages);
}
else {
const jid = item.keys[0].remoteJid;
const dictionary = yield this.repos.messageDics.findOne({
where: {
jid,
DBAuth: { id: this.auth.id },
},
relations: ["messages"],
});
if (!dictionary)
return;
const idSet = new Set(item.keys.map((k) => k.id));
yield this.repos.messages.remove(dictionary.messages.filter((msg) => Array.from(idSet).includes(msg.msgId)));
}
}));
ev.on("groups.update", (updates) => __awaiter(this, void 0, void 0, function* () {
for (const update of updates) {
const id = update.id;
let group = yield this.repos.groups.findOneBy({
id,
DBAuth: { id: this.auth.id },
});
if (!group)
return;
Object.assign(group, update);
yield this.repos.groups.save(group);
}
}));
ev.on("group-participants.update", (_a) => __awaiter(this, [_a], void 0, function* ({ id, participants, action }) {
const metadata = yield this.repos.groups.findOneBy({
id,
DBAuth: { id: this.auth.id },
});
if (!metadata)
return;
switch (action) {
case "add":
metadata.participants.push(...participants.map((id) => ({
id,
isAdmin: false,
isSuperAdmin: false,
})));
break;
case "demote":
case "promote":
metadata.participants.forEach((participant) => participants.includes(participant.id) &&
(participant.isAdmin = action === "promote"));
break;
case "remove":
metadata.participants = metadata.participants.filter((p) => !participants.includes(p.id));
break;
}
yield this.repos.groups.save(metadata);
}));
ev.on("message-receipt.update", (updates) => __awaiter(this, void 0, void 0, function* () {
for (const { key, receipt } of updates) {
const dictionary = yield this.repos.messageDics.findOne({
where: {
jid: key.remoteJid,
DBAuth: { id: this.auth.id },
},
relations: ["messages"],
});
if (!dictionary)
return;
const msg = dictionary.messages.find((x) => x.key.id === key.id);
if (!msg)
continue;
(0, baileys_1.updateMessageWithReceipt)(msg, receipt);
yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
yield this.repos.messageDics.save(dictionary);
}));
}
}));
ev.on("messages.reaction", (reactions) => __awaiter(this, void 0, void 0, function* () {
for (const { key, reaction } of reactions) {
const dictionary = yield this.repos.messageDics.findOne({
where: {
jid: key.remoteJid,
DBAuth: { id: this.auth.id },
},
relations: ["messages"],
});
if (!dictionary)
return;
const msg = dictionary.messages.find((x) => x.key.id === key.id);
if (!msg)
continue;
(0, baileys_1.updateMessageWithReaction)(msg, reaction);
yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
yield this.repos.messageDics.save(dictionary);
}));
}
}));
};
this.loadMessages = (jid, count, cursor) => __awaiter(this, void 0, void 0, function* () {
const dictionary = yield this.repos.messageDics.findOne({
where: {
jid,
DBAuth: { id: this.auth.id }
},
relations: ["messages"],
});
if (!dictionary) {
return [];
}
const mode = !cursor || "before" in cursor ? "before" : "after";
const cursorKey = cursor && "before" in cursor ? cursor.before : cursor === null || cursor === void 0 ? void 0 : cursor['after'];
const cursorValue = cursorKey
? dictionary.messages.find((x) => x.msgId === cursorKey.id)
: undefined;
let messages = [];
if (mode === "before" && (!cursorKey || cursorValue)) {
if (cursorValue) {
const msgIdx = dictionary.messages.findIndex((m) => m.key.id === (cursorKey === null || cursorKey === void 0 ? void 0 : cursorKey.id));
messages = dictionary.messages.slice(Math.max(0, msgIdx - count), msgIdx);
}
else {
messages = dictionary.messages;
}
const diff = count - messages.length;
if (diff > 0) {
const remainingMessages = yield this.repos.messages.find({
where: {
id: (0, typeorm_1.In)(dictionary.messages.map((msg) => msg.id)),
msgId: (0, typeorm_1.LessThan)(messages[0].msgId),
},
order: {
msgId: "DESC",
},
take: diff,
});
messages = remainingMessages.concat(messages);
}
}
return messages;
});
// loadMessage = async (
// jid: string,
// id: string
// ): Promise<DBMessage | undefined> =>
// (
// // await this.repos.messageDics.findOne({
// // where: {
// // jid,
// // DBAuth: { id: this.auth.id },
// // },
// // relations: ["messages"],
// // })
// await this.repos.messageDics.createQueryBuilder("dic")
// .leftJoinAndSelect("dic.DBAuth", "auth")
// .leftJoinAndSelect("dic.messages", "messages")
// .where("dic.jid = :jid", { jid })
// .andWhere("auth.id = :id", { id: this.auth.id })
// .andWhere("messages.msgId = :id", { id })
// .getOne()
// )?.messages.find((x) => x.msgId === id);
this.loadMessage = (jid, id) => __awaiter(this, void 0, void 0, function* () {
const message = yield this.repos.messages.findOne({
where: {
msgId: id,
dictionary: {
jid,
// DBAuth: this.auth,
DBAuth: { id: this.auth.id }
},
},
});
return message;
});
this.mostRecentMessage = (jid) => __awaiter(this, void 0, void 0, function* () {
const message = yield this.repos.messages.findOne({
where: {
dictionary: {
jid,
DBAuth: { id: this.auth.id }
},
},
order: {
msgId: "DESC",
},
});
return message;
});
this.fetchImageUrl = (jid, sock) => __awaiter(this, void 0, void 0, function* () {
const contact = yield this.repos.contacts.findOne({ where: { id: jid } });
if (!contact)
return sock === null || sock === void 0 ? void 0 : sock.profilePictureUrl(jid);
if (typeof contact.imgUrl === "undefined")
yield this.repos.contacts.save(Object.assign(Object.assign({}, contact), { imgUrl: yield (sock === null || sock === void 0 ? void 0 : sock.profilePictureUrl(jid)) }));
return contact.imgUrl;
});
this.fetchGroupMetadata = (jid, sock) => __awaiter(this, void 0, void 0, function* () {
var group = yield this.repos.groups.findOneBy({
id: jid,
DBAuth: { id: this.auth.id },
});
if (!group) {
const metadata = yield (sock === null || sock === void 0 ? void 0 : sock.groupMetadata(jid).catch((error) => console.log('fetchGroupMetadata groupMetadata error', error)));
metadata && (group = yield this.retryOperation(() => __awaiter(this, void 0, void 0, function* () {
return yield this.repos.groups.save(Object.assign(Object.assign({}, metadata), { DBAuth: { id: this.auth.id } }));
})));
}
return group;
});
this.fetchMessageReceipts = (_a) => __awaiter(this, [_a], void 0, function* ({ remoteJid, id }) {
const receipt = yield this.repos.messages.findOne({
// relations: {
// dictionary: true,
// },
where: {
msgId: id,
dictionary: {
jid: remoteJid,
DBAuth: { id: this.auth.id }
},
},
select: ["userReceipt"],
});
return receipt === null || receipt === void 0 ? void 0 : receipt.userReceipt;
});
this.options = Object.assign({ disableDelete: [] }, (this.options || {}));
}
retryOperation(operation_1) {
return __awaiter(this, arguments, void 0, function* (operation, maxRetries = 3, delay = 100) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return yield operation();
}
catch (error) {
if (error.code === 'SQLITE_BUSY' && attempt < maxRetries) {
console.warn(`Database busy, retrying (${attempt}/${maxRetries})...`);
yield this.sleep(delay * attempt); // Backoff exponencial
continue;
}
throw error;
}
}
});
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
exports.default = StoreHandle;
//# sourceMappingURL=StoreHandle.js.map