forked from lesderid/salty-ircd
Implement WHOIS
This commit is contained in:
parent
132c0229a7
commit
0ac5cc07ba
|
@ -7,6 +7,7 @@ import std.range;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import std.socket;
|
import std.socket;
|
||||||
import std.utf;
|
import std.utf;
|
||||||
|
import std.datetime;
|
||||||
|
|
||||||
import vibe.core.core;
|
import vibe.core.core;
|
||||||
import vibe.stream.operations;
|
import vibe.stream.operations;
|
||||||
|
@ -28,6 +29,12 @@ class Connection
|
||||||
string hostname;
|
string hostname;
|
||||||
char[] modes;
|
char[] modes;
|
||||||
|
|
||||||
|
SysTime lastMessageTime;
|
||||||
|
|
||||||
|
string awayMessage;
|
||||||
|
|
||||||
|
bool connected;
|
||||||
|
|
||||||
@property auto channels() { return _server.channels.filter!(c => c.members.canFind(this)); }
|
@property auto channels() { return _server.channels.filter!(c => c.members.canFind(this)); }
|
||||||
|
|
||||||
@property string mask() { return nick ~ "!" ~ user ~ "@" ~ hostname; }
|
@property string mask() { return nick ~ "!" ~ user ~ "@" ~ hostname; }
|
||||||
|
@ -35,10 +42,6 @@ class Connection
|
||||||
@property bool isOperator() { return modes.canFind('o') || modes.canFind('O'); }
|
@property bool isOperator() { return modes.canFind('o') || modes.canFind('O'); }
|
||||||
@property string servername() { return _server.name; } //TODO: Support server linking
|
@property string servername() { return _server.name; } //TODO: Support server linking
|
||||||
|
|
||||||
string awayMessage;
|
|
||||||
|
|
||||||
bool connected;
|
|
||||||
|
|
||||||
this(TCPConnection connection, Server server)
|
this(TCPConnection connection, Server server)
|
||||||
{
|
{
|
||||||
_connection = connection;
|
_connection = connection;
|
||||||
|
@ -104,6 +107,13 @@ class Connection
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//NOTE: The RFCs don't specify what 'being idle' means
|
||||||
|
// We assume that it's sending any message that isn't a PING/PONG.
|
||||||
|
if(message.command != "PING" && message.command != "PONG")
|
||||||
|
{
|
||||||
|
lastMessageTime = Clock.currTime;
|
||||||
|
}
|
||||||
|
|
||||||
writeln("C> " ~ message.toString);
|
writeln("C> " ~ message.toString);
|
||||||
|
|
||||||
//TODO: If RFC-strictness is off, ignore case
|
//TODO: If RFC-strictness is off, ignore case
|
||||||
|
@ -185,6 +195,10 @@ class Connection
|
||||||
if(!registered) sendErrNotRegistered();
|
if(!registered) sendErrNotRegistered();
|
||||||
else onIson(message);
|
else onIson(message);
|
||||||
break;
|
break;
|
||||||
|
case "WHOIS":
|
||||||
|
if(!registered) sendErrNotRegistered();
|
||||||
|
else onWhois(message);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
writeln("unknown command '", message.command, "'");
|
writeln("unknown command '", message.command, "'");
|
||||||
send(Message(_server.name, "421", [nick, message.command, "Unknown command"]));
|
send(Message(_server.name, "421", [nick, message.command, "Unknown command"]));
|
||||||
|
@ -658,6 +672,33 @@ class Connection
|
||||||
_server.ison(this, message.parameters[0].split);
|
_server.ison(this, message.parameters[0].split);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onWhois(Message message)
|
||||||
|
{
|
||||||
|
if(message.parameters.length < 1)
|
||||||
|
{
|
||||||
|
sendErrNoNickGiven();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(message.parameters.length > 1)
|
||||||
|
{
|
||||||
|
notImplemented("forwarding WHOIS to another server");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mask = message.parameters[0];
|
||||||
|
//TODO: Support user masks
|
||||||
|
if(!_server.canFindConnectionByNick(mask) || !_server.findConnectionByNick(mask)[0].visibleTo(this))
|
||||||
|
{
|
||||||
|
sendErrNoSuchNick(mask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_server.whois(this, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
send(Message(_server.name, "318", [nick, mask, "End of WHOIS list"], true));
|
||||||
|
}
|
||||||
|
|
||||||
void sendWhoReply(string channel, Connection user, uint hopCount)
|
void sendWhoReply(string channel, Connection user, uint hopCount)
|
||||||
{
|
{
|
||||||
auto flags = user.modes.canFind('a') ? "G" : "H";
|
auto flags = user.modes.canFind('a') ? "G" : "H";
|
||||||
|
|
|
@ -26,6 +26,7 @@ class Server
|
||||||
enum versionString = "salty-ircd-" ~ packageVersion;
|
enum versionString = "salty-ircd-" ~ packageVersion;
|
||||||
|
|
||||||
string name;
|
string name;
|
||||||
|
enum string info = "A salty-ircd server"; //TODO: Make server info configurable
|
||||||
|
|
||||||
string motd;
|
string motd;
|
||||||
|
|
||||||
|
@ -364,6 +365,24 @@ class Server
|
||||||
connection.send(Message(name, "303", [connection.nick, reply], true));
|
connection.send(Message(name, "303", [connection.nick, reply], true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void whois(Connection connection, string mask)
|
||||||
|
{
|
||||||
|
auto user = findConnectionByNick(mask)[0];
|
||||||
|
|
||||||
|
connection.send(Message(name, "311", [connection.nick, user.nick, user.user, user.hostname, "*", user.hostname], true));
|
||||||
|
//TODO: Send information about the user's actual server (which is not necessarily this one)
|
||||||
|
connection.send(Message(name, "312", [connection.nick, user.nick, name, info], true));
|
||||||
|
if(user.isOperator)
|
||||||
|
{
|
||||||
|
connection.send(Message(name, "313", [connection.nick, user.nick, "is an IRC operator"], true));
|
||||||
|
}
|
||||||
|
auto idleSeconds = (Clock.currTime - user.lastMessageTime).total!"seconds";
|
||||||
|
connection.send(Message(name, "317", [connection.nick, user.nick, idleSeconds.to!string, "seconds idle"], true));
|
||||||
|
//TODO: Prepend nick prefix (i.e. '@' or '+') when applicable
|
||||||
|
auto userChannels = user.channels.map!(c => c.name).join(' ');
|
||||||
|
connection.send(Message(name, "319", [connection.nick, user.nick, userChannels], true));
|
||||||
|
}
|
||||||
|
|
||||||
void listen(ushort port = 6667)
|
void listen(ushort port = 6667)
|
||||||
{
|
{
|
||||||
listenTCP(port, &acceptConnection);
|
listenTCP(port, &acceptConnection);
|
||||||
|
|
Loading…
Reference in New Issue