// ==UserScript==
// @name GGn No-Intro Helper
// @description A GGn user script to help with No-Intro uploads/trumps
// @namespace http://tampermonkey.net/
// @version 2.3.1
// @author BestGrapeLeaves
// @license MIT
// @match *://gazellegames.net/upload.php?groupid=*
// @match *://gazellegames.net/torrents.php?id=*
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @grant GM_listValues
// @grant GM_deleteValue
// @grant GM_setValue
// @grant GM_getValue
// @connect datomatic.no-intro.org
// @icon https://i.imgur.com/UFOk0Iu.png
// ==/UserScript==
/******/ (() => { // webpackBootstrap
/******/ "use strict";
var __webpack_exports__ = {};
;// CONCATENATED MODULE: ./src/inserts/checkForTrumpsButton.ts
function checkForTrumpsButton() {
const existing = $("#check-for-no-intro-trumps-button");
const button = existing.length > 0 ? existing : $(`<input id="check-for-no-intro-trumps-button" type="button" value="Check for No-Intro Trumps" style="background: hotpink; color: black; font-weight: bold; margin-left: 10px;"/>`);
const progress = (text)=>{
button.val(text);
};
const disable = ()=>{
button.prop("disabled", true);
button.css("background-color", "pink");
button.css("color", "darkslategray");
button.css("box-shadow", "none");
};
const insert = ()=>{
button.detach();
$(".torrent_table > tbody > tr:first-child > td:first-child").first().append(button);
};
return {
disable,
progress,
insert,
button
};
}
;// CONCATENATED MODULE: ./src/utils/dom/extractNoIntroLinkFromDescription.ts
function extractNoIntroLinkFromDescription(torrentId) {
const links = $(`#torrent_${torrentId} #description a`);
return links.map(function() {
return $(this).attr("href");
}).get().map((link)=>{
const url = new URL(link);
url.protocol = "https:"; // Rarely descriptions have the http protocol
return url.toString();
}).find((link)=>link.startsWith("https://datomatic.no-intro.org/"));
}
;// CONCATENATED MODULE: ./src/utils/dom/getNoIntroTorrentsOnPage.ts
function notFalse(x) {
return x !== false;
}
function getNoIntroTorrentsOnPage() {
return $('a[title="Permalink"]').map(function() {
const torrentId = new URLSearchParams($(this).attr("href").replace("torrents.php", "")).get("torrentid");
const noIntroLink = extractNoIntroLinkFromDescription(torrentId);
if (!noIntroLink) {
return false;
}
const reported = $(this).parent().parent().find(".reported_label").text() === "Reported";
return {
torrentId,
a: $(this),
noIntroLink,
reported,
permalink: window.location.origin + "/" + $(this).attr("href")
};
}).get().filter(notFalse);
}
;// CONCATENATED MODULE: ./src/inserts/insertAddCopyHelpers.ts
function insertAddCopyHelpers() {
getNoIntroTorrentsOnPage().forEach((param)=>{
let { torrentId , a , noIntroLink } = param;
// Extract edition information
const editionInfo = a.parents(".group_torrent").parent().prev().find(".group_torrent > td > strong").text();
const [editionYear, ...rest] = editionInfo.split(" - ");
const editionName = rest.join(" - ");
const formatedEditionInfo = `${editionName} (${editionYear})`;
// GroupId
const groupId = new URLSearchParams(window.location.search).get("id");
// Create params
const params = new URLSearchParams();
params.set("groupid", groupId);
params.set("edition", formatedEditionInfo);
params.set("no-intro", noIntroLink);
// Insert button
const addCopyButton = $(`<a href="upload.php?${params.toString()}" title="Add Copy" id="ac_${torrentId}">AC</a>`);
$([
" | ",
addCopyButton
]).insertAfter(a);
});
}
;// CONCATENATED MODULE: ./src/constants.ts
// REGEXES
const PARENS_TAGS_REGEX = /\(.*?\)/g;
const NO_INTRO_TAGS_REGEX = /\((Unl|Proto|Sample|Aftermarket|Homebrew)\)|\(Rev \d+\)|\(v[\d\.]+\)|\(Beta(?: \d+)?\)/;
// LISTS
const GGN_REGIONS = [
"USA",
"Europe",
"Japan",
"Asia",
"Australia",
"France",
"Germany",
"Spain",
"Italy",
"UK",
"Netherlands",
"Sweden",
"Russia",
"China",
"Korea",
"Hong Kong",
"Taiwan",
"Brazil",
"Canada",
"Japan, USA",
"Japan, Europe",
"USA, Europe",
"Europe, Australia",
"Japan, Asia",
"UK, Australia",
"World",
"Region-Free",
"Other",
];
// TABLES
const REGION_TO_LANGUAGE = {
USA: "English",
Europe: "English",
Japan: "Japanese",
World: "English",
"USA, Europe": "English",
Other: "English",
Korea: "Korean",
Taiwan: "Chinese"
};
const TWO_LETTER_REGION_CODE_TO_NAME = {
en: "English",
de: "German",
fr: "French",
cz: "Czech",
zh: "Chinese",
it: "Italian",
ja: "Japanese",
ko: "Korean",
pl: "Polish",
pt: "Portuguese",
ru: "Russian",
es: "Spanish"
};
;// CONCATENATED MODULE: ./src/utils/GMCache.ts
class GMCache {
getKeyName(key) {
return `cache${this.name}.${key}`;
}
get(key) {
const res = GM_getValue(this.getKeyName(key));
if (res === undefined) {
return undefined;
}
const { value , expires } = res;
if (expires && expires < Date.now()) {
this.delete(key);
return undefined;
}
return value;
}
set(key, value, ttl) {
const expires = Date.now() + ttl;
GM_setValue(this.getKeyName(key), {
value,
expires
});
}
delete(key) {
GM_deleteValue(this.getKeyName(key));
}
cleanUp() {
const keys = GM_listValues();
keys.forEach((key)=>{
if (key.startsWith(this.getKeyName(""))) {
const { expires } = GM_getValue(key);
if (expires < Date.now()) {
GM_deleteValue(key);
}
}
});
}
clear() {
const keys = GM_listValues();
keys.forEach((key)=>{
if (key.startsWith(this.getKeyName(""))) {
GM_deleteValue(key);
}
});
}
constructor(name){
this.name = name;
}
}
;// CONCATENATED MODULE: ./src/utils/noIntroToGGnLanguage.ts
function noIntroToGGnLanguage(region, possiblyLanguages) {
if (possiblyLanguages === undefined) {
// @ts-expect-error
return REGION_TO_LANGUAGE[region] || "Other";
}
const twoLetterCodes = possiblyLanguages.split(",").map((l)=>l.trim().toLowerCase());
const isLanguages = twoLetterCodes.every((l)=>l.length === 2);
if (!isLanguages || twoLetterCodes.length === 0) {
// @ts-expect-error
return REGION_TO_LANGUAGE[region] || "Other";
}
if (twoLetterCodes.length > 1) {
return "Multi-Language";
}
return TWO_LETTER_REGION_CODE_TO_NAME[twoLetterCodes[0]] || "Other";
}
;// CONCATENATED MODULE: ./src/utils/fetchNoIntro.ts
const cache = new GMCache("no-intro");
// @ts-expect-error
unsafeWindow.GGN_NO_INTRO_HELPER_CACHE = cache;
function fetchNoIntro(url) {
return new Promise((resolve, reject)=>{
if (url.endsWith("n=")) {
return reject(new Error("Blacklist no-intro url. Fetch was aborted to prevent IP ban."));
}
const cached = cache.get(url);
if (cached) {
resolve({
...cached,
cached: true
});
return;
}
GM_xmlhttpRequest({
method: "GET",
url,
timeout: 5000,
onload: (param)=>{
let { responseText } = param;
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)");
if (!dumpsTitle) {
// @ts-expect-error
unsafeWindow.GMPARSER = scraped;
console.error("GGn No-Intro Helper: dumps title not found, set parser as global: GMPARSER", responseText);
throw new Error("No dump's title found");
}
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();
// Region/Lang
const [region, possiblyLanguages] = title.match(/\(.+?\)/g).map((p)=>p.slice(1, -1));
const matchedGGnRegion = GGN_REGIONS.find((r)=>r === region) || "Other";
const matchedGGnLanguage = noIntroToGGnLanguage(matchedGGnRegion, possiblyLanguages);
// One hour seems appropriate
const extension = filename.split(".").pop() || "";
const info = {
// We stopped shipping entire filenames
// when zibzab reported that it varies from dump to dump
// like some can have a "bad" filename
// title is 100% accurate, and filename shouldn't vary
extension,
title,
filename: title + "." + extension,
language: matchedGGnLanguage,
region: matchedGGnRegion,
cached: false
};
cache.set(url, info, 1000 * 60 * 60);
resolve(info);
} catch (err) {
console.error("zibzab helper failed to parse no-intro:", err);
reject(new Error("Failed to parse no-intro :/\nPlease report to BestGrapeLeaves,\nincluding the error that was logged to the browser console"));
}
},
ontimeout: ()=>{
reject(new Error("Request to No-Intro timed out after 5 seconds"));
}
});
});
}
;// CONCATENATED MODULE: ./src/utils/dom/fetchTorrentFilelist.ts
// We are fetching files for checking,
// might as well reduce load on servers and save to dom (like the button does)
function fetchTorrentFilelist(torrentId) {
const parseFromDom = ()=>$(`#files_${torrentId} > table > tbody > tr:not(.colhead_dark) > td:first-child`).map(function() {
return $(this).text();
}).get();
return new Promise((resolve)=>{
// @ts-expect-error
if ($("#files_" + torrentId).raw().innerHTML === "") {
// $('#files_' + torrentId).gshow().raw().innerHTML = '<h4>Loading...</h4>';
ajax.get("torrents.php?action=torrentfilelist&torrentid=" + torrentId, function(response) {
// @ts-expect-error
$("#files_" + torrentId).ghide();
// @ts-expect-error
$("#files_" + torrentId).raw().innerHTML = response;
resolve(parseFromDom());
});
} else {
resolve(parseFromDom());
}
});
}
;// CONCATENATED MODULE: ./src/utils/dom/checkIfTrumpable.ts
async function checkIfTrumpable(torrent) {
try {
const { title , cached } = await fetchNoIntro(torrent.noIntroLink);
const desiredFilename = title + ".zip";
const files = await fetchTorrentFilelist(torrent.torrentId);
if (files.length !== 1) {
return {
trumpable: true,
desiredFilename,
cached,
inditermint: "Couldn't determine if the torrent is trumpable -\nMultiple/No zip files found in torrent"
};
}
const actualFilename = files[0];
return {
trumpable: desiredFilename !== actualFilename,
desiredFilename,
actualFilename,
cached
};
} catch (err) {
console.error("GGn No-Intro Helper: Error checking trumpability", err);
return {
trumpable: true,
cached: false,
inditermint: "Couldn't determine if the torrent is trumpable -\nFailed fetching No-Intro:\n" + err.message
};
}
}
;// CONCATENATED MODULE: ./src/inserts/smallPre.ts
function smallPre(text, bgColor) {
return `<pre style="
padding: 0px;
margin: 0;
background-color: ${bgColor};
color: black;
font-weight: bold;
font-size: 12px;
padding-left: 3px;
padding-right: 3px;
width: fit-content;
">${text}</pre>`;
}
;// CONCATENATED MODULE: ./src/inserts/insertTrumpNotice.ts
function inditermintNoticeInfo(param) {
let { inditermint } = param;
return {
title: "Couldn't determine if the torrent is trumpable:",
details: inditermint,
color: "pink"
};
}
function reportedNoticeInfo(param) {
let { inditermint } = param;
return {
title: "Torrent was trumped and reported!",
details: "",
color: "var(--darkRed)"
};
}
function trumpableNoticeInfo(param) {
let { actualFilename , desiredFilename } = param;
return {
title: "This torrent is trumpable!",
details: `The filename in the torrent is: ${smallPre(actualFilename, "lightcoral")} but the desired filename, based on <i>No-Intro</i> is: ${smallPre(desiredFilename, "lightgreen")}`,
color: "hotpink"
};
}
function reportableNoticeInfo(param) {
let { fixedVersion , torrentId , actualFilename , desiredFilename , noIntroLink } = param;
const form = $("<div/></div>");
const trumpingTorrentInput = $(`<input type="text" value="${fixedVersion.permalink}" placeholder="https://gazellegames.net/torrents.php?id=xxxxx&torrentid=yyyyyy" style="width: 75%; background: #ffb952; color: black;"/>`);
const commentTextarea = $(`<textarea placeholder="Previous upload didn't like hummus" style="height: 100px; width: 90%; background: #ffb952; color: black; margin: 0;"/>`);
commentTextarea.text(`ROM name changed on No-Intro.
Reported filename : ${actualFilename}
Trumping filename : ${desiredFilename}
No-Intro for reference : ${noIntroLink}`);
const submitInputButton = $(`<input id="no-intro-helper-submit-trump-report-${torrentId}" type="button" value="REPORT" style="width: 70px; margin: 0; background: #ffb952; color: black; font-weight: bolder;"/>`);
const errorMessage = $("<div style='color: red; font-weight: bold; font-size: 13px; white-space: pre-line;'></div>").hide();
form.append(`<p style="font-size: 12px;">Trumping Torrent Permalink:</p>`, trumpingTorrentInput, `<p style="font-size: 12px;">Report Comment:</p>`, commentTextarea, `<p style="font-size: 12px;">Submit Report:</p>`, submitInputButton, errorMessage);
submitInputButton.click(async ()=>{
// If it's disabled this should in theory not trigger,
// but just in case jquery does some shenaningans
// when you manually trigger a click event
if (submitInputButton.prop("disabled") === true) {
return;
}
errorMessage.hide();
submitInputButton.prop("disabled", true);
const data = new FormData();
data.append("submit", "true");
data.append("torrentid", torrentId);
data.append("categoryid", "1");
data.append("type", "trump");
data.append("sitelink", fixedVersion.permalink);
data.append("extra", commentTextarea.val());
data.append("id_token", new Date().getTime().toString());
try {
await fetch("/reportsv2.php?action=takereport", {
method: "POST",
body: data
});
location.reload();
} catch (err) {
console.error("Error submitting trump report", err);
console.error("Form data sent:", Object.fromEntries([
...data.entries()
]));
errorMessage.text(`An error occurred while submitting the trump report. If you believe this is a problem with the script, please report to BestGrapeLeaves (including console logs if you can).
Error Message:
${err.message}`);
errorMessage.show();
submitInputButton.prop("disabled", false);
}
});
return {
title: "Torrent needs to be reported for trump!",
details: form,
color: "#ff7600"
};
}
function insertTrumpNotice(torrent) {
const { inditermint , fixedVersion , torrentId , reported } = torrent;
// Settings
let info;
let type;
if (inditermint) {
type = "inditermint";
info = inditermintNoticeInfo(torrent);
} else if (fixedVersion) {
if (reported) {
type = "reported";
info = reportedNoticeInfo(torrent);
} else {
type = "reportable";
info = reportableNoticeInfo(torrent);
}
} else {
type = "trumpable";
info = trumpableNoticeInfo(torrent);
}
const { color , details , title } = info;
// Elements
const detailsDiv = $(`<div style="font-weight: normal; color: white;"></div>`).hide();
detailsDiv.append(details);
const titleSpan = $(`
<span style="color: ${color}; font-size: 14px; font-weight: bold;">${title}</span>`);
const actionsDiv = $(`<div id="trump-notice-links-${torrentId}" style="font-weight: normal; font-size: 11px; display: inline; margin: 5px; user-select: none;"></div>`);
// Toggle Details
if (type !== "reported") {
const toggleDetailsActionSpan = $(`<span style="cursor: pointer; margin-right: 5px;">[Expand]</span>`);
toggleDetailsActionSpan.click(()=>{
const collapsed = toggleDetailsActionSpan.text() === "[Expand]";
if (collapsed) {
toggleDetailsActionSpan.text("[Collapse]");
detailsDiv.show();
} else {
toggleDetailsActionSpan.text("[Expand]");
detailsDiv.hide();
}
});
actionsDiv.append(toggleDetailsActionSpan);
}
// Send Report
if (type === "reportable") {
const sendReportActionSpan = $(`<span style="cursor: pointer; margin-right: 5px;">[Send Report]</span>`);
sendReportActionSpan.click(()=>{
$(`#no-intro-helper-submit-trump-report-${torrentId}`).click();
});
actionsDiv.append(sendReportActionSpan);
}
// Cheer
if (type === "reported") {
const cheerActionSpan = $(`<span style="cursor: pointer; margin-right: 5px; position: absolute;">[Cheer]</span>`);
cheerActionSpan.click(()=>{
cheerActionSpan.text("HOORAY!");
cheerActionSpan.animate({
opacity: 0
}, // @ts-expect-error
{
duration: 2000,
step: function(now) {
cheerActionSpan.css({
transform: "rotate(" + now * 360 * 5 + "deg)"
});
}
}, "swing");
});
actionsDiv.append(cheerActionSpan);
}
// Tree
const wrapper = $(`<div></div>`);
titleSpan.append(actionsDiv);
wrapper.append(titleSpan);
wrapper.append(detailsDiv);
// Place
let currentlyAdaptedToSmallScreen;
function placeTrumpNotice() {
console.log("adapting", window.innerWidth);
if (window.innerWidth <= 800) {
if (currentlyAdaptedToSmallScreen) {
return;
}
currentlyAdaptedToSmallScreen = true;
$(`#torrent${torrentId}`).css("border-bottom", "none");
wrapper.css("margin-left", "25px");
wrapper.detach();
wrapper.insertAfter(`#torrent${torrentId}`);
} else {
if (currentlyAdaptedToSmallScreen === false) {
return;
}
currentlyAdaptedToSmallScreen = false;
$(`#torrent${torrentId}`).css("border-bottom", "");
wrapper.css("margin-left", "0px");
wrapper.detach();
wrapper.appendTo(`#torrent${torrentId} > td:first-child`);
}
}
placeTrumpNotice();
$(window).resize(placeTrumpNotice);
// Call global hook (for other scripts)
// @ts-expect-error
if (typeof unsafeWindow.GM_GGN_NOINTRO_HELPER_ADDED_LINKS === "function") {
// @ts-expect-error
unsafeWindow.GM_GGN_NOINTRO_HELPER_ADDED_LINKS({
...torrent,
links: actionsDiv
});
}
}
;// CONCATENATED MODULE: ./src/inserts/insertTrumpSuggestions.ts
async function checkForImproperlyNamedTorrents(torrents) {
const { disable , progress } = checkForTrumpsButton();
disable();
let prevCached = false;
const results = [];
for(let i = 0; i < torrents.length; i++){
const torrent = torrents[i];
progress(`Checking For Trumps ${i + 1}/${torrents.length}...`);
// timeout to avoid rate limiting
if (!prevCached) {
await new Promise((resolve)=>setTimeout(resolve, 500));
}
// Check trump
const TrumpCheckResult = await checkIfTrumpable(torrent);
const { cached } = TrumpCheckResult;
prevCached = cached;
results.push({
...TrumpCheckResult,
...torrent
});
}
return results;
}
// Filter the torrents that have a trump uploaded
function attachFixedVersionsToTorrents(torrents) {
const trumpCanidates = [];
const validTorrents = [];
for (const torrent of torrents){
if (torrent.trumpable) {
trumpCanidates.push(torrent);
continue;
}
validTorrents.push(torrent);
}
// Efficiency is not my greatest of concerns,
// if you want implement a graph theory solution in O(1) or something
const processed = trumpCanidates.map((c)=>({
...c,
fixedVersion: validTorrents.find((v)=>!v.inditermint && v.noIntroLink === c.noIntroLink)
}));
return [
...validTorrents,
...processed
];
}
async function insertTrumpSuggestions(results) {
const { progress } = checkForTrumpsButton();
let trumps = 0;
results.forEach((torrent)=>{
if (!torrent.trumpable) {
return;
}
if (!torrent.inditermint && !torrent.fixedVersion) {
trumps++;
}
insertTrumpNotice(torrent);
});
if (trumps === 0) {
progress("No Trumps Found");
} else if (trumps === 1) {
progress("1 Trump Found");
} else {
progress(`${trumps} Trumps Found`);
}
}
async function findAndDisplayTrumps() {
const torrents = getNoIntroTorrentsOnPage();
const results = await checkForImproperlyNamedTorrents(torrents);
const processed = attachFixedVersionsToTorrents(results);
console.log("GGn No-Intro Helper: Trumps", processed);
insertTrumpSuggestions(processed);
}
;// CONCATENATED MODULE: ./src/pages/torrents.ts
function trumpSuggestions() {
const torrents = getNoIntroTorrentsOnPage();
if (torrents.length === 0) {
return;
}
const { button , insert } = checkForTrumpsButton();
insert();
if (torrents.length <= 4) {
findAndDisplayTrumps();
}
button.click((e)=>{
e.stopImmediatePropagation();
findAndDisplayTrumps();
});
}
function torrentsPageMain() {
insertAddCopyHelpers();
trumpSuggestions();
}
;// CONCATENATED MODULE: ./src/inserts/uploadLinkParserUI.ts
function uploadNoIntroLinkParserUI() {
// elements
const container = $(`<tr id="no-intro-url" name="no-intro-url">
<td class="label">No-Intro Link</td>
</tr>`);
const input = $('<input type="text" id="no-intro-url-input" name="no-intro-url-input" size="70%" class="input_tog" value="">');
const error = $('<p id="no-intro-url-error" name="no-intro-url-error" style="color: red; white-space:pre-line;"></p>').hide();
const loading = $('<p id="no-intro-url-loading" name="no-intro-url-loading" style="color: green;">Loading...</p>').hide();
// structure
const td = $("<td></td>");
td.append(input);
td.append(error);
td.append(loading);
container.append(td);
// utils
const setError = (msg)=>{
error.text(msg);
error.show();
};
const setLoading = (isLoading)=>{
if (isLoading) {
loading.show();
} else {
loading.hide();
}
};
return {
loading,
error,
container,
input,
setError,
setLoading
};
}
;// CONCATENATED MODULE: ./src/utils/dom/setUploadEdition.ts
function setUploadEdition(edition) {
try {
$("#groupremasters").val(edition).change();
GroupRemaster();
} catch {
// group remaster always throws (regardless of the userscript)
}
}
;// CONCATENATED MODULE: ./src/utils/generateTorrentDescription.ts
const generateTorrentDescription = function() {
let url = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "xxx", filename = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "xxx";
return `[align=center]${filename} matches [url=${url}]No-Intro checksum[/url]
Compressed with [url=https://sourceforge.net/projects/trrntzip/]torrentzip.[/url][/align]
`;
};
;// CONCATENATED MODULE: ./src/pages/upload.ts
function linkParser() {
// UI
const { error , container , input , setError , setLoading } = uploadNoIntroLinkParserUI();
// watch link input
let justChecked = "";
input.on("paste", (e)=>{
e.preventDefault();
const text = e.originalEvent.clipboardData.getData("text/plain");
input.val(text);
submit();
});
input.change(submit);
// React to release type change, and insert input
$("select#miscellaneous").change(function() {
const selected = $("select#miscellaneous option:selected").text();
if (selected === "ROM") {
container.insertBefore("#regionrow");
$("textarea#release_desc").val(generateTorrentDescription()); /// xxx temporary
} else {
container.detach();
}
});
// handle submit
async function submit() {
// Prechecks
error.hide();
const url = input.val();
if (justChecked === url) {
return;
}
if (!url.startsWith("https://datomatic.no-intro.org/")) {
setError("Invalid URL");
return;
}
// Go
justChecked = url;
setLoading(true);
try {
const { filename , language , region } = await fetchNoIntro(url);
$("textarea#release_desc").val(generateTorrentDescription(url, filename));
$("select#region").val(region);
$("select#language").val(language);
} catch (err) {
setError(err.message || err || "An unexpected error has occurred");
} finally{
setLoading(false);
}
}
}
function magicNoIntroPress() {
const filename = $("#file").val();
const tags = filename ? filename.match(PARENS_TAGS_REGEX).filter((p)=>NO_INTRO_TAGS_REGEX.test(p)).join(" ") : "";
// Release type = ROM
$("select#miscellaneous").val("ROM").change();
// It is a special edition
if (!$("input#remaster").prop("checked")) {
$("input#remaster").prop("checked", true);
Remaster();
}
// Not a scene release
$("#ripsrc_home").prop("checked", true);
// @ts-expect-error Update title
updateReleaseTitle($("#title").raw().value + " " + tags);
// Get url params
const params = new URLSearchParams(window.location.search);
// Set correct edition (fallback to guessing)
const editionInfo = params.get("edition");
$("#groupremasters > option").each(function() {
const title = $(this).text().toLowerCase();
console.log("checking", title);
if (editionInfo && title === editionInfo.toLowerCase()) {
setUploadEdition($(this).val());
return false; // This breaks out of the jquery loop
} else {
if (title.includes("no-intro") || title.includes("nointro")) {
setUploadEdition($(this).val());
}
}
});
// Trigger no-intro link scraper
const noIntroLink = params.get("no-intro");
if (noIntroLink) {
$("#no-intro-url-input").val(noIntroLink).change();
}
}
function uploadPageMain() {
// Insert No Intro magic button
const noIntroMagicButton = $('<input type="button" value="No-Intro"></input>');
noIntroMagicButton.click(()=>magicNoIntroPress());
noIntroMagicButton.insertAfter("#file");
linkParser();
}
;// CONCATENATED MODULE: ./src/index.ts
async function main() {
console.log("GGn No-Intro Helper: Starting...");
if (window.location.pathname === "/torrents.php") {
torrentsPageMain();
} else if (window.location.pathname === "/upload.php") {
uploadPageMain();
}
// Blacklist no-intro URLs that lead to ban
$("a").click(function() {
if (/https?:\/\/datomatic\.no-intro\.org\/index\.php\?page=show_record&s=(.*?)&n=$/i.test($(this).attr("href"))) {
$(this).text("BLACKLISTED");
return false;
}
});
}
main().catch((e)=>{
console.log(e);
});
/******/ })()
;