wa-js
wa-js copied to clipboard
Running on chrome extension
When i try to load wppconnect-wa.js using manifest.json content scripts, the WPP gets available in the window object and then disappears. The status never changes for ready.
// manifest.json
{
"manifest_version": 3,
"name": "Hitter",
"homepage_url": "https://hitter.pro",
"description": "Acelere as suas vendas no WhatsApp!",
"update_url": "https://clients2.google.com/service/update2/crx",
"version": "0.0.1",
"permissions": [
"tabs",
"storage",
"webNavigation",
"unlimitedStorage",
"downloads"
],
"action": {
"default_popup": "index.html",
"default_title": "React Browser Extension Template"
},
"web_accessible_resources": [
{
"matches": [
"*://web.whatsapp.com/*"
],
"resources": [
"static/js/content.bundle.js"
]
}
],
"background": {
"service_worker": "static/js/worker.bundle.js"
},
"content_scripts": [
{
"matches": [
"*://web.whatsapp.com/*"
],
"js": [
"static/js/wppconnect-wa.js",
"static/js/content.bundle.js"
]
}
],
"commands": {
"_execute_browser_action": {
"suggested_key": {
"default": "Ctrl+Shift+H",
"mac": "MacCtrl+Shift+H",
"linux": "Ctrl+Shift+H",
"windows": "Alt+Shift+H"
},
"description": "Abre o Hitter"
}
},
"key": ""
}
Content scripts injected using the declarative method have a separate window object than the page. Injecting using the manifest.json won't allow wa-js to access whatsapp web internals, you need to inject it programmatically. Here's how I do that:
let scriptEl = document.createElement("script");
scriptEl.src = chrome.runtime.getURL("assets/js/vendor/wpp.js");
(document.head || document.documentElement).appendChild(scriptEl);
@uhzair Thanks this works. What happens to the separate window object? Does it stay un referenced and garbage collected?
Hey @rahulbansal16, I was incorrect there, content scripts don't have a separate window object; they just run in isolated environment and the window object is isolated from content-scripts. You can read more about that here
@uhzair so content scripts run in isolated form but they can access the dom. Is there a way to communicate or share the functions between the content scripts and the page scripts?
@rahulbansal16 The communication between content scrips and page scripts may be acomplished through events:
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#communicating_with_the_web_page
PS: the only difference is that instead of wa-js i'm injecting venom bot api.
// content.bundle.js
window.addEventListener('hitter:chat-change', updateChat)
// injected.bundle.js
import 'venom-bot/dist/lib/wapi/wapi'
import { Chat } from '@/lib/wapi'
import { observable, observe, toJS } from 'mobx'
import { debounce } from '@/lib/debounce'
const store = observable({
chat: new Chat({})
})
window.WAPI.waitForStore('Chat', () => {
const getCurrentChat = debounce(async () => {
const found = await window.Store.Chat.models.find((chat) => chat.active)
if (found && String(found.contact.id) !== store.chat.id) {
const chat = found.contact
store.chat = new Chat({
id: chat.id.toString(),
phone: chat.userid
})
}
}, 400)
window.addEventListener('click', getCurrentChat)
})
// Observe all fields.
const disposer = observe(store, (change) => {
window.dispatchEvent(
new CustomEvent('hitter:chat-change', {
detail: toJS(store.chat)
})
)
})
Hey guys, thank you for the examples, they pointed me to the right direction.
I still have one issue though, I was able to inject the 'wppconnect-wa.js' module on the page using the method @uhzair shared, and the WPP variable got available through the window object. The problem is that I'm still not able to send the store data from the page to the content script.
I tried to setup the communication between the page and the content script through the window's postMessage API, as stated in the chrome docs, but when I try to send the data from the WPP I just can't. I believe that's because the return of the WPP are classes instances, and they're not JSON serializable.
For instance, this is the error that I get when I try to send the return of await window.WPP.contact.list() through the postMessage.

I also tried to follow @JimmyBastos example, but I wasn't able to adapt the code to my needs. Btw, do I really need mobx for this communication?
Does someone know how I can make this communication?