Greasy Fork

Zibzab's GameDox/Rom Upload Helper

try to take over the world :)

目前为 2022-09-03 提交的版本。查看 最新版本

// ==UserScript==
// @name         Zibzab's GameDox/Rom Upload Helper
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  try to take over the world :)
// @author       BestGrapeLeaves
// @match        https://gazellegames.net/upload.php?groupid=*
// @icon         https://i.imgur.com/UFOk0Iu.png
// @grant        GM_xmlhttpRequest
// @connect      datomatic.no-intro.org
// @license      MIT
// ==/UserScript==

const GAME_DOX_INSERT = `[align=center] pdf pages
[/align]
`;

const genRomInsert = (
  url = "xxx",
  filename = "xxx"
) => `[align=center]${filename} matches [url=${url}]No-Intro checksum[/url]
Compressed with [url=https://sourceforge.net/projects/trrntzip/]torrentzip.[/url][/align]
`;

const regionToLanguage = {
  USA: "English",
  Europe: "English",
  Japan: "Japanese",
  World: "English",
  "USA, Europe": "English",
  Other: "English",
  Korea: "Korean",
  Taiwan: "Chinese"
};

const twoLetterLanguageCodeToGGn = {
  en: "English",
  de: "German",
  fr: "French",
  cz: "Czech",
  zh: "Chinese",
  it: "Italian",
  ja: "Japanese",
  ko: "Korean",
  pl: "Polish",
  pt: "Portuguese",
  ru: "Russian",
  es: "Spanish",
};

const parseLanguage = (region, possiblyLanguages) => {
  if (possiblyLanguages === undefined) {
    return regionToLanguage[region] || "Other";
  }

  const twoLetterCodes = possiblyLanguages
    .split(",")
    .map((l) => l.trim().toLowerCase());
  const isLanguages = twoLetterCodes.every((l) => l.length === 2);
  if (!isLanguages || twoLetterCodes.length === 0) {
    return regionToLanguage[region] || "Other";
  }

  if (twoLetterCodes.length > 1) {
    return "Multi-Language";
  }

  return twoLetterLanguageCodeToGGn[twoLetterCodes[0]] || "Other";
};

function noIntroUI() {
  // elements
  const noIntroContainer = $(
    `<tr id="no-intro-url" name="no-intro-url">
      <td class="label">No-Intro Link</td>
    </tr>`
  );
  const noIntroInput = $(
    '<input type="text" id="no-intro-url-input" name="no-intro-url-input" size="70%" class="input_tog" value="">'
  );
  const noIntroError = $(
    '<p id="no-intro-url-error" name="no-intro-url-error" style="color: red; white-space:pre-line;"></p>'
  ).hide();
  const noIntroLoading = $(
    '<p id="no-intro-url-loading" name="no-intro-url-loading" style="color: green;">Loading...</p>'
  ).hide();
  // structure
  const td = $("<td></td>");
  td.append(noIntroInput);
  td.append(noIntroError);
  td.append(noIntroLoading);
  noIntroContainer.append(td);
  // utils
  const error = (msg) => {
    noIntroError.text(msg);
    noIntroError.show();
  };
  const loading = (isLoading) => {
    if (isLoading) {
      noIntroLoading.show();
    } else {
      noIntroLoading.hide();
    }
  };
  return { loading, error, noIntroContainer, noIntroInput, noIntroError };
}

(function () {
  "use strict";

  const { noIntroContainer, noIntroInput, noIntroError, error, loading } =
    noIntroUI();
  // handle url
  let justChecked = "";
  const submitNoInput = () => {
    noIntroError.hide();
    const url = noIntroInput.val();

    if (justChecked === url) {
      return;
    }

    if (!url.startsWith("https://datomatic.no-intro.org/")) {
      error("Invalid URL");
      return;
    }

    justChecked = url;
    loading(true);
    GM_xmlhttpRequest({
      method: "GET",
      url,
      timeout: 5000,
      onload: ({ responseText }) => {
        try {
          const parser = new DOMParser();
          const scraped = parser.parseFromString(responseText, "text/html");

          // HTML is great
          const dumpsTitle = [...scraped
            .querySelectorAll("td.TableTitle")]
            .find(td => td.innerText.trim() === "Dump(s)")
          const filename = dumpsTitle.parentElement.parentElement.parentElement.nextElementSibling.querySelector(
              "table > tbody > tr:nth-child(2) > td:last-child"
            )
            .innerText.trim();
          const title = scraped
            .querySelector("tr.romname_section > td")
            .innerText.trim();
          const parenMatches = title
            .match(/\(.+?\)/g)
            .map((p) => p.slice(1, -1));
          const [region, possiblyLanguages] = parenMatches;
          const matchedGGnRegion =
            php_torrent_form_regions.find((r) => r === region) || "Other";
          const matchedGGnLanguage = parseLanguage(
            matchedGGnRegion,
            possiblyLanguages
          );
          $("textarea#release_desc").val(genRomInsert(url, filename));
          $("select#region").val(matchedGGnRegion);
          $("select#language").val(matchedGGnLanguage);
          loading(false);
        } catch (err) {
          loading(false);
          error(
            "Failed to parse no-intro :/\nPlease report to BestGrapeLeaves,\nthe error was logged to the browser console"
          );
          console.error("zibzab helper failed to parse no-intro:", err);
        }
      },
      ontimeout: () => {
        loading(false);
        error("Request to no-intro timed out after 5 seconds");
      },
    });
  };

  // bind events
  noIntroInput.on("paste", (e) => {
    e.preventDefault();
    const text = e.originalEvent.clipboardData.getData("text/plain");
    noIntroInput.val(text);
    submitNoInput();
  });
  noIntroInput.blur(submitNoInput);

  $("select#miscellaneous").change(function () {
    const selected = $("select#miscellaneous option:selected").text();
    if (selected === "GameDOX") {
      noIntroContainer.detach();
      $("input#release_title").val(
        $("input#release_title").val() + " - Manual"
      );
      $("select#gamedox").val("Guide").change();
      $("select#format").val("PDF").change();
      $("input#scan").click();
      Scan();
      $("textarea#release_desc").val(
        $("textarea#release_desc").val() + GAME_DOX_INSERT
      );
    } else if (selected === "ROM") {
      // const url = prompt("Please enter the ROM's No-Intro link:");
      noIntroContainer.insertBefore("#regionrow");
      $("textarea#release_desc").val(genRomInsert());
    } else {
      noIntroContainer.detach();
    }
  });
})();