/* chanserv.c - Channel service bot
* Copyright 2000-2004 srvx Development Team
*
- * This program is free software; you can redistribute it and/or modify
+ * This file is part of srvx.
+ *
+ * srvx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version. Important limitations are
- * listed in the COPYING file that accompanies this software.
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, email srvx-maintainers@srvx.net.
+ * along with srvx; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include "chanserv.h"
{ "CSMSG_DELETED_YOU", "Your $b%d$b access has been deleted from $b%s$b." },
/* User management */
- { "CSMSG_ADDED_USER", "Added new %s to the %s user list with access %d." },
+ { "CSMSG_ADDED_USER", "Added %s to the %s user list with access %d." },
{ "CSMSG_DELETED_USER", "Deleted %s (with access %d) from the %s user list." },
{ "CSMSG_BAD_RANGE", "Invalid access range; minimum (%d) must be greater than maximum (%d)." },
{ "CSMSG_DELETED_USERS", "Deleted accounts matching $b%s$b with access from $b%d$b to $b%d$b from the %s user list." },
struct mod_chanmode change;
unsigned int ii;
bans = bd->channel->channel->banlist;
- change.modes_set = change.modes_clear = 0;
- change.argc = 0;
+ mod_chanmode_init(&change);
for(ii=0; ii<bans.used; ii++)
{
if(!strcmp(bans.list[ii]->ban, bd->mask))
else if(!IsSuspended(channel->channel_info))
{
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_CHANOP;
change.args[0].member = AddChannelUser(chanserv, target);
return 0;
}
channel->channel_info->may_opchan = 0;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_CHANOP;
change.args[0].member = GetUserMode(channel, chanserv);
struct userData *uData;
const char *errmsg;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].member = GetUserMode(channel, user);
if(!change.args[0].member)
{
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].member = GetUserMode(channel, user);
if(!change.args[0].member)
free(bData->reason);
bData->reason = strdup(reason);
safestrncpy(bData->owner, (user->handle_info ? user->handle_info->handle : user->nick), sizeof(bData->owner));
- reply("CSMSG_REASON_CHANGE", ban);
+ if(cmd)
+ reply("CSMSG_REASON_CHANGE", ban);
if(!bData->expires)
goto post_add_ban;
}
if(bData->expires)
timeq_add(bData->expires, expire_ban, bData);
- if(duration)
+ if(!cmd)
+ {
+ /* automated kickban */
+ }
+ else if(duration)
reply("CSMSG_BAN_EXTENDED", ban, intervalString(interval, duration));
else
reply("CSMSG_BAN_ADDED", name, channel->name);
goto post_add_ban;
}
}
- reply("CSMSG_REDUNDANT_BAN", name, channel->name);
+ if(cmd)
+ reply("CSMSG_REDUNDANT_BAN", name, channel->name);
free(ban);
return 0;
if(channel->banlist.used >= MAXBANS)
{
- reply("CSMSG_BANLIST_FULL", channel->name);
+ if(cmd)
+ reply("CSMSG_BANLIST_FULL", channel->name);
free(ban);
return 0;
}
if(exists && (action == ACTION_BAN))
{
- reply("CSMSG_REDUNDANT_BAN", name, channel->name);
+ if(cmd)
+ reply("CSMSG_REDUNDANT_BAN", name, channel->name);
free(ban);
return 0;
}
{
table_send(cmd->parent->bot, user->nick, 0, NULL, tbl);
reply("MSG_NONE");
+ free(tbl.contents[0]);
+ free(tbl.contents);
return 0;
}
{
struct modeNode *mn = channel->members.list[ii];
struct userData *uData;
+
if(IsService(mn->user))
+ continue;
+
+ uData = GetChannelAccess(cData, mn->user->handle_info);
+ if(!cData->lvlOpts[lvlGiveOps]
+ || (uData && uData->access >= cData->lvlOpts[lvlGiveOps]))
{
- /* must not change modes for this user */
- }
- else if(!(uData = GetChannelAccess(cData, mn->user->handle_info)))
- {
- if(mn->modes)
+ if(!(mn->modes & MODE_CHANOP))
{
- changes->args[used].mode = MODE_REMOVE | mn->modes;
+ changes->args[used].mode = MODE_CHANOP;
changes->args[used++].member = mn;
}
}
- else if(uData->access < cData->lvlOpts[lvlGiveOps])
+ else if(!cData->lvlOpts[lvlGiveVoice]
+ || (uData && uData->access >= cData->lvlOpts[lvlGiveVoice]))
{
if(mn->modes & MODE_CHANOP)
{
}
else
{
- if(!(mn->modes & MODE_CHANOP))
+ if(mn->modes)
{
- changes->args[used].mode = MODE_CHANOP;
+ changes->args[used].mode = MODE_REMOVE | mn->modes;
changes->args[used++].member = mn;
}
}
{
REQUIRE_PARAMS(3);
msg = unsplit_string(argv + 2, argc - 2, NULL);
- send_target_message(1, argv[1], cmd->parent->bot, "%s", msg);
+ send_target_message(5, argv[1], cmd->parent->bot, "%s", msg);
}
else
{
- reply("You must specify the name of a channel or user.");
+ reply("MSG_NOT_TARGET_NAME");
return 0;
}
return 1;
else if(GetUserH(argv[1]))
{
msg = unsplit_string(argv + 2, argc - 2, NULL);
- send_target_message(1, argv[1], cmd->parent->bot, "\001ACTION %s\001", msg);
+ send_target_message(5, argv[1], cmd->parent->bot, "\001ACTION %s\001", msg);
}
else
{
- reply("You must specify the name of a channel or user.");
+ reply("MSG_NOT_TARGET_NAME");
return 0;
}
return 1;
channel = suspended->cData->channel;
suspended->cData->channel = channel;
suspended->cData->flags &= ~CHANNEL_SUSPENDED;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_CHANOP;
change.args[0].member = AddChannelUser(chanserv, channel);
CHANNEL_BINARY_OPTION("CSMSG_SET_DYNLIMIT", CHANNEL_DYNAMIC_LIMIT);
}
-/* TODO: reimplement
-
-static MODCMD_FUNC(chan_opt_userinfo)
-{
- CHANNEL_BINARY_OPTION("CSMSG_SET_USERINFO", CHANNEL_INFO_LINES);
-}
-
-static MODCMD_FUNC(chan_opt_voice)
-{
- CHANNEL_BINARY_OPTION("CSMSG_SET_VOICE", CHANNEL_VOICE_ALL);
-}
-
-static MODCMD_FUNC(chan_opt_topicsnarf)
-{
- if((argc > 0) && !check_user_level(channel, user, lvlEnfTopic, 1, 0))
- {
- reply("CSMSG_TOPIC_LOCKED", channel->name);
- return 0;
- }
- CHANNEL_BINARY_OPTION("CSMSG_SET_TOPICSNARF", CHANNEL_TOPIC_SNARF);
-}
-
-static MODCMD_FUNC(chan_opt_peoninvite)
-{
- CHANNEL_BINARY_OPTION("CSMSG_SET_PEONINVITE", CHANNEL_PEON_INVITE);
-}
-
-*/
-
static MODCMD_FUNC(chan_opt_defaults)
{
struct userData *uData;
static CHANSERV_FUNC(cmd_huggle)
{
- char response[MAXLEN];
- const char *fmt;
/* CTCP must be via PRIVMSG, never notice */
if(channel)
- {
- fmt = user_find_message(user, "CSMSG_HUGGLES_HIM");
- sprintf(response, fmt, user->nick);
- irc_privmsg(cmd->parent->bot, channel->name, response);
- }
+ send_target_message(1, channel->name, cmd->parent->bot, "CSMSG_HUGGLES_HIM", user->nick);
else
- {
- fmt = user_find_message(user, "CSMSG_HUGGLES_YOU");
- irc_privmsg(cmd->parent->bot, user->nick, fmt);
- }
+ send_target_message(1, user->nick, cmd->parent->bot, "CSMSG_HUGGLES_YOU");
return 1;
}
return;
}
+ mod_chanmode_init(&change);
change.modes_set = MODE_LIMIT;
- change.modes_clear = 0;
change.new_limit = limit;
- change.argc = 0;
mod_chanmode_announce(chanserv, channel, &change);
}
}
}
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
if(channel->banlist.used < MAXBANS)
{
if(bData != cData->bans)
{
/* Shuffle the ban to the head of the list. */
- if(bData->next) bData->next->prev = bData->prev;
- if(bData->prev) bData->prev->next = bData->next;
+ if(bData->next)
+ bData->next->prev = bData->prev;
+ if(bData->prev)
+ bData->prev->next = bData->next;
bData->prev = NULL;
bData->next = cData->bans;
if(!user->handle_info)
return;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
for(channel = user->handle_info->channels; channel; channel = channel->u_next)
{
change.args[0].mode = MODE_CHANOP;
else if(channel->access >= cn->channel_info->lvlOpts[lvlGiveVoice])
change.args[0].mode = MODE_VOICE;
+ else
+ change.args[0].mode = 0;
change.args[0].member = mn;
- mod_chanmode_announce(chanserv, cn, &change);
+ if(change.args[0].mode)
+ mod_chanmode_announce(chanserv, cn, &change);
}
channel->seen = now;
}
if((uData = GetTrueChannelAccess(cData, user->handle_info)))
+ {
scan_user_presence(uData, user);
+ uData->seen = now;
+ }
if(IsHelping(user) && IsSupportHelper(user))
{
static void
handle_kick(struct userNode *kicker, struct userNode *victim, struct chanNode *channel)
{
+ struct userData *uData;
+
if(!channel->channel_info || !kicker || IsService(kicker)
|| (kicker == victim) || IsSuspended(channel->channel_info)
|| (kicker->handle_info && kicker->handle_info == victim->handle_info))
const char *reason = user_find_message(kicker, "CSMSG_USER_PROTECTED");
KickChannelUser(kicker, channel, chanserv, reason);
}
+
+ if((uData = GetTrueChannelAccess(channel->channel_info, victim->handle_info)))
+ uData->seen = now;
}
static int
&& mode_lock_violated(&channel->channel_info->modes, change))
{
char correct[MAXLEN];
- bounce = mod_chanmode_alloc(change->argc + 1);
- *bounce = channel->channel_info->modes;
+ bounce = mod_chanmode_dup(&channel->channel_info->modes, change->argc + 1);
mod_chanmode_format(&channel->channel_info->modes, correct);
send_message(user, chanserv, "CSMSG_MODE_LOCKED", correct, channel->name);
}
unsigned int ii, jj;
char kick_reason[MAXLEN];
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_BAN;
for(ii = 0; ii < user->channels.used; ++ii)
if(!(cData->flags & CHANNEL_SUSPENDED))
{
struct mod_chanmode change;
- change.modes_set = change.modes_clear = 0;
+ mod_chanmode_init(&change);
change.argc = 1;
change.args[0].mode = MODE_CHANOP;
change.args[0].member = AddChannelUser(chanserv, cNode);
DEFINE_COMMAND(mdelpeon, 2, MODCMD_REQUIRE_CHANUSER, "access", "master", NULL);
DEFINE_COMMAND(trim, 3, MODCMD_REQUIRE_CHANUSER, "access", "master", NULL);
- DEFINE_COMMAND(opchan, 1, MODCMD_REQUIRE_REGCHAN, "access", "1", NULL);
+ DEFINE_COMMAND(opchan, 1, MODCMD_REQUIRE_REGCHAN|MODCMD_NEVER_CSUSPEND, "access", "1", NULL);
DEFINE_COMMAND(clvl, 3, MODCMD_REQUIRE_CHANUSER, "access", "master", NULL);
DEFINE_COMMAND(giveownership, 2, MODCMD_REQUIRE_CHANUSER, "access", "owner", "flags", "+loghostmask", NULL);