Comments (69)
@cprcrack Of course, it's really not that hard. Note that I'm just using the standard Chrome developer tools here; Chromium, Vivaldi etc. are using the same.
WhatsApp Web's JavaScript source code is organized into two files: app.js
and app2.js
. After pressing F12 to open the developer tools, click on the Sources tab, then onto app.***.js
(where ***
is a short hash code), then pretty-print this file using the two-brackets-icon in the bottom left corner. Do the same thing for app2.***.js
. Note that you may have to wait a bit between actions, as the source files are very large and the CPU usage of your PC could go up a bit for a short amount of time.
First, consider the basic structure of the app.js
source file. At the very top of it, the function webpackJsonp
is called with three parameters:
[63]
(not sure what that's for)- an object whose keys correspond to the internal names of all modules ever defined
['"caggjbieeb"']
(at the very bottom ofapp.js
; obviously another module name, but not really sure about this one either; it isn't important right now anyway)
Next thing was that I was just looking for the Webpack module defining the window.Store.Wap
object and I remembered that it had an attribute called profilePicFind
. So I searched for that string in app.js
and a fitting match defining this function turned up (all other matches are just calls of this function or for profilePicFindThumbFromPhone
, which is irrelevant right now):
profilePicFind: function(e) {
return j["default"].isServer(e) ? s["default"].resolve({}) : _["default"].sendEphemeral2({
data: ["query", "ProfilePicThumb", e],
retryOn5xx: !0
})
}
Now scroll up from this position until you reach a line that is indented with just four spaces (which means that it's an attribute of the object of the second parameter to webpackJsonp
). And, voilà, there it is:
'"dgfhfgbdeb"': function(e, t, n) {
This means that the module with the unique name dgfhfgbdeb
is the one which constructs the Wap
object (this final piece of information is not specifically mentioned anywhere, but you can assume it from the context). And, as stated before, this is the final solution.
The only remaining tricky thing about discovering the command in the comment above was to make webpackJsonp
actually somehow return a reference to the return value of the module (and not just construct it), but I got it after a bit of fiddling around with it.
from whatsapp-web-reveng.
New solution for missing window.Store
:
- Run the hole script in console: https://github.com/pedroslopez/moduleRaid/blob/master/moduleraid.js
- the function
moduleRaid
will be globally available
- Copy from line 7 to 34 from this script into console: https://github.com/pedroslopez/whatsapp-web.js/blob/master/src/util/Injected.js
- those lines will use
moduleRaid
to find those webpack objects. For example I ran as follows:
window.mR = moduleRaid();
window.Store = window.mR.findModule('Chat')[0].default;
window.Store.Wap = window.mR.findModule('Wap')[0].default;
from whatsapp-web-reveng.
So I think I've found a solution. Execute the following command in the console once after the page has been loaded (any other call has no effect, as the module is loaded then and the (x, y, z)
callback function is not executed anymore):
window.Store = {}; webpackJsonp([], { "dgfhfgbdeb": (x, y, z) => window.Store.Wap = z('"dgfhfgbdeb"') }, "dgfhfgbdeb");
Here, "dgfhfgbdeb"
is the Webpack module that returns the definition of the Store.Wap
object. This module name could change between builds, I'm at version 0.2.9547 right now. Does the command work for other people as well?
from whatsapp-web-reveng.
Well, even if it is private, there has to be some scope where it's accessible, assuming it still exists in its old form somewhere. So one could just set a breakpoint there and assign it to window.Store
by themselves.
EDIT: It's kind of interesting that this change happened just when the GDPR law from the EU got into place. Is this just a coincidence?
from whatsapp-web-reveng.
Solution based on https://gist.github.com/phpRajat/a6422922efae32914f4dbd1082f3f412
function getAllModules() {
return new Promise((resolve) => {
const id = _.uniqueId("fakeModule_");
window["webpackJsonp"](
[],
{
[id]: function(module, exports, __webpack_require__) {
resolve(__webpack_require__.c);
}
},
[id]
);
});
}
modules = getAllModules()._value;
for (var key in modules) {
if (modules[key].exports) {
if (modules[key].exports.default) {
if (modules[key].exports.default.Chat) {
console.log(modules[key]);
_module = modules[key];
}
}
}
}
window.Store = _module.exports.default;
from whatsapp-web-reveng.
For whatsapp web, open javascript console and paste my code:
!function(){for(var t of document.getElementsByTagName("script"))t.src.indexOf("/app.")>0&&fetch(t.src,{method:"get"}).then(function(t){return t.text().then(function(t){var e=t.indexOf('var a={};t["default"]')-89;window.ZStore=window.webpackJsonp([],null,JSON.stringify(t.substr(e,10))).default})})}();
Window.ZStore will contain the Store object, whatever the name.
from whatsapp-web-reveng.
@sigalor awesome, thanks for sharing! Once we find a module, such as "bfhecaifff" for the Chat module, I've been experimenting on how to retrieve to a new StoreChat
object following your method:
webpackJsonp([], { "bfhecaifff": (x, y, z) => window.StoreChat = z('"bfhecaifff"') }, "bfhecaifff");
and I realized that two of the module ids don't seem to be required, this is simpler and works as well:
webpackJsonp([], { "": (x, y, z) => window.StoreChat = z('"bfhecaifff"') }, "");
I've been searching for more info on the webpackJsonp()
function in the webpack repository but couldn't find anything useful. @sigalor do you know how does this function work and why is your (x, y, z) callback called?
from whatsapp-web-reveng.
Very simple indeed:
ZStore.Presence.filter(a=>a.__x_isOnline)
Returns online contacts :D
Example:
ZStore.Presence.filter(a=>a.__x_isOnline).forEach(a=>console.log(ZStore.Contact._index[a.id].name))
from whatsapp-web-reveng.
ZStore.Contact.add
from whatsapp-web-reveng.
https://developers.google.com/web/tools/chrome-devtools/console/api
from whatsapp-web-reveng.
Dear all, I noticed Store object is not obtainable anymore (with methods described above) since 2 days ago when my WA Web was updated to version 0.3.3321.
from whatsapp-web-reveng.
not able to get the store https://lh3.googleusercontent.com/-6RYTvxsiUSk/XoGIJkT2gzI/AAAAAAAAB8o/50svvpYX8u4T4VGXMb7In6Cuyhkj-cYnACK8BGAsYHg/s0/2020-03-29.png
getting this issue
from whatsapp-web-reveng.
socket
@sigalor This issue is not a discussion about this repository. but please keep this without closing. because of recent whatsapp changes we need to find a solution for it.
Anyone know how to get messages that receiving to web socket. I can view data through chrome developer tools. but I need to get that data to a function on an extension. Is it can do or not?
EDIT : I found one thing. If I open chat window for a contact on android (not on whatsapp web), whatsapp subscribe that presence update for 10 min. also whatsapp web receiving a message when presence available/unavailable. so I created a uiautomation script to run on my old android phone, It automatically open chat screen for few contacts that I need to track. so I need to know is it possible to call my own function on websocket get message.
@sigalor This issue is not a discussion about this repository. but please keep this without closing. because of recent whatsapp changes we need to find a solution for it.
Anyone know how to get messages that receiving to web socket. I can view data through chrome developer tools. but I need to get that data to a function on an extension. Is it can do or not?
EDIT : I found one thing. If I open chat window for a contact on android (not on whatsapp web), whatsapp subscribe that presence update for 10 min. also whatsapp web receiving a message when presence available/unavailable. so I created a uiautomation script to run on my old android phone, It automatically open chat screen for few contacts that I need to track. so I need to know is it possible to call my own function on websocket get message.
Have you found a solution for accessing the websocket directly?
from whatsapp-web-reveng.
whatsapp changed their api. Store
object not available now
from whatsapp-web-reveng.
As stated already in my first comment at #34, this project's purpose is not to document the WA Web JS console API, but the underlying websocket communication. For me, the Store
object still exists, but I'm sure the change will be rolled out here in the next few hours/days as well.
Anyway, I think that WhatsApp has just changed the Store.Wap
functions to be invisible and they still exist internally somewhere. If someone would like to find this out, I'd be happy to accept their contribution, otherwise I will close this issue.
from whatsapp-web-reveng.
Yes, I want to collaborate, any tips?
from whatsapp-web-reveng.
I think we must find similar code, like “466665@[a].us” or “.us” global search
from whatsapp-web-reveng.
@jhow2892 I guess you could look through the original WA Web JS source code (i.e. the app.js
and app2.js
files) and search for the desired function names (e.g. profilePicFind
). Then set the appropriate breakpoints, trigger the event using the UI and eventually find the function's scope.
from whatsapp-web-reveng.
I have found the methods, I will analyze how to make the calls and if I can get post here
from whatsapp-web-reveng.
@sigalor This issue is not a discussion about this repository. but please keep this without closing. because of recent whatsapp changes we need to find a solution for it.
Anyone know how to get messages that receiving to web socket. I can view data through chrome developer tools. but I need to get that data to a function on an extension. Is it can do or not?
EDIT : I found one thing. If I open chat window for a contact on android (not on whatsapp web), whatsapp subscribe that presence update for 10 min. also whatsapp web receiving a message when presence available/unavailable. so I created a uiautomation script to run on my old android phone, It automatically open chat screen for few contacts that I need to track. so I need to know is it possible to call my own function on websocket get message.
from whatsapp-web-reveng.
guys the Store method disappeared, follow image, I'm analyzing the js code to see how we can work around this problem
in this image I am using the old version of WhatsApp web that is in Store. in whatsapp web version 0.2.9546 does not have any more.
from whatsapp-web-reveng.
With React Developer Tools I was able to find the Store object. It's really hard to find it now. I guess WhatsApp made it private :(
from whatsapp-web-reveng.
@rmanguinho it works?
from whatsapp-web-reveng.
@rmanguinho you mean the full Store object or some of its content? If you found the full objcet, can you share the way to find it?
from whatsapp-web-reveng.
Maybe you shouldn't necessarily store a phone number as an integer...
Store.Wap.lastseenFind("[email protected]").then(function(r){ console.log(r)})
or
Store.Wap.lastseenFind("[email protected]").then(r => console.log(r))
if you fancy ES6 should work. Of course you need to take care of error codes if the requested user does not share their last online status. You can also try out statusFind
first, because even if the requested user does not exist, the server still returns the default {status: "Hey there! I am using WhatsApp."}
.
Apart from that, it's possbile that the Wap
definition isn't even part of the "dgfhfgbdeb"
module for you. Could you check your contents of Store.Wap
first?
from whatsapp-web-reveng.
@sigalor It's working. Thanks. great work.
anyway, did't you found Store.Presence object?
from whatsapp-web-reveng.
@karopass
use the code that @sigalor mentioned.
Store.Wap.lastseenFind("[email protected]").then(r => console.log(r.t))
or
Store.Wap.lastseenFind("XXNUMBERXX"+"@c.us").then(r => console.log(r.t))
from whatsapp-web-reveng.
Some other interesting module names in version 0.2.9547:
window.Store.Conn
:"jfefjijii"
(but just use the["default"]
attribute from the callback result)window.Store.Stream
:"djddhaidag"
(just the["default"]
attribute as well)window.Store.Wap
:"dgfhfgbdeb"
"bcihgfbdeb"
seems interesting as well, and @InfaSoftLanka, it also contains aPresence
attribute, but I don't really know what to do with it...
from whatsapp-web-reveng.
@karopass Just use the same pattern:
webpackJsonp([], { "bcihgfbdeb": (x, y, z) => window.Store.Presence = z('"bcihgfbdeb"').Presence }, "bcihgfbdeb");
But the resulting window.Store.Presence
object seems kind of useless/internal to me. Is it really the same like before?
from whatsapp-web-reveng.
@karopass just copy & past it to console on whatsapp web. then press Enter to execute that command.
then you are done. don't think about that code. Store.Wap
object is available now as old whatsapp web.
you can execute command as normal.
eg: Store.Wap.//any command//
from whatsapp-web-reveng.
@sigalor
window.Store.Presence
is very important to me because some contacts hide their last seen.
so I can check online status with Presence
object.
I know it's useless after change of whatsapp. online data can get only for 10 min after open chat for the contact on android app.
but I have running automated script on my old android phone. it will open chat window automatically for few contacts with last seen hidden.
@karopass **if you finding with 'Presence' object it's working only if you open chat window on your phone.(not on whatsapp web) - but after 10 min you need to re open chat window
from whatsapp-web-reveng.
@karopass
Yes. still the same problem. we have to wait until whatsapp change their whatsapp web api to work alone.
from whatsapp-web-reveng.
What's the name of that app? We could reverse engineer it.
from whatsapp-web-reveng.
@karopass what is the application? I have reverse engineered app named whats agent and get thins what I need. but it's stop working after change of whatsapp
from whatsapp-web-reveng.
@karopass
according to their reviews they could use whatsapp web for get online data. if yes, I think there is no hidden method on whatsapp web. because whatsapp web not using it to show person is online/offline on whatsapp web.
the only trick that I can guess is they can reverse engineer whatsapp android application and automatically subscribe for presence. I'm trying it also. but no luck with whatsapp official application. I'm trying with GBwhatsapp now.
from whatsapp-web-reveng.
Could someone of you please open a new issue for the presence problem with all the information gathered here already regarding that?
I assume the original issue dealing with window.Store
is more or less resolved?
from whatsapp-web-reveng.
@sigalor could you share the method you used to find those objects such as the one with "bcihgfbdeb"? I'm trying with React Developer Tools but I'm a little bit lost not having any experience with ReactJs. Any insight or hint would be really helpful. Thanks for your work!
from whatsapp-web-reveng.
@sigalor would it be possible to send messages using this approach ? There is an object called Msg inside Store object, and it has a method called send
from whatsapp-web-reveng.
@cprcrack Great, thanks for finding this easier solution!
Regarding the webpackJsonp
function, I have a few clues:
- If you look at the
progress.js
original WA Web source file, you can see that it sets up/defineswindow.webpackJsonp
. When looking at the pretty-printed version of this file, you can see that it's just dealing with arrays, objects and stuff, but here it's hard to understand, as all the variable names are just one letter long. - In the Webpack configuration documentation,
output.jsonpFunction
is set to"webpackJsonp"
by default, as described here. A better description of the function's purpose can be found here, apparently it's used for asynchronously loading various modules. Still, there seems to be almost no official documentation about how the function internally works. A section on this other website tries to dive deep into the internals of Webpack, but I'm not sure whether all of this is still up to date. Still, I guess from this information, the(x, y, z)
parameters could be renamed to more meaningful names.
from whatsapp-web-reveng.
@coolnickname
Do you have a good skill with reverse engineering.
from whatsapp-web-reveng.
Reverse engineering is a broad term, if you're talking about Android applications I do have some experience.
from whatsapp-web-reveng.
@coolnickname
Yes I'm talking about android applications.
have you tried to decompile and recompile WA apk. it's not working after recompile because they are validating the apk signature.
I have found few methods that they are getting apk signatures. But not undrstand how to bypass it. It could be done because GB-WA have bypassed it.
also I tried with GB-WA add some of my methods to code. It's working fine. but there is some network issues with GB-WA.
I appreciate if you can try to decompile and recompile WA apk.
from whatsapp-web-reveng.
@coolnickname @InfaSoftLanka, I have modified the original WhatsApp APK, recompiled and successfully executed it on my Android 8.0 device before and I would like to publish this information.
Could someone of you open a new issue to collect all information previously discussed about the topic in this thread and respecify the problem description? I will add everything I know about it there later.
I will close this issue now, as the original question is answered. @cprcrack, if you would like to discuss more about Webpack internals or anything else regarding the project, please open a new issue or contact me via the email address from my profile.
from whatsapp-web-reveng.
@sigalor @cprcrack @infahash
How can we learn the status, online - offline? (not a registered number)
Is there any way?
var nr = phone number; Store.Presence.find(nr+ '@c.us').then(function(r){ console.log(r)})
it does not work anymore
from whatsapp-web-reveng.
For whatsapp web, open javascript console and paste my code:
!function(){for(var t of document.getElementsByTagName("script"))t.src.indexOf("/app.")>0&&fetch(t.src,{method:"get"}).then(function(t){return t.text().then(function(t){var e=t.indexOf('var a={};t["default"]')-89;window.ZStore=window.webpackJsonp([],null,JSON.stringify(t.substr(e,10))).default})})}();
Window.ZStore will contain the Store object, whatever the name.
Thanks @Zibri
from whatsapp-web-reveng.
You're welcome.
https://github.com/Zibri/WhatsAppWebApi/blob/master/zstore.js
from whatsapp-web-reveng.
from whatsapp-web-reveng.
@func0207 @Zibri I'm also trying to get the online status and saw you mention the zstore script. When you run this script on WhatsApp, I assume something like this is what I should be calling:
Window.ZStore.Presence.find
Would that be correct? They've really made it more difficult and I'm trying to understand more about what I need to change in one of my scripts.
Edit 1 - I got this part sorted. I now have the store object (thanks!) but now I'm getting "Presence.gadd called without an id attr(id) at t.value". Hmmm.
Edit 2 - Ouch. Sorted out the other problem too but looks like isOnline is no longer there on WhatsApp web.
from whatsapp-web-reveng.
hi @Zibri can I know if a number is online or not without being on my contacts list or previous chat ?
from whatsapp-web-reveng.
Hi @Zibri is it possible to add new contacts through the web client using the store object ?
from whatsapp-web-reveng.
@Zibri i understand its Contact.add but thats a function that recieve 2 param, can you help me with an example ? Is the function recieve for instance ("name","phoneNum") ?
the goal is to add a contact to my list so i can search his Presence or status.
does adding the contact will allow me to search for him ?
is there anything else you can do in order to search for someone who is not in your contact list?
I really appreciate your help
from whatsapp-web-reveng.
I tried to duplicate an existing contact from my phone to an temp var and then start to change his info by that i mean the phone number and name, and then use the Contact.add function to add it but with no success.
Can you please give me an explanation or example for how you should add new contact ?
from whatsapp-web-reveng.
@JackieMond
Learn to reverse engineer... that's how we learn things.
Hint: the browser "monitor" command could be useful.
Example:
monitor(Store.Chat.find)
then switch to a different chat in the interface and you will see how the function is invoked.
from whatsapp-web-reveng.
@Zibri thanks for the monitor lesson i'm still new to this and its super interesting.
I managed to invoke all kind of functions, all of them receiving ********@c.us or -@g.us, but i didn't manage to invoke Store.Contact.add or any other function that receiving an Object as a parameter
I would be really appreciate if you could help me create new contact.
**Update
when i managed to invoked Store.Contact.add i received this:
function value called with arguments: [object Object], [object Object]
how to i understand the structure of the objects ?
from whatsapp-web-reveng.
hi @JackieMond can u tell me how can u did that
whats is monitor & how to use it
from whatsapp-web-reveng.
@Zibri thanks for the monitor lesson i'm still new to this and its super interesting.
I managed to invoke all kind of functions, all of them receiving ********@c.us or -@g.us, but i didn't manage to invoke Store.Contact.add or any other function that receiving an Object as a parameter
I would be really appreciate if you could help me create new contact.**Update
when i managed to invoked Store.Contact.add i received this:
function value called with arguments: [object Object], [object Object]how to i understand the structure of the objects ?
Just create a wrapper function around it.
from whatsapp-web-reveng.
Example:
var sendorig = Store.Msg.send;
(function() {
Store.Msg.send = function() {
var args = [].splice.call(arguments, 0);
console.log('Store.Msg.send (', args, ')');
return sendorig.apply(Store.Msg, args);
}
}
)();
from whatsapp-web-reveng.
Or more generically:
var spy = function(func) {
return function() {
var args = [].splice.call(arguments, 0);
console.log('function (', args, ')');
return func.apply(this, args);
}
};
example:
alert=spy(alert);
alert("hello");
from whatsapp-web-reveng.
@Zibri after 1 month of research i still did not manage to create new contact :(
I managed to duplicate and many other things but to find the builder and create new contact no.
I learned a lot and i found the ability to put breakpoints and see the parameters in all kind of terms and functions but my goal is still not reached.
Please help me zibri :(
What is the right command that will allow me to add new contact, and much more important than that what is the parameter it accepts.
from whatsapp-web-reveng.
sincerely I didn't check but contacts are made on the PHONE.. and then transmitted to the web client...
what you should do is to add a contact on the phone while monitoring the web app to understand that.
from whatsapp-web-reveng.
Hi,
webpackJsonp([], {"bcihgfbdeb": (x, y, z) => window.Store = z('"bcihgfbdeb"')}, "bcihgfbdeb")
does not work anymore with new WA Web version.
window.Store.Chat: Uncaught TypeError: Cannot read property 'Chat' of undefined
Is there any solution?
from whatsapp-web-reveng.
Solution based on https://gist.github.com/phpRajat/a6422922efae32914f4dbd1082f3f412
function getAllModules() { return new Promise((resolve) => { const id = _.uniqueId("fakeModule_"); window["webpackJsonp"]( [], { [id]: function(module, exports, __webpack_require__) { resolve(__webpack_require__.c); } }, [id] ); }); } modules = getAllModules()._value; for (var key in modules) { if (modules[key].exports) { if (modules[key].exports.default) { if (modules[key].exports.default.Chat) { console.log(modules[key]); _module = modules[key]; } } } } window.Store = _module.exports.default;
Hello, a question how can I send a message to a contact?
from whatsapp-web-reveng.
Hello, a question how can I send a message to a contact?
Check this link:
https://gist.github.com/phpRajat/a6422922efae32914f4dbd1082f3f412
from whatsapp-web-reveng.
how it works now?
from whatsapp-web-reveng.
Store not returning chat.models if any solution please share
from whatsapp-web-reveng.
The solution proposed by previous posters in 2019 doesn't work anymore, as webpackJsonp in 2020 now has a different structure. I'm trying to reverse-engineer app.js / app2.js but I'm a bit stuck. Currently this is what I've done :
webpackJsonp.forEach(el => console.log(JSON.stringify(Object.keys(el[1])) ))
This will output in the console all the keys available inside webpackJsonp.
Then I download app..js and app2..js, format them with
prettier --write *.js
and open them with vscode. I try to find corresponding keys between the files and the output of my code but 80% of the keys don't correspond with the keys previously outputted in the console. For example,profilePicFind
has keybegfaahgdb
in app.js, but this key doesn't appear in the console output.I'm kind of stuck, will update if I find a solution.
Any Update ?
from whatsapp-web-reveng.
I have seen the interception code and it works for most of the exposed modules but I would like to know how to find the modules. Although a significant amount of functions can be listed, I would like, for example, to find the function that allows you to change the theme from light to dark.
from whatsapp-web-reveng.
@asm95 Thank you very much, this will help me a lot to finish my chrome extensions
from whatsapp-web-reveng.
@geanrt current not work ?
from whatsapp-web-reveng.
Related Issues (20)
- Error installing dependencies HOT 7
- Multi-Device beta WebSocket is only binary with encryption
- Get a group of users HOT 1
- Is it possible that answering audio call and video call? HOT 2
- It is possible create new chat? HOT 2
- Error QR Generate via docker HOT 1
- How can ı get user presence with no contact HOT 1
- Whatapp monitoring
- some question about HISTORY_SYNC_NOTIFICATION
- hi,some one known how to use this kind data?repay for it!
- wa.web
- Invalid QR code
- update for python3 and run with 0.0.0.0
- lo que ha hecho y hace
- 'cmd': {version: '2.2126.11', type: 'upgrade_md_prod'} HOT 1
- error when requesting to generate qr code HOT 2
- Cod
- I also have a new version,And update in real-time HOT 2
- Is this repo alive? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from whatsapp-web-reveng.