// ==UserScript== // @name SGTools Notifier // @namespace https://rafaelgssa.gitlab.io/monkey-scripts // @version 4.1.3 // @author rafaelgssa // @description Notifies the user when a SGTools rules check is complete and optionally redirects to the giveaway. // @match https://www.sgtools.info/* // @match https://www.steamgifts.com/giveaway/* // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js // @require https://greasyfork.org/scripts/405802-monkey-dom/code/Monkey%20DOM.js?version=820314 // @require https://greasyfork.org/scripts/405831-monkey-storage/code/Monkey%20Storage.js?version=820315 // @require https://greasyfork.org/scripts/405813-monkey-utils/code/Monkey%20Utils.js?version=820304 // @require https://greasyfork.org/scripts/405840-monkey-wizard/code/Monkey%20Wizard.js?version=820318 // @run-at document-idle // @grant GM.info // @grant GM.setValue // @grant GM.getValue // @grant GM.deleteValue // @grant GM_info // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @noframes // @downloadURL none // ==/UserScript== /* global DOM, PersistentStorage, SettingsWizard */ (async () => { 'use strict'; const scriptId = 'sgtn'; const scriptName = GM.info.script.name; /** @type {WizardSchema[]} */ const schemas = [ { type: 'multi', id: 'doRedirect', message: 'Do you want to be redirected to the giveaway when the check is complete?', defaultValue: false, choices: [ { id: 'y', template: '"%" for yes', value: true, }, { id: 'n', template: '"%" for no', value: false, }, ], }, ]; let doRedirect = false; /** @type {HTMLElement | null} */ let checkButton; /** * Loads the script. * @returns {Promise} */ const load = async () => { if (window.location.hostname === 'www.steamgifts.com') { return removePageUrlFragment(); } doRedirect = /** @type {boolean} */ (await PersistentStorage.getSetting('doRedirect')); checkButton = document.querySelector('#check'); if (checkButton) { checkButton.addEventListener('click', waitForRulesCheck); } }; /** * Removes the fragment from the page URL and notifies the user if exists. * @returns {Promise} */ const removePageUrlFragment = async () => { if (window.location.hash === `#${scriptId}`) { window.history.replaceState( '', document.title, `${window.location.origin}${window.location.pathname}${window.location.search}` ); notifyUser(true); } }; /** * Waits until the check is complete and notifies the user. * @returns {Promise} */ const waitForRulesCheck = async () => { if (!checkButton) { return; } const result = await DOM.dynamicQuerySelector('#getlink, #error_alert:not(.hidden)', 1800); if (!result) { // Rules have not been checked after 30 minutes. return; } if (result.matches('#getlink')) { // User passed the rules. if (doRedirect) { checkButton.removeEventListener('click', waitForRulesCheck); checkButton.dispatchEvent(new MouseEvent('click', { bubbles: true })); await waitForGiveawayLink(); } else { notifyUser(true); } } else { // User failed to pass the rules. notifyUser(false); } }; /** * Waits for the giveaway link, redirects to the giveaway and notifies the user. * @returns {Promise} */ const waitForGiveawayLink = async () => { const link = /** @type {HTMLAnchorElement} */ (await DOM.dynamicQuerySelector('#gaurl a')); if (link) { window.location.href = `${link.href}#${scriptId}`; } else { notifyUser(true); } }; /** * Notifies the user. * @param {boolean} isSuccess Whether the user passed the rules or not. */ const notifyUser = (isSuccess) => { const [emoji, message] = isSuccess ? ['✔️', 'You passed the rules!'] : ['❌', 'You failed to pass the rules.']; if (window.location.hostname === 'www.sgtools.info') { document.title = `${emoji} ${document.title}`; } if (document.hidden) { // Only show a browser notification if the user is away from the tab. showBrowserNotification(`${emoji} ${message}`); } }; /** * Shows a browser notification. * @param {string} body The message to show. * @return {Promise} */ const showBrowserNotification = async (body) => { if (Notification.permission !== 'granted') { await Notification.requestPermission(); } if (Notification.permission === 'granted') { new Notification(scriptName, { body }); } }; try { await PersistentStorage.init(scriptId, { settings: { doRedirect: false, }, }); await SettingsWizard.init(scriptId, scriptName, schemas); await load(); } catch (err) { console.log(`Failed to load ${scriptName}: `, err); } })();