wa-js icon indicating copy to clipboard operation
wa-js copied to clipboard

Running on chrome extension

Open JimmyBastos opened this issue 3 years ago • 1 comments

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": ""
}

JimmyBastos avatar Apr 24 '22 01:04 JimmyBastos

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 avatar Aug 14 '22 11:08 uhzair

@uhzair Thanks this works. What happens to the separate window object? Does it stay un referenced and garbage collected?

rahulbansal16 avatar Jan 14 '23 17:01 rahulbansal16

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 avatar Jan 15 '23 12:01 uhzair

@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 avatar Jan 28 '23 16:01 rahulbansal16

@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)
    })
  )
})

JimmyBastos avatar Feb 03 '23 18:02 JimmyBastos

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. image

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?

Harukisatoh avatar May 01 '23 17:05 Harukisatoh