Steam | Відобразити мови гри

Виводить обрані мови (svg картинка) на сторінці пошуку ігор в steam.

Встановити цей скрипт?
Скрипт запропонований Автором

Вам також може сподобатись Steam | Приховати приватну інформацію.

Встановити цей скрипт
// ==UserScript==
// @name            Steam | Display game languages
// @name:uk         Steam | Відобразити мови гри
// @namespace       http://tampermonkey.net/
// @version         06.06.2024
// @description     Display images of selected languages on store search steam page.
// @description:uk  Виводить обрані мови (svg картинка) на сторінці пошуку ігор в steam.
// @author          Black_Yuzia
// @match           https://store.steampowered.com/search*
// @match           https://store.steampowered.com/charts/*
// @icon            https://store.steampowered.com/favicon.ico
// @grant           GM_addStyle
// @grant           GM.xmlHttpRequest
// @grant           GM.getValue
// @grant           GM.setValue
// @grant           GM.registerMenuCommand
// @grant           GM.notification
// @run-at          document-end
// @license         CC BY-NC-ND 4.0
// @license-url     https://creativecommons.org/licenses/by-nc-nd/4.0/
// @compatible      firefox
// @compatible      chrome
// @compatible      opera
// @compatible      safari
// @compatible      edge
// @connect         localhost:1500
// @connect         tm.starserv.net
// ==/UserScript==
(() => {
  // src/index.ts
  (async function() {
    "use strict";
    GM_addStyle(`
        .mr-2 {
            margin-right: 2px
        }
    `);
    const languages = await initLanguages();
    await registerMenuCommands();
    const leftcol = document.querySelector(".leftcol");
    const charts = waitForElement("div[class*=steamchartsshell_SteamChartsShell]");
    if (leftcol) {
      await proceedStoreGames();
      const searchObserver = new MutationObserver(proceedStoreGames);
      searchObserver.observe(leftcol, {
        childList: true,
        subtree: true
      });
    }
    if (await charts) {
      await proceedChartsGames();
      const chartsObserver = new MutationObserver(proceedChartsGames);
      chartsObserver.observe(await charts, {
        childList: true,
        subtree: true
      });
    }
    async function proceedStoreGames() {
      const games = [...document.querySelectorAll(".search_result_row:not(.sld_process)")];
      for (const game of games) {
        game.className += " sld_process";
      }
      if (games.length > 0) {
        const ids = games.map(parseGameID);
        const res = await GM.xmlHttpRequest({
          // @ts-expect-error
          url: `${"https://tm.starserv.net"}/steam/games/lang?id=${ids.join(",")}`,
          method: "GET",
          responseType: "json",
          fetch: true
        });
        if (res.status === 200) {
          const { response } = res;
          for (let i = 0; i < response.length; i++) {
            const items = response[i];
            if (items.length > 0) {
              for (const lang of languages) {
                if (items.includes(lang)) {
                  const game = games[i];
                  const img = document.createElement("img");
                  img.height = 20;
                  img.width = 20;
                  img.className = "mr-2";
                  img.src = `https://fastdl.starserv.net/languages/${lang}@2x.svg`;
                  game.querySelector(".platform_img")?.parentElement.prepend(img);
                }
              }
            }
          }
        }
      }
    }
    async function proceedChartsGames() {
      const games = [...document.querySelectorAll("tr[class*=weeklytopsellers_TableRow]:not(.sld_process)")];
      for (const game of games) {
        game.className += " sld_process";
      }
      if (games.length > 0) {
        const ids = games.map((game) => parseGameID(game.querySelector("a")));
        const res = await GM.xmlHttpRequest({
          // @ts-expect-error
          url: `${"https://tm.starserv.net"}/steam/games/lang?id=${ids.join(",")}`,
          method: "GET",
          responseType: "json",
          fetch: true
        });
        if (res.status === 200) {
          const { response } = res;
          for (let i = 0; i < response.length; i++) {
            const items = response[i];
            if (items.length > 0) {
              for (const lang of languages) {
                if (items.includes(lang)) {
                  const game = games[i];
                  const img = document.createElement("img");
                  img.height = 20;
                  img.width = 20;
                  img.className = "mr-2";
                  img.src = `https://fastdl.starserv.net/languages/${lang}@2x.svg`;
                  game.querySelector("div[class*=weeklytopsellers_GameName]")?.prepend(img);
                }
              }
            }
          }
        }
      }
    }
  })();
  function parseGameID(e) {
    const [id] = e?.href?.match(/\d+/) || [];
    return id;
  }
  async function initLanguages() {
    const notification = await GM.getValue("notification", false);
    const languages = await GM.getValue("languages", ["ukrainian", "russian"]);
    console.log("lang", languages);
    if (!notification) {
      GM.notification("Please choose languages in menu! Default lang: 'Ukrainian,\u0279ussian'", "Warning");
    }
    return languages.reverse();
  }
  async function registerMenuCommands() {
    await GM.registerMenuCommand("Set Languages", async () => {
      const languages = prompt("Set language(s) [example: Ukrainian,English,\u0279ussian]");
      if (languages) {
        await GM.setValue("notification", true);
        await GM.setValue("languages", languages.split(",").map((v) => v.trim().toLowerCase()));
      }
    });
  }
  function waitForElement(selector) {
    return new Promise((resolve) => {
      if (document.querySelector(selector)) {
        return resolve(document.querySelector(selector));
      }
      const observer = new MutationObserver(() => {
        if (document.querySelector(selector)) {
          observer.disconnect();
          resolve(document.querySelector(selector));
        }
      });
      observer.observe(document.body, {
        childList: true,
        subtree: true
      });
      setTimeout(() => {
        resolve(null);
      }, 3e4);
    });
  }
})();