From 7f2468efcf3d5a4595fab9d9f7d08953819e21e4 Mon Sep 17 00:00:00 2001 From: Adhiraj Date: Sun, 19 Jul 2020 23:26:48 +0530 Subject: [PATCH] Change Profile Picture + Change Group Settings + Send Message to Oneself --- Media/cat.jpeg | Bin 0 -> 25241 bytes README.md | 31 +++++++++++++++++++++---------- package.json | 2 +- src/Binary/Encoder.ts | 29 ++++++++++++++--------------- src/Binary/Tests.ts | 12 ++++++++++-- src/WAClient/Base.ts | 22 +++++++++++++++++++--- src/WAClient/Constants.ts | 11 ++++++++++- src/WAClient/Groups.ts | 27 ++++++++++++++++++++++----- src/WAClient/Messages.ts | 3 ++- src/WAClient/Tests.ts | 36 +++++++++++++++++++++--------------- src/WAClient/Utils.ts | 9 +++++++++ src/WAConnection/Utils.ts | 2 +- 12 files changed, 130 insertions(+), 54 deletions(-) create mode 100644 Media/cat.jpeg diff --git a/Media/cat.jpeg b/Media/cat.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..5063d0996fed304369a8079f047d566226225b4b GIT binary patch literal 25241 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 9b2198a..d08c608 100644 --- a/README.md +++ b/README.md @@ -161,13 +161,6 @@ Implement the following callbacks in your code: ``` ts client.setOnUnexpectedDisconnect (reason => console.log ("disconnected unexpectedly: " + reason) ) ``` -- Called when you log into WhatsApp Web somewhere else - ``` ts - client.setOnTakenOver (async () => { - // reconnect to gain connection back here - await client.connect () - }) - ``` ## Sending Messages Send like, all types of messages with a single function: @@ -296,7 +289,8 @@ await client.deleteChat (jid) // will delete the chat (can be a group or broadca **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 +## Misc + - To check if a given ID is on WhatsApp ``` ts const id = 'xyz@s.whatsapp.net' @@ -324,6 +318,12 @@ await client.deleteChat (jid) // will delete the chat (can be a group or broadca const ppUrl = await client.getProfilePicture ("xyz@g.us") // leave empty to get your own console.log("download profile picture from: " + ppUrl) ``` +- To change your display picture or a group's + ``` ts + const jid = '111234567890-1594482450@g.us' // can be your own too + const img = fs.readFileSync ('new-profile-picture.jpeg') // can be PNG also + await client.updateProfilePicture (jid, newPP) + ``` - To get someone's presence (if they're typing, online) ``` ts // the presence update is fetched and called here @@ -353,10 +353,21 @@ Append ``` @s.whatsapp.net ``` for individuals & ``` @g.us ``` for groups. // id & people to add to the group (will throw error if it fails) const response = await client.groupAdd ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"]) ``` -- To make someone admin on a group +- To make/demote admins on a group ``` ts // id & people to make admin (will throw error if it fails) - await client.groupMakeAdmin ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"]) + await client.groupMakeAdmin ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"]) + await client.groupDemoteAdmin ("abcd-xyz@g.us", ["abcd@s.whatsapp.net", "efgh@s.whatsapp.net"]) // demote admins + ``` +- To change group settings + ``` ts + import { GroupSettingChange } from '@adiwajshing/baileys' + // only allow admins to send messages + await client.groupSettingChange ("abcd-xyz@g.us", GroupSettingChange.messageSend, true) + // allow everyone to modify the group's settings -- like display picture etc. + await client.groupSettingChange ("abcd-xyz@g.us", GroupSettingChange.settingChange, false) + // only allow admins to modify the group's settings + await client.groupSettingChange ("abcd-xyz@g.us", GroupSettingChange.settingChange, true) ``` - To leave a group ``` ts diff --git a/package.json b/package.json index 3135095..cab0d39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@adiwajshing/baileys", - "version": "2.1.0", + "version": "2.2.0", "description": "WhatsApp Web API", "homepage": "https://github.com/adiwajshing/Baileys", "main": "lib/WAClient/WAClient.js", diff --git a/src/Binary/Encoder.ts b/src/Binary/Encoder.ts index a70882f..d4122ce 100644 --- a/src/Binary/Encoder.ts +++ b/src/Binary/Encoder.ts @@ -2,12 +2,12 @@ import { WA } from './Constants' import { proto } from '../../WAMessage/WAMessage' export default class Encoder { - data: Array = [] + data: number[] = [] pushByte(value: number) { this.data.push(value & 0xff) } - pushInt(value: number, n: number, littleEndian = false) { + pushInt(value: number, n: number, littleEndian=false) { for (let i = 0; i < n; i++) { const curShift = littleEndian ? i : n - 1 - i this.data.push((value >> (curShift * 8)) & 0xff) @@ -16,17 +16,17 @@ export default class Encoder { pushInt20(value: number) { this.pushBytes([(value >> 16) & 0x0f, (value >> 8) & 0xff, value & 0xff]) } - pushBytes(bytes: Uint8Array | Array) { - this.data.push.apply(this.data, bytes) + pushBytes(bytes: Uint8Array | Buffer | number[]) { + bytes.forEach (b => this.data.push(b)) + //this.data.push.apply(this.data, bytes) } pushString(str: string) { const bytes = Buffer.from (str, 'utf-8') this.pushBytes(bytes) } writeByteLength(length: number) { - if (length >= 4294967296) { - throw new Error('string too large to encode: ' + length) - } + if (length >= 4294967296) throw new Error('string too large to encode: ' + length) + if (length >= 1 << 20) { this.pushByte(WA.Tags.BINARY_32) this.pushInt(length, 4) // 32 bit integer @@ -101,19 +101,18 @@ export default class Encoder { this.pushBytes([WA.Tags.LIST_16, listSize]) } } - writeChildren(children: string | Array | Object) { - if (!children) { - return - } + writeChildren(children: string | Array | Buffer | Object) { + if (!children) return if (typeof children === 'string') { this.writeString(children, true) + } else if (Buffer.isBuffer(children)) { + this.writeByteLength (children.length) + this.pushBytes(children) } else if (Array.isArray(children)) { this.writeListStart(children.length) - children.forEach((c) => { - if (c) this.writeNode(c) - }) - } else if (typeof children === 'object') { + children.forEach(c => c && this.writeNode(c)) + } else if (typeof children === 'object') { const buffer = WA.Message.encode(children as proto.WebMessageInfo).finish() this.writeByteLength(buffer.length) this.pushBytes(buffer) diff --git a/src/Binary/Tests.ts b/src/Binary/Tests.ts index 703089b..18669c8 100644 --- a/src/Binary/Tests.ts +++ b/src/Binary/Tests.ts @@ -3,7 +3,7 @@ import Encoder from './Encoder' import Decoder from './Decoder' describe('Binary Coding Tests', () => { - const testVectors: [[string, Object]] = [ + const testVectors: [string, Object][] = [ [ 'f806092f5a0a10f804f80234fc6c0a350a1b39313735323938373131313740732e77686174736170702e6e657410011a143345423030393637354537454433374141424632122b0a292a7069616e6f20726f6f6d2074696d696e6773206172653a2a0a20363a3030414d2d31323a3030414d18b3faa7f3052003f80234fc4c0a410a1b39313735323938373131313740732e77686174736170702e6e657410001a20304643454335333330463634393239433645394132434646443242433845414418bdfaa7f305c00101f80234fc930a350a1b39313735323938373131313740732e77686174736170702e6e657410011a14334542303033433742353339414644303937353312520a50536f727279206672656e2c204920636f756c646e277420756e6465727374616e6420274c69627261272e2054797065202768656c702720746f206b6e6f77207768617420616c6c20492063616e20646f18c1faa7f3052003f80234fc540a410a1b39313735323938373131313740732e77686174736170702e6e657410001a20413132333042384436423041314437393345433241453245413043313638443812090a076c69627261727918c2faa7f305', [ @@ -62,12 +62,20 @@ describe('Binary Coding Tests', () => { ], ], ], + [ + 'f8063f2dfafc0831323334353637385027fc0431323334f801f80228fc0701020304050607', + [ + 'picture', + {jid: '12345678@c.us', id: '1234'}, + [['image', null, Buffer.from([1,2,3,4,5,6,7])]] + ] + ] ] const encoder = new Encoder() const decoder = new Decoder() it('should decode strings', () => { - testVectors.forEach((pair) => { + testVectors.forEach(pair => { const buff = Buffer.from(pair[0], 'hex') const decoded = decoder.read(buff) diff --git a/src/WAClient/Base.ts b/src/WAClient/Base.ts index 7bbfeb8..ab47e47 100644 --- a/src/WAClient/Base.ts +++ b/src/WAClient/Base.ts @@ -1,5 +1,5 @@ import WAConnection from '../WAConnection/WAConnection' -import { MessageStatusUpdate, PresenceUpdate, Presence, WABroadcastListInfo } from './Constants' +import { MessageStatusUpdate, PresenceUpdate, Presence, WABroadcastListInfo, WAProfilePictureChange } from './Constants' import { WAMessage, WANode, @@ -8,6 +8,9 @@ import { MessageLogLevel, WATag, } from '../WAConnection/Constants' +import { generateProfilePicture } from '../WAClient/Utils' +import { generateMessageTag } from '../WAConnection/Utils' + export default class WhatsAppWebBase extends WAConnection { /** Set the callback for message status updates (when a message is delivered, read etc.) */ @@ -185,9 +188,22 @@ export default class WhatsAppWebBase extends WAConnection { } return loadMessage() as Promise } + async updateProfilePicture (jid: string, img: Buffer) { + const data = await generateProfilePicture (img) + const tag = generateMessageTag (this.msgCount) + const query: WANode = [ + 'picture', + { jid: jid, id: tag, type: 'set' }, + [ + ['image', null, data.img], + ['preview', null, data.preview] + ] + ] + return this.setQuery ([query], [14, 136], tag) as Promise + } /** Generic function for action, set queries */ - async setQuery (nodes: WANode[], binaryTags: WATag = [WAMetric.group, WAFlag.ignore]) { + async setQuery (nodes: WANode[], binaryTags: WATag = [WAMetric.group, WAFlag.ignore], tag?: string) { const json = ['action', {epoch: this.msgCount.toString(), type: 'set'}, nodes] - return this.queryExpecting200(json, binaryTags) as Promise<{status: number}> + return this.queryExpecting200(json, binaryTags, null, tag) as Promise<{status: number}> } } diff --git a/src/WAClient/Constants.ts b/src/WAClient/Constants.ts index 87860ea..97b1d3d 100644 --- a/src/WAClient/Constants.ts +++ b/src/WAClient/Constants.ts @@ -81,6 +81,11 @@ export interface WAUrlInfo { description: string jpegThumbnail?: Buffer } +export interface WAProfilePictureChange { + status: number + tag: string + eurl: string +} export interface MessageInfo { reads: {jid: string, t: string}[] deliveries: {jid: string, t: string}[] @@ -94,7 +99,11 @@ export interface MessageStatusUpdate { /** Message IDs read/delivered */ ids: string[] /** Status of the Message IDs */ - type: proto.WebMessageInfo.WEB_MESSAGE_INFO_STUBTYPE + type: proto.WebMessageInfo.WEB_MESSAGE_INFO_STATUS +} +export enum GroupSettingChange { + messageSend = 'announcement', + settingsChange = 'locked', } export interface PresenceUpdate { id: string diff --git a/src/WAClient/Groups.ts b/src/WAClient/Groups.ts index 8e15421..5e274cc 100644 --- a/src/WAClient/Groups.ts +++ b/src/WAClient/Groups.ts @@ -1,23 +1,24 @@ import WhatsAppWebBase from './Base' import { WAMessage, WAMetric, WAFlag, WANode, WAGroupMetadata, WAGroupCreateResponse, WAGroupModification } from '../WAConnection/Constants' +import { GroupSettingChange } from './Constants' import { generateMessageTag } from '../WAConnection/Utils' export default class WhatsAppWebGroups extends WhatsAppWebBase { /** Generic function for group queries */ - async groupQuery(type: string, jid?: string, subject?: string, participants?: string[]) { + async groupQuery(type: string, jid?: string, subject?: string, participants?: string[], additionalNodes?: WANode[]) { + const tag = generateMessageTag(this.msgCount) const json: WANode = [ 'group', { author: this.userMetaData.id, - id: generateMessageTag(), + id: tag, type: type, jid: jid, subject: subject, }, - participants ? participants.map((str) => ['participant', { jid: str }, null]) : [], + participants ? participants.map(str => ['participant', { jid: str }, null]) : additionalNodes, ] - const q = ['action', { type: 'set', epoch: this.msgCount.toString() }, [json]] - return this.queryExpecting200(q, [WAMetric.group, WAFlag.ignore]) + return this.setQuery ([json], [WAMetric.group, WAFlag.ignore], tag) } /** Get the metadata of the group */ groupMetadata = (jid: string) => this.queryExpecting200(['query', 'GroupMetadata', jid]) as Promise @@ -79,6 +80,22 @@ export default class WhatsAppWebGroups extends WhatsAppWebBase { */ groupMakeAdmin = (jid: string, participants: string[]) => this.groupQuery('promote', jid, null, participants) as Promise + /** + * Make demote an admin on the group + * @param jid the ID of the group + * @param participants the people to make admin + */ + groupDemoteAdmin = (jid: string, participants: string[]) => + this.groupQuery('demote', jid, null, participants) as Promise + /** + * Make demote an admin on the group + * @param jid the ID of the group + * @param participants the people to make admin + */ + groupSettingChange = (jid: string, setting: GroupSettingChange, onlyAdmins: boolean) => { + const node: WANode = [ setting, {value: onlyAdmins ? 'true' : 'false'}, null ] + return this.groupQuery('prop', jid, null, null, [node]) as Promise<{status: number}> + } /** Get the invite link of the given group */ async groupInviteCode(jid: string) { const json = ['query', 'inviteCode', jid] diff --git a/src/WAClient/Messages.ts b/src/WAClient/Messages.ts index 55e12ab..03ac316 100644 --- a/src/WAClient/Messages.ts +++ b/src/WAClient/Messages.ts @@ -326,7 +326,8 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups { status: WAMessageProto.proto.WebMessageInfo.WEB_MESSAGE_INFO_STATUS.PENDING } const json = ['action', {epoch: this.msgCount.toString(), type: 'relay'}, [['message', null, messageJSON]]] - const response = await this.queryExpecting200(json, [WAMetric.message, WAFlag.ignore], null, messageJSON.key.id) + const flag = id === this.userMetaData.id ? WAFlag.acknowledge : WAFlag.ignore // acknowledge when sending message to oneself + const response = await this.queryExpecting200(json, [WAMetric.message, flag], null, messageJSON.key.id) return { status: response.status as number, messageID: messageJSON.key.id, diff --git a/src/WAClient/Tests.ts b/src/WAClient/Tests.ts index b698258..458cf4a 100644 --- a/src/WAClient/Tests.ts +++ b/src/WAClient/Tests.ts @@ -1,7 +1,8 @@ import { WAClient } from './WAClient' -import { MessageType, MessageOptions, Mimetype, Presence, ChatModification } from './Constants' +import { MessageType, MessageOptions, Mimetype, Presence, ChatModification, GroupSettingChange } from './Constants' import * as fs from 'fs' import * as assert from 'assert' +import fetch from 'node-fetch' import { decodeMediaMessage, validateJIDForSending } from './Utils' import { promiseTimeout, createTimeout } from '../WAConnection/Utils' @@ -117,6 +118,20 @@ WAClientTest('Misc', (client) => { it('should return the stories', async () => { await client.getStories() }) + it('should change the profile picture', async () => { + await createTimeout (5000) + + const ppUrl = await client.getProfilePicture(client.userMetadata.id) + const fetched = await fetch(ppUrl, { headers: { Origin: 'https://web.whatsapp.com' } }) + const buff = await fetched.buffer () + + const newPP = fs.readFileSync ('./Media/cat.jpeg') + const response = await client.updateProfilePicture (client.userMetadata.id, newPP) + + await createTimeout (10000) + + await client.updateProfilePicture (client.userMetaData.id, buff) // revert back + }) it('should return the profile picture', async () => { const response = await client.getProfilePicture(testJid) assert.ok(response) @@ -177,6 +192,11 @@ WAClientTest('Groups', (client) => { const metadata = await client.groupMetadata(gid) assert.strictEqual(metadata.subject, subject) }) + it('should update the group settings', async () => { + await client.groupSettingChange (gid, GroupSettingChange.messageSend, true) + await createTimeout (5000) + await client.groupSettingChange (gid, GroupSettingChange.settingsChange, true) + }) it('should remove someone from a group', async () => { await client.groupRemove(gid, [testJid]) }) @@ -204,18 +224,4 @@ WAClientTest('Events', (client) => { const response = await client.sendMessage(testJid, 'My Name Jeff', MessageType.text) await promiseTimeout(10000, waitForUpdate()) }) - /*it ('should update me on presence', async () => { - //client.logUnhandledMessages = true - client.setOnPresenceUpdate (presence => { - console.log (presence) - }) - const response = await client.requestPresenceUpdate (client.userMetaData) - assert.strictEqual (response.status, 200) - await createTimeout (25000) - })*/ }) -/*WAClientTest ('Testz', client => { - it ('should work', async () => { - - }) -})*/ \ No newline at end of file diff --git a/src/WAClient/Utils.ts b/src/WAClient/Utils.ts index a707a65..c67176b 100644 --- a/src/WAClient/Utils.ts +++ b/src/WAClient/Utils.ts @@ -67,6 +67,15 @@ export const compressImage = async (buffer: Buffer) => { const jimp = await Jimp.read (buffer) return jimp.resize(48, 48).getBufferAsync (Jimp.MIME_JPEG) } +export const generateProfilePicture = async (buffer: Buffer) => { + const jimp = await Jimp.read (buffer) + const min = Math.min(jimp.getWidth (), jimp.getHeight ()) + const cropped = jimp.crop (0, 0, min, min) + return { + img: await cropped.resize(640, 640).getBufferAsync (Jimp.MIME_JPEG), + preview: await cropped.resize(96, 96).getBufferAsync (Jimp.MIME_JPEG) + } +} /** generates a thumbnail for a given media, if required */ export async function generateThumbnail(buffer: Buffer, mediaType: MessageType, info: MessageOptions) { if (info.thumbnail === null || info.thumbnail) { diff --git a/src/WAConnection/Utils.ts b/src/WAConnection/Utils.ts index bff4163..bf81c52 100644 --- a/src/WAConnection/Utils.ts +++ b/src/WAConnection/Utils.ts @@ -66,7 +66,7 @@ export function promiseTimeout(ms: number, promise: Promise) { // whatsapp requires a message tag for every message, we just use the timestamp as one export function generateMessageTag(epoch?: number) { let tag = new Date().getTime().toString() - if (epoch) tag += '-' + epoch // attach epoch if provided + if (epoch) tag += '.--' + epoch // attach epoch if provided return tag } // generate a random 16 byte client ID