From df31fe2a8ba90813b4801be15ea1ba1bc63ea6ec Mon Sep 17 00:00:00 2001 From: devlikepro Date: Thu, 1 Aug 2024 11:51:45 +0700 Subject: [PATCH] [core] NOWEB labels --- src/core/engines/noweb/session.noweb.core.ts | 106 +++++++++++++++++- .../engines/noweb/store/IChatRepository.ts | 2 + .../store/ILabelAssociationsRepository.ts | 19 ++++ .../engines/noweb/store/ILabelsRepository.ts | 14 +++ src/core/engines/noweb/store/INowebStorage.ts | 37 +++++- src/core/engines/noweb/store/INowebStore.ts | 9 ++ .../engines/noweb/store/NowebInMemoryStore.ts | 17 +++ .../noweb/store/NowebPersistentStore.ts | 61 +++++++++- src/core/engines/noweb/store/Schema.ts | 22 ++++ .../store/sqlite3/Sqlite3KVRepository.ts | 9 ++ .../Sqlite3LabelAssociationsRepository.ts | 40 +++++++ .../store/sqlite3/Sqlite3LabelsRepository.ts | 8 ++ .../noweb/store/sqlite3/Sqlite3Storage.ts | 53 ++++++++- src/core/engines/webjs/session.webjs.core.ts | 4 +- src/structures/enums.dto.ts | 4 + src/structures/labels.dto.ts | 52 +++++++++ src/structures/webhooks.dto.ts | 43 +++++++ yarn.lock | 4 +- 18 files changed, 485 insertions(+), 19 deletions(-) create mode 100644 src/core/engines/noweb/store/ILabelAssociationsRepository.ts create mode 100644 src/core/engines/noweb/store/ILabelsRepository.ts create mode 100644 src/core/engines/noweb/store/sqlite3/Sqlite3LabelAssociationsRepository.ts create mode 100644 src/core/engines/noweb/store/sqlite3/Sqlite3LabelsRepository.ts diff --git a/src/core/engines/noweb/session.noweb.core.ts b/src/core/engines/noweb/session.noweb.core.ts index 9bb18a5d..64614ad5 100644 --- a/src/core/engines/noweb/session.noweb.core.ts +++ b/src/core/engines/noweb/session.noweb.core.ts @@ -11,7 +11,6 @@ import makeWASocket, { isRealMessage, jidNormalizedUser, makeCacheableSignalKeyStore, - MinimalMessage, NewsletterMetadata, normalizeMessageContent, PresenceData, @@ -20,6 +19,8 @@ import makeWASocket, { WAMessageKey, } from '@adiwajshing/baileys'; import { WACallEvent } from '@adiwajshing/baileys/lib/Types/Call'; +import { Label as NOWEBLabel } from '@adiwajshing/baileys/lib/Types/Label'; +import { LabelAssociationType } from '@adiwajshing/baileys/lib/Types/LabelAssociation'; import { isLidUser } from '@adiwajshing/baileys/lib/WABinary/jid-utils'; import { Logger as BaileysLogger } from '@adiwajshing/baileys/node_modules/pino'; import { UnprocessableEntityException } from '@nestjs/common'; @@ -35,7 +36,11 @@ import { } from '@waha/structures/channels.dto'; import { GetChatsQuery } from '@waha/structures/chats.dto'; import { ContactQuery, ContactRequest } from '@waha/structures/contacts.dto'; -import { Label } from '@waha/structures/labels.dto'; +import { + Label, + LabelChatAssociation, + LabelID, +} from '@waha/structures/labels.dto'; import { PollVote, PollVotePayload, @@ -728,8 +733,47 @@ export class WhatsappSessionNoWebCore extends WhatsappSession { * Labels methods */ - public getLabels(): Promise { - throw new NotImplementedByEngineError(); + public async getLabels(): Promise { + const labels = await this.store.getLabels(); + return labels.map(this.toLabel); + } + + public async getChatsByLabelId(labelId: string) { + const chats = await this.store.getChatsByLabelId(labelId); + // Remove unreadCount, it's not ready yet + chats.forEach((chat) => delete chat.unreadCount); + return chats; + } + + public async getChatLabels(chatId: string): Promise { + const jid = toJID(chatId); + const labels = await this.store.getChatLabels(jid); + return labels.map(this.toLabel); + } + + public async putLabelsToChat(chatId: string, labels: LabelID[]) { + const jid = toJID(chatId); + const labelsIds = labels.map((label) => label.id); + const currentLabels = await this.store.getChatLabels(jid); + const currentLabelsIds = currentLabels.map((label) => label.id); + const addLabelsIds = lodash.difference(labelsIds, currentLabelsIds); + const removeLabelsIds = lodash.difference(currentLabelsIds, labelsIds); + for (const labelId of addLabelsIds) { + await this.sock.addChatLabel(jid, labelId); + } + for (const labelId of removeLabelsIds) { + await this.sock.removeChatLabel(jid, labelId); + } + } + + protected toLabel(label: NOWEBLabel): Label { + const color = label.color; + return { + id: label.id, + name: label.name, + color: color, + colorHex: Label.toHex(color), + }; } /** @@ -1084,6 +1128,60 @@ export class WhatsappSessionNoWebCore extends WhatsappSession { } }); return true; + case WAHAEvents.LABEL_UPSERT: + this.sock.ev.on('labels.edit', (data: NOWEBLabel) => { + if (data.deleted) { + return; + } + const body = this.toLabel(data); + handler(body); + }); + return true; + case WAHAEvents.LABEL_REMOVED: + this.sock.ev.on('labels.edit', (data: NOWEBLabel) => { + if (!data.deleted) { + return; + } + const body = this.toLabel(data); + handler(body); + }); + return true; + case WAHAEvents.LABEL_CHAT_ADDED: + this.sock.ev.on('labels.association', async ({ association, type }) => { + if (type !== 'add') { + return; + } + if (association.type !== LabelAssociationType.Chat) { + return; + } + const labelData = await this.store.getLabelById(association.labelId); + const label = labelData ? this.toLabel(labelData) : null; + const body: LabelChatAssociation = { + labelId: association.labelId, + chatId: association.chatId, + label: label, + }; + handler(body); + }); + return true; + case WAHAEvents.LABEL_CHAT_REMOVED: + this.sock.ev.on('labels.association', async ({ association, type }) => { + if (type !== 'remove') { + return; + } + if (association.type !== LabelAssociationType.Chat) { + return; + } + const labelData = await this.store.getLabelById(association.labelId); + const label = labelData ? this.toLabel(labelData) : null; + const body: LabelChatAssociation = { + labelId: association.labelId, + chatId: association.chatId, + label: label, + }; + handler(body); + }); + return true; default: return false; } diff --git a/src/core/engines/noweb/store/IChatRepository.ts b/src/core/engines/noweb/store/IChatRepository.ts index e80b3c1e..a856bebd 100644 --- a/src/core/engines/noweb/store/IChatRepository.ts +++ b/src/core/engines/noweb/store/IChatRepository.ts @@ -3,6 +3,8 @@ import { Chat } from '@adiwajshing/baileys'; export interface IChatRepository { getAll(): Promise; + getAllByIds(ids: string[]): Promise; + getAllWithMessages(limit?: number, offset?: number): Promise; getById(id: string): Promise; diff --git a/src/core/engines/noweb/store/ILabelAssociationsRepository.ts b/src/core/engines/noweb/store/ILabelAssociationsRepository.ts new file mode 100644 index 00000000..8fa8204c --- /dev/null +++ b/src/core/engines/noweb/store/ILabelAssociationsRepository.ts @@ -0,0 +1,19 @@ +import { + LabelAssociation, + LabelAssociationType, +} from '@adiwajshing/baileys/lib/Types/LabelAssociation'; + +export interface ILabelAssociationRepository { + deleteOne(association: LabelAssociation): Promise; + + save(association: LabelAssociation): Promise; + + deleteByLabelId(labelId: string): Promise; + + getAssociationsByLabelId( + labelId: string, + type: LabelAssociationType, + ): Promise; + + getAssociationsByChatId(chatId: string): Promise; +} diff --git a/src/core/engines/noweb/store/ILabelsRepository.ts b/src/core/engines/noweb/store/ILabelsRepository.ts new file mode 100644 index 00000000..62184cc0 --- /dev/null +++ b/src/core/engines/noweb/store/ILabelsRepository.ts @@ -0,0 +1,14 @@ +import { Contact } from '@adiwajshing/baileys'; +import { Label } from '@adiwajshing/baileys/lib/Types/Label'; + +export interface ILabelsRepository { + getById(id: string): Promise