Last active
August 11, 2022 22:48
-
-
Save kadiwa4/709ee81fd1f681f64422cf7bafe7dec5 to your computer and use it in GitHub Desktop.
may save you a few clicks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name speedrun.com | |
| // @namespace https://www.speedrun.com/ | |
| // @version 0.1.6 | |
| // @description may save you some time | |
| // @match https://www.speedrun.com/* | |
| // @icon https://www.speedrun.com/themeasset/68q1p7rp/1st | |
| // @updateURL https://gist.github.com/KaDiWa4/709ee81fd1f681f64422cf7bafe7dec5/raw/speedrun.com.user.js | |
| // @downloadURL https://gist.github.com/KaDiWa4/709ee81fd1f681f64422cf7bafe7dec5/raw/speedrun.com.user.js | |
| // ==/UserScript== | |
| (function src() { | |
| "use strict"; | |
| function onAddedChild(parent, fn) { | |
| const observer = new MutationObserver((records, observer) => { | |
| for (let record of records) { | |
| for (let node of record.addedNodes) { | |
| fn(node, observer); | |
| } | |
| } | |
| }); | |
| observer.observe(parent, { childList: true }); | |
| return observer; | |
| } | |
| function childLoaded(parent, pred = () => true) { | |
| return new Promise((resolve) => { | |
| let node = parent.children[0]; | |
| if (node !== undefined && pred(node)) { | |
| resolve(node); | |
| } | |
| let resolved = false; | |
| const observer = onAddedChild(parent, (node, observer) => { | |
| if (!resolved && pred(node)) { | |
| resolved = true; | |
| observer.disconnect(); | |
| resolve(node); | |
| } | |
| }); | |
| // Check if the child has been loaded in the meantime. | |
| node = parent.children[0]; | |
| if (node !== undefined && pred(node)) { | |
| observer.disconnect(); | |
| resolve(node); | |
| } | |
| }); | |
| } | |
| function srcUrlEscape(str) { | |
| // This might not always work. | |
| return str.replaceAll(" ", "_").replace(/\W/g, (char) => (char === "-") ? "-" : ""); | |
| } | |
| // Delete this script (cargo.js) before it downloads more stuff. | |
| // Same can maybe be done with sb.scorecardresearch.com, www.google-analytics.com | |
| // and static.hotjar.com. | |
| document.head.querySelector('script[src*="//cloud-strife.speedrun.com/"]')?.remove(); | |
| // Stripe is only needed for payment, but is always loaded. | |
| if (!location.pathname.endsWith("/supporter/subscribe")) { | |
| let stripeIFramesRemoved = 0; | |
| onAddedChild(document.body, (node, observer) => { | |
| if (node instanceof HTMLIFrameElement && node.src !== "" && new URL(node.src).hostname === "js.stripe.com") { | |
| stripeIFramesRemoved++; | |
| if (stripeIFramesRemoved >= 2) { | |
| observer.disconnect(); | |
| } | |
| node.remove(); | |
| } | |
| }); | |
| } | |
| function homePage() { | |
| const latestTweets = document.getElementById("latest-tweets"); | |
| if (latestTweets === null) { return; } | |
| latestTweets.parentNode.remove(); | |
| let twitterIFramesRemoved = 0; | |
| onAddedChild(document.body, (node, observer) => { | |
| if (node instanceof HTMLIFrameElement && node.title !== "" && node.title.startsWith("Twitter ")) { | |
| twitterIFramesRemoved++; | |
| if (twitterIFramesRemoved >= 2) { | |
| observer.disconnect(); | |
| } | |
| node.remove(); | |
| } | |
| }); | |
| } | |
| homePage(); | |
| function leaderboardPage() { | |
| // Check that we're on a leaderboard page and have moderator rights. | |
| if (document.getElementsByClassName("gamemenu-mod-tools").length === 0) { return; } | |
| const leaderboarddiv = document.getElementById("leaderboarddiv"); | |
| function newPrimaryLeaderboard(table) { | |
| for (let row of table.querySelectorAll("tbody > tr")) { | |
| let url = row.getAttribute("data-target").match(/^\/\w+\/run\/\w+$/)[0]; | |
| url += "/edit"; | |
| const cell = document.createElement("td"); | |
| cell.className = "nobr center hidden-xs hidden-md-down"; | |
| const anchor = document.createElement("a"); | |
| anchor.href = url; | |
| const image = document.createElement("i"); | |
| image.className = "fas fa-edit"; | |
| image.title = "Edit"; | |
| anchor.appendChild(image); | |
| cell.appendChild(anchor); | |
| row.appendChild(cell); | |
| } | |
| } | |
| onAddedChild(leaderboarddiv, (node) => { | |
| if (node.id === "primary-leaderboard") { | |
| newPrimaryLeaderboard(node); | |
| } | |
| }); | |
| const table = leaderboarddiv.getElementById("primary-leaderboard"); | |
| if (table !== null) { | |
| newPrimaryLeaderboard(table); | |
| } | |
| } | |
| leaderboardPage(); | |
| async function modhubPage() { | |
| const moderationPage = document.querySelector("main [component-name=ModerationPage]"); | |
| const sidebarLayout = (await childLoaded(moderationPage)).querySelector(".panel, :scope > .sidebar-layout"); | |
| const contentColumn = await childLoaded(sidebarLayout, (node) => node.className === "content-column"); | |
| const tickets = await childLoaded(contentColumn, (node) => node.previousSibling?.className === "panel"); | |
| function updateTicket(ticket) { | |
| const viewAnchor = ticket.querySelector(".ticket-actions-container a"); | |
| let categoryDiv = ticket.querySelector(".ticket-label-container > :last-child > :first-child"); | |
| let url = viewAnchor.getAttribute("href").match(/^(\/\w+)\/run\//)[1]; | |
| if (categoryDiv.childNodes[0].data === "Level: ") { | |
| const level = categoryDiv.getElementsByTagName("span")[0].textContent; | |
| categoryDiv = categoryDiv.nextSibling; | |
| url += `/level/${srcUrlEscape(level)}`; | |
| } | |
| const category = categoryDiv.getElementsByTagName("span")[0].textContent; | |
| url += `#${srcUrlEscape(category)}`; | |
| // Add the link to the page. | |
| const title = ticket.getElementsByClassName("ticket-title")[0]; | |
| title.normalize(); | |
| const titleText = title.childNodes[0]; | |
| titleText.splitText(titleText.length - 4); | |
| const anchor = document.createElement("a"); | |
| anchor.href = url; | |
| anchor.target = "_blank"; | |
| anchor.textContent = titleText.data; | |
| title.replaceChild(anchor, titleText); | |
| } | |
| onAddedChild(tickets, updateTicket); | |
| for (let ticket of tickets.children) { | |
| if (ticket.className === "ticket-container") { | |
| updateTicket(ticket); | |
| } | |
| } | |
| } | |
| if (location.pathname === "/modhub") { | |
| modhubPage(); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment