Includes : Updater

Updater Function

  1. // ==UserScript==
  2. // @name Includes : Updater
  3. // @description Updater Function
  4. // @author You
  5. // @version 1.0
  6. // @include nowhere
  7. // @exclude *
  8. // @grant GM_addStyle
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @grant GM_deleteValue
  12. // @grant GM_xmlhttpRequest
  13. // @grant GM_getResourceText
  14. // @namespace https://greasyfork.org/users/1385333
  15. // ==/UserScript==
  16.  
  17. /**************************************************************************
  18.  
  19. Author's NOTE
  20.  
  21. This script was made from scratch.
  22.  
  23. Based on https://userscripts-mirror.org/scripts/show/52251 (by Buzzy)
  24.  
  25. ***************************************************************************
  26.  
  27. This program is free software: you can redistribute it and/or modify
  28. it under the terms of the GNU General Public License as published by
  29. the Free Software Foundation, either version 3 of the License, or
  30. (at your option) any later version.
  31.  
  32. This program is distributed in the hope that it will be useful,
  33. but WITHOUT ANY WARRANTY; without even the implied warranty of
  34. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  35. GNU General Public License for more details.
  36.  
  37. You should have received a copy of the GNU General Public License
  38. along with this program. If not, see <http://www.gnu.org/licenses/>.
  39.  
  40. **************************************************************************/
  41.  
  42.  
  43. // for compatibility only
  44. var Updater = {};
  45.  
  46. (function () { // script scope
  47. var parseHeader = function (text) {
  48. var output = {"resources" : {}, "histories" : {}},
  49. re = /^\/\/ @([\w:]+)\s+(.+)$/gm,
  50. item;
  51.  
  52. while (item = re.exec(text)) {
  53. var k = item[1].toLowerCase();
  54.  
  55. if ("resource" == k) {
  56. if (/^([\w:.]+)\s+(.+)/.test(item[2])) {
  57. output.resources[RegExp.$1] = RegExp.$2;
  58. }
  59. } else if ("history" == k) {
  60. if (/^([\w:.]+)\s+(.+)/.test(item[2])) {
  61. if (RegExp.$1 in output.histories) {
  62. output.histories[RegExp.$1].push(RegExp.$2);
  63. } else {
  64. output.histories[RegExp.$1] = [RegExp.$2];
  65. }
  66. }
  67. } else {
  68. if (~["include", "exclude"].indexOf(k)) {
  69. k += "s";
  70. } else if (~["match"].indexOf(k)) {
  71. k += "es";
  72. }
  73.  
  74. if (k in output) {
  75. if (!(output[k] instanceof Array)) {
  76. output[k] = [output[k]];
  77. }
  78.  
  79. output[k].push(item[2]);
  80. } else {
  81. output[k] = item[2];
  82. }
  83. }
  84. }
  85.  
  86. return output;
  87. };
  88.  
  89. if (GM_getValue("cfuw_enabled", true)) {
  90. (function recursive (new_header) {
  91. var last = Date.parse(GM_getValue("cfuw_last_check", "Sat Oct 9 2010 20:10:26 GMT-0300")),
  92. curr = new Date(),
  93. interval = 86400000; // 24 * 60 * 60 * 1000 = 1 day
  94.  
  95. if (curr - interval > last) {
  96. var old_header = null;
  97.  
  98. try {
  99. old_header = parseHeader(GM_getResourceText("meta"));
  100. } catch (e) {
  101. console.warn('Resource META is required for the script "' + GM_info.script.name + '".\nUpdate checking was ignored!');
  102. }
  103.  
  104. if (old_header) {
  105. GM_setValue("cfuw_last_check", (last = new Date(curr - interval + 310000)).toString());
  106.  
  107. function nextstep(new_header) {
  108. var parent = document.createElement("div"),
  109. params = {
  110. "id" : old_header["uso:script"] || "",
  111. "name" : old_header.name || "",
  112. "old_version" : old_header.version || old_header["uso:version"] || I18n.get("cfuw.version.unknown"),
  113. "new_version" : new_header.version || new_header["uso:version"] || I18n.get("cfuw.version.unknown"),
  114. "history" : "",
  115. "i18n.title" : I18n.get("cfuw.title"), //New version available for
  116. "i18n.cversion" : I18n.get("cfuw.cversion.label"), //Current version
  117. "i18n.lversion" : I18n.get("cfuw.lversion.label"), //Lastest version
  118. "i18n.install" : I18n.get("cfuw.install.label"), // Install
  119. "i18n.visit" : I18n.get("cfuw.visit.label"), // Visit
  120. "i18n.cancel" : I18n.get("cfuw.cancel.label"), // Cancel
  121. "i18n.disable" : I18n.get("cfuw.disable.label"), // Don't ask me again for this script
  122. };
  123.  
  124. for (var key in old_header.histories) {
  125. if (key in new_header.histories) {
  126. delete new_header.histories[key];
  127. }
  128. }
  129.  
  130. for (var key in new_header.histories) {
  131. params.history += "<span>" + key + "</span><ul>";
  132.  
  133. // Update 'for each' to 'for...of'
  134. for (let item of new_header.histories[key]) {
  135. params.history += "<li>" + item + "</li>";
  136. }
  137.  
  138. params.history += "</ul>";
  139. }
  140.  
  141. parent.innerHTML = GM_getResourceText("updaterWindowHtml").replace(/{([\w.]+)}/g, function ($0, $1) {
  142. return ($1 in params ? params[$1] : $0)
  143. });
  144.  
  145. document.body.appendChild(parent);
  146.  
  147. var closeWin = setTimeout(function (w) {
  148. if (w) {
  149. w.parentNode.removeChild(w);
  150. }
  151. }, 120000, parent),
  152. win = "id('cfuw_" + old_header["uso:script"] + "')";
  153.  
  154. if (params.history.length) {
  155. xpath(win + "//div[@class='history']")[0].style.visibility = "visible";
  156. }
  157.  
  158. if (old_header.name + old_header.namespace != new_header.name + new_header.namespace) {
  159. xpath(win + "//a[contains(@class,'install')]")[0].addEventListener("click", function (e) {
  160. I18n.get("cfuw.uninstall.msg.error", alert); // The script name/namespace has changed.\nYou will need to uninstall the old version manually.
  161. }, true);
  162. }
  163.  
  164. // Update 'for each' to 'for...of'
  165. for (let btn of xpath(win + "//a[contains(@class,'close')]")) {
  166. btn.addEventListener("click", function (e) {
  167. parent.parentNode.removeChild(parent);
  168. clearTimeout(closeWin);
  169. GM_setValue("cfuw_last_check", new Date().toString());
  170. }, false);
  171. }
  172.  
  173. xpath(win+"//td[@class='disable']/input")[0].addEventListener("click", function (e) {
  174. GM_setValue("cfuw_enabled", !e.target.checked);
  175. }, false);
  176.  
  177. setTimeout(recursive, last - curr + interval, new_header);
  178. }
  179.  
  180. if (new_header) {
  181. nextstep(new_header);
  182. } else {
  183. GM_xmlhttpRequest({
  184. "method" : "get",
  185. "url" : old_header.resources.meta,
  186. "onerror" : function (xhr) {
  187. setTimeout(recursive, last - curr + interval);
  188. },
  189. "onload" : function (xhr) {
  190. var new_header = parseHeader(xhr.responseText),
  191. curr = new Date();
  192.  
  193. if (/^2/.test(xhr.status) && "" + old_header["uso:hash"] != "" + new_header["uso:hash"]) {
  194. GM_addStyle(GM_getResourceText("updaterWindowCss"));
  195.  
  196. nextstep(new_header);
  197. } else {
  198. GM_setValue("cfuw_last_check", curr.toString());
  199.  
  200. setTimeout(recursive, interval);
  201. }
  202. }
  203. });
  204. }
  205. }
  206. } else {
  207. setTimeout(recursive, last - curr + interval);
  208. }
  209. }());
  210. }
  211. }());