Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

361 строка
8.5 KiB

  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. }