SGTools Notifier

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

当前为 2020-06-22 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name SGTools Notifier
  3. // @namespace https://rafaelgssa.gitlab.io/monkey-scripts
  4. // @version 4.1.0
  5. // @author rafaelgssa
  6. // @description Notifies the user when a SGTools rules check is complete and optionally redirects to the giveaway.
  7. // @match https://www.sgtools.info/*
  8. // @match https://www.steamgifts.com/giveaway/*
  9. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  10. // @require https://greasyfork.org/scripts/405802-monkey-dom/code/Monkey%20DOM.js
  11. // @require https://greasyfork.org/scripts/405831-monkey-storage/code/Monkey%20Storage.js
  12. // @require https://greasyfork.org/scripts/405813-monkey-utils/code/Monkey%20Utils.js
  13. // @require https://greasyfork.org/scripts/405840-monkey-wizard/code/Monkey%20Wizard.js
  14. // @run-at document-idle
  15. // @grant GM.info
  16. // @grant GM.setValue
  17. // @grant GM.getValue
  18. // @grant GM.deleteValue
  19. // @grant GM_info
  20. // @grant GM_setValue
  21. // @grant GM_getValue
  22. // @grant GM_deleteValue
  23. // @noframes
  24. // ==/UserScript==
  25.  
  26. /* global MonkeyDom, MonkeyStorage, MonkeyWizard */
  27.  
  28. (async () => {
  29. 'use strict';
  30.  
  31. const scriptId = 'sgtn';
  32. const scriptName = GM.info.script.name;
  33.  
  34. /** @type {MonkeyWizardSchema[]} */
  35. const schemas = [
  36. {
  37. type: 'multi',
  38. id: 'doRedirect',
  39. message: 'Do you want to be redirected to the giveaway when the check is complete?',
  40. defaultValue: false,
  41. choices: [
  42. {
  43. id: 'y',
  44. template: '"%" for yes',
  45. value: true,
  46. },
  47. {
  48. id: 'n',
  49. template: '"%" for no',
  50. value: false,
  51. },
  52. ],
  53. },
  54. ];
  55.  
  56. let doRedirect = false;
  57.  
  58. /** @type {HTMLElement | null} */
  59. let checkButton;
  60.  
  61. /**
  62. * Loads the script.
  63. * @returns {Promise<void>}
  64. */
  65. const load = async () => {
  66. if (window.location.hostname === 'www.steamgifts.com') {
  67. return _removePageUrlFragment();
  68. }
  69. doRedirect = /** @type {boolean} */ (await MonkeyStorage.getSetting('doRedirect'));
  70. checkButton = document.querySelector('#check');
  71. if (checkButton) {
  72. checkButton.addEventListener('click', _waitForRulesCheck);
  73. }
  74. };
  75.  
  76. /**
  77. * Removes the fragment from the page URL and notifies the user if exists.
  78. * @returns {Promise<void>}
  79. */
  80. const _removePageUrlFragment = async () => {
  81. if (window.location.hash === `#${scriptId}`) {
  82. window.history.replaceState(
  83. '',
  84. document.title,
  85. `${window.location.origin}${window.location.pathname}${window.location.search}`
  86. );
  87. _notifyUser(true);
  88. }
  89. };
  90.  
  91. /**
  92. * Waits until the check is complete and notifies the user.
  93. * @returns {Promise<void>}
  94. */
  95. const _waitForRulesCheck = async () => {
  96. if (!checkButton) {
  97. return;
  98. }
  99. const result = await MonkeyDom.dynamicQuerySelector(
  100. '#getlink, #error_alert:not(.hidden)',
  101. 1800
  102. );
  103. if (!result) {
  104. // Rules have not been checked after 30 minutes.
  105. return;
  106. }
  107. if (result.matches('#getlink')) {
  108. // User passed the rules.
  109. if (doRedirect) {
  110. checkButton.removeEventListener('click', _waitForRulesCheck);
  111. checkButton.dispatchEvent(new MouseEvent('click', { bubbles: true }));
  112. await _waitForGiveawayLink();
  113. } else {
  114. _notifyUser(true);
  115. }
  116. } else {
  117. // User failed to pass the rules.
  118. _notifyUser(false);
  119. }
  120. };
  121.  
  122. /**
  123. * Waits for the giveaway link, redirects to the giveaway and notifies the user.
  124. * @returns {Promise<void>}
  125. */
  126. const _waitForGiveawayLink = async () => {
  127. const link = /** @type {HTMLAnchorElement} */ (await MonkeyDom.dynamicQuerySelector(
  128. '#gaurl a'
  129. ));
  130. if (link) {
  131. window.location.href = `${link.href}#${scriptId}`;
  132. } else {
  133. _notifyUser(true);
  134. }
  135. };
  136.  
  137. /**
  138. * Notifies the user.
  139. * @param {boolean} isSuccess Whether the user passed the rules or not.
  140. */
  141. const _notifyUser = (isSuccess) => {
  142. const [emoji, message] = isSuccess
  143. ? ['✔️', 'You passed the rules!']
  144. : ['❌', 'You failed to pass the rules.'];
  145. if (window.location.hostname === 'www.sgtools.info') {
  146. document.title = `${emoji} ${document.title}`;
  147. }
  148. if (document.hidden) {
  149. // Only show a browser notification if the user is away from the tab.
  150. _showBrowserNotification(`${emoji} ${message}`);
  151. }
  152. };
  153.  
  154. /**
  155. * Shows a browser notification.
  156. * @param {string} body The message to show.
  157. * @return {Promise<void>}
  158. */
  159. const _showBrowserNotification = async (body) => {
  160. if (Notification.permission !== 'granted') {
  161. await Notification.requestPermission();
  162. }
  163. if (Notification.permission === 'granted') {
  164. new Notification(scriptName, { body });
  165. }
  166. };
  167.  
  168. try {
  169. await MonkeyStorage.init(scriptId, {
  170. settings: {
  171. doRedirect: false,
  172. },
  173. });
  174. await MonkeyWizard.init(scriptId, scriptName, schemas);
  175. await load();
  176. } catch (err) {
  177. console.log(`Failed to load ${scriptName}: `, err);
  178. }
  179. })();