Syleront / VK Media Api Support

// ==UserScript==
// @name VK Media Api Support
// @description Adds support for browser's media api in VK
// @version 1.0.0
// @author Syleront
// @match *://*.vk.com/*
// @run-at document-idle
// @license MIT
// @copyright 2020, Syleront
// ==/UserScript==

(() => {
  const { navigator } = unsafeWindow;

  if ("mediaSession" in navigator) {
    const { getAudioPlayer, MediaMetadata } = unsafeWindow;
    const ap = getAudioPlayer();

    ap.on(null, "start", (audioData) => {
      const title = XmlDecode(audioData[3]);
      const artist = XmlDecode(audioData[4]);
      const artworks = audioData[14] || null;

      let artwork;
      if (artworks !== null) {
        let list = artworks.split(",");
        artwork = [{ src: list[list.length - 1], sizes: "80x80", type: "image/jpeg" }];
      }

      navigator.mediaSession.metadata = new MediaMetadata({ title, artist, artwork });
    });

    navigator.mediaSession.setActionHandler("play", () => {
      ap.play();
    });
    navigator.mediaSession.setActionHandler("pause", () => {
      ap.pause();
    });
    navigator.mediaSession.setActionHandler("nexttrack", () => {
      ap.playNext();
    });
    navigator.mediaSession.setActionHandler("previoustrack", () => {
      ap.playPrev();
    });
  } else {
    console.log("Media api is not supported in this browser");
  }

  function XmlDecode(str) {
    // source: https://github.com/mdevils/node-html-entities/blob/master/lib/xml-entities.js

    const ALPHA_INDEX = {
      "&lt": "<",
      "&gt": ">",
      "&quot": "\"",
      "&apos": "\"",
      "&amp": "&",
      "&lt;": "<",
      "&gt;": ">",
      "&quot;": "\"",
      "&apos;": "\"",
      "&amp;": "&"
    };

    if (!str || !str.length) {
      return "";
    }

    return str.replace(/&#?[0-9a-zA-Z]+;?/g, (s) => {
      if (s.charAt(1) === "#") {
        let code = s.charAt(2).toLowerCase() === "x" ?
          parseInt(s.substr(3), 16) :
          parseInt(s.substr(2));

        if (isNaN(code) || code < -32768 || code > 65535) {
          return "";
        }

        return String.fromCharCode(code);
      }

      return ALPHA_INDEX[s] || s;
    });
  }
})();