summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864>2009-11-11 02:47:05 +0000
committerAdam- <Adam-@5417fbe8-f217-4b02-8779-1006273d7864>2009-11-11 02:47:05 +0000
commit86e43f1f144cfd04b039a844959af1f7aec3e6da (patch)
treec5d5fb8b025d7066365afbf0d1e274e2bb5265cb /src
parent9d37cf1d5afeaa054f31e0df85275521410bde61 (diff)
Added support for permanent channels. This supports both permanent channel modes and the ability to have BotServ bots stay in the channel to keep it open.
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2638 5417fbe8-f217-4b02-8779-1006273d7864
Diffstat (limited to 'src')
-rw-r--r--src/bots.cpp9
-rw-r--r--src/channels.c41
-rw-r--r--src/config.c1
-rw-r--r--src/core/bs_unassign.c8
-rw-r--r--src/core/cs_info.c1
-rw-r--r--src/core/cs_register.c10
-rw-r--r--src/core/cs_set.c82
7 files changed, 143 insertions, 9 deletions
diff --git a/src/bots.cpp b/src/bots.cpp
index 8a4198b74..6d7728a93 100644
--- a/src/bots.cpp
+++ b/src/bots.cpp
@@ -164,8 +164,13 @@ void BotInfo::UnAssign(User *u, ChannelInfo *ci)
if (MOD_RESULT == EVENT_STOP)
return;
- if (u && ci->c && ci->c->usercount >= BSMinUsers)
- ircdproto->SendPart(ci->bi, ci->name, "UNASSIGN from %s", u->nick);
+ if (ci->c && ci->c->usercount >= BSMinUsers)
+ {
+ if (u)
+ ircdproto->SendPart(ci->bi, ci->name, "UNASSIGN from %s", u->nick);
+ else
+ ircdproto->SendPart(ci->bi, ci->name, "");
+ }
ci->bi->chancount--;
ci->bi = NULL;
diff --git a/src/channels.c b/src/channels.c
index 9bd3abdc3..919628358 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -39,6 +39,13 @@ bool Channel::HasMode(ChannelModeName Name)
void Channel::SetMode(ChannelModeName Name)
{
modes[(size_t)Name] = true;
+
+ /* Channel mode +P or so was set, mark this channel as persistant */
+ if (Name == CMODE_PERM && ci)
+ {
+ ci->SetFlag(CI_PERSIST);
+ }
+
FOREACH_MOD(I_OnChannelModeSet, OnChannelModeSet(this, Name));
}
@@ -63,6 +70,16 @@ void Channel::SetMode(char Mode)
void Channel::RemoveMode(ChannelModeName Name)
{
modes[(size_t)Name] = false;
+
+ if (Name == CMODE_PERM && ci)
+ {
+ ci->UnsetFlag(CI_PERSIST);
+ if (s_BotServ && ci->bi && usercount == BSMinUsers - 1)
+ ircdproto->SendPart(ci->bi, name, NULL);
+ if (!users)
+ chan_delete(this);
+ }
+
FOREACH_MOD(I_OnChannelModeUnset, OnChannelModeUnset(this, Name));
}
@@ -323,9 +340,12 @@ void chan_deluser(User * user, Channel * c)
delete u;
c->usercount--;
- if (s_BotServ && c->ci && c->ci->bi && c->usercount == BSMinUsers - 1) {
+ /* Channel is persistant, it shouldn't be deleted and the service bot should stay */
+ if (c->ci && c->ci->HasFlag(CI_PERSIST))
+ return;
+
+ if (s_BotServ && c->ci && c->ci->bi && c->usercount == BSMinUsers - 1)
ircdproto->SendPart(c->ci->bi, c->name, NULL);
- }
if (!c->users)
chan_delete(c);
@@ -1819,10 +1839,15 @@ void chan_adduser2(User * user, Channel * c)
* and the ignored user dosnt just leave, the bot will never
* make it into the channel, leaving the channel botless even for
* legit users - Rob
+ * But don't join the bot if the channel is persistant - Adam
**/
- if (s_BotServ && c->ci && c->ci->bi) {
+ if (s_BotServ && c->ci && c->ci->bi && !c->ci->HasFlag(CI_PERSIST))
+ {
if (c->usercount == BSMinUsers)
bot_join(c->ci);
+ }
+ if (s_BotServ && c->ci && c->ci->bi)
+ {
if (c->usercount >= BSMinUsers && (c->ci->botflags.HasFlag(BS_GREET))
&& user->nc && user->nc->greet
&& check_access(user, c->ci, CA_GREET)) {
@@ -1884,6 +1909,16 @@ Channel *chan_create(const char *chan, time_t ts)
restore_topic(chan);
}
+ /* A channel set as persistant when it was not created has just
+ * been created, mark it as persistant
+ */
+ ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_PERM);
+ if (cm && c->ci && c->ci->HasFlag(CI_PERSIST) && !c->HasMode(CMODE_PERM))
+ {
+ ircdproto->SendMode(whosends(c->ci), c->name, "+%c", cm->ModeChar);
+ c->SetMode(CMODE_PERM);
+ }
+
FOREACH_MOD(I_OnChannelCreate, OnChannelCreate(c));
return c;
diff --git a/src/config.c b/src/config.c
index 03f1fde24..e531dafa1 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1848,6 +1848,7 @@ int read_config(int reload)
else if (option == "opnotice") CSDefFlags.SetFlag(CI_OPNOTICE);
else if (option == "xop") CSDefFlags.SetFlag(CI_XOP);
else if (option == "peace") CSDefFlags.SetFlag(CI_PEACE);
+ else if (option == "persist") CSDefFlags.SetFlag(CI_PERSIST);
}
}
diff --git a/src/core/bs_unassign.c b/src/core/bs_unassign.c
index 6b8a89eba..25a5c2ada 100644
--- a/src/core/bs_unassign.c
+++ b/src/core/bs_unassign.c
@@ -15,8 +15,6 @@
#include "module.h"
-int do_unassign(User * u);
-
class CommandBSUnassign : public Command
{
public:
@@ -28,6 +26,7 @@ class CommandBSUnassign : public Command
{
const char *chan = params[0].c_str();
ChannelInfo *ci = cs_findchan(chan);
+ ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_PERM);
if (readonly)
notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY);
@@ -35,7 +34,10 @@ class CommandBSUnassign : public Command
notice_lang(s_BotServ, u, ACCESS_DENIED);
else if (!ci->bi)
notice_help(s_BotServ, u, BOT_NOT_ASSIGNED);
- else {
+ else if (ci->HasFlag(CI_PERSIST) && !cm)
+ notice_help(s_BotServ, u, BOT_UNASSIGN_PERSISTANT_CHAN);
+ else
+ {
ci->bi->UnAssign(u, ci);
notice_lang(s_BotServ, u, BOT_UNASSIGN_UNASSIGNED, ci->name);
}
diff --git a/src/core/cs_info.c b/src/core/cs_info.c
index 52699b515..6d89ada02 100644
--- a/src/core/cs_info.c
+++ b/src/core/cs_info.c
@@ -118,6 +118,7 @@ class CommandCSInfo : public Command
CheckOptStr(optbuf, CI_SIGNKICK_LEVEL, getstring(u, CHAN_INFO_OPT_SIGNKICK), ci, u->nc);
CheckOptStr(optbuf, CI_TOPICLOCK, getstring(u, CHAN_INFO_OPT_TOPICLOCK), ci, u->nc);
CheckOptStr(optbuf, CI_XOP, getstring(u, CHAN_INFO_OPT_XOP), ci, u->nc);
+ CheckOptStr(optbuf, CI_PERSIST, getstring(u, CHAN_INFO_OPT_PERSIST), ci, u->nc);
notice_lang(s_ChanServ, u, CHAN_INFO_OPTIONS, optbuf.empty() ? getstring(u, CHAN_INFO_OPT_NONE) : optbuf.c_str());
notice_lang(s_ChanServ, u, CHAN_INFO_MODE_LOCK, get_mlock_modes(ci, 1));
diff --git a/src/core/cs_register.c b/src/core/cs_register.c
index e6ccde8cf..0ea7e58dc 100644
--- a/src/core/cs_register.c
+++ b/src/core/cs_register.c
@@ -86,6 +86,16 @@ class CommandCSRegister : public Command
else if ((cm = ModeManager::FindChannelModeByName(CMODE_PROTECT)))
ircdproto->SendMode(findbot(s_ChanServ), chan, "+%c %s", cm->ModeChar, u->nick);
+ /* Mark the channel as persistant */
+ if (c->HasMode(CMODE_PERM))
+ ci->SetFlag(CI_PERSIST);
+ /* Persist may be in def cflags, set it here */
+ else if (ci->HasFlag(CI_PERSIST) && (cm = ModeManager::FindChannelModeByName(CMODE_PERM)))
+ {
+ ircdproto->SendMode(whosends(ci), chan, "+%c", cm->ModeChar);
+ ci->SetFlag(CI_PERSIST);
+ }
+
FOREACH_MOD(I_OnChanRegistered, OnChanRegistered(ci));
}
return MOD_CONT;
diff --git a/src/core/cs_set.c b/src/core/cs_set.c
index 48eef2ba9..96c8ae35c 100644
--- a/src/core/cs_set.c
+++ b/src/core/cs_set.c
@@ -498,6 +498,82 @@ class CommandCSSet : public Command
return MOD_CONT;
}
+ CommandReturn DoSetPersist(User *u, ChannelInfo *ci, const char *param)
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_PERM);
+
+ if (!stricmp(param, "ON"))
+ {
+ if (!ci->HasFlag(CI_PERSIST))
+ {
+ ci->SetFlag(CI_PERSIST);
+
+ /* Channel doesn't exist, create it internally */
+ if (!ci->c)
+ {
+ chan_create(ci->name, time(NULL));
+ if (ci->bi)
+ bot_join(ci);
+ }
+
+ /* No botserv bot, no channel mode */
+ if (!ci->bi && !cm)
+ {
+ /* Give them ChanServ
+ * Yes, this works fine with no s_BotServ
+ */
+ findbot(s_ChanServ)->Assign(NULL, ci);
+ }
+
+ /* Set the perm mode */
+ if (cm && ci->c && !ci->c->HasMode(CMODE_PERM))
+ {
+ ci->c->SetMode(CMODE_PERM);
+ ircdproto->SendMode(whosends(ci), ci->c->name, "+%c", cm->ModeChar);
+ }
+ }
+
+ notice_lang(s_ChanServ, u, CHAN_SET_PERSIST_ON, ci->name);
+ }
+ else if (!stricmp(param, "OFF"))
+ {
+ if (ci->HasFlag(CI_PERSIST))
+ {
+ ci->UnsetFlag(CI_PERSIST);
+
+ /* Unset perm mode */
+ if (ci->c && ci->c->HasMode(CMODE_PERM))
+ {
+ ircdproto->SendMode(whosends(ci), ci->c->name, "-%c", cm->ModeChar);
+ ci->c->RemoveMode(CMODE_PERM);
+ }
+ /* Persist is set off... remove the bot and delete the channel if its empty */
+ else if (ci->c)
+ {
+ if (s_BotServ && ci->bi && ci->c->usercount == BSMinUsers - 1)
+ ircdproto->SendPart(ci->bi, ci->c->name, NULL);
+ if (!ci->c->users)
+ chan_delete(ci->c);
+
+ /* No channel mode, no BotServ, but using ChanServ as the botserv bot
+ * which was assigned when persist was set on
+ */
+ if (!cm && !s_BotServ && ci->bi)
+ {
+ /* Unassign bot */
+ findbot(s_ChanServ)->UnAssign(NULL, ci);
+ }
+ }
+ }
+
+ notice_lang(s_ChanServ, u, CHAN_SET_PERSIST_OFF, ci->name);
+ }
+ else
+ syntax_error(s_ChanServ, u, "SET PERSIST", CHAN_SET_PERSIST_SYNTAX);
+
+ return MOD_CONT;
+ }
+
CommandReturn DoSetNoExpire(User * u, ChannelInfo * ci, const char *param)
{
if (!u->nc->HasCommand("chanserv/set/noexpire"))
@@ -593,7 +669,9 @@ class CommandCSSet : public Command
}
} else if (cmd == "PEACE") {
DoSetPeace(u, ci, param);
- } else if (cmd == "NOEXPIRE") {
+ } else if (cmd == "PERSIST")
+ DoSetPersist(u, ci, param);
+ else if (cmd == "NOEXPIRE") {
DoSetNoExpire(u, ci, param);
} else {
notice_lang(s_ChanServ, u, CHAN_SET_UNKNOWN_OPTION, cmd.c_str());
@@ -648,6 +726,8 @@ class CommandCSSet : public Command
notice_help(s_ChanServ, u, CHAN_HELP_SET_XOP);
else if (subcommand == "PEACE")
notice_help(s_ChanServ, u, CHAN_HELP_SET_PEACE);
+ else if (subcommand == "PERSIST")
+ notice_help(s_ChanServ, u, CHAN_HELP_SET_PERSIST);
else if (subcommand == "NOEXPIRE")
notice_help(s_ChanServ, u, CHAN_SERVADMIN_HELP_SET_NOEXPIRE);
else