js/Thread.alt.js

  1. /**=====LICENSE STATEMENT START=====
  2. Translator++
  3. CAT (Computer-Assisted Translation) tools and framework to create quality
  4. translations and localizations efficiently.
  5. Copyright (C) 2018 Dreamsavior<dreamsavior@gmail.com>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. =====LICENSE STATEMENT END=====*/
  17. // Alternative thread. using HTTP server instead
  18. const { resolve } = require('path');
  19. class WSv {
  20. constructor(options) {
  21. this.options = options || {};
  22. }
  23. }
  24. WSv.actions = {
  25. echo: async function(data, req, res) {
  26. console.log("response back:", data.post.msg);
  27. res.write(data.post.msg);
  28. },
  29. run: async function(data, req, res) {
  30. try {
  31. if (data.post.type == "function") data.post.msg = `return (${data.post.msg})()`
  32. let AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
  33. var thisVal = new AsyncFunction(data.post.msg);
  34. var result = await thisVal() || ""
  35. res.write(result);
  36. } catch (e) {
  37. res.write("Error executing "+data.post.msg+"\n"+e.toString());
  38. }
  39. },
  40. close: async function(data, req, res) {
  41. window.close(true);
  42. }
  43. }
  44. WSv.prototype.action = async function(action, data, req, res) {
  45. if (!ThreadHost.actions[action]) return;
  46. return await ThreadHost.actions[action].call(this, data, req, res)
  47. }
  48. WSv.prototype.closeServer = function() {
  49. this.server.close();
  50. }
  51. WSv.prototype.startServer = function() {
  52. var http = require('http');
  53. var url = require('url');
  54. var querystring = require('querystring');
  55. var hostname = '127.0.0.1';
  56. //this.port = 29942;
  57. var collectRequestData = async function(request, callback) {
  58. callback = callback || async function() {}
  59. return new Promise(async (resolve, reject) => {
  60. const FORM_URLENCODED = 'application/x-www-form-urlencoded';
  61. if(request.headers['content-type'].includes(FORM_URLENCODED)) {
  62. let body = '';
  63. request.on('data', chunk => {
  64. body += chunk.toString();
  65. });
  66. request.on('end', async () => {
  67. await callback(querystring.parse(body));
  68. resolve(querystring.parse(body));
  69. });
  70. }
  71. else {
  72. await callback(null);
  73. resolve(null);
  74. }
  75. })
  76. }
  77. this.server = http.createServer(async (req, res) => {
  78. console.log("Incoming connection:");
  79. console.log("Request:", req);
  80. console.log("response:", res);
  81. var query;
  82. var postData;
  83. if (req.url.includes("?")) {
  84. var queryStr = req.url.substring(req.url.indexOf("?")+1);
  85. query = querystring.parse(queryStr);
  86. console.log("query", query);
  87. // close server if success
  88. //this.server.close();
  89. }
  90. if (req.method === 'POST') {
  91. postData = await collectRequestData(req);
  92. console.log("Post data:", postData);
  93. }
  94. res.statusCode = 200;
  95. res.setHeader("Access-Control-Allow-Origin", "*");
  96. res.setHeader('Content-Type', 'text/plain');
  97. if (query.action) {
  98. await this.action(query.action, {post:postData, get:query}, req, res);
  99. }
  100. // end the response
  101. res.end();
  102. });
  103. this.server.listen(this.port, hostname, () => {
  104. this.setStatus(`Server running at http://${hostname}:${this.port}/`);
  105. });
  106. }
  107. WSv.prototype.setStatus = function(str) {
  108. $('[data-window="thread"] .status').html(str);
  109. console.log(str);
  110. }
  111. /**
  112. * @class
  113. */
  114. class Thread {
  115. constructor(options) {
  116. this.options = options || {};
  117. this.port = this.options.port || common.rand(30000, 40000);
  118. while (Thread.list[this.port]) {
  119. this.port = common.rand(30000, 40000);
  120. }
  121. Thread.list[this.port] = this;
  122. }
  123. }
  124. Thread.list = [];
  125. Thread.close = function() {
  126. delete Thread.list[this.port];
  127. }
  128. Thread.prototype.setReadyState = function(state) {
  129. this.isReady = state;
  130. }
  131. Thread.prototype.getReadyState = function(state) {
  132. this.isReady = state;
  133. }
  134. Thread.prototype.openThreadWindow = async function() {
  135. return new Promise((resolve, reject) => {
  136. nw.Window.open("www/thread.html?port="+this.port, {new_instance:true}, (win) => {
  137. console.log(arguments);
  138. resolve();
  139. });
  140. })
  141. }
  142. Thread.prototype.send = async function(command, msg, options) {
  143. options = options || {};
  144. options.msg = msg || options.msg;
  145. options.type = typeof options.msg;
  146. if (options.type == "function") {
  147. options.msg = options.msg.toString();
  148. }
  149. this.setReadyState(false);
  150. return new Promise((resolve, reject) => {
  151. $.post(`http://127.0.0.1:${this.port}/?action=${command}`, options, function(data) {
  152. resolve(data);
  153. })
  154. .fail(function() {
  155. reject();
  156. })
  157. .always(()=> {
  158. this.setReadyState(true);
  159. })
  160. })
  161. }
  162. Thread.prototype.init = async function() {
  163. }
  164. /**
  165. * Handle socket as a server
  166. * @class
  167. */
  168. var ThreadServer = function() {
  169. this.threadList = Thread.list;
  170. }
  171. ThreadServer.prototype.distributeTask = async function(tasks=[]) {
  172. if (Array.isArray(tasks) == false) tasks = [tasks]
  173. }
  174. /**
  175. * Add task to the iddle process.
  176. * If none is iddle, will wait until there is iddle process
  177. */
  178. ThreadServer.prototype.addTask = async function() {
  179. }
  180. ThreadServer.actions = {
  181. echo: async function(data, req, res) {
  182. console.log("response back:", data.post.msg);
  183. res.write(data.post.msg);
  184. }
  185. }
  186. ThreadServer.prototype.action = async function(action, data, req, res) {
  187. if (!ThreadServer.actions[action]) return;
  188. return await ThreadServer.actions[action].call(this, data, req, res)
  189. }
  190. ThreadServer.prototype.startServer = function() {
  191. var http = require('http');
  192. var url = require('url');
  193. var querystring = require('querystring');
  194. var hostname = '127.0.0.1';
  195. this.port = 41014;
  196. var collectRequestData = async function(request, callback) {
  197. callback = callback || async function() {}
  198. return new Promise(async (resolve, reject) => {
  199. const FORM_URLENCODED = 'application/x-www-form-urlencoded';
  200. if(request.headers['content-type'].includes(FORM_URLENCODED)) {
  201. let body = '';
  202. request.on('data', chunk => {
  203. body += chunk.toString();
  204. });
  205. request.on('end', async () => {
  206. await callback(querystring.parse(body));
  207. resolve(querystring.parse(body));
  208. });
  209. }
  210. else {
  211. await callback(null);
  212. resolve(null);
  213. }
  214. })
  215. }
  216. this.server = http.createServer(async (req, res) => {
  217. console.log("Incoming connection:");
  218. console.log("Request:", req);
  219. console.log("response:", res);
  220. var query;
  221. var postData;
  222. if (req.url.includes("?")) {
  223. var queryStr = req.url.substring(req.url.indexOf("?")+1);
  224. query = querystring.parse(queryStr);
  225. console.log("query", query);
  226. // close server if success
  227. //this.server.close();
  228. }
  229. if (req.method === 'POST') {
  230. postData = await collectRequestData(req);
  231. console.log("Post data:", postData);
  232. }
  233. res.statusCode = 200;
  234. res.setHeader("Access-Control-Allow-Origin", "*");
  235. res.setHeader('Content-Type', 'text/plain');
  236. if (query.action) {
  237. await this.action(query.action, {post:postData, get:query}, req, res);
  238. }
  239. // end the response
  240. res.end();
  241. });
  242. this.server.listen(this.port, hostname, () => {
  243. this.setStatus(`Server running at http://${hostname}:${this.port}/`);
  244. });
  245. }
  246. /**
  247. * Handle socket as a client
  248. * @class
  249. */
  250. class ThreadHost extends WSv {
  251. constructor(options) {
  252. super(options);
  253. this.init();
  254. }
  255. }
  256. ThreadHost.prototype.init = function() {
  257. this.query = window.location.search.substr(1)
  258. var searchparam = new URLSearchParams(this.query);
  259. this.port = searchparam.get("port")
  260. }
  261. $(document).ready(function() {
  262. if ($('body').is('[data-window="thread"]') == false) return;
  263. window.threadHost = new ThreadHost();
  264. threadHost.startServer();
  265. })