1 module app; 2 3 import std.file : read; 4 import std.json : JSONValue; 5 import std.regex : ctRegex; 6 7 import lighttp; 8 9 void main(string[] args) { 10 11 auto server = new Server(new Chat()); 12 server.host("0.0.0.0", 80); 13 14 while(true) server.eventLoop.loop(); 15 16 } 17 18 class Chat : Router { 19 20 @Get("") Resource index; 21 22 private Room[string] rooms; 23 24 this() { 25 this.index = new CachedResource("text/html", read("res/chat.html")); 26 } 27 28 @Get(`room`, `([a-z0-9]{2,16})@([a-zA-Z0-9]{3,16})`) class Client : WebSocket { 29 30 private static uint _id = 0; 31 32 public uint id; 33 public string name; 34 private Room* room; 35 36 void onConnect(NetworkAddress address, string room, string name) { 37 this.id = _id++; 38 this.name = name; 39 if(room !in rooms) rooms[room] = new Room(); 40 this.room = room in rooms; 41 this.room.add(this); 42 } 43 44 override void onClose() { 45 this.room.remove(this); 46 } 47 48 override void onReceive(ubyte[] data) { 49 this.room.broadcast(this, JSONValue(["type": "message", "message": cast(string)data])); 50 } 51 52 } 53 54 } 55 56 class Room { 57 58 Chat.Client[uint] clients; 59 60 void add(Chat.Client client) { 61 this.clients[client.id] = client; 62 this.broadcast(client, JSONValue(["type": "join"])); 63 } 64 65 void remove(Chat.Client client) { 66 this.clients.remove(client.id); 67 this.broadcast(client, JSONValue(["type": "leave"])); 68 } 69 70 void broadcast(Chat.Client client, JSONValue json) { 71 json["user"] = ["id": JSONValue(client.id), "name": JSONValue(client.name)]; 72 string message = json.toString(); 73 foreach(client ; this.clients) client.send(message); 74 } 75 76 }