Greasy Fork

SGTools Notifier

Notifies the user when a SGTools rules check is complete and optionally redirects to the giveaway.

目前为 2020-06-25 提交的版本。查看 最新版本

// ==UserScript==
// @name SGTools Notifier
// @namespace https://rafaelgssa.gitlab.io/monkey-scripts
// @version 4.1.2
// @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
// ==/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<void>}
	 */
	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<void>}
	 */
	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<void>}
	 */
	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<void>}
	 */
	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<void>}
	 */
	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);
	}
})();