#define KEY_NOTES "notes"
#define KEY_TOPIC_MASK "topic_mask"
#define KEY_OWNER_TRANSFER "owner_transfer"
+#define KEY_EXPIRE "expire"
/* User data */
#define KEY_LEVEL "level"
{ "CSMSG_SET_CTCPREACTION", "$bCTCPReaction$b %d - %s" },
{ "CSMSG_SET_TOPICREFRESH", "$bTopicRefresh$b %d - %s" },
{ "CSMSG_SET_UNREVIEWED", "$bUnreviewed $b %s" },
+ { "CSMSG_SET_EXPIRE", "$bExpire $b %s" },
+ { "CSMSG_SET_EXPIRE_OFF", "$bExpire $b off" },
{ "CSMSG_USET_NOAUTOOP", "$bNoAutoOp $b %s" },
{ "CSMSG_USET_NOAUTOVOICE", "$bNoAutoVoice $b %s" },
{ "CSMSG_USET_AUTOINVITE", "$bAutoInvite $b %s" },
return 1;
}
+static void
+chanserv_expire_channel(void *data)
+{
+ struct chanData *channel = data;
+ char reason[MAXLEN];
+ sprintf(reason, "channel expired.");
+ channel->expiry = 0;
+ spamserv_cs_unregister(NULL, channel->channel, expire, NULL);
+ unregister_channel(channel, reason);
+}
+
+static MODCMD_FUNC(chan_opt_expire)
+{
+ struct chanData *cData = channel->channel_info;
+ unsigned long value = cData->expiry;
+
+ if(argc > 1)
+ {
+ if((!IsOper(user) || !user->handle_info || (user->handle_info->opserv_level < chanserv_conf.nodelete_level)))
+ {
+ reply("MSG_SETTING_PRIVILEGED", argv[0]);
+ return 0;
+ }
+ unsigned long expiry,duration;
+
+ /* The two directions can have different ACLs. */
+ if(!strcmp(argv[1], "0"))
+ expiry = 0;
+ else if((duration = ParseInterval(argv[1])))
+ expiry = now + duration;
+ else
+ {
+ reply("MSG_INVALID_DURATION", argv[1]);
+ return 0;
+ }
+
+ if (expiry != value)
+ {
+ if(value) {
+ //unset old timer
+ timeq_del(value, chanserv_expire_channel, cData, 0);
+ }
+ value = expiry;
+ cData->expiry = value;
+ if(value > 0) {
+ //New timer!
+ timeq_add(expiry, chanserv_expire_channel, cData);
+ }
+ }
+ }
+
+ if(cData->expiry > now) {
+ char expirestr[INTERVALLEN];
+ reply("CSMSG_SET_EXPIRE", intervalString(expirestr, cData->expiry - now, user->handle_info));
+ } else
+ reply("CSMSG_SET_EXPIRE_OFF");
+ return 1;
+}
+
static int
mode_lock_violated(const struct mod_chanmode *orig, const struct mod_chanmode *change)
{
return ud;
}
-static void unregister_channel(struct chanData *channel, const char *reason);
-
void
del_channel_user(struct userData *user, int do_gc)
{
if(cNode)
cNode->channel_info = NULL;
}
+ if(channel->expiry)
+ timeq_del(channel->expiry, chanserv_expire_channel, channel, 0);
channel->channel->channel_info = NULL;
dict_delete(channel->notes);
/* multiple choice options */
"CtcpReaction", "Protect", "Toys", "TopicRefresh",
/* binary options */
- "DynLimit", "NoDelete",
+ "DynLimit", "NoDelete", "expire",
/* delimiter */
NULL
};
cData->chOpts[chOpt] = ((count <= charOptions[chOpt].old_idx) ? str : CHANNEL_DEFAULT_OPTIONS)[charOptions[chOpt].old_idx];
}
+ if((str = database_get_data(hir->d.object, KEY_EXPIRE, RECDB_QSTRING)))
+ {
+ cData->expiry = atoi(str);
+ if(cData->expiry > 0) {
+ if(cData->expiry > now) {
+ timeq_add(cData->expiry, chanserv_expire_channel, cData);
+ } else {
+ timeq_add(1, chanserv_expire_channel, cData);
+ }
+ }
+ } else {
+ cData->expiry = 0;
+ }
+
if((obj = database_get_data(hir->d.object, KEY_SUSPENDED, RECDB_OBJECT)))
{
suspended = chanserv_read_suspended(obj);
saxdb_write_string(ctx, KEY_TOPIC_MASK, channel->topic_mask);
if(channel->suspended)
chanserv_write_suspended(ctx, "suspended", channel->suspended);
+ if(channel->expiry)
+ saxdb_write_int(ctx, KEY_EXPIRE, channel->expiry);
saxdb_start_record(ctx, KEY_OPTIONS, 0);
saxdb_write_int(ctx, KEY_FLAGS, channel->flags);
DEFINE_CHANNEL_OPTION(ctcpreaction);
DEFINE_CHANNEL_OPTION(inviteme);
DEFINE_CHANNEL_OPTION(unreviewed);
+ modcmd_register(chanserv_module, "set expire", chan_opt_expire, 1, 0, "flags", "+helping", NULL);
modcmd_register(chanserv_module, "set unreviewed on", NULL, 0, 0, "flags", "+helping", NULL);
modcmd_register(chanserv_module, "set unreviewed off", NULL, 0, 0, "flags", "+oper", NULL);
if(off_channel > 1)