diff --git a/source/ircd/channel.d b/source/ircd/channel.d index 4b5ccb5..3aa891d 100644 --- a/source/ircd/channel.d +++ b/source/ircd/channel.d @@ -37,4 +37,12 @@ class Channel connection.send(Message(_server.name, "353", [connection.nick, channelType, name, members.map!(m => m.nick).join(' ')], true)); connection.send(Message(_server.name, "366", [connection.nick, name, "End of NAMES list"], true)); } + + void sendPrivMsg(Connection sender, string text) + { + foreach(member; members.filter!(m => m.nick != sender.nick)) + { + member.send(Message(sender.mask, "PRIVMSG", [name, text], true)); + } + } } diff --git a/source/ircd/connection.d b/source/ircd/connection.d index d07dc89..86b001a 100644 --- a/source/ircd/connection.d +++ b/source/ircd/connection.d @@ -118,6 +118,9 @@ class Connection case "PART": onPart(message); break; + case "PRIVMSG": + onPrivMsg(message); + break; default: writeln("unknown command '", message.command, "'"); send(Message(_server.name, "421", [nick, message.command, "Unknown command"])); @@ -176,7 +179,7 @@ class Connection auto channel = message.parameters[0]; if(!Server.isValidChannelName(channel)) { - send(Message(_server.name, "403", [nick, channel, "No such channel"], true)); + sendErrNoSuchChannel(channel); } else { @@ -191,7 +194,7 @@ class Connection auto channel = message.parameters[0]; if(!Server.isValidChannelName(channel)) { - send(Message(_server.name, "403", [nick, channel, "No such channel"], true)); + sendErrNoSuchChannel(channel); } else if(!channels.canFind!(c => c.name == channel)) { @@ -210,6 +213,62 @@ class Connection } } + void onPrivMsg(Message message) + { + //TODO: Support special message targets + auto target = message.parameters[0]; + auto text = message.parameters[1]; + + if(message.parameters.length == 0) + { + send(Message(_server.name, "411", [nick, "No recipient given (PRIVMSG)"], true)); + return; + } + if(message.parameters.length == 1) + { + send(Message(_server.name, "412", [nick, "No text to send"], true)); + return; + } + + if(Server.isValidChannelName(target)) + { + if(!_server.channels.canFind!(c => c.name == target)) + { + sendErrNoSuchNick(target); + } + else + { + _server.sendToChannel(this, target, text); + } + } + else if(Server.isValidNick(target)) + { + if(!_server.connections.canFind!(c => c.nick == target)) + { + sendErrNoSuchNick(target); + } + else + { + _server.sendToUser(this, target, text); + } + } + else + { + //is this the right response? + sendErrNoSuchNick(target); + } + } + + void sendErrNoSuchChannel(string name) + { + send(Message(_server.name, "403", [nick, name, "No such channel"], true)); + } + + void sendErrNoSuchNick(string name) + { + send(Message(_server.name, "401", [nick, name, "No such nick/channel"], true)); + } + string getHost() { auto address = parseAddress(_connection.peerAddress); diff --git a/source/ircd/message.d b/source/ircd/message.d index d48866f..d12ca69 100644 --- a/source/ircd/message.d +++ b/source/ircd/message.d @@ -24,6 +24,7 @@ struct Message line = line[prefix.length + 1 .. $]; } + //stop early when no space character can be found (message without parameters) if(!line.canFind(' ')) { return Message(prefix, line, [], false); diff --git a/source/ircd/server.d b/source/ircd/server.d index 44bbc07..4412070 100644 --- a/source/ircd/server.d +++ b/source/ircd/server.d @@ -58,6 +58,12 @@ class Server return (name.startsWith('#') || name.startsWith('&')) && name.length <= 200; } + static bool isValidNick(string name) + { + //TODO: Use the real rules + return !name.startsWith('#') && !name.startsWith('&') && name.length <= 9; + } + void join(Connection connection, string channelName) { auto channelRange = channels.find!(c => c.name == channelName); @@ -132,6 +138,18 @@ class Server } } + void sendToChannel(Connection sender, string target, string text) + { + auto channel = channels.find!(c => c.name == target)[0]; + channel.sendPrivMsg(sender, text); + } + + void sendToUser(Connection sender, string target, string text) + { + auto user = connections.find!(c => c.nick == target)[0]; + user.send(Message(sender.mask, "PRIVMSG", [target, text], true)); + } + void listen(ushort port = 6667) { listenTCP(port, &acceptConnection);