Advertisement
Guest User

Untitled

a guest
Aug 21st, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.99 KB | None | 0 0
  1. /* eslint-disable */
  2. let airIndex = new Error();
  3. // ===============================================================================
  4. // AIRBAG - API Crash Handler
  5. //
  6. // Version 1.3.2
  7. //
  8. // By: github.com/VoltCruelerz
  9. //
  10. // Forked by github.come/Eunomiac:
  11. // - chat message is now HTML formatted for easier reading/clarity
  12. // - log message parsed for easier reading
  13. // - ALL line references in the stack trace are converted to local
  14. // ===============================================================================
  15. // ===============================================================================
  16.  
  17. // Whether or not the code is operational
  18. let codebaseRunning = false;
  19.  
  20. // System States
  21. const rezMsg = "[API IS STARTING]";
  22. const runMsg = "[API OPERATIONAL]";
  23.  
  24. // Log for Airbag
  25. const airLog = (logMsg, chatMsg) => {
  26. log(logMsg);
  27. sendChat("Airbag", `/w gm ${chatMsg || logMsg}`);
  28. };
  29.  
  30. // HTML Styles for Reporting
  31. const HTML = {
  32. ChatBox: content => `<div style="display: block; width: 100%; padding: 5px 5px; margin: -30px 0px 0px -42px; border: 3px outset rgb(255, 0, 0); background-color: rgb(120, 0, 0); position: relative;">${content}</div>`,
  33. TitleBox: content => `<div style="display: block; height: auto; width: 90%; line-height: 23px; margin: 0px 5%; font-family: 'copperplate gothic'; font-variant: small-caps; font-size: 16px; text-align: center; text-align-last: center; background-color: rgb(80, 80, 80); color: rgb(255, 255, 255); position: relative;">${content}</div>`,
  34. StackBox: content => `<div style="display: block; width: auto; padding: 5px 5px; font-family: input, verdana, sans-serif; font-size: 10px; background-color: rgb(255, 255, 255); border: 2px solid rgb(0,0,0); line-height: 14px; position: relative; ">${content}</div>`,
  35. MessageBox: content => `<div style=" display: block; width: auto; padding: 5px 25px; font-family: input, verdana, sans-serif; font-size: 18px; text-align: center; text-align-last: center; background-color: rgb(200, 200, 200); border: 2px solid rgb(0,0,0); line-height: 14px; position: relative;">${content}</div>`
  36. }
  37.  
  38. // ===========================================================================
  39. // Line number Handling
  40. // ===========================================================================
  41.  
  42. // Denote the occupation ranges of the installed scripts that Airbag insulates
  43. let scriptRanges = [];
  44.  
  45. // Line Number Parser
  46. const GetScriptLine = (traceable, markMode) => {
  47. const match = traceable.stack.match(/apiscript.js:(\d+)/g) || ["", ""];
  48. if (markMode) {
  49. return parseInt(match[1].split(':')[1]);
  50. }
  51. return parseInt(match[0].split(':')[1]);
  52. };
  53.  
  54. // The last range entry that was added
  55. let lastStart = {
  56. Name: 'AirbagStart',
  57. StartLine: GetScriptLine(airIndex, false),
  58. StopLine: -1
  59. };
  60.  
  61. // Manual insert since Airbag can't use its own MarkStart function
  62. scriptRanges.push(lastStart);
  63.  
  64. // Available for dependent scripts.
  65. const MarkStart = (scriptName) => {
  66. let index = new Error();
  67. let line = GetScriptLine(index, true);
  68. lastStart = {
  69. Name: scriptName,
  70. StartLine: line,
  71. StopLine: -1
  72. };
  73. scriptRanges.push(lastStart);
  74. };
  75.  
  76. // Available for dependent scripts
  77. const MarkStop = (scriptName) => {
  78. let index = new Error();
  79. let line = GetScriptLine(index, true);
  80. lastStart.StopLine = line;
  81. };
  82.  
  83. // Prints the list of scripts and their line number ranges
  84. // (called at end of AirbagStop)
  85. const printScriptRanges = () => {
  86. scriptRanges.forEach((range) => {
  87. const msg = range.StopLine > 0
  88. ? `[${range.StartLine}, ${range.StopLine}]`
  89. : `[${range.StartLine}, ???]`;
  90. log('Airbag Handling ' + range.Name + ': ' + msg);
  91. });
  92. };
  93.  
  94. // Converts a global line number to a local one
  95. const ConvertGlobalLineToLocal = (gline) => {
  96. let prevRange = {
  97. Name: 'PREV_RANGE',
  98. StartLine: -1,
  99. StopLine: -1
  100. };
  101. for(var i = 0; i < scriptRanges.length; i++) {
  102. let curRange = scriptRanges[i];
  103. // Checking equals in both directions because of minification
  104. if (gline >= prevRange.StartLine && gline <= curRange.StartLine) {
  105. if (prevRange.StartLine === prevRange.StopLine) {
  106. log(`Airbag has detected a minified file for ${prevRange.Name}. Line estimation may be inaccurate.`);
  107. }
  108. let localLine = gline - prevRange.StartLine + 1;
  109. // Check to see if there was an unmarked script in between
  110. // If an author didn't flag the end of the file, blame them
  111. if (prevRange.StopLine === -1 || prevRange.StopLine >= gline) {
  112. //log(`Global[${gline}] => ${prevRange.Name}[${localLine}]`);
  113. return {
  114. Name: prevRange.Name,
  115. Line: localLine
  116. };
  117. } else {
  118. //log(`Global[${gline}] => UNKNOWN SCRIPT between ${prevRange.Name} and ${curRange.Name} at 'local' line ${localLine}`);
  119. return {
  120. Name: prevRange.Name,
  121. Line: localLine
  122. };
  123. }
  124. }
  125. prevRange = curRange;
  126. }
  127. return {
  128. Name: 'Unknown Script',
  129. Line: -1
  130. };
  131. };
  132.  
  133. // ===========================================================================
  134. // Function shadows
  135. // ===========================================================================
  136. const airOn = on;
  137. const airSetTimeout = setTimeout;
  138. const airSetInterval = setInterval;
  139. const airClearTimeout = clearTimeout;
  140. const airClearInterval = clearInterval;
  141.  
  142. // On Registrations
  143. let onRegistrations = [];// Erased after Airbag deployed
  144. let onRegisteredTypes = [];// NOT erased after Airbag deployed (if it was, we'd get double-registrations)
  145. // Builds a handler for the specified type
  146. const getAirbagOnHandler = (eventType) => {
  147. // The master handler that wraps the registrations of the scripts
  148. const airbagOnHandler = (...handlerArgs) => {
  149. let type = eventType;
  150. try{
  151. // Iterate over the registrations. If they match the type,
  152. // execute them.
  153. onRegistrations.forEach((registration) => {
  154. if (registration.Type === type) {
  155. registration.UserHandler.apply(null, Array.prototype.slice.call(handlerArgs));
  156. }
  157. });
  158. } catch (e) {
  159. handleCrash(e);
  160. }
  161. };
  162. return airbagOnHandler;
  163. }
  164.  
  165. // Delay registrations
  166. let airDelays = [];
  167. let airIntervals = [];
  168. // Attempt to perform the delayed function
  169. const airDelayHandler = (func, params) => {
  170. if (!codebaseRunning) return;
  171. try {
  172. func.apply(null, Array.prototype.slice.call(params));
  173. } catch(e) {
  174. handleCrash(e);
  175. }
  176. };
  177.  
  178. // Airbag codebase reboot command handler
  179. on('chat:message', (msg) => {
  180. if (msg.type !== 'api') return;
  181. if (msg.content !== '!airbag') return;
  182. codebase();
  183. });
  184.  
  185. // Halt codebase()'s operations, cancel async tasks, and alert user
  186. const handleCrash = (e) => {
  187. log('Handling Crash...');
  188. codebaseRunning = false;
  189.  
  190. // Kill all internal on() registrations
  191. onRegistrations = [];
  192.  
  193. // Cancel all delayed operations
  194. airDelays.forEach((delayRef) => {
  195. airClearTimeout(delayRef);
  196. });
  197. airDelays = [];
  198.  
  199. // Flush gc
  200. globalconfig = {};
  201.  
  202. let globalLine = GetScriptLine(e, false);
  203. let src = ConvertGlobalLineToLocal(globalLine);
  204.  
  205. let stackLines = _.map(e.stack.split(/\n|apiscript\.js/gu), v => {
  206. if (v.startsWith(":")) {
  207. const globalLineNum = parseInt(v.match(/^:(\d+):/u)[1]),
  208. localLine = ConvertGlobalLineToLocal(globalLineNum)
  209. return v.replace(/^:\d+:/gu, `@@${localLine.Name}:${localLine.Line}:`).trim()
  210. }
  211. return v.trim()
  212. })
  213.  
  214. const rawErrorMsg = _.compact([
  215. "[AIRBAG",
  216. src.Line > 0 ? `at ${src.Name}:${src.Line}]` : "]",
  217. `▌${e.message}▐`,
  218. `STACK: ${stackLines.join(" ").replace(/\s@@/gu, " ").replace(/[^\s\(]+underscore\.js:/gu, "_:").replace(/\(\s+/gu, "(")}`
  219. ]).join(" ").replace(/\n/gu, "")
  220.  
  221. const styledErrorMsg = HTML.ChatBox(_.compact([
  222. HTML.TitleBox(`AIRBAG DEPLOYED${src.Line > 0 ? ` at ${src.Name}: ${src.Line}` : ""}`),
  223. HTML.MessageBox(e.message),
  224. HTML.StackBox(stackLines.join("\n")).
  225. replace(/\n/gu, "<br>").
  226. replace(/<br>@@/gu, "").
  227. replace(/\bat\b/gu, "<i><span style=\"margin-left: 20px; color: rgb(150, 150, 150); display: inline-block; width: auto; \">at ... </span></i>").
  228. replace(/[^\s\(]+underscore\.js:(\d*?):/gu, "<span style=\"color: rgb(0,0,255);\">_</span>@@<span style=\"color: rgb(0,0,255);\">$1</span>@@").
  229. replace(/[^\s\(]+firebase-node\.js:(\d*?):/gu, "<span style=\"color: rgb(0,195,0);\">firebase</span>@@<span style=\"color: rgb(0,195,0);\">$1</span>@@").
  230. replace(/(\(?)([^:\.\s]*?):(\d*?):/gu, "$1<b><span style=\"color: rgb(255,0,0)\">$2</span>:<span style=\"color: rgb(255,0,0)\">$3</span></b>:").
  231. replace(/@@/gu, ":"),
  232. HTML.TitleBox("[ REBOOT API ](!airbag)")
  233. ]).join(""))
  234.  
  235. airLog(rawErrorMsg, styledErrorMsg);
  236. }
  237.  
  238. // ===========================================================================
  239. // Code Base
  240. // ===========================================================================
  241. let codebase = () => {
  242. if (codebaseRunning) return;
  243. codebaseRunning = true;
  244. airLog(rezMsg);
  245.  
  246. // ===========================================================================
  247. // Function shadows
  248. // ===========================================================================
  249.  
  250. // ===========================================================================
  251. // on(type, handler)
  252. // DESC: Register in Airbag's internal list that the script wanted to subscribe
  253. // to the event in question.
  254. const on = (type, userHandler) => {
  255. // Add a new registration
  256. let registration = {
  257. Type: type,
  258. UserHandler: userHandler
  259. };
  260. onRegistrations.push(registration);
  261.  
  262. // Airbag registers for the events on behalf of the script calling on() if
  263. // it hasn't already registered to this type.
  264. if (!onRegisteredTypes[type]) {
  265. log('Airbag is Registering on ' + type + ' for the first time.');
  266. onRegisteredTypes[type] = true;
  267. let handler = getAirbagOnHandler(type);
  268. airOn(type, handler);
  269. }
  270. };
  271.  
  272. // ===========================================================================
  273. // setTimeout(func, delay, ...params)
  274. // DESC: Schedule Airbag's timeout handler
  275. const setTimeout = (func, delay, ...params) => {
  276. let delayRef = airSetTimeout(airDelayHandler, delay, func, params);
  277. airDelays.push(delayRef);
  278. return delayRef;
  279. };
  280.  
  281. // ===========================================================================
  282. // setTimeout(func, delay, ...params)
  283. // DESC: remove from Airbag's memory, then clear the schedule
  284. const clearTimeout = (delayRef) => {
  285. airDelays = airDelays.filter(item => item !== delayRef);
  286. airClearTimeout(delayRef);
  287. };
  288.  
  289. try {
  290. MarkStop('AirbagStart');
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement