GreasyForkScriptUpdate

Check update for Greasyfork userscript

当前为 2021-08-27 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/scripts/431490/964614/GreasyForkScriptUpdate.js

  1. /* eslint-disable no-multi-spaces */
  2. // ==UserScript==
  3. // @name GreasyForkScriptUpdate
  4. // @namespace GreasyForkScriptUpdate
  5. // @version 0.3
  6. // @description Check update for Greasyfork userscript
  7. // @author PY-DNG
  8. // @include http*://*/*
  9. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  10. // @grant GM_xmlhttpRequest
  11. // @grant unsafeWindow
  12. // ==/UserScript==
  13. (function () {
  14. 'use strict';
  15.  
  16. // Accessable in Global_Scope
  17. typeof(unsafeWindow) !== 'object' && (window.unsafeWindow = window);
  18. unsafeWindow.GreasyForkUpdater = GreasyForkUpdater;
  19.  
  20. // Use 'new' keyword
  21. function GreasyForkUpdater() {
  22. const GFU = this;
  23.  
  24. // Parse '// ==UserScript==\n...\n// ==/UserScript==' to {name: '', namespace: '', version: '', ...}
  25. // Returns metaData object directly
  26. GFU.parseMetaData = function(metaText) {
  27. const metaData = {};
  28. const lines = metaText.split('\n');
  29. const edgeMatcher = /==\/?UserScript==/i;
  30. const keyValueMatcher = /^\/\/ *@([^@ ]+) +(.+) *$/;
  31. const keyOnlyMatcher = /^\/\/ *@([^@ ]+) *$/;
  32. for (let line of lines) {
  33. // Get & validate line
  34. line = line.trim();
  35. if (line.match(edgeMatcher)) {continue;};
  36. if (!line.match(keyValueMatcher) && !line.match(keyOnlyMatcher)) {continue;};
  37.  
  38. // Get key-value
  39. const match = line.match(keyValueMatcher) ? line.match(keyValueMatcher) : line.match(keyOnlyMatcher);
  40. const key = match[1];
  41. const value = match[2] ? match[2] : true;
  42.  
  43. // Attach to metaData object
  44. if (!metaData[key]) {
  45. metaData[key] = value;
  46. } else {
  47. if (metaData[key] instanceof Array) {
  48. metaData[key].push(value);
  49. } else {
  50. metaData[key] = [metaData[key], value];
  51. }
  52. }
  53. }
  54. return metaData;
  55. }
  56.  
  57. // Request latest script meta text from greasyfork
  58. // You'll get metaText string as the first argument in your callback function
  59. GFU.requestMetaText = function(scriptID, callback, args=[]) {
  60. if (!scriptID) {return false;};
  61. const url = 'https://greasyfork.org/scripts/{SID}/code/script.meta.js'.replace('{SID}', String(scriptID));
  62. GM_xmlhttpRequest({
  63. method: 'GET',
  64. url: url,
  65. responseType: 'text',
  66. onload: function(e) {
  67. callback && callback.apply(null, [e.responseText].concat(args));
  68. }
  69. })
  70. }
  71.  
  72. // Request & parse latest script meta data from greasyfork
  73. // You'll get metaData object as the first argument in your callback function
  74. GFU.getMetaData = function(scriptID, callback, args=[]) {
  75. if (!scriptID) {return false;};
  76. GFU.requestMetaText(scriptID, function(metaText) {
  77. const metaData = GFU.parseMetaData(metaText);
  78. callback && callback.apply(null, [metaData].concat(args));
  79. })
  80. }
  81.  
  82. // Compare two version texts(v1, v2), returns true if v1 > v2
  83. // Returns null while version text contains Non-demical text period(s)
  84. GFU.versionNewer = function(v1, v2) {
  85. v1 = v1.trim().split('.');
  86. v2 = v2.trim().split('.');
  87.  
  88. for (let i = 0; i < Math.min(v1.length, v2.length); i++) {
  89. v1[i] = Number(v1[i]);
  90. v2[i] = Number(v2[i]);
  91. if (!v1[i] || !v2[i]) {return null;};
  92. if (v1[i] !== v2[i]) {return v1[i] > v2[i];};
  93. }
  94.  
  95. return v1.length > v2.length;
  96. }
  97.  
  98. // Check if there's new version of the script on GreasyFork using scriptID, current version text
  99. // You'll get update(bool), updateurl(string), metaData(object) as the first, second and third argument in your callback function
  100. GFU.checkUpdate = function(scriptID, curver, callback, args=[]) {
  101. if (!scriptID) {return false;};
  102. GFU.getMetaData(scriptID, function(metaData) {
  103. const update = GFU.versionNewer(metaData.version, curver);
  104. const updateurl = 'https://greasyfork.org/scripts/{SID}/code/script.user.js'.replace('{SID}', String(scriptID));
  105. callback && callback.apply(null, [update, updateurl, metaData].concat(args));
  106. })
  107. }
  108.  
  109. // Check & Install update automatically
  110. GFU.update = function(scriptID, curver) {
  111. GFU.checkUpdate(scriptID, curver, function() {
  112. const url = 'https://greasyfork.org/scripts/{SID}/code/script.user.js'.replace('{SID}', String(scriptID));
  113. location.href = url;
  114. })
  115. }
  116. }
  117. })();