您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

278 行
6.4 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 redis = require("redis");
  7. var request = require('superagent');
  8. var conf = get_conf();
  9. var subscriber = redis.createClient(conf.redis_async_broker_port);
  10. // serve socketio
  11. http.listen(conf.socketio_port, function(){
  12. console.log('listening on *:', conf.socketio_port);
  13. });
  14. // test route
  15. app.get('/', function(req, res){
  16. res.sendfile('index.html');
  17. });
  18. // on socket connection
  19. io.on('connection', function(socket){
  20. if (get_hostname(socket.request.headers.host) != get_hostname(socket.request.headers.origin)) {
  21. return;
  22. }
  23. // console.log("connection!");
  24. var sid = cookie.parse(socket.request.headers.cookie).sid
  25. if(!sid) {
  26. return;
  27. }
  28. socket.user = cookie.parse(socket.request.headers.cookie).user_id;
  29. // console.log("firing get_user_info");
  30. request.get(get_url(socket, '/api/method/frappe.async.get_user_info'))
  31. .type('form')
  32. .send({
  33. sid: sid
  34. })
  35. .end(function(err, res) {
  36. if(err) {
  37. console.log(err);
  38. return;
  39. }
  40. if(res.status == 200) {
  41. var room = get_user_room(socket, res.body.message.user);
  42. // console.log('joining', room);
  43. socket.join(room);
  44. socket.join(get_site_room(socket));
  45. }
  46. });
  47. socket.on('task_subscribe', function(task_id) {
  48. var room = 'task:' + task_id;
  49. socket.join(room);
  50. });
  51. socket.on('progress_subscribe', function(task_id) {
  52. var room = 'task_progress:' + task_id;
  53. socket.join(room);
  54. send_existing_lines(task_id, socket);
  55. });
  56. socket.on('doc_subscribe', function(doctype, docname) {
  57. // console.log('trying to subscribe', doctype, docname)
  58. can_subscribe_doc({
  59. socket: socket,
  60. sid: sid,
  61. doctype: doctype,
  62. docname: docname,
  63. callback: function(err, res) {
  64. var room = get_doc_room(socket, doctype, docname);
  65. // console.log('joining', room)
  66. socket.join(room);
  67. }
  68. });
  69. });
  70. socket.on('doc_unsubscribe', function(doctype, docname) {
  71. var room = get_doc_room(socket, doctype, docname);
  72. socket.leave(room);
  73. });
  74. socket.on('task_unsubscribe', function(task_id) {
  75. var room = 'task:' + task_id;
  76. socket.leave(room);
  77. });
  78. socket.on('doc_open', function(doctype, docname) {
  79. // show who is currently viewing the form
  80. can_subscribe_doc({
  81. socket: socket,
  82. sid: sid,
  83. doctype: doctype,
  84. docname: docname,
  85. callback: function(err, res) {
  86. var room = get_open_doc_room(socket, doctype, docname);
  87. // console.log('joining', room)
  88. socket.join(room);
  89. send_viewers({
  90. socket: socket,
  91. doctype: doctype,
  92. docname: docname,
  93. });
  94. }
  95. });
  96. });
  97. socket.on('doc_close', function(doctype, docname) {
  98. // remove this user from the list of 'who is currently viewing the form'
  99. var room = get_open_doc_room(socket, doctype, docname);
  100. socket.leave(room);
  101. send_viewers({
  102. socket: socket,
  103. doctype: doctype,
  104. docname: docname,
  105. });
  106. });
  107. // socket.on('disconnect', function (arguments) {
  108. // console.log("user disconnected", arguments);
  109. // });
  110. });
  111. subscriber.on("message", function(channel, message) {
  112. message = JSON.parse(message);
  113. io.to(message.room).emit(message.event, message.message);
  114. // console.log(message.room, message.event, message.message)
  115. });
  116. subscriber.subscribe("events");
  117. function send_existing_lines(task_id, socket) {
  118. subscriber.hgetall('task_log:' + task_id, function(err, lines) {
  119. socket.emit('task_progress', {
  120. "task_id": task_id,
  121. "message": {
  122. "lines": lines
  123. }
  124. })
  125. })
  126. }
  127. function get_doc_room(socket, doctype, docname) {
  128. return get_site_name(socket) + ':doc:'+ doctype + '/' + docname;
  129. }
  130. function get_open_doc_room(socket, doctype, docname) {
  131. return get_site_name(socket) + ':open_doc:'+ doctype + '/' + docname;
  132. }
  133. function get_user_room(socket, user) {
  134. return get_site_name(socket) + ':user:' + user;
  135. }
  136. function get_site_room(socket) {
  137. return get_site_name(socket) + ':all';
  138. }
  139. function get_site_name(socket) {
  140. if (conf.default_site) {
  141. return conf.default_site;
  142. }
  143. else if (socket.request.headers['x-frappe-site-name']) {
  144. return get_hostname(socket.request.headers['x-frappe-site-name']);
  145. }
  146. else if (socket.request.headers.origin) {
  147. return get_hostname(socket.request.headers.origin);
  148. }
  149. else {
  150. return get_hostname(socket.request.headers.host);
  151. }
  152. }
  153. function get_hostname(url) {
  154. if (!url) return undefined;
  155. if (url.indexOf("://") > -1) {
  156. url = url.split('/')[2];
  157. }
  158. return ( url.match(/:/g) ) ? url.slice( 0, url.indexOf(":") ) : url
  159. }
  160. function get_url(socket, path) {
  161. if (!path) {
  162. path = '';
  163. }
  164. return socket.request.headers.origin + path;
  165. }
  166. function can_subscribe_doc(args) {
  167. request.get(get_url(args.socket, '/api/method/frappe.async.can_subscribe_doc'))
  168. .type('form')
  169. .send({
  170. sid: args.sid,
  171. doctype: args.doctype,
  172. docname: args.docname
  173. })
  174. .end(function(err, res) {
  175. if (!res) {
  176. console.log("No response for doc_subscribe");
  177. } else if (res.status == 403) {
  178. return;
  179. } else if (err) {
  180. console.log(err);
  181. } else if (res.status == 200) {
  182. args.callback(err, res);
  183. } else {
  184. console.log("Something went wrong", err, res);
  185. }
  186. });
  187. }
  188. function send_viewers(args) {
  189. // send to doc room, 'users currently viewing this document'
  190. if (!(args && args.doctype && args.docname)) {
  191. return;
  192. }
  193. // open doc room
  194. var room = get_open_doc_room(args.socket, args.doctype, args.docname);
  195. var socketio_room = io.sockets.adapter.rooms[room] || {};
  196. // for compatibility with both v1.3.7 and 1.4.4
  197. var clients_dict = ("sockets" in socketio_room) ? socketio_room.sockets : socketio_room;
  198. // socket ids connected to this room
  199. var clients = Object.keys(clients_dict || {});
  200. var viewers = [];
  201. for (var i in io.sockets.sockets) {
  202. var s = io.sockets.sockets[i];
  203. if (clients.indexOf(s.id)!==-1) {
  204. // this socket is connected to the room
  205. viewers.push(s.user);
  206. }
  207. }
  208. // notify
  209. io.to(room).emit("doc_viewers", {
  210. doctype: args.doctype,
  211. docname: args.docname,
  212. viewers: viewers
  213. });
  214. }
  215. function get_conf() {
  216. // defaults
  217. var conf = {
  218. redis_async_broker_port: 12311,
  219. socketio_port: 3000
  220. };
  221. // get ports from bench/config.json
  222. if(fs.existsSync('config.json')){
  223. var bench_config = JSON.parse(fs.readFileSync('config.json'));
  224. for (var key in conf) {
  225. if (bench_config[key]) {
  226. conf[key] = bench_config[key];
  227. }
  228. }
  229. }
  230. // detect current site
  231. if(fs.existsSync('sites/currentsite.txt')) {
  232. conf.default_site = fs.readFileSync('sites/currentsite.txt').toString().trim();
  233. }
  234. return conf;
  235. }