InstaSynchP Core

The core for a modular plugin system for InstaSynch

目前为 2014-12-22 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name InstaSynchP Core
  3. // @namespace InstaSynchP
  4. // @description The core for a modular plugin system for InstaSynch
  5.  
  6. // @version 1.2.1
  7. // @author Zod-
  8. // @source https://github.com/Zod-/InstaSynchP-Core
  9. // @license MIT
  10.  
  11. // @include http://*.instasynch.com/*
  12. // @include http://instasynch.com/*
  13. // @include http://*.instasync.com/*
  14. // @include http://instasync.com/*
  15. // @grant none
  16. // @run-at document-end
  17.  
  18. // @require https://greasyfork.org/scripts/2855-gm-config/code/GM_config.js
  19. // @require https://greasyfork.org/scripts/2859-video-url-parser/code/Video%20Url%20Parser.js
  20.  
  21. // @require https://greasyfork.org/scripts/5647-instasynchp-library/code/InstaSynchP%20Library.js?version=22833
  22. // @require https://greasyfork.org/scripts/5718-instasynchp-cssloader/code/InstaSynchP%20CSSLoader.js?version=26081
  23. // @require https://greasyfork.org/scripts/5719-instasynchp-settings/code/InstaSynchP%20Settings.js?version=22826
  24. // @require https://greasyfork.org/scripts/6332-instasynchp-commands/code/InstaSynchP%20Commands.js?version=25596
  25. // @require https://greasyfork.org/scripts/6573-instasynchp-plugin-manager/code/InstaSynchP%20Plugin%20Manager.js?version=26383
  26.  
  27. // @require https://greasyfork.org/scripts/2857-jquery-bind-first/code/jquerybind-first.js?version=26080
  28. // @require https://greasyfork.org/scripts/5651-instasynchp-event-hooks/code/InstaSynchP%20Event%20Hooks.js?version=26378
  29. // ==/UserScript==
  30.  
  31. function Core(version) {
  32. "use strict";
  33. this.version = version;
  34. this.name = 'InstaSynchP Core';
  35. this.listeners = {};
  36. this.connected = false;
  37. }
  38.  
  39. Core.prototype.executeOnceCore = function () {
  40. "use strict";
  41. var th = this;
  42. window.events = (function () {
  43. return {
  44. //bind event handlers
  45. 'on': function (ref, eventNames, callback, preOld) {
  46. if (typeof callback === 'undefined') {
  47. return;
  48. }
  49.  
  50. var arr = eventNames.split(','),
  51. eventName,
  52. i;
  53. for (i = 0; i < arr.length; i += 1) {
  54. eventName = arr[i].trim();
  55. if (typeof th.listeners[eventName] === 'undefined') {
  56. th.listeners[eventName] = {
  57. 'preOld': [],
  58. 'postOld': []
  59. };
  60. }
  61. //execute it before are after the overwritten function
  62. if (preOld) {
  63. th.listeners[eventName].preOld.push({
  64. ref: ref,
  65. callback: callback
  66. });
  67. } else {
  68. th.listeners[eventName].postOld.push({
  69. ref: ref,
  70. callback: callback
  71. });
  72. }
  73. }
  74. },
  75. //bind event handler and remove any previous once
  76. 'once': function (ref, eventNames, callback, preOld) {
  77. this.unbind(eventNames, callback);
  78. this.on(ref, eventNames, callback, preOld);
  79. },
  80. //unbind event handlers
  81. 'unbind': function (eventNames, callback) {
  82. var arr = eventNames.split(','),
  83. i, temp;
  84.  
  85. //search all occurences of callback and remove it
  86. function removeCallback(eventName, old) {
  87. if (typeof th.listeners[eventName] === 'undefined') {
  88. return;
  89. }
  90. for (var j = 0; j < th.listeners[eventName][old].length; j += 1) {
  91. if (th.listeners[eventName][old][j].callback === callback) {
  92. th.listeners[eventName][old].splice(j, 1);
  93. j -= 1;
  94. }
  95. }
  96. }
  97. for (i = 0; i < arr.length; i += 1) {
  98. temp = arr[i].trim();
  99. removeCallback(temp, 'preOld');
  100. removeCallback(temp, 'postOld');
  101. }
  102. },
  103. //fire the event with the given parameters
  104. 'fire': function (eventName, parameters, preOld) {
  105. var i,
  106. listenersCopy;
  107. if (typeof th.listeners[eventName] === 'undefined') {
  108. return;
  109. }
  110. //make a copy of the listener list since some handlers
  111. //could remove listeners changing the length of the array
  112. //while iterating over it
  113. if (preOld) {
  114. listenersCopy = [].concat(th.listeners[eventName].preOld);
  115. } else {
  116. listenersCopy = [].concat(th.listeners[eventName].postOld);
  117. }
  118. //fire the events and catch possible errors
  119. for (i = 0; i < listenersCopy.length; i += 1) {
  120. try {
  121. listenersCopy[i].callback.apply(listenersCopy[i].ref, parameters);
  122. } catch (err) {
  123. window.console.log(
  124. ("Error: {0}, eventName {1}, function {2} %s %s %o, " +
  125. "please check the console " +
  126. "and make a pastebin of everything in there").format(
  127. err.message, eventName, listenersCopy[i].callback.name),
  128. listenersCopy[i].callback, err.stack, err);
  129. }
  130. }
  131. }
  132. };
  133. }());
  134. };
  135.  
  136. Core.prototype.resetVariables = function () {
  137. "use strict";
  138. this.connected = false;
  139. window.userInfo = undefined;
  140. };
  141.  
  142. Core.prototype.main = function () {
  143. "use strict";
  144. var th = this;
  145. th.executeOnceCore();
  146. window.plugins.commands.executeOnceCore();
  147. window.plugins.pluginManager.executeOnceCore();
  148. events.on(window.plugins.cssLoader, 'ExecuteOnce', window.plugins.cssLoader.executeOnceCore);
  149. events.on(window.plugins.settings, 'ExecuteOnce', window.plugins.settings.executeOnceCore);
  150. events.on(th, 'PreConnect,Disconnect', function () {
  151. events.fire('ResetVariables');
  152. });
  153. //prepare plugins
  154. for (var pluginName in window.plugins) {
  155. if (!window.plugins.hasOwnProperty(pluginName)) {
  156. continue;
  157. }
  158. var plugin = window.plugins[pluginName];
  159. if (!plugin.enabled) {
  160. continue;
  161. }
  162. events.on(plugin, 'PreConnect', plugin.preConnect);
  163. events.on(plugin, 'PostConnect', plugin.postConnect);
  164. events.on(plugin, 'ExecuteOnce', plugin.executeOnce);
  165. events.on(plugin, 'ResetVariables', plugin.resetVariables);
  166. commands.bind(plugin.commands);
  167. if (Object.prototype.toString.call(plugin.settings) === '[object Array]') {
  168. window.plugins.settings.fields = window.plugins.settings.fields.concat(plugin.settings);
  169. }
  170.  
  171. }
  172.  
  173. function load() {
  174. //we are not connected yet
  175. events.fire('PreConnect');
  176. //if the script was loading slow and we are already connected
  177. if (window.userInfo) {
  178. th.connected = true;
  179. events.fire('PostConnect');
  180. }
  181. }
  182. //these need to be executed last
  183. events.on(window.plugins.eventHooks, 'ExecuteOnce', window.plugins.eventHooks.executeOnceCore);
  184. events.on(th, 'LoadUserlist', function () {
  185. th.connected = true;
  186. events.fire('PostConnect');
  187. });
  188. //execute one time only scripts
  189. events.fire('ExecuteOnce');
  190. //load the scripts
  191. if (global.page.name !== 'index') {
  192. load();
  193. }
  194. //reload the scripts when changing a room
  195. events.on(th, 'LoadRoom', load);
  196. };
  197.  
  198. window.plugins = window.plugins || {};
  199. window.plugins.core = new Core('1.2.1');
  200. if (window.document.readyState === 'complete') {
  201. window.plugins.core.main();
  202. } else {
  203. window.addEventListener('load', function () {
  204. window.plugins.core.main();
  205. }, false);
  206. }