From 5a7077c675948e54ae59c752bfa5e2bf392240b3 Mon Sep 17 00:00:00 2001 From: Edgard Date: Mon, 14 Dec 2020 23:01:14 -0300 Subject: [PATCH] Added method to clear chat and star/unstar message --- src/Tests/Tests.Misc.ts | 60 +++++++++++++++++++++++ src/WAConnection/7.MessagesExtra.ts | 74 ++++++++++++++++++++++++++--- src/WAConnection/Constants.ts | 4 +- 3 files changed, 130 insertions(+), 8 deletions(-) diff --git a/src/Tests/Tests.Misc.ts b/src/Tests/Tests.Misc.ts index 047f95d..23fc234 100644 --- a/src/Tests/Tests.Misc.ts +++ b/src/Tests/Tests.Misc.ts @@ -116,6 +116,66 @@ WAConnectionTest('Misc', conn => { await delay (2000) await conn.modifyChat (testJid, ChatModification.unmute) }) + it('should star/unchar messages', async () => { + for (let i = 1; i <= 5; i++) { + await conn.sendMessage(testJid, `Message ${i}`, MessageType.text) + await delay(1000) + } + + let response = await conn.loadMessages(testJid, 5) + let starred = response.messages.filter(m => m.starred) + assert.strictEqual(starred.length, 0) + + conn.starMessage(response.messages[2].key) + await delay(2000) + conn.starMessage(response.messages[4].key) + await delay(2000) + + response = await conn.loadMessages(testJid, 5) + starred = response.messages.filter(m => m.starred) + assert.strictEqual(starred.length, 2) + await delay(2000) + + conn.starMessage(response.messages[2].key, 'unstar') + await delay(2000) + + response = await conn.loadMessages(testJid, 5) + starred = response.messages.filter(m => m.starred) + assert.strictEqual(starred.length, 1) + }) + it('should clear a chat', async () => { + // Uses chat with yourself to avoid losing chats + const selfJid = conn.user.jid + + for (let i = 1; i <= 5; i++) { + await conn.sendMessage(selfJid, `Message ${i}`, MessageType.text) + await delay(1000) + } + + let response = await conn.loadMessages(selfJid, 50) + const initialCount = response.messages.length + + assert.ok(response.messages.length >= 0) + + conn.starMessage(response.messages[2].key) + await delay(2000) + conn.starMessage(response.messages[4].key) + await delay(2000) + + await conn.modifyChat(selfJid, ChatModification.clear) + await delay(2000) + + response = await conn.loadMessages(selfJid, 50) + await delay(2000) + assert.ok(response.messages.length < initialCount) + assert.ok(response.messages.length > 1) + + await conn.modifyChat(selfJid, ChatModification.clear, true) + await delay(2000) + + response = await conn.loadMessages(selfJid, 50) + assert.strictEqual(response.messages.length, 1) + }) it('should return search results', async () => { const jids = [null, testJid] for (let i in jids) { diff --git a/src/WAConnection/7.MessagesExtra.ts b/src/WAConnection/7.MessagesExtra.ts index 993039b..67789ac 100644 --- a/src/WAConnection/7.MessagesExtra.ts +++ b/src/WAConnection/7.MessagesExtra.ts @@ -1,6 +1,6 @@ import {WAConnection as Base} from './6.MessagesSend' -import { MessageType, WAMessageKey, MessageInfo, WAMessageContent, WAMetric, WAFlag, WANode, WAMessage, WAMessageProto, ChatModification, BaileysError, WAChatIndex } from './Constants' -import { whatsappID, delay, toNumber, unixTimestampSeconds, GET_MESSAGE_ID, WA_MESSAGE_ID, isGroupID } from './Utils' +import { MessageType, WAMessageKey, MessageInfo, WAMessageContent, WAMetric, WAFlag, WANode, WAMessage, WAMessageProto, ChatModification, BaileysError, WAChatIndex, WAChat } from './Constants' +import { whatsappID, delay, toNumber, unixTimestampSeconds, GET_MESSAGE_ID, WA_MESSAGE_ID, isGroupID, newMessagesDB } from './Utils' import { Mutex } from './Mutex' export class WAConnection extends Base { @@ -285,6 +285,38 @@ export class WAConnection extends Base { } return result } + /** + * Star or unstar a message + * @param messageKey key of the message you want to star or unstar + */ + @Mutex (m => m.remoteJid) + async starMessage (messageKey: WAMessageKey, type: 'star' | 'unstar' = 'star') { + const attrs: WANode = [ + 'chat', + { + jid: messageKey.remoteJid, + type + }, + [ + ['item', {owner: `${messageKey.fromMe}`, index: messageKey.id}, null] + ] + ] + const result = await this.setQuery ([attrs]) + + const chat = this.chats.get (whatsappID(messageKey.remoteJid)) + if (result.status == 200 && chat) { + const message = chat.messages.get (GET_MESSAGE_ID(messageKey)) + if (message) { + message.starred = type === 'star' + + const chatUpdate: Partial = { jid: messageKey.remoteJid, messages: newMessagesDB([ message ]) } + this.emit ('chat-update', chatUpdate) + // emit deprecated + this.emit ('message-update', message) + } + } + return result + } /** * Delete a message in a chat for everyone * @param id the person or group where you're trying to delete the message @@ -344,25 +376,39 @@ export class WAConnection extends Base { deleteChat (jid: string) { return this.modifyChat(jid, 'delete') } + /** + * Clear the chat messages + * @param jid the ID of the person/group you are modifiying + * @param includeStarred delete starred messages, default false + */ + async modifyChat (jid: string, type: ChatModification.clear, includeStarred?: boolean): Promise<{status: number;}>; /** * Modify a given chat (archive, pin etc.) * @param jid the ID of the person/group you are modifiying * @param durationMs only for muting, how long to mute the chat for */ + async modifyChat (jid: string, type: ChatModification.pin | ChatModification.mute, durationMs: number): Promise<{status: number;}>; + /** + * Modify a given chat (archive, pin etc.) + * @param jid the ID of the person/group you are modifiying + */ + async modifyChat (jid: string, type: ChatModification | (keyof typeof ChatModification)): Promise<{status: number;}>; @Mutex ((jid, type) => jid+type) - async modifyChat (jid: string, type: ChatModification | (keyof typeof ChatModification), durationMs?: number) { + async modifyChat (jid: string, type: (keyof typeof ChatModification), arg?: number | boolean): Promise<{status: number;}> { jid = whatsappID (jid) const chat = this.assertChatGet (jid) let chatAttrs: Record = {jid: jid} - if (type === ChatModification.mute && !durationMs) { + if (type === ChatModification.mute && !arg) { throw new BaileysError( 'duration must be set to the timestamp of the time of pinning/unpinning of the chat', { status: 400 } ) } - durationMs = durationMs || 0 + const durationMs:number = arg as number || 0 + const includeStarred:boolean = arg as boolean + let index: WAChatIndex; switch (type) { case ChatModification.pin: case ChatModification.mute: @@ -375,16 +421,30 @@ export class WAConnection extends Base { chatAttrs.type = type.replace ('un', '') // replace 'unpin' with 'pin' chatAttrs.previous = chat[type.replace ('un', '')] break + case ChatModification.clear: + chatAttrs.type = type + chatAttrs.star = includeStarred ? 'true' : 'false' + index = await this.getChatIndex(jid) + chatAttrs = { ...chatAttrs, ...index } + delete chatAttrs.participant + break default: chatAttrs.type = type - const index = await this.getChatIndex(jid) + index = await this.getChatIndex(jid) chatAttrs = { ...chatAttrs, ...index } break } const response = await this.setQuery ([['chat', chatAttrs, null]], [ WAMetric.chat, WAFlag.ignore ]) - if (chat) { + if (chat && response.status === 200) { + if (type === ChatModification.clear) { + if (includeStarred) { + chat.messages.clear () + } else { + chat.messages = chat.messages.filter(m => m.starred) + } + } if (type.includes('un')) { type = type.replace ('un', '') as ChatModification delete chat[type.replace('un','')] diff --git a/src/WAConnection/Constants.ts b/src/WAConnection/Constants.ts index 46f87ba..b495514 100644 --- a/src/WAConnection/Constants.ts +++ b/src/WAConnection/Constants.ts @@ -219,6 +219,7 @@ export interface WAChat { /** number of unread messages, is < 0 if the chat is manually marked unread */ count: number archive?: 'true' | 'false' + clear?: 'true' | 'false' read_only?: 'true' | 'false' mute?: string pin?: string @@ -321,7 +322,8 @@ export enum ChatModification { unpin='unpin', mute='mute', unmute='unmute', - delete='delete' + delete='delete', + clear='clear' } export const HKDFInfoKeys = { [MessageType.image]: 'WhatsApp Image Keys',