diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bots.cpp | 9 | ||||
-rw-r--r-- | src/channels.c | 41 | ||||
-rw-r--r-- | src/config.c | 1 | ||||
-rw-r--r-- | src/core/bs_unassign.c | 8 | ||||
-rw-r--r-- | src/core/cs_info.c | 1 | ||||
-rw-r--r-- | src/core/cs_register.c | 10 | ||||
-rw-r--r-- | src/core/cs_set.c | 82 |
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 |