From 9f8f244b6691fca229ad177cf125dcd270c6793e Mon Sep 17 00:00:00 2001 From: Adhiraj Singh Date: Fri, 20 Nov 2020 12:50:14 +0530 Subject: [PATCH] Added offline check for isOnWhatsApp --- README.md | 1 + package.json | 1 + src/WAConnection/0.Base.ts | 7 +++--- src/WAConnection/5.User.ts | 27 +++++++++++++++++++++- yarn.lock | 46 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2fb25f5..94d7607 100644 --- a/README.md +++ b/README.md @@ -368,6 +368,7 @@ await conn.deleteChat (jid) // will delete the chat (can be a group or broadcast } ``` - To check if a given ID is on WhatsApp + Note: this method falls back to using `https://wa.me` to determine whether a number is on WhatsApp in case the WebSocket connection is not open yet. ``` ts const id = '123456' const exists = await conn.isOnWhatsApp (id) diff --git a/package.json b/package.json index 8aa47dc..e8f4906 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "WAMessage/*" ], "devDependencies": { + "@types/node-fetch": "^2.5.7", "@types/mocha": "^7.0.2", "@types/node": "^14.6.2", "@types/pino": "^6.3.2", diff --git a/src/WAConnection/0.Base.ts b/src/WAConnection/0.Base.ts index 2e9835a..f8d946c 100644 --- a/src/WAConnection/0.Base.ts +++ b/src/WAConnection/0.Base.ts @@ -3,7 +3,7 @@ import WS from 'ws' import * as Utils from './Utils' import Encoder from '../Binary/Encoder' import Decoder from '../Binary/Decoder' -import fetch from 'node-fetch' +import fetch, { RequestRedirect } from 'node-fetch' import { AuthenticationCredentials, WAUser, @@ -31,7 +31,7 @@ const logger = pino({ prettyPrint: { levelFirst: true, ignore: 'hostname', trans export class WAConnection extends EventEmitter { /** The version of WhatsApp Web we're telling the servers we are */ - version: [number, number, number] = [2, 2045, 19] + version: [number, number, number] = [2, 2047, 10] /** The Browser we're telling the WhatsApp Web servers we are */ browserDescription: [string, string, string] = Utils.Browsers.baileys ('Chrome') /** Metadata like WhatsApp id, name set on WhatsApp etc. */ @@ -406,10 +406,11 @@ export class WAConnection extends EventEmitter { /** * Does a fetch request with the configuration of the connection */ - protected fetchRequest = (endpoint: string, method: string = 'GET', body?: any, agent?: Agent, headers?: {[k: string]: string}) => ( + protected fetchRequest = (endpoint: string, method: string = 'GET', body?: any, agent?: Agent, headers?: {[k: string]: string}, redirect: RequestRedirect = 'follow') => ( fetch(endpoint, { method, body, + redirect, headers: { Origin: DEFAULT_ORIGIN, ...(headers || {}) }, agent: agent || this.connectOptions.fetchAgent }) diff --git a/src/WAConnection/5.User.ts b/src/WAConnection/5.User.ts index 65850a5..c806a21 100644 --- a/src/WAConnection/5.User.ts +++ b/src/WAConnection/5.User.ts @@ -8,6 +8,7 @@ import { } from '../WAConnection/Constants' import { generateProfilePicture, whatsappID } from './Utils' import { Mutex } from './Mutex' +import { URL } from 'url' // All user related functions -- get profile picture, set status etc. @@ -18,9 +19,33 @@ export class WAConnection extends Base { * @returns undefined if the number doesn't exists, otherwise the correctly formatted jid */ isOnWhatsApp = async (str: string) => { + if (this.state !== 'open') { + return this.isOnWhatsAppNoConn(str) + } const { status, jid } = await this.query({json: ['query', 'exist', str], requiresPhoneConnection: false}) if (status === 200) return { exists: true, jid: whatsappID(jid) } - } + } + /** + * Query whether a given number is registered on WhatsApp, without needing to open a WS connection + * @param str phone number/jid you want to check for + * @returns undefined if the number doesn't exists, otherwise the correctly formatted jid + */ + isOnWhatsAppNoConn = async (str: string) => { + let phone = str.split('@')[0] + const url = `https://wa.me/${phone}` + const response = await this.fetchRequest(url, 'GET', undefined, undefined, undefined, 'manual') + const loc = response.headers.get('Location') + if (!loc) { + this.logger.warn({ url, status: response.status }, 'did not get location from request') + return + } + const locUrl = new URL('', loc) + if (!locUrl.pathname.endsWith('send/')) { + return + } + phone = locUrl.searchParams.get('phone') + return { exists: true, jid: `${phone}@s.whatsapp.net` } + } /** * Tell someone about your presence -- online, typing, offline etc. * @param jid the ID of the person/group who you are updating diff --git a/yarn.lock b/yarn.lock index 18b7f4a..59c956b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -382,6 +382,14 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce" integrity sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w== +"@types/node-fetch@^2.5.7": + version "2.5.7" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" + integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*", "@types/node@^14.6.2": version "14.14.8" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.8.tgz#2127bd81949a95c8b7d3240f3254352d72563aec" @@ -536,6 +544,11 @@ assert@^2.0.0: object-is "^1.0.1" util "^0.12.0" +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" @@ -712,6 +725,13 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -771,6 +791,11 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + diff@4.0.2, diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -951,6 +976,15 @@ foreach@^2.0.5: resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= +form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fs-extra@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" @@ -1418,6 +1452,18 @@ meow@^3.3.0: redent "^1.0.0" trim-newlines "^1.0.0" +mime-db@1.44.0: + version "1.44.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== + +mime-types@^2.1.12: + version "2.1.27" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" + integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== + dependencies: + mime-db "1.44.0" + mime@^1.3.4: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"