Implement channel key and user limit management

This commit is contained in:
Les De Ridder 2017-05-14 05:46:06 +02:00
parent f50f602eea
commit 6a6006c2c5
No known key found for this signature in database
GPG Key ID: 5EC132DFA85DB372
2 changed files with 117 additions and 20 deletions

View File

@ -2,6 +2,7 @@ module ircd.channel;
import std.algorithm; import std.algorithm;
import std.string; import std.string;
import std.typecons : Nullable;
import ircd.connection; import ircd.connection;
import ircd.server; import ircd.server;
@ -18,8 +19,8 @@ class Channel
char[][Connection] memberModes; char[][Connection] memberModes;
string[][char] maskLists; string[][char] maskLists;
string key; //TODO: Fully implement key string key;
//TODO: Implement member limit (+l) Nullable!uint userLimit;
private Server _server; private Server _server;
@ -136,17 +137,27 @@ class Channel
void sendModes(Connection user) void sendModes(Connection user)
{ {
auto specialModes = "";
string[] specialModeParameters;
if(members.canFind(user) && key !is null) if(members.canFind(user) && key !is null)
{ {
user.send(Message(_server.name, "324", [user.nick, name, "+" ~ modes.idup ~ "k", key])); specialModes ~= "k";
specialModeParameters ~= key;
} }
else
if(members.canFind(user) && !userLimit.isNull)
{ {
user.send(Message(_server.name, "324", [user.nick, name, "+" ~ modes.idup])); import std.conv : to;
specialModes ~= "l";
specialModeParameters ~= userLimit.to!string;
} }
user.send(Message(_server.name, "324", [user.nick, name, "+" ~ modes.idup ~ specialModes] ~ specialModeParameters));
} }
bool setMemberMode(Connection setter, Connection target, char mode) bool setMemberMode(Connection target, char mode)
{ {
if(memberModes[target].canFind(mode)) if(memberModes[target].canFind(mode))
{ {
@ -157,7 +168,7 @@ class Channel
return true; return true;
} }
bool unsetMemberMode(Connection setter, Connection target, char mode) bool unsetMemberMode(Connection target, char mode)
{ {
if(!memberModes[target].canFind(mode)) if(!memberModes[target].canFind(mode))
{ {
@ -172,7 +183,7 @@ class Channel
return true; return true;
} }
bool setMode(Connection setter, char mode) bool setMode(char mode)
{ {
if(modes.canFind(mode)) if(modes.canFind(mode))
{ {
@ -184,7 +195,7 @@ class Channel
return true; return true;
} }
bool unsetMode(Connection setter, char mode) bool unsetMode(char mode)
{ {
if(!modes.canFind(mode)) if(!modes.canFind(mode))
{ {
@ -199,7 +210,7 @@ class Channel
return true; return true;
} }
bool addMaskListEntry(Connection origin, string mask, char mode) bool addMaskListEntry(string mask, char mode)
{ {
if(maskLists[mode].canFind!(m => m.toIRCLower == mask.toIRCLower)) if(maskLists[mode].canFind!(m => m.toIRCLower == mask.toIRCLower))
{ {
@ -211,7 +222,7 @@ class Channel
return true; return true;
} }
bool removeMaskListEntry(Connection origin, string mask, char mode) bool removeMaskListEntry(string mask, char mode)
{ {
if(!maskLists[mode].canFind!(m => m.toIRCLower == mask.toIRCLower)) if(!maskLists[mode].canFind!(m => m.toIRCLower == mask.toIRCLower))
{ {
@ -253,6 +264,42 @@ class Channel
connection.send(Message(_server.name, "347", [connection.nick, name, "End of channel invite list"], true)); connection.send(Message(_server.name, "347", [connection.nick, name, "End of channel invite list"], true));
} }
bool setKey(string key)
{
this.key = key;
return true;
}
bool unsetKey(string key)
{
if(this.key != key)
{
return false;
}
this.key = null;
return true;
}
void setUserLimit(uint userLimit)
{
this.userLimit = userLimit;
}
bool unsetUserLimit()
{
if(userLimit.isNull)
{
return false;
}
userLimit.nullify();
return true;
}
string prefixedNick(Connection member) string prefixedNick(Connection member)
{ {
if(memberModes[member].canFind('o')) if(memberModes[member].canFind('o'))

View File

@ -975,9 +975,9 @@ Lforeach:
break Lforeach; break Lforeach;
} }
auto success = false; bool success;
if(add) success = channel.setMemberMode(this, member, mode); if(add) success = channel.setMemberMode(member, mode);
else success = channel.unsetMemberMode(this, member, mode); else success = channel.unsetMemberMode(member, mode);
if(success) if(success)
{ {
processedModes ~= mode; processedModes ~= mode;
@ -1000,24 +1000,74 @@ Lforeach:
break Lforeach; break Lforeach;
} }
auto success = false; bool success;
if(add) success = channel.addMaskListEntry(this, mask, mode); if(add) success = channel.addMaskListEntry(mask, mode);
else success = channel.removeMaskListEntry(this, mask, mode); else success = channel.removeMaskListEntry(mask, mode);
if(success) if(success)
{ {
processedModes ~= mode; processedModes ~= mode;
processedParameters ~= mask; processedParameters ~= mask;
} }
break; break;
case 'k': //TODO: Implement channel key
if(i + 1 == message.parameters.length)
{
//TODO: Figure out what to do when we need more mode parameters
break Lforeach;
}
auto key = message.parameters[++i];
bool success;
if(add) success = channel.setKey(key);
else success = channel.unsetKey(key);
if(success)
{
processedModes ~= mode;
processedParameters ~= key;
}
break;
case 'l': //TODO: Implement user limit
if(add)
{
if(i + 1 == message.parameters.length)
{
//TODO: Figure out what to do when we need more mode parameters
break Lforeach;
}
auto limitString = message.parameters[++i];
uint limit = 0;
try
{
limit = limitString.to!uint;
}
catch(Exception)
{
break Lforeach;
}
channel.setUserLimit(limit);
processedModes ~= mode;
processedParameters ~= limitString;
}
else
{
if(channel.unsetUserLimit())
{
processedModes ~= mode;
}
}
break;
case 'i': //TODO: Implement invite-only channels case 'i': //TODO: Implement invite-only channels
case 'm': //TODO: Implement channel moderation case 'm': //TODO: Implement channel moderation
case 'n': //TODO: Implement the no messages from clients on the outside flag case 'n': //TODO: Implement the no messages from clients on the outside flag
case 'p': case 'p':
case 's': case 's':
case 't': case 't':
auto success = false; bool success;
if(add) channel.setMode(this, mode); if(add) channel.setMode(mode);
else channel.unsetMode(this, mode); else channel.unsetMode(mode);
if(success) if(success)
{ {
processedModes ~= mode; processedModes ~= mode;