Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

296 linhas
7.0 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_socketio || 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. .query({
  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 = get_task_room(socket, task_id);
  49. socket.join(room);
  50. });
  51. socket.on('task_unsubscribe', function(task_id) {
  52. var room = get_task_room(socket, task_id);
  53. socket.leave(room);
  54. });
  55. socket.on('progress_subscribe', function(task_id) {
  56. var room = get_task_room(socket, task_id);
  57. socket.join(room);
  58. send_existing_lines(task_id, socket);
  59. });
  60. socket.on('doc_subscribe', function(doctype, docname) {
  61. // console.log('trying to subscribe', doctype, docname)
  62. can_subscribe_doc({
  63. socket: socket,
  64. sid: sid,
  65. doctype: doctype,
  66. docname: docname,
  67. callback: function(err, res) {
  68. var room = get_doc_room(socket, doctype, docname);
  69. // console.log('joining', room)
  70. socket.join(room);
  71. }
  72. });
  73. });
  74. socket.on('doc_unsubscribe', function(doctype, docname) {
  75. var room = get_doc_room(socket, doctype, docname);
  76. socket.leave(room);
  77. });
  78. socket.on('task_unsubscribe', function(task_id) {
  79. var room = 'task:' + task_id;
  80. socket.leave(room);
  81. });
  82. socket.on('doc_open', function(doctype, docname) {
  83. // show who is currently viewing the form
  84. can_subscribe_doc({
  85. socket: socket,
  86. sid: sid,
  87. doctype: doctype,
  88. docname: docname,
  89. callback: function(err, res) {
  90. var room = get_open_doc_room(socket, doctype, docname);
  91. // console.log('joining', room)
  92. socket.join(room);
  93. send_viewers({
  94. socket: socket,
  95. doctype: doctype,
  96. docname: docname,
  97. });
  98. }
  99. });
  100. });
  101. socket.on('doc_close', function(doctype, docname) {
  102. // remove this user from the list of 'who is currently viewing the form'
  103. var room = get_open_doc_room(socket, doctype, docname);
  104. socket.leave(room);
  105. send_viewers({
  106. socket: socket,
  107. doctype: doctype,
  108. docname: docname,
  109. });
  110. });
  111. // socket.on('disconnect', function (arguments) {
  112. // console.log("user disconnected", arguments);
  113. // });
  114. });
  115. subscriber.on("message", function(channel, message) {
  116. message = JSON.parse(message);
  117. io.to(message.room).emit(message.event, message.message);
  118. // console.log(message.room, message.event, message.message)
  119. });
  120. subscriber.subscribe("events");
  121. function send_existing_lines(task_id, socket) {
  122. var room = get_task_room(socket, task_id);
  123. subscriber.hgetall('task_log:' + task_id, function(err, lines) {
  124. io.to(room).emit('task_progress', {
  125. "task_id": task_id,
  126. "message": {
  127. "lines": lines
  128. }
  129. });
  130. });
  131. }
  132. function get_doc_room(socket, doctype, docname) {
  133. return get_site_name(socket) + ':doc:'+ doctype + '/' + docname;
  134. }
  135. function get_open_doc_room(socket, doctype, docname) {
  136. return get_site_name(socket) + ':open_doc:'+ doctype + '/' + docname;
  137. }
  138. function get_user_room(socket, user) {
  139. return get_site_name(socket) + ':user:' + user;
  140. }
  141. function get_site_room(socket) {
  142. return get_site_name(socket) + ':all';
  143. }
  144. function get_task_room(socket, task_id) {
  145. return get_site_name(socket) + ':task_progress:' + task_id;
  146. }
  147. function get_site_name(socket) {
  148. if (socket.request.headers['x-frappe-site-name']) {
  149. return get_hostname(socket.request.headers['x-frappe-site-name']);
  150. }
  151. else if (['localhost', '127.0.0.1'].indexOf(socket.request.headers.host) !== -1
  152. && conf.default_site) {
  153. // from currentsite.txt since host is localhost
  154. return conf.default_site;
  155. }
  156. else if (socket.request.headers.origin) {
  157. return get_hostname(socket.request.headers.origin);
  158. }
  159. else {
  160. return get_hostname(socket.request.headers.host);
  161. }
  162. }
  163. function get_hostname(url) {
  164. if (!url) return undefined;
  165. if (url.indexOf("://") > -1) {
  166. url = url.split('/')[2];
  167. }
  168. return ( url.match(/:/g) ) ? url.slice( 0, url.indexOf(":") ) : url
  169. }
  170. function get_url(socket, path) {
  171. if (!path) {
  172. path = '';
  173. }
  174. return socket.request.headers.origin + path;
  175. }
  176. function can_subscribe_doc(args) {
  177. if(!args) return;
  178. request.get(get_url(args.socket, '/api/method/frappe.async.can_subscribe_doc'))
  179. .type('form')
  180. .query({
  181. sid: args.sid,
  182. doctype: args.doctype,
  183. docname: args.docname
  184. })
  185. .end(function(err, res) {
  186. if (!res) {
  187. console.log("No response for doc_subscribe");
  188. } else if (res.status == 403) {
  189. return;
  190. } else if (err) {
  191. console.log(err);
  192. } else if (res.status == 200) {
  193. args.callback(err, res);
  194. } else {
  195. console.log("Something went wrong", err, res);
  196. }
  197. });
  198. }
  199. function send_viewers(args) {
  200. // send to doc room, 'users currently viewing this document'
  201. if (!(args && args.doctype && args.docname)) {
  202. return;
  203. }
  204. // open doc room
  205. var room = get_open_doc_room(args.socket, args.doctype, args.docname);
  206. var socketio_room = io.sockets.adapter.rooms[room] || {};
  207. // for compatibility with both v1.3.7 and 1.4.4
  208. var clients_dict = ("sockets" in socketio_room) ? socketio_room.sockets : socketio_room;
  209. // socket ids connected to this room
  210. var clients = Object.keys(clients_dict || {});
  211. var viewers = [];
  212. for (var i in io.sockets.sockets) {
  213. var s = io.sockets.sockets[i];
  214. if (clients.indexOf(s.id)!==-1) {
  215. // this socket is connected to the room
  216. viewers.push(s.user);
  217. }
  218. }
  219. // notify
  220. io.to(room).emit("doc_viewers", {
  221. doctype: args.doctype,
  222. docname: args.docname,
  223. viewers: viewers
  224. });
  225. }
  226. function get_conf() {
  227. // defaults
  228. var conf = {
  229. redis_async_broker_port: 12311,
  230. socketio_port: 3000
  231. };
  232. var read_config = function(path) {
  233. if(fs.existsSync(path)){
  234. var bench_config = JSON.parse(fs.readFileSync(path));
  235. for (var key in bench_config) {
  236. if (bench_config[key]) {
  237. conf[key] = bench_config[key];
  238. }
  239. }
  240. }
  241. }
  242. // get ports from bench/config.json
  243. read_config('config.json');
  244. read_config('sites/common_site_config.json');
  245. // detect current site
  246. if(fs.existsSync('sites/currentsite.txt')) {
  247. conf.default_site = fs.readFileSync('sites/currentsite.txt').toString().trim();
  248. }
  249. return conf;
  250. }