forked from lesderid/salty-ircd
Implement TOPIC
This commit is contained in:
parent
4f8aedddc9
commit
8a94d845e8
|
@ -9,27 +9,25 @@ import ircd.message;
|
|||
|
||||
class Channel
|
||||
{
|
||||
private string _name;
|
||||
string name;
|
||||
|
||||
Connection[] members;
|
||||
Connection owner;
|
||||
|
||||
string topic = "";
|
||||
|
||||
char[] modes;
|
||||
|
||||
private Server _server;
|
||||
|
||||
this(string name, Connection owner, Server server)
|
||||
{
|
||||
this._name = name;
|
||||
this.name = name;
|
||||
this.owner = owner;
|
||||
this.members = [owner];
|
||||
this._server = server;
|
||||
}
|
||||
|
||||
@property
|
||||
string name()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
void sendNames(Connection connection)
|
||||
{
|
||||
enum channelType = "="; //TODO: Support secret and private channels
|
||||
|
@ -53,4 +51,26 @@ class Channel
|
|||
member.send(Message(sender.mask, "NOTICE", [name, text], true));
|
||||
}
|
||||
}
|
||||
|
||||
void sendTopic(Connection connection)
|
||||
{
|
||||
if(topic.empty)
|
||||
{
|
||||
connection.send(Message(_server.name, "331", [connection.nick, name, "No topic is set"]));
|
||||
}
|
||||
else
|
||||
{
|
||||
connection.send(Message(_server.name, "332", [connection.nick, name, topic], true));
|
||||
}
|
||||
}
|
||||
|
||||
void setTopic(Connection connection, string newTopic)
|
||||
{
|
||||
topic = newTopic;
|
||||
|
||||
foreach(member; members)
|
||||
{
|
||||
member.send(Message(connection.mask, "TOPIC", [name, newTopic], true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,6 +149,10 @@ class Connection
|
|||
if(!registered) sendErrNotRegistered();
|
||||
else onAway(message);
|
||||
break;
|
||||
case "TOPIC":
|
||||
if(!registered) sendErrNotRegistered();
|
||||
else onTopic(message);
|
||||
break;
|
||||
default:
|
||||
writeln("unknown command '", message.command, "'");
|
||||
send(Message(_server.name, "421", [nick, message.command, "Unknown command"]));
|
||||
|
@ -404,6 +408,47 @@ class Connection
|
|||
}
|
||||
}
|
||||
|
||||
void onTopic(Message message)
|
||||
{
|
||||
if(message.parameters.length == 0)
|
||||
{
|
||||
sendErrNeedMoreParams(message.command);
|
||||
return;
|
||||
}
|
||||
|
||||
auto channelName = message.parameters[0];
|
||||
if(message.parameters.length == 1)
|
||||
{
|
||||
if(!_server.channels.canFind!(c => c.name == channelName && (!(c.modes.canFind('s') || c.modes.canFind('p')) || c.members.canFind(this))))
|
||||
{
|
||||
//NOTE: The RFCs don't allow ERR_NOSUCHCHANNEL as a response to TOPIC
|
||||
//TODO: If RFC-strictness is off, do send ERR_NOSUCHCHANNEL
|
||||
send(Message(_server.name, "331", [nick, channelName, "No topic is set"], true));
|
||||
}
|
||||
else
|
||||
{
|
||||
_server.sendChannelTopic(this, channelName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto newTopic = message.parameters[1];
|
||||
if(!channels.canFind!(c => c.name == channelName))
|
||||
{
|
||||
sendErrNotOnChannel(channelName);
|
||||
}
|
||||
//TODO: Allow operators to set flags
|
||||
else if(channels.find!(c => c.name == channelName).map!(c => c.modes.canFind('t') /* && this user isn't an operator */).array[0])
|
||||
{
|
||||
sendErrChanopPrivsNeeded(channelName);
|
||||
}
|
||||
else
|
||||
{
|
||||
_server.setChannelTopic(this, channelName, newTopic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendWhoReply(string channel, Connection user, uint hopCount)
|
||||
{
|
||||
auto flags = user.modes.canFind('a') ? "G" : "H";
|
||||
|
@ -433,6 +478,11 @@ class Connection
|
|||
send(Message(_server.name, "431", [nick, "No nickname given"], true));
|
||||
}
|
||||
|
||||
void sendErrNotOnChannel(string channel)
|
||||
{
|
||||
send(Message(_server.name, "442", [nick, channel, "You're not on that channel"], true));
|
||||
}
|
||||
|
||||
void sendErrNotRegistered()
|
||||
{
|
||||
send(Message(_server.name, "451", ["(You)", "You have not registered"], true));
|
||||
|
@ -443,6 +493,11 @@ class Connection
|
|||
send(Message(_server.name, "461", [nick, command, "Not enough parameters"], true));
|
||||
}
|
||||
|
||||
void sendErrChanopPrivsNeeded(string channel)
|
||||
{
|
||||
send(Message(_server.name, "482", [nick, channel, "You're not channel operator"], true));
|
||||
}
|
||||
|
||||
void sendWelcome()
|
||||
{
|
||||
send(Message(_server.name, "001", [nick, "Welcome to the Internet Relay Network " ~ mask], true));
|
||||
|
|
|
@ -91,6 +91,11 @@ class Server
|
|||
}
|
||||
|
||||
channel.sendNames(connection);
|
||||
|
||||
if(!channel.topic.empty)
|
||||
{
|
||||
channel.sendTopic(connection);
|
||||
}
|
||||
}
|
||||
|
||||
void part(Connection connection, string channelName, string partMessage)
|
||||
|
@ -163,7 +168,7 @@ class Server
|
|||
.filter!(c => !operatorsOnly || c.isOperator)
|
||||
.filter!(c => [c.hostname, c.servername, c.realname, c.nick].any!(n => wildcardMatch(n, mask))))
|
||||
{
|
||||
//TODO: Don't leak secret/private channels (even if the RFCs don't say anything about it?)
|
||||
//TODO: Don't leak secret/private channels if RFC-strictness is off (the RFCs don't seem to say anything about it?)
|
||||
auto channelName = c.channels.empty ? "*" : c.channels.array[0].name;
|
||||
//TODO: Support hop count
|
||||
origin.sendWhoReply(channelName, c, 0);
|
||||
|
@ -194,6 +199,18 @@ class Server
|
|||
user.send(Message(sender.mask, "NOTICE", [target, text], true));
|
||||
}
|
||||
|
||||
void sendChannelTopic(Connection origin, string channelName)
|
||||
{
|
||||
auto channel = channels.find!(c => c.name == channelName)[0];
|
||||
channel.sendTopic(origin);
|
||||
}
|
||||
|
||||
void setChannelTopic(Connection origin, string channelName, string newTopic)
|
||||
{
|
||||
auto channel = channels.find!(c => c.name == channelName)[0];
|
||||
channel.setTopic(origin, newTopic);
|
||||
}
|
||||
|
||||
void listen(ushort port = 6667)
|
||||
{
|
||||
listenTCP(port, &acceptConnection);
|
||||
|
|
Loading…
Reference in New Issue