NH_userscript

Wrappers for dealing with variations in userscript managers.

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/478349/1337643/NH_userscript.js

  1. // ==UserScript==
  2. // ==UserLibrary==
  3. // @name NH_userscript
  4. // @description Wrappers for dealing with variations in userscript managers.
  5. // @version 6
  6. // @license GPL-3.0-or-later; https://www.gnu.org/licenses/gpl-3.0-standalone.html
  7. // @homepageURL https://github.com/nexushoratio/userscripts
  8. // @supportURL https://github.com/nexushoratio/userscripts/issues
  9. // @match https://www.example.com/*
  10. // ==/UserLibrary==
  11. // ==/UserScript==
  12.  
  13. window.NexusHoratio ??= {};
  14.  
  15. window.NexusHoratio.userscript = (function userscript() {
  16. 'use strict';
  17.  
  18. /** @type {number} - Bumped per release. */
  19. const version = 6;
  20.  
  21. const NH = window.NexusHoratio.base.ensure(
  22. [{name: 'base', minVersion: 52}]
  23. );
  24.  
  25. /** Library specific exception. */
  26. class Exception extends NH.base.Exception {}
  27.  
  28. /**
  29. * @typedef LicenseData
  30. * @property {string} name - License name.
  31. * @property {string} url - URL pointing to the license.
  32. */
  33.  
  34. /**
  35. * Per the *old* GM docs:
  36. * https://sourceforge.net/p/greasemonkey/wiki/Metadata_Block/#license
  37. * @returns {LicenseData} - Extracted from the userscript header.
  38. * @throws {Error} - If cannot be extracted.
  39. */
  40. function licenseData() {
  41. let license = GM.info.script.license;
  42. if (!license) {
  43. const magic = '// @license ';
  44.  
  45. // Try a legacy way
  46. const header = GM.info.scriptMetaStr;
  47. if (header) {
  48. const line = header.split('\n')
  49. .find(l => l.startsWith(magic));
  50. if (line) {
  51. license = line.slice(magic.length)
  52. .trim();
  53. }
  54. }
  55. }
  56.  
  57. if (!license) {
  58. const msg = [
  59. 'Unable to extract license information from the userscript.',
  60. // eslint-disable-next-line no-magic-numbers
  61. JSON.stringify(GM.info, null, 2),
  62. ].join('\n');
  63. throw new Exception(msg);
  64. }
  65.  
  66. const [name, url] = license.split(';');
  67.  
  68. return {
  69. name: name.trim(),
  70. url: url.trim(),
  71. };
  72. }
  73.  
  74. /** @returns {string[]} - Raw text about the current environment. */
  75. function environmentData() {
  76. const gm = GM.info;
  77. const msgs = [`${gm.script.name}: ${gm.script.version}`];
  78. msgs.push('NexusHoratio libraries:');
  79. for (const [lib, obj] of Object.entries(window.NexusHoratio)) {
  80. if (Object.hasOwn(obj, 'version')) {
  81. msgs.push(` ${lib}: ${obj.version}`);
  82. } else {
  83. msgs.push(` ${lib}: Unknown version`);
  84. }
  85. }
  86.  
  87. msgs.push(`Userscript manager: ${gm.scriptHandler} ${gm.version}`);
  88.  
  89. if (gm.injectInto) {
  90. msgs.push(` injected into "${gm.injectInto}"`);
  91. }
  92.  
  93. // Violentmonkey
  94. if (gm.platform) {
  95. msgs.push(`Platform: ${gm.platform.browserName} ` +
  96. `${gm.platform.browserVersion} ${gm.platform.os} ` +
  97. `${gm.platform.arch}`);
  98. }
  99.  
  100. // Tampermonkey
  101. if (gm.userAgentData) {
  102. let msg = 'Platform: ';
  103. for (const brand of gm.userAgentData.brands.values()) {
  104. msg += `${brand.brand} ${brand.version} `;
  105. }
  106. msg += `${gm.userAgentData?.platform} `;
  107. msg +=
  108. `${gm.userAgentData?.architecture}-${gm.userAgentData?.bitness}`;
  109. msgs.push(msg);
  110. }
  111. return msgs;
  112. }
  113.  
  114. /**
  115. * Fetches value from userscript storage if granted.
  116. *
  117. * Purposefully no errors if permissions are not granted
  118. *
  119. * @param {string} key - The name of the value to load.
  120. * @param {*} defaultValue - Value if not stored OR not enabled.
  121. * @returns {Promise<*>} - The value fetched or defaultValue.
  122. */
  123. function getValue(key, defaultValue) {
  124. if (GM.getValue) {
  125. return GM.getValue(key, defaultValue);
  126. }
  127. return Promise.resolve(defaultValue);
  128. }
  129.  
  130. /**
  131. * Sets a value in userscript storage if granted.
  132. *
  133. * Purposefully no errors if permissions are not granted
  134. *
  135. * @param {string} key - The name to use in the storage.
  136. * @param {*} value - The value to set.
  137. * @returns {Promise<*>} - Always resolves to null; mostly used to ensure
  138. * the write is complete.
  139. */
  140. function setValue(key, value) {
  141. if (GM.setValue) {
  142. return GM.setValue(key, value);
  143. }
  144. return Promise.resolve(null);
  145. }
  146.  
  147. return {
  148. version: version,
  149. Exception: Exception,
  150. UserscriptError: Exception,
  151. licenseData: licenseData,
  152. environmentData: environmentData,
  153. getValue: getValue,
  154. setValue: setValue,
  155. };
  156.  
  157. }());