Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Jan 11th, 2012  |  syntax: CoffeeScript  |  size: 9.08 KB  |  hits: 82  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. # required modules
  2. crypto = require 'crypto'
  3. config = require './config'
  4. db = require './db'
  5. buffer = require './buffer'
  6. shared = require './shared'
  7.  
  8. # moderator socket connected flag
  9. exports.moderated = false
  10.  
  11. # spawn socket engine
  12. exports.spawn = (app) ->
  13.         # get socket.io
  14.         sio = require('socket.io').listen app
  15.        
  16.         # moderator socket referene
  17.         socket_moderator = null
  18.        
  19.         # users' sockets buffer
  20.         sockets = {}
  21.        
  22.         # expired invites buffer
  23.         expired_invites = {}
  24.        
  25.         # bans buffer
  26.         bans =
  27.                 addresses: {}
  28.                 nicks: {}
  29.  
  30.         # on socket connection
  31.         sio.sockets.on 'connection', (socket) ->
  32.                 ### Events/messages handlers ###
  33.                
  34.                 # moderator socket sign-in routine #
  35.                 signModerator = (err, chat) ->
  36.                        
  37.                         # set nick to chat's main guest name
  38.                         socket.set 'nick', chat.person, ->
  39.                                 # extracts nick from sockets buffer #
  40.                                 getClients = (moderated = true) ->
  41.                                         clients = for id, client of sockets when client.moderated is moderated
  42.                                                 { id: id, nick: client.nick }
  43.                                        
  44.                                 # put socket into chat room
  45.                                 socket.join 'chat'
  46.                                
  47.                                 # mark socket as moderator socket
  48.                                 socket.set 'moderator', true
  49.                                
  50.                                 # send connected sockets list, chat events and chat progress to moderator
  51.                                 socket.emit 'mod connected',
  52.                                         clients:
  53.                                                 moderated: getClients true
  54.                                                 unmoderated: getClients false
  55.                                         progress: buffer.read 'chat'
  56.                                         events: buffer.read 'events'
  57.                                
  58.                 # socket sign-in routine #
  59.                 sign = (id, nick, invited = false) ->
  60.                         # socket allowed flag
  61.                         allowed = true
  62.                        
  63.                         # if socket with invitation hash
  64.                         if invited
  65.                                 # if invitation expired
  66.                                 if expired_invites.hasOwnProperty id
  67.                                         # emit message
  68.                                         socket.emit 'invitation expired'
  69.                                        
  70.                                         # disconnect socket
  71.                                         socket.disconnect()
  72.                                        
  73.                                         # disallow socket
  74.                                         allowed = false
  75.                                 else
  76.                                         # put into expired invitations
  77.                                         expired_invites[id] = null
  78.                        
  79.                         # if socket allowed
  80.                         if allowed
  81.                                 # store socket reference in sockets buffer
  82.                                 sockets[id] =
  83.                                         socket: socket
  84.                                         nick: nick
  85.                                         moderated: invited
  86.  
  87.                                 # set socket's moderated flag
  88.                                 socket.set 'moderated', invited
  89.                                
  90.                                 # put socket into chat room
  91.                                 socket.join 'chat'
  92.                                
  93.                                 # emit sign-in operation confirmation message
  94.                                 socket.emit 'user signed', invited: invited
  95.                                
  96.                                 buffer.write shared.messages.sign(nick: nick), 'events'
  97.  
  98.                                 # if moderator socket connected
  99.                                 if socket_moderator?
  100.                                         # emit socket sign-in event
  101.                                         socket_moderator.emit 'mod user signed',
  102.                                                 id: id
  103.                                                 nick: nick
  104.                        
  105.                         allowed
  106.                        
  107.                 # socket moderation routine #
  108.                 moderateClient = (client, invited = false) ->
  109.                         # set socket's moderated flag
  110.                         sockets[client].moderated = true
  111.                        
  112.                         # get socket reference
  113.                         socket = sockets[client].socket
  114.                        
  115.                         # set socket moderated flag
  116.                         socket.set 'moderated', true, ->
  117.                                 # emit moderation confirmation message
  118.                                 socket.emit 'user moderated',
  119.                                         # send chat progress to connected socket
  120.                                         progress: buffer.read 'chat'
  121.                                
  122.                                 if invited and socket_moderator?
  123.                                         socket_moderator.emit 'user invited moderated',
  124.                                                 id: client
  125.                
  126.                 # bulk moderation #
  127.                 moderateBulk = (payload) ->
  128.                         moderateClient client for client in payload.clients
  129.                        
  130.                         clients = for key, id of payload.clients
  131.                                 sockets[id].nick
  132.                                
  133.                         buffer.write shared.messages.moderateBulk(clients), 'events'
  134.                
  135.                 # sends sockets chat message to moderator socket #
  136.                 clientMessage = (payload) ->
  137.                         # get sender nick
  138.                         socket.get 'id', (err, id) ->
  139.                                 buffer.write shared.messages.clientMessage({nick: sockets[id].nick, message: payload.message}), 'events'
  140.                                
  141.                                 # if success and moderator socket connected
  142.                                 if not err and id and socket_moderator?
  143.                                         # emit message and payload
  144.                                         socket_moderator.emit 'mod user message',
  145.                                                 id: id
  146.                                                 message: payload.message
  147.  
  148.                 # socket disconnection routine #
  149.                 disconnectClient = (err, id) ->
  150.                         # if success and socket in sockets buffer
  151.                         if not err and id and sockets[id]?                     
  152.                                 buffer.write shared.messages.disconnectClient(nick: sockets[id].nick), 'events'
  153.                                
  154.                                 # remove socket from buffer
  155.                                 delete sockets[id]
  156.                                
  157.                                 # if moderator socket connected
  158.                                 if socket_moderator?
  159.                                         # emit disconnect message
  160.                                         socket_moderator.emit 'mod user unsigned',
  161.                                                 id: id
  162.                                                
  163.                 # chat closure routine #
  164.                 close = ->
  165.                         # broadcast closure message
  166.                         socket_moderator.broadcast.emit 'mod close'
  167.  
  168.                         # forced sockets disconnect
  169.                         for id, client of sockets
  170.                                 client.socket.disconnect()
  171.                        
  172.                         # empty buffers buffer
  173.                         sockets = {}
  174.                         expired_invites = {}
  175.                         bans =
  176.                                 addresses: {}
  177.                                 nicks: {}
  178.                        
  179.                         # save chat data
  180.                         db.saveChat (chat) ->
  181.                                 id = chat._id
  182.                                 delete chat._id
  183.  
  184.                                 chat.active = false
  185.                                 chat.started = false
  186.                                 chat.history = buffer.read 'chat'
  187.                                
  188.                                 buffer.wipe()
  189.                                 id
  190.  
  191.                 # performs chat database quasi-locking routine #
  192.                 start = ->
  193.                         # save flag in database
  194.                         db.saveChat (chat) ->
  195.                                 id = chat._id
  196.                                 delete chat._id
  197.  
  198.                                 chat.started = true
  199.                                
  200.                                 id
  201.  
  202.                 # calculates message digest based on configured global hashing algorith
  203.                 digest = (message) ->
  204.                         hash = crypto.createHash config.app.hashing()
  205.                         hash.update message
  206.                         hash.digest 'hex'
  207.                        
  208.                 timestamp = ->
  209.                         dt = new Date()
  210.                         hours =  parseInt dt.getHours()
  211.                         minutes = parseInt dt.getMinutes()
  212.                         seconds = parseInt dt.getSeconds()
  213.  
  214.                         if hours < 10
  215.                                 hours = "0#{hours}"
  216.                         if minutes < 10
  217.                                 minutes = "0#{minutes}"
  218.                         if seconds < 10
  219.                                 seconds = "0#{seconds}"
  220.  
  221.                         "#{hours}:#{minutes}:#{seconds}"
  222.                        
  223.                 ban = (payload) ->
  224.                         for id, key in payload.clients
  225.                                 bans.nicks[id] = true
  226.                                 bans.addresses[sockets[id].socket.handshake.address.address] = true
  227.                                
  228.                                 sockets[id].socket.emit 'user banned'
  229.                                 sockets[id].socket.disconnect()
  230.                                 delete sockets[id]
  231.                                
  232.                 ### Communication section ###
  233.                
  234.                 # weak moderator socket discovery
  235.                 if socket.handshake.headers.referer.indexOf('chat/moderator') > 0
  236.                         # moderator socket connected flag
  237.                         exports.moderated = true
  238.                        
  239.                         # moderator socket reference
  240.                         socket_moderator = socket
  241.                        
  242.                         # call moderator sign-in routine
  243.                         db.getChat signModerator
  244.                        
  245.                         # moderator socket disconnect routine
  246.                         socket.on 'disconnect', ->
  247.                                 # wipe moderator socket reference
  248.                                 socket_moderator = null
  249.                                
  250.                                 # moderator socket not connected flag
  251.                                 exports.moderated = false
  252.                                
  253.                 # if moderator socket not discovered
  254.                 else
  255.                         db.getChat (err, chat) ->
  256.                                 # if chat closed (access with invitations)
  257.                                 if chat.closed
  258.                                         # emit message
  259.                                         socket.emit 'chat closed'
  260.                                 # if chat opened
  261.                                 else
  262.                                         if bans.addresses.hasOwnProperty socket.handshake.address.address
  263.                                                 socket.emit 'user banned'
  264.                                         else
  265.                                                 socket.get 'id', (err, id) ->
  266.                                                         # if socket not already signed-in
  267.                                                         if not err and not id
  268.                                                                 # put socket in purgatory (moderator's waiting room)
  269.                                                                 socket.join 'purgatory'
  270.  
  271.                                                                 # emit message
  272.                                                                 socket.emit 'user unsigned'
  273.  
  274.                         # calls socket disconnect routine
  275.                         socket.on 'disconnect', ->
  276.                                 socket.get 'id', disconnectClient
  277.  
  278.                 # handles socket invitation request routine
  279.                 socket.on 'invitation', (payload) ->
  280.                         db.getChat (err, chat) ->
  281.                                 # validate invitation
  282.                                 if chat.invites.hasOwnProperty payload.invitation
  283.                                         # get nick assigned to invitation
  284.                                         nick = chat.invites[payload.invitation]
  285.                                         id = digest nick
  286.                                        
  287.                                         # set assigned nick
  288.                                         socket.set 'id', id, ->
  289.                                                 # call socket sign-in routine
  290.                                                 if sign id, nick, true
  291.                                                         # call socket moderate routine
  292.                                                         moderateClient id, true
  293.                                 else
  294.                                         socket.emit 'invitation invalid'
  295.                
  296.                 # handles socket manual sign-in routine
  297.                 socket.on 'user sign', (payload) ->
  298.                         id = digest payload.nick
  299.                        
  300.                         # check against nicks ban list
  301.                         if bans.nicks.hasOwnProperty id
  302.                                 socket.emit 'user nick banned'
  303.                         # if nick already binded to different socket
  304.                         else if sockets.hasOwnProperty id
  305.                                 socket.emit 'user nick invalid'
  306.                         else
  307.                                 socket.set 'id', id, ->
  308.                                         # call socket sign-in routine
  309.                                         sign id, payload.nick
  310.                
  311.                 # handles moderator socket asked question broadcast routine
  312.                 socket.on 'mod question', (payload) ->
  313.                         payload.time = timestamp()
  314.                        
  315.                         # write payload to chat's buffer
  316.                         buffer.write payload, 'chat'
  317.                        
  318.                         # broadcast payload
  319.                         socket_moderator.broadcast.emit 'mod user question', payload
  320.                        
  321.                 # handles moderator socket message broadcast routine
  322.                 socket.on 'mod message', (payload) ->
  323.                         # store moderator socket reference
  324.                         sock = socket_moderator
  325.                         sock.get 'nick', (err, nick) ->
  326.                                 # get moderator socket nick
  327.                                 payload.nick = nick
  328.                                 payload.time = timestamp()
  329.                                
  330.                                 # write payload to chat's buffer
  331.                                 buffer.write payload, 'chat'
  332.                                
  333.                                 # broadcast payload
  334.                                 sock.broadcast.emit 'mod answer', payload
  335.  
  336.                 # bind handlers to events
  337.                 socket.on 'mod moderate', moderateBulk
  338.                 socket.on 'mod ban', ban
  339.                 socket.on 'user message', clientMessage
  340.                 socket.on 'mod close', close
  341.                 socket.on 'mod start', start
  342.                
  343.         console.log 'Chat spawned'