Chat server: Difference between revisions

Content added Content deleted
(→‎{{header|Go}}: small simplification, possible now with new delete function)
(CoffeeScript)
Line 91: Line 91:
end loop;
end loop;
end Chat_Server;</lang>
end Chat_Server;</lang>

=={{header|CoffeeScript}}==

This is ported from the JavaScript version. The tool js2coffee got me a mostly working version, and then I manually converted JS-style classes to CS "class class" syntax.

<lang coffeescript>
net = require("net")
sys = require("sys")
EventEmitter = require("events").EventEmitter

isNicknameLegal = (nickname) ->
return false unless nickname.replace(/[A-Za-z0-9]*/, "") is ""
for used_nick of @chatters
return false if used_nick is nickname
true

class ChatServer
constructor: ->
@chatters = {}
@server = net.createServer @handleConnection
@server.listen 1212, "localhost"

handleConnection: (connection) =>
console.log "Incoming connection from " + connection.remoteAddress
connection.setEncoding "utf8"
chatter = new Chatter(connection, this)
chatter.on "chat", @handleChat
chatter.on "join", @handleJoin
chatter.on "leave", @handleLeave

handleChat: (chatter, message) =>
@sendToEveryChatterExcept chatter, chatter.nickname + ": " + message

handleJoin: (chatter) =>
console.log chatter.nickname + " has joined the chat."
@sendToEveryChatter chatter.nickname + " has joined the chat."
@addChatter chatter

handleLeave: (chatter) =>
console.log chatter.nickname + " has left the chat."
@removeChatter chatter
@sendToEveryChatter chatter.nickname + " has left the chat."

addChatter: (chatter) =>
@chatters[chatter.nickname] = chatter

removeChatter: (chatter) =>
delete @chatters[chatter.nickname]

sendToEveryChatter: (data) =>
for nickname of @chatters
@chatters[nickname].send data

sendToEveryChatterExcept: (chatter, data) =>
for nickname of @chatters
@chatters[nickname].send data unless nickname is chatter.nickname


class Chatter extends EventEmitter
constructor: (socket, server) ->
EventEmitter.call this
@socket = socket
@server = server
@nickname = ""
@lineBuffer = new SocketLineBuffer(socket)
@lineBuffer.on "line", @handleNickname
@socket.on "close", @handleDisconnect
@send "Welcome! What is your nickname?"

handleNickname: (nickname) =>
if isNicknameLegal(nickname)
@nickname = nickname
@lineBuffer.removeAllListeners "line"
@lineBuffer.on "line", @handleChat
@send "Welcome to the chat, " + nickname + "!"
@emit "join", this
else
@send "Sorry, but that nickname is not legal or is already in use!"
@send "What is your nickname?"

handleChat: (line) =>
@emit "chat", this, line

handleDisconnect: =>
@emit "leave", this

send: (data) =>
@socket.write data + "\r\n"


class SocketLineBuffer extends EventEmitter
constructor: (socket) ->
EventEmitter.call this
@socket = socket
@buffer = ""
@socket.on "data", @handleData

handleData: (data) =>
console.log "Handling data", data
i = 0

while i < data.length
char = data.charAt(i)
@buffer += char
if char is "\n"
@buffer = @buffer.replace("\r\n", "")
@buffer = @buffer.replace("\n", "")
@emit "line", @buffer
console.log "incoming line: #{@buffer}"
@buffer = ""
i++

server = new ChatServer()
</lang>



=={{header|Erlang}}==
=={{header|Erlang}}==