SGTools Notifier

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

目前為 2020-06-23 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name SGTools Notifier
// @namespace https://rafaelgssa.gitlab.io/monkey-scripts
// @version 4.1.1
// @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=819513
// @require https://greasyfork.org/scripts/405831-monkey-storage/code/Monkey%20Storage.js?version=819508
// @require https://greasyfork.org/scripts/405813-monkey-utils/code/Monkey%20Utils.js?version=819175
// @require https://greasyfork.org/scripts/405840-monkey-wizard/code/Monkey%20Wizard.js?version=819509
// @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 MonkeyDom, MonkeyStorage, MonkeyWizard */

(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 MonkeyStorage.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 MonkeyDom.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 MonkeyDom.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 MonkeyStorage.init(scriptId, {
			settings: {
				doRedirect: false,
			},
		});
		await MonkeyWizard.init(scriptId, scriptName, schemas);
		await load();
	} catch (err) {
		console.log(`Failed to load ${scriptName}: `, err);
	}
})();