From db4300eb762aee8753595117b3147803cebda28d Mon Sep 17 00:00:00 2001 From: Les De Ridder Date: Wed, 22 Mar 2017 16:58:03 +0100 Subject: [PATCH] Implement INVITE --- source/ircd/connection.d | 69 ++++++++++++++++++++++++++++++++++++++++ source/ircd/server.d | 6 ++++ 2 files changed, 75 insertions(+) diff --git a/source/ircd/connection.d b/source/ircd/connection.d index 34714f7..f8f05d4 100644 --- a/source/ircd/connection.d +++ b/source/ircd/connection.d @@ -161,6 +161,10 @@ class Connection if(!registered) sendErrNotRegistered(); else onList(message); break; + case "INVITE": + if(!registered) sendErrNotRegistered(); + else onInvite(message); + break; default: writeln("unknown command '", message.command, "'"); send(Message(_server.name, "421", [nick, message.command, "Unknown command"])); @@ -504,6 +508,65 @@ class Connection } } + void onInvite(Message message) + { + if(message.parameters.length < 2) + { + sendErrNeedMoreParams(message.command); + return; + } + + auto targetNick = message.parameters[0]; + auto targetUserRange = _server.connections.find!(c => c.nick == targetNick); + if(targetUserRange.empty) + { + sendErrNoSuchNick(targetNick); + return; + } + auto targetUser = targetUserRange[0]; + + auto channelName = message.parameters[1]; + auto channelRange = _server.channels.find!(c => c.name == channelName); + if(channelRange.empty) + { + _server.invite(this, targetUser.nick, channelName); + + sendRplInviting(channelName, targetUser.nick); + + if(targetUser.modes.canFind('a')) + { + sendRplAway(targetUser.nick, targetUser.awayMessage); + } + } + else + { + auto channel = channelRange[0]; + if(!channel.members.canFind(this)) + { + sendErrNotOnChannel(channel.name); + } + else if(channel.members.canFind(targetUser)) + { + send(Message(_server.name, "443", [nick, targetUser.nick, channel.name, "is already on channel"], true)); + } + else if(channel.modes.canFind('i') /* TODO: and this connection isn't a chanop */) + { + sendErrChanopPrivsNeeded(channel.name); + } + else + { + _server.invite(this, targetUser.nick, channel.name); + + sendRplInviting(channel.name, targetUser.nick); + + if(targetUser.modes.canFind('a')) + { + sendRplAway(targetUser.nick, targetUser.awayMessage); + } + } + } + } + void sendWhoReply(string channel, Connection user, uint hopCount) { auto flags = user.modes.canFind('a') ? "G" : "H"; @@ -528,6 +591,12 @@ class Connection send(Message(_server.name, "323", [nick, "End of LIST"], true)); } + void sendRplInviting(string channelName, string name) + { + //TODO: If RFC-strictness is off, send parameters in reverse order + send(Message(_server.name, "341", [nick, channelName, name])); + } + void sendRplEndOfNames(string channelName) { send(Message(_server.name, "366", [nick, channelName, "End of NAMES list"], true)); diff --git a/source/ircd/server.d b/source/ircd/server.d index fa5df94..fadbe4b 100644 --- a/source/ircd/server.d +++ b/source/ircd/server.d @@ -251,6 +251,12 @@ class Server connection.sendRplListEnd(); } + void invite(Connection inviter, string target, string channelName) + { + auto user = connections.find!(c => c.nick = target)[0]; + user.send(Message(inviter.mask, "INVITE", [user.nick, channelName])); + } + void listen(ushort port = 6667) { listenTCP(port, &acceptConnection);