2zqa / GroepTeller

// ==UserScript==
// @name        GroepTeller
// @author      Marijn
// @homepageURL https://openuserjs.org/scripts/2zqa/GroepTeller
// @namespace   https://openuserjs.org/users/2zqa/
// @description Voegt een knop toe die laat zien in hoeveel groepen je zit.
// @copyright   2023, 2zqa (https://openuserjs.org/users/2zqa)
// @license     MIT
// @version     1.2
// @match       https://web.whatsapp.com/*
// @icon        https://www.google.com/s2/favicons?domain=whatsapp.com
// @updateURL   https://openuserjs.org/meta/2zqa/GroepTeller.meta.js
// @downloadURL https://openuserjs.org/install/2zqa/GroepTeller.user.js
// @require     https://github.com/wppconnect-team/wa-js/releases/download/nightly/wppconnect-wa.js
// @grant       none
// ==/UserScript==
'use strict';
console.debug('Script geladen');
WPP.webpack.onReady(main);

function main() {
  console.debug('wppconnect is beschikbaar');
  addButtonOnLoad(() => printGroupStats());
}

async function addButtonOnLoad(callback) {
  let listElm = await getButtonList();
  let button = getButtonElm();
  button.addEventListener("click", callback);
  listElm.prepend(button);
  console.debug('Injected button');
}

async function getButtonList() {
  // Retrieval might need to be changed to something more
  // futureproof if class names change with Whatsapp updates
  let elm = await waitForElm('._604FD');
  return elm.firstElementChild.firstElementChild;
}

function printGroupStats() {
  WPP.group.getAllGroups().then((groups) => {
    const groupCount = groups.length;
    let groupList = '';

    for (const groupName in groups) {
      if (groups.hasOwnProperty(groupName)) {
        groupList += `- ${groups[groupName].__x_name}\n`;
      }
    }

    alert(`Je zit in ${groupCount} groepen:\n${groupList}`);
  }).catch((error) => {
    console.error(error);
  });
}

function getButtonElm() {
  // TODO: Probably doesn't need most tags here. Code generated from
  // the buttons that were already in the list, and didn't want to change
  // too much.
  const div1 = document.createElement("div");
  div1.setAttribute("class", "_3OtEr rOo0o");
  div1.setAttribute("data-testid", "menu-bar-groupcount");

  const div2 = document.createElement("div");
  div2.setAttribute("aria-disabled", "false");
  div2.setAttribute("role", "button");
  div2.setAttribute("tabindex", "0");
  div2.setAttribute("class", "_3ndVb");
  div2.setAttribute("data-tab", "2");
  div2.setAttribute("title", "Group Counter");
  div2.setAttribute("aria-label", "Group Counter");

  const span1 = document.createElement("span");

  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  svg.setAttribute("viewBox", "0 96 960 960");
  svg.setAttribute("height", "24"); // used to be 28
  svg.setAttribute("width", "24");
  svg.setAttribute("preserveAspectRatio", "xMidYMid meet");
  svg.setAttribute("class", "");
  svg.setAttribute("fill", "none");

  const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
  path.setAttribute("fill-rule", "evenodd");
  path.setAttribute("clip-rule", "evenodd");
  path.setAttribute("fill", "currentColor");
  path.setAttribute("d", "m 690.882,786 q 25.883,0 44,-19 Q 753,748 753,722.118 q 0,-25.883 -18.118,-44 Q 716.765,660 690.882,660 665,660 646,678.118 q -19,18.117 -19,44 0,25.882 19,44.882 19,19 44.882,19 z M 689.5,911 q 33.5,0 60.5,-14 27,-14 46,-40 -26,-14 -51.962,-21 -25.961,-7 -54,-7 -28.038,0 -54.538,7 -26.5,7 -51.5,21 19,26 45.5,40 26.5,14 60,14 z M 480,976 Q 342,944 251,819.5 160,695 160,534 V 295 L 480,175 800,295 V 565 Q 786,558 770,552.5 754,547 740,545 V 337 L 480,241 220,337 v 197 q 0,76 24.5,140 24.5,64 62.5,112.5 38,48.5 84,80.5 46,32 89,46 6,12 18,27 12,15 20,23 -9,5 -19,7.5 -10,2.5 -19,5.5 z m 212.5,0 Q 615,976 560,920.5 505,865 505,789 505,710.565 559.99,655.282 614.98,600 693,600 770,600 825.5,655.282 881,710.565 881,789 881,865 825.5,920.5 770,976 692.5,976 Z M 480,577 Z");

  svg.appendChild(path);
  span1.appendChild(svg);
  div2.appendChild(span1);
  div1.appendChild(div2);

  const span2 = document.createElement("span");
  div1.appendChild(span2);

  return div1;
}

// From: https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists
function waitForElm(selector) {
  return new Promise(resolve => {
    if (document.querySelector(selector)) {
      return resolve(document.querySelector(selector));
    }

    const observer = new MutationObserver(mutations => {
      if (document.querySelector(selector)) {
        resolve(document.querySelector(selector));
        observer.disconnect();
      }
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true
    });
  });
}