You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 9 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 9 години
преди 10 години
преди 9 години
преди 10 години
преди 9 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 9 години
преди 7 години
преди 10 години
преди 10 години
преди 9 години
преди 9 години
преди 10 години
преди 9 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 9 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 8 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. var app = require('express')();
  2. var http = require('http').Server(app);
  3. var io = require('socket.io')(http);
  4. var cookie = require('cookie')
  5. var fs = require('fs');
  6. var path = require('path');
  7. var redis = require("redis");
  8. var request = require('superagent');
  9. var conf = get_conf();
  10. var flags = {};
  11. var files_struct = {
  12. name: null,
  13. type: null,
  14. size: 0,
  15. data: [],
  16. slice: 0,
  17. site_name: null,
  18. is_private: 0
  19. };
  20. var subscriber = redis.createClient(conf.redis_socketio || conf.redis_async_broker_port);
  21. // serve socketio
  22. http.listen(conf.socketio_port, function() {
  23. console.log('listening on *:', conf.socketio_port); //eslint-disable-line
  24. });
  25. // test route
  26. app.get('/', function(req, res) {
  27. res.sendfile('index.html');
  28. });
  29. // on socket connection
  30. io.on('connection', function(socket) {
  31. if (get_hostname(socket.request.headers.host) != get_hostname(socket.request.headers.origin)) {
  32. return;
  33. }
  34. // console.log("connection!");
  35. var sid = cookie.parse(socket.request.headers.cookie).sid
  36. if(!sid) {
  37. return;
  38. }
  39. if(flags[sid]) {
  40. // throttle this function
  41. return;
  42. }
  43. flags[sid] = sid;
  44. setTimeout(function() { flags[sid] = null; }, 10000);
  45. socket.user = cookie.parse(socket.request.headers.cookie).user_id;
  46. socket.files = {};
  47. // console.log("firing get_user_info");
  48. request.get(get_url(socket, '/api/method/frappe.async.get_user_info'))
  49. .type('form')
  50. .query({
  51. sid: sid
  52. })
  53. .end(function(err, res) {
  54. if(err) {
  55. console.log(err);
  56. return;
  57. }
  58. if(res.status == 200) {
  59. var room = get_user_room(socket, res.body.message.user);
  60. // console.log('joining', room);
  61. socket.join(room);
  62. socket.join(get_site_room(socket));
  63. }
  64. });
  65. socket.on('disconnect', function() {
  66. delete socket.files;
  67. })
  68. socket.on('task_subscribe', function(task_id) {
  69. var room = get_task_room(socket, task_id);
  70. socket.join(room);
  71. });
  72. socket.on('task_unsubscribe', function(task_id) {
  73. var room = get_task_room(socket, task_id);
  74. socket.leave(room);
  75. });
  76. socket.on('progress_subscribe', function(task_id) {
  77. var room = get_task_room(socket, task_id);
  78. socket.join(room);
  79. send_existing_lines(task_id, socket);
  80. });
  81. socket.on('doc_subscribe', function(doctype, docname) {
  82. // console.log('trying to subscribe', doctype, docname)
  83. can_subscribe_doc({
  84. socket: socket,
  85. sid: sid,
  86. doctype: doctype,
  87. docname: docname,
  88. callback: function(err, res) {
  89. var room = get_doc_room(socket, doctype, docname);
  90. // console.log('joining', room)
  91. socket.join(room);
  92. }
  93. });
  94. });
  95. socket.on('doc_unsubscribe', function(doctype, docname) {
  96. var room = get_doc_room(socket, doctype, docname);
  97. socket.leave(room);
  98. });
  99. socket.on('task_unsubscribe', function(task_id) {
  100. var room = 'task:' + task_id;
  101. socket.leave(room);
  102. });
  103. socket.on('doc_open', function(doctype, docname) {
  104. // show who is currently viewing the form
  105. can_subscribe_doc({
  106. socket: socket,
  107. sid: sid,
  108. doctype: doctype,
  109. docname: docname,
  110. callback: function(err, res) {
  111. var room = get_open_doc_room(socket, doctype, docname);
  112. // console.log('joining', room)
  113. socket.join(room);
  114. send_viewers({
  115. socket: socket,
  116. doctype: doctype,
  117. docname: docname,
  118. });
  119. }
  120. });
  121. });
  122. socket.on('doc_close', function(doctype, docname) {
  123. // remove this user from the list of 'who is currently viewing the form'
  124. var room = get_open_doc_room(socket, doctype, docname);
  125. socket.leave(room);
  126. send_viewers({
  127. socket: socket,
  128. doctype: doctype,
  129. docname: docname,
  130. });
  131. });
  132. socket.on('upload-accept-slice', (data) => {
  133. try {
  134. if (!socket.files[data.name]) {
  135. socket.files[data.name] = Object.assign({}, files_struct, data);
  136. socket.files[data.name].data = [];
  137. }
  138. //convert the ArrayBuffer to Buffer
  139. data.data = new Buffer(new Uint8Array(data.data));
  140. //save the data
  141. socket.files[data.name].data.push(data.data);
  142. socket.files[data.name].slice++;
  143. if (socket.files[data.name].slice * 100000 >= socket.files[data.name].size) {
  144. // do something with the data
  145. var fileBuffer = Buffer.concat(socket.files[data.name].data);
  146. const file_url = path.join((socket.files[data.name].is_private ? 'private' : 'public'),
  147. 'files', data.name);
  148. const file_path = path.join('sites', get_site_name(socket), file_url);
  149. fs.writeFile(file_path, fileBuffer, (err) => {
  150. delete socket.files[data.name];
  151. if (err) return socket.emit('upload error');
  152. socket.emit('upload-end', {
  153. file_url: '/' + file_url
  154. });
  155. });
  156. } else {
  157. socket.emit('upload-request-slice', {
  158. currentSlice: socket.files[data.name].slice
  159. });
  160. }
  161. } catch (e) {
  162. console.log(e);
  163. socket.emit('upload-error', {
  164. error: e.message
  165. });
  166. }
  167. });
  168. });
  169. subscriber.on("message", function(channel, message) {
  170. message = JSON.parse(message);
  171. io.to(message.room).emit(message.event, message.message);
  172. // console.log(message.room, message.event, message.message)
  173. });
  174. subscriber.subscribe("events");
  175. function send_existing_lines(task_id, socket) {
  176. var room = get_task_room(socket, task_id);
  177. subscriber.hgetall('task_log:' + task_id, function(err, lines) {
  178. io.to(room).emit('task_progress', {
  179. "task_id": task_id,
  180. "message": {
  181. "lines": lines
  182. }
  183. });
  184. });
  185. }
  186. function get_doc_room(socket, doctype, docname) {
  187. return get_site_name(socket) + ':doc:'+ doctype + '/' + docname;
  188. }
  189. function get_open_doc_room(socket, doctype, docname) {
  190. return get_site_name(socket) + ':open_doc:'+ doctype + '/' + docname;
  191. }
  192. function get_user_room(socket, user) {
  193. return get_site_name(socket) + ':user:' + user;
  194. }
  195. function get_site_room(socket) {
  196. return get_site_name(socket) + ':all';
  197. }
  198. function get_task_room(socket, task_id) {
  199. return get_site_name(socket) + ':task_progress:' + task_id;
  200. }
  201. function get_site_name(socket) {
  202. if (socket.request.headers['x-frappe-site-name']) {
  203. return get_hostname(socket.request.headers['x-frappe-site-name']);
  204. }
  205. else if (['localhost', '127.0.0.1'].indexOf(socket.request.headers.host) !== -1
  206. && conf.default_site) {
  207. // from currentsite.txt since host is localhost
  208. return conf.default_site;
  209. }
  210. else if (socket.request.headers.origin) {
  211. return get_hostname(socket.request.headers.origin);
  212. }
  213. else {
  214. return get_hostname(socket.request.headers.host);
  215. }
  216. }
  217. function get_hostname(url) {
  218. if (!url) return undefined;
  219. if (url.indexOf("://") > -1) {
  220. url = url.split('/')[2];
  221. }
  222. return ( url.match(/:/g) ) ? url.slice( 0, url.indexOf(":") ) : url
  223. }
  224. function get_url(socket, path) {
  225. if (!path) {
  226. path = '';
  227. }
  228. return socket.request.headers.origin + path;
  229. }
  230. function can_subscribe_doc(args) {
  231. if(!args) return;
  232. if(!args.doctype || !args.docname) return;
  233. request.get(get_url(args.socket, '/api/method/frappe.async.can_subscribe_doc'))
  234. .type('form')
  235. .query({
  236. sid: args.sid,
  237. doctype: args.doctype,
  238. docname: args.docname
  239. })
  240. .end(function(err, res) {
  241. if (!res) {
  242. console.log("No response for doc_subscribe");
  243. } else if (res.status == 403) {
  244. return;
  245. } else if (err) {
  246. console.log(err);
  247. } else if (res.status == 200) {
  248. args.callback(err, res);
  249. } else {
  250. console.log("Something went wrong", err, res);
  251. }
  252. });
  253. }
  254. function send_viewers(args) {
  255. // send to doc room, 'users currently viewing this document'
  256. if (!(args && args.doctype && args.docname)) {
  257. return;
  258. }
  259. // open doc room
  260. var room = get_open_doc_room(args.socket, args.doctype, args.docname);
  261. var socketio_room = io.sockets.adapter.rooms[room] || {};
  262. // for compatibility with both v1.3.7 and 1.4.4
  263. var clients_dict = ("sockets" in socketio_room) ? socketio_room.sockets : socketio_room;
  264. // socket ids connected to this room
  265. var clients = Object.keys(clients_dict || {});
  266. var viewers = [];
  267. for (var i in io.sockets.sockets) {
  268. var s = io.sockets.sockets[i];
  269. if (clients.indexOf(s.id)!==-1) {
  270. // this socket is connected to the room
  271. viewers.push(s.user);
  272. }
  273. }
  274. // notify
  275. io.to(room).emit("doc_viewers", {
  276. doctype: args.doctype,
  277. docname: args.docname,
  278. viewers: viewers
  279. });
  280. }
  281. function get_conf() {
  282. // defaults
  283. var conf = {
  284. redis_async_broker_port: 12311,
  285. socketio_port: 3000
  286. };
  287. var read_config = function(path) {
  288. if(fs.existsSync(path)){
  289. var bench_config = JSON.parse(fs.readFileSync(path));
  290. for (var key in bench_config) {
  291. if (bench_config[key]) {
  292. conf[key] = bench_config[key];
  293. }
  294. }
  295. }
  296. }
  297. // get ports from bench/config.json
  298. read_config('config.json');
  299. read_config('sites/common_site_config.json');
  300. // detect current site
  301. if(fs.existsSync('sites/currentsite.txt')) {
  302. conf.default_site = fs.readFileSync('sites/currentsite.txt').toString().trim();
  303. }
  304. return conf;
  305. }