NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Retro Enhanced // @namespace https://github.com/miagui // @version 1.4.5 // @description Additional functionality for retro gaming related sites. // @author Miagui // @match *://retroachievements.org/* // @license MIT // @updateURL https://openuserjs.org/meta/Miagui/Retro_Enhanced.meta.js // @downloadURL https://openuserjs.org/install/Miagui/Retro_Enhanced.user.js // @grant GM_xmlhttpRequest // @grant GM_log // @grant GM_setValue // @grant GM_getValue // @grant GM_listValues // @grant GM_deleteValue // @connect archive.org // @connect the-eye.eu // @connect raw.githubusercontent.com // @connect sheets.googleapis.com // @connect emuparadise.me // @connect speedrun.com // @connect myrient.erista.me // @require http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js // ==/UserScript== (async function () { var pageWithParams = (location.pathname + location.search).substr(1); var page = location.pathname; var loggedUser = $(".brand-top strong > a").text(); var sectionName = window.location.hash.slice(1); // Configs var enableSpeedrun = await GM_getValue("enableSpeedrun", false); var enableRomSearch = await GM_getValue("enableRomSearch", true); var enableCustomBG = await GM_getValue("enableCustomBG", true); var enableGameplayVideo = await GM_getValue("enableGameplayVideo", true); var enableEmuparadise = await GM_getValue("enableEmuparadise", false); var prioritizeEmuparadise = await GM_getValue("prioritizeEmuparadise", false); var enableGlassEffect = await await GM_getValue("enableGlassEffect", true); const RAConsole = { ARCADE: "Arcade", SNES: "SNES/Super Famicom", NES: "NES/Famicom", GAMEBOY: "Game Boy", GAMEBOYCOLOR: "Game Boy Color", GAMEBOYADVANCE: "Game Boy Advance", NINTENDO64: "Nintendo 64", GAMECUBE: "GameCube", NINTENDODS: "Nintendo DS", NINTENDODSI: "Nintendo DSi", ATARI2600: "Atari 2600", ATARI7800: "Atari 7800", ATARIJAGUAR: "Atari Jaguar", ATARIJAGUARCD: "Atari Jaguar CD", ATARILYNX: "Atari Lynx", PCENGINE: "PC Engine/TurboGrafx-16", PCENGINECD: "PC Engine CD/TurboGrafx-CD", MASTERSYSTEM: "Master System", GAMEGEAR: "Game Gear", MEGADRIVE: "Genesis/Mega Drive", SEGA32X: "32X", SEGACD: "Sega CD", SATURN: "Saturn", DREAMCAST: "Dreamcast", PS1: "PlayStation", PS2: "PlayStation 2", PSP: "PlayStation Portable", P3DO: "3DO Interactive Multiplayer", NEOGEOCD: "Neo Geo CD", NEOGEOPOCKET: "Neo Geo Pocket", POKEMINI: "Pokemon Mini", VIRTUALBOY: "Virtual Boy", SG1000: "SG-1000", COLECO: "ColecoVision", MSX: "MSX", WII: "Wii", WONDERSWAN: "WonderSwan", VECTREX: "Vectrex", NEC8800: "PC-8000/8800", APPLEII: "Apple II", PCFX: "PC-FX", ARDUBOY: "Arduboy", ARCADIA: "Arcadia 2001", FAIRCHILD: "Fairchild Channel F", MAGNAVOXODYSSEY2: "Magnavox Odyssey 2", INTELLIVISION: "Intellivision", INTERTONVC4000: "Interton VC 4000", MEGADUCK: "Mega Duck", WATARA: "Watara Supervision", ZEEBO: "Zeebo" }; const SRConsole = { PC: "8gej2n93", APPLEII: "w89ryw6l", ATARI2600: "o0644863", ARCADE: "vm9vn63k", NEC8800: "7g6mw8er", COLECOVISION: "wxeo8d6r", COMMODORE64: "gz9qox60", MSX: "jm950z6o", NES: "jm95z9ol", MSX2: "83exkk6l", MASTERSYSTEM: "83exwk6l", ATARI7800: "gde33gek", FAMICOMDISKSYSTEM: "mr6k409z", PCENGINE: "5negxk6y", MEGADRIVE: "mr6k0ezw", GAMEBOY: "n5683oev", NEOGEOAES: "mx6p4w63", GAMEGEAR: "w89r3w9l", SNES: "83exk6l5", PHILIPSCDI: "w89rjw6l", SEGACD: "31670d9q", PANASONIC3D0: "8gejmne3", NEOGEOCD: "kz9w7mep", PCFX: "p36n8568", PS1: "wxeod9rn", SEGA32X: "kz9wrn6p", SEGASATURN: "lq60l642", VIRTUALBOY: "7g6mk8er", NINTENDO64: "w89rwelk", GAMEBOYCOLOR: "gde3g9k1", NEOGEOPOCKETCOLOR: "7m6ydw6p", TURBOGRAFX16CD: "p36nlxe8", DREAMCAST: "v06d394z", WONDERSWAN: "vm9v8n63", PLAYSTATION2: "n5e17e27", WONDERSWANCOLOUR: "n568kz6v", GAMEBOYADVANCE: "3167d6q2", GAMECUBE: "4p9z06rn", POKÉMONMINI: "vm9vr1e3", NINTENDODS: "7g6m8erk", PLAYSTATIONPORTABLE: "5negk9y7", WII: "v06dk3e4" } const archiveCollectionDict = { [RAConsole.SATURN]: { name: "Redump Sega Saturn 2018", url: "https://archive.org/download/SegaSaturn2018July10" }, [RAConsole.DREAMCAST]: { name: "CHD-ZSTD - Sega Dreamcast (Redump)", url: "https://archive.org/download/dc-chd-zstd-redump/dc-chd-zstd" }, [RAConsole.SEGACD]: { name: "Redump Sega Mega CD & Sega CD", url: "https://archive.org/download/redump.sega_megacd-segacd" }, [RAConsole.NEOGEOCD]: { name: "[REDUMP] Disc Image Collection: SNK - Neo Geo CD", url: "https://archive.org/download/redump.ngcd.revival" }, [RAConsole.ATARI2600]: { name: "No-Intro Atari 2600", url: "https://archive.org/download/nointro2600atarii" }, [RAConsole.NINTENDODS]: { name: "No-Intro Nintendo DS Decrypted", url: "https://archive.org/download/noIntroNintendoDsDecrypted2019Jun30" }, [RAConsole.APPLEII]: { name: "Apple 2 TOSEC 2012", url: "https://archive.org/details/Apple_2_TOSEC_2012_04_23" } }; const myrientCollectionDict = { // CDs and DVDs files [RAConsole.PS1]: { name: "chd_psx", urls: [ "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx/CHD-PSX-USA/", "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx_eur/CHD-PSX-EUR/", "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx_jap/CHD-PSX-JAP/", "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx_jap_p2/CHD-PSX-JAP/", "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_psx_misc/CHD-PSX-Misc/" ] }, [RAConsole.PSP]: { name: "psp-chd-zstd-redump", urls: [ "https://myrient.erista.me/files/Internet%20Archive/chadmaster/psp-chd-zstd-redump-part1/psp-chd-zstd/", "https://myrient.erista.me/files/Internet%20Archive/chadmaster/psp-chd-zstd-redump-part2/psp-chd-zstd/", ] }, [RAConsole.PS2]: { name: "Sony - PlayStation 2", urls: [ "https://myrient.erista.me/files/Redump/Sony%20-%20PlayStation%202/" ] }, [RAConsole.SATURN]: { name: "chd_saturn", urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_saturn/CHD-Saturn/USA/", "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_saturn/CHD-Saturn/Japan/", "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_saturn/CHD-Saturn/Europe/" ] }, [RAConsole.DREAMCAST]: { name: "dc-chd-zstd", urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/dc-chd-zstd-redump/dc-chd-zstd/"] }, [RAConsole.GAMECUBE]: { name: "Nintendo - GameCube - NKit RVZ [zstd-19-128k]", urls: ["https://myrient.erista.me/files/Redump/Nintendo%20-%20GameCube%20-%20NKit%20RVZ%20%5Bzstd-19-128k%5D/"] }, [RAConsole.WII]: { name: "Nintendo - Wii - NKit RVZ [zstd-19-128k]", urls: ["https://myrient.erista.me/files/Redump/Nintendo%20-%20Wii%20-%20NKit%20RVZ%20%5Bzstd-19-128k%5D/"] }, [RAConsole.SEGACD]: { name: "chd_segacd", urls: [ "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_segacd/CHD-SegaCD-NTSC/", "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_segacd/CHD-MegaCD-NTSCJ/", "https://myrient.erista.me/files/Internet%20Archive/chadmaster/chd_segacd/CHD-MegaCD-PAL/", ] }, [RAConsole.P3DO]: { name: "3do-chd-zstd", urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/3do-chd-zstd-redump/3do-chd-zstd/"] }, [RAConsole.ATARIJAGUARCD]: { name: "jagcd-chd-zstd", urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/jagcd-chd-zstd/jagcd-chd-zstd/"] }, [RAConsole.NEOGEOCD]: { name: "ngcd-chd-zstd", urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/ngcd-chd-zstd-redump/ngcd-chd-zstd/"] }, [RAConsole.PCENGINECD]: { name: "pcecd-chd-zstd", urls: ["https://myrient.erista.me/files/Internet%20Archive/chadmaster/pcecd-chd-zstd-redump/pcecd-chd-zstd/"] }, [RAConsole.PCFX]: { name: "PC-FX", urls: ["https://myrient.erista.me/files/Redump/NEC%20-%20PC-FX%20%26%20PC-FXGA/"] }, // Cartridge roms [RAConsole.ARDUBOY]: { name: "Arduboy", urls: ["https://myrient.erista.me/files/No-Intro/Arduboy%20Inc%20-%20Arduboy/"] }, [RAConsole.ATARI2600]: { name: "Atari - 2600", urls: ["https://myrient.erista.me/files/No-Intro/Atari%20-%202600/"] }, [RAConsole.ATARI7800]: { name: "Atari - 7800", urls: ["https://myrient.erista.me/files/No-Intro/Atari%20-%207800/"] }, [RAConsole.ATARIJAGUAR]: { name: "Atari - Jaguar (ROM)", urls: ["https://myrient.erista.me/files/No-Intro/Atari%20-%20Jaguar%20%28ROM%29/"] }, [RAConsole.ATARILYNX]: { name: "Atari - Lynx (LYX)", urls: ["https://myrient.erista.me/files/No-Intro/Atari%20-%20Lynx%20%28LYX%29/"] }, [RAConsole.WONDERSWAN]: { name: "Wonderswan", urls: ["https://myrient.erista.me/files/No-Intro/Bandai%20-%20WonderSwan/", "https://myrient.erista.me/files/No-Intro/Bandai%20-%20WonderSwan%20Color/" ] }, [RAConsole.COLECO]: { name: "Coleco - ColecoVision", urls: ["https://myrient.erista.me/files/No-Intro/Coleco%20-%20ColecoVision/", ] }, [RAConsole.ARCADIA]: { name: "Emerson - Arcadia 2001", urls: ["https://myrient.erista.me/files/No-Intro/Emerson%20-%20Arcadia%202001/"] }, [RAConsole.FAIRCHILD]: { name: "https://myrient.erista.me/files/No-Intro/Fairchild%20-%20Channel%20F/", urls: ["Fairchild - Channel F"] }, [RAConsole.VECTREX]: { name: "GCE - Vectrex", urls: ["https://myrient.erista.me/files/No-Intro/GCE%20-%20Vectrex/"] }, [RAConsole.MAGNAVOXODYSSEY2]: { name: "Magnavox - Odyssey 2", urls: ["https://myrient.erista.me/files/No-Intro/Magnavox%20-%20Odyssey%202/"] }, [RAConsole.INTELLIVISION]: { name: "Mattel - Intellivision", urls: ["https://myrient.erista.me/files/No-Intro/Mattel%20-%20Intellivision/"] }, [RAConsole.INTERTONVC4000]: { name: "Interton - VC 4000", urls: ["https://myrient.erista.me/files/No-Intro/Interton%20-%20VC%204000/"] }, [RAConsole.MEGADUCK]: { name: "Welback - Mega Duck", urls: ["https://myrient.erista.me/files/No-Intro/Welback%20-%20Mega%20Duck/"] }, [RAConsole.MSX]: { name: "Microsoft - MSX", urls: ["https://myrient.erista.me/files/No-Intro/Microsoft%20-%20MSX/", "https://myrient.erista.me/files/No-Intro/Microsoft%20-%20MSX2/" ] }, [RAConsole.NEC8800]: { name: "Neo Kobe - NEC PC-8801 (2016-02-25)", urls: ["https://ia801307.us.archive.org/view_archive.php?archive=/35/items/Neo_Kobe_NEC_PC-8001_2016-02-25/Neo%20Kobe%20-%20NEC%20PC-8001%20%282016-02-25%29.zip", "https://ia801305.us.archive.org/view_archive.php?archive=/32/items/Neo_Kobe_NEC_PC-8801_2016-02-25/Neo%20Kobe%20-%20NEC%20PC-8801%20%282016-02-25%29.zip" ] }, [RAConsole.PCENGINE]: { name: "NEC - PC Engine SuperGrafx", urls: ["https://myrient.erista.me/files/No-Intro/NEC%20-%20PC%20Engine%20-%20TurboGrafx-16/", "https://myrient.erista.me/files/No-Intro/NEC%20-%20PC%20Engine%20SuperGrafx/" ] }, [RAConsole.NES]: { name: "Nintendo - Nintendo Entertainment System (Headered)", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%20Entertainment%20System%20%28Headered%29/", "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Family%20Computer%20Disk%20System%20%28FDS%29/", "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%20Entertainment%20System%20%28Headered%29%20%28Private%29/" ] }, [RAConsole.GAMEBOY]: { name: "Nintendo - Game Boy", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Game%20Boy/"] }, [RAConsole.GAMEBOYADVANCE]: { name: "Nintendo - Game Boy Advance", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Game%20Boy%20Advance/"] }, [RAConsole.GAMEBOYCOLOR]: { name: "Nintendo - Game Boy Color", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Game%20Boy%20Color/"] }, [RAConsole.NINTENDO64]: { name: "Nintendo - Nintendo 64 (BigEndian)", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%2064%20%28BigEndian%29/"] }, [RAConsole.NINTENDODS]: { name: "Nintendo - Nintendo DS (Decrypted)", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%20DS%20%28Decrypted%29/"] }, [RAConsole.NINTENDODSI]: { name: "Nintendo - Nintendo DSi (Digital)", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Nintendo%20DSi%20%28Digital%29/"] }, [RAConsole.POKEMINI]: { name: "Nintendo - Pokemon Mini", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Pokemon%20Mini/"] }, [RAConsole.SNES]: { name: "Nintendo - Super Nintendo Entertainment System", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System/", "https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Super%20Nintendo%20Entertainment%20System%20%28Private%29/" ] }, [RAConsole.VIRTUALBOY]: { name: "Nintendo - Virtual Boy", urls: ["https://myrient.erista.me/files/No-Intro/Nintendo%20-%20Virtual%20Boy/"] }, [RAConsole.NEOGEOPOCKET]: { name: "SNK - NeoGeo Pocket Color", urls: ["https://myrient.erista.me/files/No-Intro/SNK%20-%20NeoGeo%20Pocket%20Color/", "https://myrient.erista.me/files/No-Intro/SNK%20-%20NeoGeo%20Pocket/" ] }, [RAConsole.SEGA32X]: { name: "Sega - 32X", urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%2032X/"] }, [RAConsole.GAMEGEAR]: { name: "Sega - Game Gear", urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%20Game%20Gear/"] }, [RAConsole.MASTERSYSTEM]: { name: "Sega - Master System - Mark III", urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%20Master%20System%20-%20Mark%20III/"] }, [RAConsole.MEGADRIVE]: { name: "Sega - Mega Drive - Genesis", urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%20Mega%20Drive%20-%20Genesis/", "https://myrient.erista.me/files/No-Intro/Sega%20-%20Mega%20Drive%20-%20Genesis%20%28Private%29/" ] }, [RAConsole.SG1000]: { name: "Sega - SG-1000", urls: ["https://myrient.erista.me/files/No-Intro/Sega%20-%20SG-1000/"] }, [RAConsole.WATARA]: { name: "Watara - Supervision", urls: ["https://myrient.erista.me/files/No-Intro/Watara%20-%20Supervision/"] }, [RAConsole.ZEEBO]: { name: "Zeebo - Zeebo", urls: ["https://myrient.erista.me/files/No-Intro/Zeebo%20-%20Zeebo/"] }, // [RAConsole.]: { // name: "", // urls: [""] // }, // TODO: Missing Amstrad CPC, Apple II, Elektor TV Games Computer, Uzebox, WASM4 // TODO: Find better source for PC88? }; // GM_log(enableSpeedrun) // GM_log(enableRomSearch) // GM_log(enableCustomBG) // GM_log(page) // GM_log(sectionName) if (page == "/settings") { (function () { let id = setInterval(function () { if ($('#app').length) { clearInterval(id); $('.with-sidebar article > div > div').children().eq(2).after("<div id='enhanced-settings' class='p-6 text-card-foreground rounded-lg border border-embed-highlight bg-embed shadow-sm w-full'></div>") let settingsDiv = $("#enhanced-settings"); settingsDiv.append("<h3 class='pb-2 border-b-0 text-2xl font-semibold leading-none tracking-tight'>Retro Enhanced</h3>") settingsDiv.append(`<div class="flex flex-col gap-5 @xl:hidden"> <div class="flex gap-1"> <input id="enhanced-romsearch" type="checkbox" ${enableRomSearch ? "checked='checked'" : ""}> <div class='pl-1 text-menu-link'>Enable ROMs search</div> </div> <div class="flex gap-1"> <input id="enhanced-epromsearch" type="checkbox" ${enableEmuparadise ? "checked='checked'" : ""}> <div class='pl-1 text-menu-link'>Add Emuparadise to ROMs search <div style="font-size: 0.8em; color:rgb(185, 185, 185);">(for Chrome users: <a href="https://experienceleague.adobe.com/docs/target/using/experiences/vec/troubleshoot-composer/mixed-content.html?lang=en#task_FF297A08F66E47A588C14FD67C037B3A">enable this</a>; for all browsers: must click on "Add Exception and Get my File!" for the first time)</div></div> </div> <div class="flex gap-1"> <input id="enhanced-prioritize_ep" type="checkbox" ${prioritizeEmuparadise ? "checked='checked'" : ""}> <div class='pl-1 text-menu-link'>Prioritize Emuparadise for ROMs search <div style="font-size: 0.8em; color:rgb(185, 185, 185);">(must have "Add Emuparadise to ROMs search" enabled)</div></div> </div> <div class="flex gap-1"> <input id="enhanced-speedrun" type="checkbox" ${enableSpeedrun ? "checked='checked'" : ""}> <div class='pl-1 text-menu-link'>Enable Speedrun.com stats</div> </div> <div class="flex gap-1"> <input id="enhanced-gameplayvideo" type="checkbox" ${enableGameplayVideo ? "checked='checked'" : ""}> <div class='pl-1 text-menu-link'>Enable gameplay video on the game page</div> </div> <div class="flex gap-1"> <input id="enhanced-custombg" type="checkbox" ${enableCustomBG ? "checked='checked'" : ""}> <div class='pl-1 text-menu-link'>Enable custom game page background</div> </div> <div class="flex gap-1"> <input id="enhanced-glassEffect" type="checkbox" ${enableGlassEffect ? "checked='checked'" : ""}> <div class='pl-1 text-menu-link'>Enable glass background effect</div> </div> </div>`) } }, 100); })(); $(document).on('change', '#enhanced-romsearch', function () { GM_setValue("enableRomSearch", $("#enhanced-romsearch").is(":checked")) }) $(document).on('change', '#enhanced-epromsearch', function () { GM_setValue("enableEmuparadise", $("#enhanced-epromsearch").is(":checked")) }) $(document).on('change', '#enhanced-prioritize_ep', function () { GM_setValue("prioritizeEmuparadise", $("#enhanced-prioritize_ep").is(":checked")) }) $(document).on('change', '#enhanced-speedrun', function () { GM_setValue("enableSpeedrun", $("#enhanced-speedrun").is(":checked")) }) $(document).on('change', '#enhanced-custombg', function () { GM_setValue("enableCustomBG", $("#enhanced-custombg").is(":checked")) }) $(document).on('change', '#enhanced-gameplayvideo', function () { GM_setValue("enableGameplayVideo", $("#enhanced-gameplayvideo").is(":checked")) }) $(document).on('change', '#enhanced-glassEffect', function () { GM_setValue("enableGlassEffect", $("#enhanced-glassEffect").is(":checked")) }) } // ========================================= // Game Set Page // ========================================= // Regex: game/13918 else if (page.match(/game\/[0-9]/g) != null || page == "/gameInfo.php") { // General var console = $(".navpath").children().eq(1).text(); // var game = $(".navpath").children().eq(2).text(); // var gameId = /([^\/]+)\/?$/g.exec($("meta[property='og:url']").attr("content"))[0]; // var points = $("#achievement .TrueRatio").eq(0).prev().text(); var icon = $("#achievement div:eq(2) > img").attr("src") var tag = ""; var gameImg = $("#achievement img[alt=\"In-game screenshot\"]").attr("src"); var rgxTag = /\~(.*?)\~/g; // GM_log("Icon:" + icon) // Check for tags if (game.match(rgxTag) != undefined) { tag = rgxTag.exec(game)[1]; game = game.replace(game.match(rgxTag) + " ", ""); } // GM_log(gameId) var isAvailable = false; var collection = { name: "", url: "" }; var results = []; var resultsDlcs = []; // Speedrun.com API resources var srRoot = "https://www.speedrun.com/api/v1/"; var srLogo = ""; var srVideoUrl = ""; var srGamelink = ""; var srGameId = ""; var srRuns = []; // GM_log(game) // GM_log(console) // Avoid unwanted exceptions for hubs pages. if (console == "") return // ========================================= // Divs Insertion // ========================================= // Set custom background if (gameImg != "https://media.retroachievements.org/Images/000002.png" && enableCustomBG) { $("body").append(`<style> body:before { content: ""; position: fixed; width : 110%; height: 110%; background: inherit; background-size: cover; z-index: -1; overflow: hidden; filter : blur(8px); -moz-filter : blur(8px); -webkit-filter: blur(8px); -o-filter : blur(8px); } </style>`); $("body").css({ "background-image": `url(${gameImg})`, "background-attachment": "fixed", "background-size": "90%", "background-position": "center", "background-repeat": "no-repeat" }) } // Change to glass background if (enableGlassEffect) { $(":root").attr("style", "--box-bg-color: rgba(35, 35, 35, 0.95);") $("#leftcontainer").attr("style", "background: var(--box-bg-color);") $("#rightcontainer").attr("style", "background: var(--box-bg-color);") } // Change top nav to body color $(".brand-top").addClass("bg-body") // Change header background to transparent // $(".brand-top + nav").removeClass("bg-body") // Prepare divs $("aside > .gamealts").first().before("<div id='romsdl'></div>") $("aside > .gamealts").first().before("<div id='speedruncom'></div>") var divRoms = $("#romsdl"); var divSpeedruncom = $("#speedruncom"); divRoms.css("margin-top", "1em") divSpeedruncom.css("margin", "1em 0em"); if (enableGameplayVideo || enableSpeedrun) getSpeedruns(game) // ========================================= // Rom Search // ========================================= if (enableRomSearch) { // Verify if system is available for (const prop in RAConsole) { if (RAConsole.hasOwnProperty(prop)) { const element = RAConsole[prop]; if (element == console) isAvailable = true; } } if ((isAvailable && tag == "") || (console == RAConsole.ARCADE && tag != "")) { var promise; // Deprecated feature to find roms for hacks and homebrews. // if (tag != "" && console != RAConsole.ARCADE) { // promise = searchCustom(); // collection.name = "Custom"; // } // Search through Emuparadise if (enableEmuparadise && prioritizeEmuparadise) { collection.name = "Emuparadise"; collection.url = "https://www.emuparadise.me/roms-isos-games.php" promise = searchEmuparadise(); } else { // resolve the promise so the function don't stop working promise = Promise.resolve() } // Search through Myrient promise.then(() => { if (results.length == 0) { if (console == RAConsole.ARCADE) { collection.name = "FB Neo Nightly"; collection.url = "https://archive.org/download/2020_01_06_fbn"; return searchArcade(); } if (myrientCollectionDict[console]) { const entry = myrientCollectionDict[console]; collection.name = entry.name; collection.url = entry.urls[0]; // GM_log(collection) const urls = Array.isArray(entry.urls) ? entry.urls : [entry.urls]; return chainSearchMyrient(urls) } else { collection.name = "No-Intro 2016" collection.url = "https://archive.org/download/No-Intro-Collection_2016-01-03_Fixed" return searchNoIntro2016(); } // exit if already has results } else return; }) .then(() => { if (enableEmuparadise && results.length == 0) { collection.name = "Emuparadise"; collection.url = "https://www.emuparadise.me/roms-isos-games.php" return searchEmuparadise(); } }) .then(() => { if (console == RAConsole.PSP) return searchArchiveDlc("https://archive.org/download/PSP-DLC/%5BNo-Intro%5D%20PSP%20DLC/") }) .then(() => { // GM_log(results); if (results.length > 0) createDownloads() if (resultsDlcs.length > 0) createDlcs() }) } else { // divRoms.append("<b>Searching roms for this system not supported.</b>"); GM_log("Searching roms for this system not supported.") } } // ========================================= // Create Content to the Page // ========================================= function createDownloads() { divRoms.append("<h3>ROMs</h3>"); // divRoms.append(`<b>Found ${results.length} related result(s)`) divRoms.append(``); for (var i = 0; i < results.length; i++) { // GM_log("pow: " + results[i].url) let dlLink = (results[i].url).replace(/ /g, "%20"); // GM_log("plim: " + dlLink) divRoms.append("<a class='dl-links' href=" + dlLink + ">" + removeExt(results[i].name) + "</a>"); } // GM_log(collection.name) // GM_log(collection.url) if (collection.url != "") divRoms.append(`<div style="margin-top:1em;">From <a href="${collection.url}">${collection.name}</a></div>`); $(".dl-links").css("display", "block"); } function createDlcs() { divRoms.append(`<h3 style="margin-top: 1em;">DLCs</h3>`); //divRoms.append(`<b>Found ${resultsDlcs.length} related result(s)`) divRoms.append(``); for (var i = 0; i < resultsDlcs.length; i++) { let dlLink = (resultsDlcs[i].url).replace(/ /g, "%20"); divRoms.append("<a class='dl-links' href=" + dlLink + ">" + removeExt(resultsDlcs[i].name) + "</a>"); } if (collection.url != "") divRoms.append(`<div style="margin-top:1em;">From <a href=https://archive.org/download/PSP-DLC/%5BNo-Intro%5D%20PSP%20DLC>PSP-DLC (No-Intro)</a></div>`); $(".dl-links").css("display", "block"); } function createSpeedrun() { divSpeedruncom.append("<h3>World Records</h3>"); // divSpeedruncom.append(`<a href=${srGamelink}> // <img style="display: block; width: 100%; object-fit: cover; margin: 1em 0em 1em 0em" // src=${srLogo}></img> // </a>`) // GM_log(srRuns) // GM_log(srRuns.length) if (srRuns.length > 0) { srRuns.forEach((runsData) => { // GM_log(runsData.link) divSpeedruncom.append(`<div><a href=${runsData.link}>${runsData.category}:</a> ${runsData.time} by ${runsData.runner}</div>`) }); } else { divSpeedruncom.append("<div>Couldn't find this game on Speedrun.com</div>") } } function createVideo() { if (srVideoUrl != "") GM_log("Creating video with URL: " + srVideoUrl) $("#achievement").children().eq(3) .after($(`<iframe style="display: block; width: 100%; height:315px; padding-bottom: 1em" src="${srVideoUrl}" allowfullscreen="allowfullscreen" autoplay="false"> </iframe>`)); } function getSrConsoleId(consoleName) { if (consoleName == RAConsole.ATARI2600) { return SRConsole.ATARI2600; } else if (consoleName == RAConsole.ATARI7800) { return SRConsole.ATARI7800; } else if (consoleName == RAConsole.APPLEII) { return SRConsole.APPLEII; } else if (consoleName == RAConsole.ARCADE) { return SRConsole.ARCADE; } else if (consoleName == RAConsole.COLECO) { return SRConsole.COLECOVISION; } else if (consoleName == RAConsole.DREAMCAST) { return SRConsole.DREAMCAST; } else if (consoleName == RAConsole.GAMEBOY) { return SRConsole.GAMEBOY; } else if (consoleName == RAConsole.GAMEBOYADVANCE) { return SRConsole.GAMEBOYADVANCE; } else if (consoleName == RAConsole.GAMEBOYCOLOR) { return SRConsole.GAMEBOYCOLOR; } else if (consoleName == RAConsole.MEGADRIVE) { return SRConsole.MEGADRIVE; } else if (consoleName == RAConsole.GAMEGEAR) { return SRConsole.GAMEGEAR; } else if (consoleName == RAConsole.NINTENDO64) { return SRConsole.NINTENDO64; } else if (consoleName == RAConsole.SATURN) { return SRConsole.SEGASATURN; } else if (consoleName == RAConsole.MASTERSYSTEM) { return SRConsole.MASTERSYSTEM; } else if (consoleName == RAConsole.NINTENDODS) { return SRConsole.NINTENDODS; } else if (consoleName == RAConsole.NEC8800) { return SRConsole.NEC8800; } else if (consoleName == RAConsole.NEOGEOPOCKET) { return SRConsole.NEOGEOPOCKETCOLOR; } else if (consoleName == RAConsole.NES) { return SRConsole.NES; } else if (consoleName == RAConsole.P3DO) { return SRConsole.PANASONIC3D0; } else if (consoleName == RAConsole.PCENGINE) { return SRConsole.PCENGINE; } else if (consoleName == RAConsole.POKEMINI) { return SRConsole.POKÉMONMINI; } else if (consoleName == RAConsole.PS1) { return SRConsole.PS1; } else if (consoleName == RAConsole.PSP) { return SRConsole.PLAYSTATIONPORTABLE } else if (consoleName == RAConsole.SEGA32X) { return SRConsole.SEGA32X; } else if (consoleName == RAConsole.SEGACD) { return SRConsole.SEGACD; } else if (consoleName == RAConsole.SG1000) { return SRConsole.MASTERSYSTEM; } else if (consoleName == RAConsole.SNES) { return SRConsole.SNES; } else if (consoleName == RAConsole.VIRTUALBOY) { return SRConsole.VIRTUALBOY; } else return ""; } function getSpeedruns(gameName) { var consoleId = getSrConsoleId(console); var srSearchUrl = encodeURI(srRoot + "games?name=" + gameName + "&platform=" + consoleId) // Games // GM_log(srSearchUrl) return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: srSearchUrl, onload: function (gamesResponse) { let gamesData = JSON.parse(gamesResponse.response).data // GM_log("Games: " + gamesData) if (gamesData.length > 0) { srGamelink = gamesData[0].weblink; srGameId = gamesData[0].id; // srLogo = gamesData[0].assets.logo.uri; don't work as of now, possibly due to API changes on Speedrun.com resolve(gamesData[0].links[3].uri); } else { throw `Couldn't find this game on Speedrun.com (${srSearchUrl}).`; } } }) }) .then((link) => { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: link, onload: function (response) { let categoriesData = JSON.parse(response.response).data resolve(categoriesData) } }) }) }, err => { throw (err) }) .then((categories) => { // GM_log("Categories: " + categories) let totalRuns = 0; return Promise.all(categories.map(category => { // Runs return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: srRoot + `runs?game=${srGameId}&category=${category.id}&status=verified`, onload: function (runsResponse) { let runsData = JSON.parse(runsResponse.response).data[0]; if (runsData != undefined && runsData.status.status != "rejected") { // Pick a eligible speedrun video and use it as the video showcase on the page // GM_log(runsData.videos) if (srVideoUrl == "" && runsData.videos) srVideoUrl = toEmbedUrl(runsData.videos.links[0].uri); // GM_log(isVideoUrl(runsData.videos.links[0].uri)) // if (isVideoUrl(runsData.videos.links[0].uri)) totalRuns++; } resolve(runsData) } }) }) .then((runsData) => { if (runsData == undefined) return false; // TODO: Resolve useless request if user is a guest. let isGuest = runsData.players[0].rel == "guest" ? true : false; return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: srRoot + "users/" + runsData.players[0].id, onload: function (userRes) { userData = JSON.parse(userRes.response).data srRuns.push({ category: category.name, time: parseIso8601(runsData.times.primary), runner: isGuest ? runsData.players[0].name : userData.names.international, link: runsData.videos ? runsData.videos.links[0].uri : "" }) // GM_log(srRuns.length) // GM_log(totalRuns) resolve(true) } }) }) }) })) .then(() => { // GM_log("Last step from promises") // GM_log(srRuns) if (enableSpeedrun) createSpeedrun(); if (enableGameplayVideo) createVideo(); }) }) } // ========================================= // Archives.org (Arcade) Function // ========================================= function searchArcade() { var mainDir = "//archive.org/download/2020_01_06_fbn/roms/arcade.zip/arcade%2F"; var datDir = "https://raw.githubusercontent.com/libretro/FBNeo/master/dats/FinalBurn%20Neo%20(ClrMame%20Pro%20XML%2C%20Arcade%20only).dat"; return new Promise((resolve, reject) => { // Find content in .dat file from FB Neo repo. GM_xmlhttpRequest({ method: "GET", url: datDir, onload: function (response) { // GM_log(response); var xmlDoc = $.parseXML(response.responseText); // Refined search $(xmlDoc).find("game").each(function (index) { let name = $(this).find("description").text(); if (tag == "" && name.toLowerCase().includes("hack")) return; if (tag == "Hack" && !name.toLowerCase().includes("hack")) return; if (refinedCompare(name, game)) { results.push({ name: name, url: mainDir + $(this).attr('name') + ".zip" }); } }) // Normal search if (results.length == 0) { $(xmlDoc).find("game").each(function (index) { let name = $(this).find("description").text(); if (tag == "" && name.toLowerCase().includes("hack")) return; if (tag == "Hack" && !name.toLowerCase().includes("hack")) return; if (compare(name, game)) { results.push({ name: name, url: mainDir + $(this).attr('name') + ".zip" }); } }) } resolve(true); } }) }); } // ========================================= // Myrient Function // ========================================= function chainSearchMyrient(urls) { let promise = searchMyrient(urls[0]); for (let i = 1; i < urls.length; i++) { promise = promise.then(() => { if (results.length === 0) { return searchMyrient(urls[i]); } }); } return promise; } // Almost the same as Archive.org, lol function searchMyrient(mainDir) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: mainDir, onload: function (response) { // GM_log(response.responseText); // Refined search $(response.responseText).find(`td`).children(":first-child").each(function (index) { let title = /([^\/]+)\/?$/g.exec($(this).text())[1]; // GM_log(title) // GM_log($(this).attr('href')) if (refinedCompare(title, game)) { // Check if the mainDir link doesn't end with / let fullUrl = mainDir.endsWith("/") ? `${mainDir}${$(this).attr('href')}` : `${mainDir}/${$(this).attr('href')}` // GM_log(mainDir.endsWith("/")) results.push({ name: title, url: fullUrl }); } }); // Normal search if (results.length == 0) { $(response.responseText).find(`td`).children(":first-child").each(function (index) { let title = /([^\/]+)\/?$/g.exec($(this).text())[1]; if (compare(title, game)) { // Check if the mainDir link doesn't end with / let fullUrl = mainDir.endsWith("/") ? `${mainDir}${$(this).attr('href')}` : `${mainDir}/${$(this).attr('href')}` // GM_log(mainDir.endsWith("/")) results.push({ name: title, url: fullUrl }); } }); } return resolve(true); } }) }); } // ========================================= // Archives.org (No Intro 2016) Function // ========================================= function searchNoIntro2016() { var mainDir = "https://archive.org/download/No-Intro-Collection_2016-01-03_Fixed/"; var consoleDir = ""; var secondaryConsoleDir = ""; if (console == RAConsole.SNES) { consoleDir = "Nintendo - Super Nintendo Entertainment System"; } if (console == RAConsole.NES) { consoleDir = "Nintendo - Nintendo Entertainment System"; } if (console == RAConsole.GAMEBOY) { consoleDir = "Nintendo - Game Boy"; } if (console == RAConsole.GAMEBOYCOLOR) { consoleDir = "Nintendo - Game Boy Color"; } if (console == RAConsole.GAMEBOYADVANCE) { consoleDir = "Nintendo - Game Boy Advance"; } if (console == RAConsole.NINTENDO64) { consoleDir = "Nintendo - Nintendo 64"; } if (console == RAConsole.ATARI7800) { consoleDir = "Atari - 7800"; } if (console == RAConsole.PCENGINE) { consoleDir = "NEC - PC Engine - TurboGrafx 16"; } if (console == RAConsole.MEGADRIVE) { consoleDir = "Sega - Mega Drive - Genesis"; } if (console == RAConsole.MASTERSYSTEM) { consoleDir = "Sega - Master System - Mark III"; } if (console == RAConsole.GAMEGEAR) { consoleDir = "Sega - Game Gear"; } if (console == RAConsole.NEOGEOPOCKET) { consoleDir = "SNK - Neo Geo Pocket"; secondaryConsoleDir = "SNK - Neo Geo Pocket Color"; } if (console == RAConsole.POKEMINI) { consoleDir = "Nintendo - Pokemon Mini"; } if (console == RAConsole.VIRTUALBOY) { consoleDir = "Nintendo - Virtual Boy.zip"; } if (console == RAConsole.SG1000) { consoleDir = "Sega - SG-1000"; } if (console == RAConsole.COLECO) { consoleDir = "Coleco - ColecoVision"; } if (console == RAConsole.MSX) { consoleDir = "Microsoft - MSX"; secondaryConsoleDir = "Microsoft - MSX 2"; } if (console == RAConsole.WONDERSWAN) { consoleDir = "Bandai - WonderSwan Color"; secondaryConsoleDir = "Bandai - WonderSwan Color" } if (console == RAConsole.VECTREX) { consoleDir = "GCE - Vectrex"; } consoleDir = consoleDir.replace(/ /g, "%20").concat(".zip/"); secondaryConsoleDir = secondaryConsoleDir.replace(/ /g, "%20").concat(".zip/"); return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: mainDir + consoleDir, onload: function (response) { // GM_log(response); // Refined search $(response.responseText).find(`td`).children(":first-child").each(function (index) { if (refinedCompare($(this).text(), game)) { results.push({ name: $(this).text(), url: $(this).attr('href') }); } }); // Normal search if (results.length == 0) { $(response.responseText).find(`td`).children(":first-child").each(function (index) { if (compare($(this).text(), game)) { results.push({ name: $(this).text(), url: $(this).attr('href') }); } }); } resolve(true); } }) }) .then(() => { if (secondaryConsoleDir != "") { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: mainDir + secondaryConsoleDir, onload: function (response) { // GM_log(response); // Refined search $(response.responseText).find(`td`).children(":first-child").each(function (index) { if (refinedCompare($(this).text(), game)) { results.push({ name: $(this).text(), url: $(this).attr('href') }); } }); // Normal search if (results.length == 0) { $(response.responseText).find(`td`).children(":first-child").each(function (index) { if (compare($(this).text(), game)) { results.push({ name: $(this).text(), url: $(this).attr('href') }); } }); } resolve(true); } }) }) } }) } // ========================================= // Archives.org (Generic) Function // ========================================= function searchArchive(mainDir) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: mainDir, onload: function (response) { // GM_log(response.responseText); // Refined search $(response.responseText).find(`td`).children(":first-child").each(function (index) { let title = /([^\/]+)\/?$/g.exec($(this).text())[1]; // Check in case link is already the full url let fullUrl = $(this).attr('href').startsWith("//archive.org/download/") ? $(this).attr('href') : `${mainDir}/${$(this).attr('href')}` // GM_log($(this).attr('href')) if (refinedCompare(title, game)) { results.push({ name: title, url: fullUrl }); } }); // Normal search if (results.length == 0) { $(response.responseText).find(`td`).children(":first-child").each(function (index) { let title = /([^\/]+)\/?$/g.exec($(this).text())[1]; let fullUrl = $(this).attr('href').startsWith("//archive.org/download/") ? $(this).attr('href') : `${mainDir}/${$(this).attr('href')}` // GM_log($(this).attr('href')) if (compare(title, game)) { results.push({ name: title, url: fullUrl }); } }); } return resolve(true); } }) }); } // ========================================= // Archives.org (DLC) Function // ========================================= function searchArchiveDlc(mainDir) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: mainDir, onload: function (response) { // GM_log(response); // Refined search $(response.responseText).find(`td`).children(":first-child").each(function (index) { let title = /([^\/]+)\/?$/g.exec($(this).text())[1]; // Check in case link is already the full url let fullUrl = $(this).attr('href').startsWith("//archive.org/download/") ? $(this).attr('href') : `${mainDir}/${$(this).attr('href')}` // GM_log($(this).attr('href')) if (refinedCompare(title, game)) { resultsDlcs.push({ name: title, url: fullUrl }); } }); // Normal search if (resultsDlcs.length == 0) { $(response.responseText).find(`td`).children(":first-child").each(function (index) { let title = /([^\/]+)\/?$/g.exec($(this).text())[1]; let fullUrl = $(this).attr('href').startsWith("//archive.org/download/") ? $(this).attr('href') : `${mainDir}/${$(this).attr('href')}` // GM_log($(this).attr('href')) if (compare(title, game)) { resultsDlcs.push({ name: title, url: fullUrl }); } }); } return resolve(true); } }) }); } // ========================================= // Emuparadise Function // ========================================= function searchEmuparadise() { var mainDir = "https://www.emuparadise.me/"; var consoleUrl; if (console == RAConsole.SNES) { consoleUrl = "Super_Nintendo_Entertainment_System_(SNES)_ROMs/List-All-Titles/5"; } if (console == RAConsole.NES) { consoleUrl = "Nintendo_Entertainment_System_ROMs/List-All-Titles/13"; } if (console == RAConsole.GAMEBOY) { consoleUrl = "Nintendo_Game_Boy_ROMs/List-All-Titles/12"; } if (console == RAConsole.GAMEBOYCOLOR) { consoleUrl = "Nintendo_Game_Boy_Color_ROMs/List-All-Titles/11"; } if (console == RAConsole.GAMEBOYADVANCE) { consoleUrl = "Nintendo_Gameboy_Advance_ROMs/List-All-Titles/31"; } if (console == RAConsole.NINTENDO64) { consoleUrl = "Nintendo_64_ROMs/List-All-Titles/9"; } if (console == RAConsole.GAMECUBE) { consoleUrl = "Nintendo_Gamecube_ISOs/List-All-Titles/42" } if (console == RAConsole.NINTENDODS) { consoleUrl = "Nintendo_DS_ROMs/List-All-Titles/32"; } if (console == RAConsole.MEGADRIVE) { consoleUrl = "Sega_Genesis_-_Sega_Megadrive_ROMs/List-All-Titles/6"; } if (console == RAConsole.MASTERSYSTEM) { consoleUrl = "Sega_Master_System_ROMs/List-All-Titles/15"; } if (console == RAConsole.SEGA32X) { consoleUrl = "Sega_32X_ROMs/61"; } if (console == RAConsole.SATURN) { consoleUrl = "Sega_Saturn_ISOs/List-All-Titles/3" } if (console == RAConsole.SEGACD) { consoleUrl = "Sega_CD_ISOs/List-All-Titles/10"; } if (console == RAConsole.GAMEGEAR) { consoleUrl = "Sega_Game_Gear_ROMs/List-All-Titles/14"; } if (console == RAConsole.NEOGEOPOCKET) { consoleUrl = "Neo_Geo_Pocket_-_Neo_Geo_Pocket_Color_(NGPx)_ROMs/38"; } if (console == RAConsole.ATARI2600) { consoleUrl = "Atari_2600_ROMs/List-All-Titles/49" } if (console == RAConsole.ATARI7800) { consoleUrl = "Atari_7800_ROMs/47" } if (console == RAConsole.PCENGINE) { consoleUrl = "PC_Engine_-_TurboGrafx16_ROMs/List-All-Titles/16"; } if (console == RAConsole.APPLEII) { consoleUrl = "Apple_][_ROMs/List-All-Titles/24"; } if (console == RAConsole.PS1) { consoleUrl = "Sony_Playstation_ISOs/List-All-Titles/2"; } if (console == RAConsole.PS2) { consoleUrl = "Sony_Playstation_2_ISOs/List-All-Titles/41"; } if (console == RAConsole.PSP) { consoleUrl = "PSP_ISOs/List-All-Titles/44"; } if (console == RAConsole.P3DO) { consoleUrl = "Panasonic_3DO_(3DO_Interactive_Multiplayer)_ISOs/List-All-Titles/20"; } return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: mainDir + consoleUrl, onload: function (response) { // GM_log(response); // Refined search $(response.responseText).find(`.index.gamelist`).each(function (index) { let epGameId = /([^\/]+)\/?$/g.exec($(this).attr('href'))[0]; // GM_log($(this).text()) if (refinedCompare($(this).text(), game)) { results.push({ name: $(this).text(), url: `https://www.emuparadise.me/roms/get-download.php?gid=${epGameId}&test=true` }); } }); // Normal search if (results.length == 0) { $(response.responseText).find(`.index.gamelist`).each(function (index) { let epGameId = /([^\/]+)\/?$/g.exec($(this).attr('href'))[0]; // GM_log($(this).text()) if (compare($(this).text(), game)) { results.push({ name: $(this).text(), url: `https://www.emuparadise.me/roms/get-download.php?gid=${epGameId}&test=true` }); } }); } return resolve(true); } }) }); } // ========================================= // Utility Functions // ========================================= async function trySearchUrls(urls) { for (let url of urls) { const result = await searchArchive(url); if (results.length > 0) return result; } return null; } function refinedCompare(a, b) { let str1 = simplify_title(a); let str2 = simplify_title(b); // GM_log("*Str 1: " + str1) // GM_log("*Str 2: " + str2) // GM_log(str1 == str2) if (str1 == str2) return true; else return false; } function compare(a, b) { // GM_log(a) let str1 = simplify_title(a); let str2 = simplify_title(b); // GM_log("Str 1: " + str1) // GM_log("Str 2: " + str2) // GM_log(str1.includes(str2)) if (str1.includes(str2)) return true; else return false; } // Remove unnecessary characters and region headering function simplify_title(str) { // Dreamcast TOSEC set puts versioning into the filename if (console == RAConsole.DREAMCAST) str = str.replace(/v[0-9].[0-9]{3}/gs, "") return str .replace(/\.(zip|7z)$/,"") .replace(/^The /g, '') .replace(", The", '') .replace(/'s/gs, '') .replace('&', 'and') .replace(/:|-| |\.|!|\?|\/|'/gs, '') .replace(/(\r\n|\n|\r)/gs, "") // remove line breaks .split('|')[0] .replace(',', "") // remove headers (old) // .replace(/\([\w\s]+\)/gs, "") // .replace(/\[[\w\s]+\]/gs, "") // remove headers (everything inside parenthesis) .replace(/\(.+\)/gs, "") .replace(/\[.+\]/gs, "") .toLowerCase() } function removeExt(str) { return str.replace(/\.(zip|7z|chd)$/,""); } function parseIso8601(time) { var parsed = ""; let regex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/; let groups = regex.exec(time); if (groups[6] != undefined) parsed = parsed.concat(`${groups[6]}h `) if (groups[7] != undefined) parsed = parsed.concat(`${groups[7]}m `) if (groups[8] != undefined) parsed = parsed.concat(`${groups[8]}s `) return parsed; } function isVideoUrl(url) { return (url.includes("www.youtu") || url.includes("www.twitch.tv")) } function toEmbedUrl(url) { if (url.includes("twitch") || url.includes("youtu")) { // GM_log(url); // https://regex101.com/r/jmV6qH/1 var regexYoutube = /(?:https?:\/{2})?(?:w{3}\.)?youtu(?:be)?\.(?:com|be)(?:\/watch\?v=|\/)?([^\s&]+)/; // https://regex101.com/r/0RofWZ/1 var regexTwitch = /(?:https?:\/{2})?www\.twitch\.tv\/(:?[\S]+\/)?([\]?)?\/([\d]+)/; if (url.match(regexYoutube) != undefined) { return "https://www.youtube.com/embed/" + url.match(regexYoutube)[1]; } else if (url.match(regexTwitch) != undefined) { return "https://player.twitch.tv/?video=" + url.match(regexTwitch)[2] + "&parent=retroachievements.org&autoplay=false"; } } return ""; } } })();