From da73905b5e504a806a72d904e118976d780fe7aa Mon Sep 17 00:00:00 2001 From: Adhiraj Date: Sun, 19 Jul 2020 13:21:44 +0530 Subject: [PATCH] Depracations + Semantic Changes --- Example/example.ts | 13 ++++++----- README.md | 43 +++++++++++++++++++++++++++-------- src/Binary/Decoder.ts | 2 +- src/Binary/Encoder.ts | 2 +- src/WAClient/Constants.ts | 18 +++++++++------ src/WAClient/Groups.ts | 2 +- src/WAClient/Messages.ts | 9 +++++++- src/WAClient/Tests.ts | 2 +- src/WAClient/Utils.ts | 5 +++- src/WAConnection/Constants.ts | 3 +-- 10 files changed, 68 insertions(+), 31 deletions(-) diff --git a/Example/example.ts b/Example/example.ts index a6a9c10..d75af81 100644 --- a/Example/example.ts +++ b/Example/example.ts @@ -1,6 +1,5 @@ import { WAClient, - getNotificationType, MessageType, decodeMediaMessage, Presence, @@ -8,6 +7,7 @@ import { Mimetype, WALocationMessage, MessageLogLevel, + WAMessageType, } from '../src/WAClient/WAClient' import * as fs from 'fs' @@ -34,12 +34,12 @@ async function example() { }) // set to false to NOT relay your own sent messages client.setOnUnreadMessage(true, async (m) => { - const [notificationType, messageType] = getNotificationType(m) // get what type of notification it is -- message, group add notification etc. - console.log('got notification of type: ' + notificationType) + const messageStubType = WAMessageType[m.messageStubType] || 'MESSAGE' + console.log('got notification of type: ' + messageStubType) - if (notificationType !== 'message') { - return - } + const messageContent = m.message + // if it is not a regular text or media message + if (!messageContent) return if (m.key.fromMe) { console.log('relayed my own message') return @@ -50,6 +50,7 @@ async function example() { // participant exists if the message is in a group sender += ' (' + m.key.participant + ')' } + const messageType = Object.keys (messageContent)[0] // message will always contain one key signifying what kind of message if (messageType === MessageType.text) { const text = m.message.conversation console.log(sender + ' sent: ' + text) diff --git a/README.md b/README.md index 8dc12f0..9b2198a 100644 --- a/README.md +++ b/README.md @@ -232,12 +232,14 @@ await client.sendReadReceipt(id, null, 'unread') // mark the chat as unread - On a `WAMessage`, the `messageID` can be accessed using ```messageID = message.key.id```. ## Update Presence + ``` ts -client.updatePresence(id, WhatsAppWeb.Presence.available) +import { Presence } from '@adiwajshing/baileys' + +client.updatePresence(id, Presence.available) ``` This lets the person/group with ``` id ``` know whether you're online, offline, typing etc. where ``` presence ``` can be one of the following: ``` ts -// call: import { Presence } from '@adiwajshing/baileys' export enum Presence { available = 'available', // "online" unavailable = 'unavailable', // "offline" @@ -250,9 +252,11 @@ export enum Presence { ## Decoding Media If you want to save & process some images, videos, documents or stickers you received ``` ts -import { getNotificationType, MessageType } from '@adiwajshing/baileys' +import { MessageType } from '@adiwajshing/baileys' client.setOnUnreadMessage (false, async m => { - const messageType = getNotificationType(m.message) // get what type of message it is -- text, image, video + if (!m.message) return // if there is no text or media message + + const messageType = Object.keys (m.message)[0]// get what type of message it is -- text, image, video // if the message is not a text message if (messageType !== MessageType.text && messageType !== MessageType.extendedText) { const savedFilename = await client.decodeMediaMessage(m.message, "filename") // extension applied automatically @@ -266,7 +270,9 @@ client.setOnUnreadMessage (false, async m => { ``` ts const jid = '1234@s.whatsapp.net' // can also be a group const response = await client.sendMessage (jid, 'hello!', MessageType.text) // send a message -await client.deleteMessage (jid, {id: response.messageID, remoteJid: jid, fromMe: true}) // will delete the sent message! + +await client.deleteMessage (jid, {id: response.messageID, remoteJid: jid, fromMe: true}) // will delete the sent message for everyone! +await client.clearMessage (jid, {id: response.messageID, remoteJid: jid, fromMe: true}) // will delete the sent message for only you! ``` ## Modifying Chats @@ -284,9 +290,12 @@ await client.modifyChat (jid, ChatModification.mute, {stamp: mutedate}) // mute setTimeout (() => { client.modifyChat (jid, ChatModification.unmute, {stamp: mutedate}) }, 5000) // unmute after 5 seconds + +await client.deleteChat (jid) // will delete the chat (can be a group or broadcast list) ``` **Note:** to unmute or unpin a chat, one must pass the timestamp of the pinning or muting. This is returned by the pin & mute functions. This is also available in the `WAChat` objects of the respective chats, as a `mute` or `pin` property. + ## Querying - To check if a given ID is on WhatsApp ``` ts @@ -332,11 +341,6 @@ Of course, replace ``` xyz ``` with an actual ID. Append ``` @s.whatsapp.net ``` for individuals & ``` @g.us ``` for groups. ## Groups -- To query the metadata of a group - ``` ts - const metadata = await client.groupMetadata ("abcd-xyz@g.us") - console.log(json.id + ", title: " + json.subject + ", description: " + json.desc) - ``` - To create a group ``` ts // title & participants @@ -363,6 +367,25 @@ Append ``` @s.whatsapp.net ``` for individuals & ``` @g.us ``` for groups. const code = await client.groupInviteCode ("abcd-xyz@g.us") console.log("group code: " + code) ``` +- To query the metadata of a group + ``` ts + const metadata = await client.groupMetadata ("abcd-xyz@g.us") + console.log(json.id + ", title: " + json.subject + ", description: " + json.desc) + + // Or if you've left the group -- call this + const metadata2 = await client.groupMetadataMinimal ("abcd-xyz@g.us") + ``` + +## Broadcast Lists & Stories + +- You can send messages to broadcast lists the same way you send messages to groups & individual chats. +- Unfortunately, WA Web does not support creating broadcast lists right now but you can still delete them. +- Broadcast IDs are in the format `12345678@broadcast` +- To query a broadcast list's recipients & name: + ``` ts + const bList = await client.getBroadcastListInfo ("1234@broadcast") + console.log (`list name: ${bList.name}, recps: ${bList.recipients}`) + ``` ## Writing Custom Functionality Baileys is written, keeping in mind, that you may require other custom functionality. Hence, instead of having to fork the project & re-write the internals, you can simply write extensions in your own code. diff --git a/src/Binary/Decoder.ts b/src/Binary/Decoder.ts index 3d481db..d480398 100644 --- a/src/Binary/Decoder.ts +++ b/src/Binary/Decoder.ts @@ -23,7 +23,7 @@ export default class Decoder { const value = this.buffer.slice(this.index, this.index + length) this.index += length - return new TextDecoder().decode(value) + return value.toString ('utf-8') } readBytes(n: number): Buffer { this.checkEOS(n) diff --git a/src/Binary/Encoder.ts b/src/Binary/Encoder.ts index 98ab4a0..a70882f 100644 --- a/src/Binary/Encoder.ts +++ b/src/Binary/Encoder.ts @@ -20,7 +20,7 @@ export default class Encoder { this.data.push.apply(this.data, bytes) } pushString(str: string) { - const bytes = new TextEncoder().encode(str) + const bytes = Buffer.from (str, 'utf-8') this.pushBytes(bytes) } writeByteLength(length: number) { diff --git a/src/WAClient/Constants.ts b/src/WAClient/Constants.ts index aa77734..87860ea 100644 --- a/src/WAClient/Constants.ts +++ b/src/WAClient/Constants.ts @@ -43,12 +43,6 @@ export enum ChatModification { mute='mute', unmute='unmute' } -export const WAMessageType = function () { - const types = proto.WebMessageInfo.WEB_MESSAGE_INFO_STUBTYPE - const dict: Record = {} - Object.keys(types).forEach(element => dict[ types[element] ] = element) - return dict -}() export const HKDFInfoKeys = { [MessageType.image]: 'WhatsApp Image Keys', [MessageType.audio]: 'WhatsApp Audio Keys', @@ -100,7 +94,7 @@ export interface MessageStatusUpdate { /** Message IDs read/delivered */ ids: string[] /** Status of the Message IDs */ - type: proto.WebMessageInfo.WEB_MESSAGE_INFO_STATUS + type: proto.WebMessageInfo.WEB_MESSAGE_INFO_STUBTYPE } export interface PresenceUpdate { id: string @@ -134,6 +128,16 @@ export interface WALocationMessage { degreesLongitude: number address?: string } +export const WA_MESSAGE_STUB_TYPE = proto.WebMessageInfo.WEB_MESSAGE_INFO_STUBTYPE +export const WA_MESSAGE_STATUS_TYPE = proto.WebMessageInfo.WEB_MESSAGE_INFO_STATUS + +/** Reverse stub type dictionary */ +export const WAMessageType = function () { + const types = WA_MESSAGE_STUB_TYPE + const dict: Record = {} + Object.keys(types).forEach(element => dict[ types[element] ] = element) + return dict +}() export type WAContactMessage = proto.ContactMessage export type WAMessageKey = proto.IMessageKey export type WATextMessage = proto.ExtendedTextMessage diff --git a/src/WAClient/Groups.ts b/src/WAClient/Groups.ts index ccbd67f..8e15421 100644 --- a/src/WAClient/Groups.ts +++ b/src/WAClient/Groups.ts @@ -22,7 +22,7 @@ export default class WhatsAppWebGroups extends WhatsAppWebBase { /** Get the metadata of the group */ groupMetadata = (jid: string) => this.queryExpecting200(['query', 'GroupMetadata', jid]) as Promise /** Get the metadata (works after you've left the group also) */ - groupCreatorAndParticipants = async (jid: string) => { + groupMetadataMinimal = async (jid: string) => { const query = ['query', {type: 'group', jid: jid, epoch: this.msgCount.toString()}, null] const response = await this.queryExpecting200(query, [WAMetric.group, WAFlag.ignore]) const json = response[2][0] diff --git a/src/WAClient/Messages.ts b/src/WAClient/Messages.ts index 5306ff3..55e12ab 100644 --- a/src/WAClient/Messages.ts +++ b/src/WAClient/Messages.ts @@ -55,8 +55,15 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups { } return this.setQuery ([['read', attributes, null]]) } - /** Mark a given chat as unread */ + /** + * Mark a given chat as unread + * @deprecated since 2.0.0, use `sendReadReceipt (jid, null, 'unread')` instead + */ async markChatUnread (jid: string) { return this.sendReadReceipt (jid, null, 'unread') } + /** + * Archive a chat + * @deprecated since 2.0.0, use `modifyChat (jid, ChatModification.archive)` instead + */ async archiveChat (jid: string) { return this.modifyChat (jid, ChatModification.archive) } /** * Modify a given chat (archive, pin etc.) diff --git a/src/WAClient/Tests.ts b/src/WAClient/Tests.ts index a50dbfe..b698258 100644 --- a/src/WAClient/Tests.ts +++ b/src/WAClient/Tests.ts @@ -182,7 +182,7 @@ WAClientTest('Groups', (client) => { }) it('should leave the group', async () => { await client.groupLeave(gid) - await client.groupCreatorAndParticipants (gid) + await client.groupMetadataMinimal (gid) }) it('should archive the group', async () => { await client.archiveChat(gid) diff --git a/src/WAClient/Utils.ts b/src/WAClient/Utils.ts index fe057fd..a707a65 100644 --- a/src/WAClient/Utils.ts +++ b/src/WAClient/Utils.ts @@ -19,7 +19,10 @@ export function validateJIDForSending (jid: string) { } } -/** Type of notification */ +/** + * Type of notification + * @deprecated use WA_MESSAGE_STUB_TYPE instead + * */ export function getNotificationType(message: WAMessage): [string, MessageType?] { if (message.message) { return ['message', Object.keys(message.message)[0] as MessageType] diff --git a/src/WAConnection/Constants.ts b/src/WAConnection/Constants.ts index 93fb52e..f81e3dc 100644 --- a/src/WAConnection/Constants.ts +++ b/src/WAConnection/Constants.ts @@ -92,7 +92,6 @@ export enum WAFlag { } /** Tag used with binary queries */ export type WATag = [WAMetric, WAFlag] -export * as WAMessageProto from '../../WAMessage/WAMessage' - +export * as WAMessageProto from '../../WAMessage/WAMessage'