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.
 
 
 
 
 
 

258 line
5.9 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 subscriber = redis.createClient(12311);
  8. var request = require('superagent')
  9. var default_site;
  10. if(fs.existsSync('sites/currentsite.txt')) {
  11. default_site = fs.readFileSync('sites/currentsite.txt').toString().trim();
  12. }
  13. app.get('/', function(req, res){
  14. res.sendfile('index.html');
  15. });
  16. io.on('connection', function(socket){
  17. if (get_hostname(socket.request.headers.host) != get_hostname(socket.request.headers.origin)) {
  18. return;
  19. }
  20. // console.log("connection!");
  21. var sid = cookie.parse(socket.request.headers.cookie).sid
  22. if(!sid) {
  23. return;
  24. }
  25. socket.user = cookie.parse(socket.request.headers.cookie).user_id;
  26. // console.log("firing get_user_info");
  27. request.get(get_url(socket, '/api/method/frappe.async.get_user_info'))
  28. .type('form')
  29. .send({
  30. sid: sid
  31. })
  32. .end(function(err, res) {
  33. if(err) {
  34. console.log(err);
  35. return;
  36. }
  37. if(res.status == 200) {
  38. var room = get_user_room(socket, res.body.message.user);
  39. // console.log('joining', room);
  40. socket.join(room);
  41. socket.join(get_site_room(socket));
  42. }
  43. });
  44. socket.on('task_subscribe', function(task_id) {
  45. var room = 'task:' + task_id;
  46. socket.join(room);
  47. });
  48. socket.on('progress_subscribe', function(task_id) {
  49. var room = 'task_progress:' + task_id;
  50. socket.join(room);
  51. send_existing_lines(task_id, socket);
  52. });
  53. socket.on('doc_subscribe', function(doctype, docname) {
  54. // console.log('trying to subscribe', doctype, docname)
  55. can_subscribe_doc({
  56. socket: socket,
  57. sid: sid,
  58. doctype: doctype,
  59. docname: docname,
  60. callback: function(err, res) {
  61. var room = get_doc_room(socket, doctype, docname);
  62. // console.log('joining', room)
  63. socket.join(room);
  64. }
  65. });
  66. });
  67. socket.on('doc_unsubscribe', function(doctype, docname) {
  68. var room = get_doc_room(socket, doctype, docname);
  69. socket.leave(room);
  70. });
  71. socket.on('task_unsubscribe', function(task_id) {
  72. var room = 'task:' + task_id;
  73. socket.leave(room);
  74. });
  75. socket.on('doc_open', function(doctype, docname) {
  76. // show who is currently viewing the form
  77. can_subscribe_doc({
  78. socket: socket,
  79. sid: sid,
  80. doctype: doctype,
  81. docname: docname,
  82. callback: function(err, res) {
  83. var room = get_open_doc_room(socket, doctype, docname);
  84. // console.log('joining', room)
  85. socket.join(room);
  86. send_viewers({
  87. socket: socket,
  88. doctype: doctype,
  89. docname: docname,
  90. });
  91. }
  92. });
  93. });
  94. socket.on('doc_close', function(doctype, docname) {
  95. // remove this user from the list of 'who is currently viewing the form'
  96. var room = get_open_doc_room(socket, doctype, docname);
  97. socket.leave(room);
  98. send_viewers({
  99. socket: socket,
  100. doctype: doctype,
  101. docname: docname,
  102. });
  103. });
  104. // socket.on('disconnect', function (arguments) {
  105. // console.log("user disconnected", arguments);
  106. // });
  107. });
  108. function send_existing_lines(task_id, socket) {
  109. subscriber.hgetall('task_log:' + task_id, function(err, lines) {
  110. socket.emit('task_progress', {
  111. "task_id": task_id,
  112. "message": {
  113. "lines": lines
  114. }
  115. })
  116. })
  117. }
  118. subscriber.on("message", function(channel, message) {
  119. message = JSON.parse(message);
  120. io.to(message.room).emit(message.event, message.message);
  121. // console.log(message.room, message.event, message.message)
  122. });
  123. subscriber.subscribe("events");
  124. http.listen(3000, function(){
  125. console.log('listening on *:3000');
  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 (default_site) {
  141. return 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. }