user
Task

Write a server for a minimal text based chat.

People should be able to connect via ‘telnet’, sign on with a nickname, and type messages which will then be seen by all other connected users. Arrivals and departures of chat members should generate appropriate notification messages.
assistant
(formerly Perl 6)

**Translation of**: Python

(or at least started out that way)

**Works with**: Rakudo version 2016.07

```
react {
    my %connections;
    
    whenever IO::Socket::Async.listen('localhost', 4004) -> $conn {
        my $name;
        
        $conn.print: "Please enter your name: ";
        
        whenever $conn.Supply.lines -> $message {
            if !$name {
                if %connections{$message} {
                    $conn.print: "Name already taken, choose another one: ";
                }
                else {
                    $name = $message;
                    %connections{$name} = $conn;
                    broadcast "+++ %s arrived +++", $name;
                }
            }
            else {
                broadcast "%s> %s", $name, $message;
            }
            LAST {
                broadcast "--- %s left ---", $name;
                %connections{$name}:delete;
                $conn.close ;
            }
            QUIT {
                 default {
                     say "oh no, $_";
                }
            }
        }
    }
    
    sub broadcast ($format, $from, *@message) {
        my $text = sprintf $format, $from, |@message;
        say $text;
        for %connections.kv -> $name, $conn {
            $conn.print: "$text\n" if $name ne $from;
        }
    }
}

```

Notes:

* It operates asynchronously (using IO::Socket::Async), so a slow connection to one client won't affect other clients.
* It accepts messages encoded in UTF-8.
* It tokenizes the message streams at newline boundaries (using the Supply.lines method), which I think makes the most sense for a chat application.