#define CLEANUP_AUTHHISTORY 60
+#define CLEANUP_MIN_CHAN_SIZE 2
+
/* Sizes of the main hashes */
#define REGUSERHASHSIZE 60000
#define MAILDOMAINHASHSIZE 60000
void cs_handleopchange(int hooknum, void *arg);
void cs_handlenewban(int hooknum, void *arg);
void cs_handlechanlostuser(int hooknum, void *arg);
+int cs_ischannelactive(channel *cp, regchan *rcp);
/* chanservmessages.c */
void initmessages();
if (rup && (rup->status & QUSTAT_DEAD))
rup=NULL;
- if (rup && (rcup=findreguseronchannel(rcp,rup)) && CUHasOpPriv(rcup) && cp->users->totalusers >= 3)
+ if (rup && (rcup=findreguseronchannel(rcp,rup)) && CUHasOpPriv(rcup) && cs_ischannelactive(cp, NULL))
rcp->lastactive=time(NULL);
/* Update last use time */
csdb_updatetopic(rcp);
}
}
+
+/*
+ * active is defined as at least 2 real users (no snailbot) currently present
+ * and at least one op/master/owner.
+ * this is O(n) worst case, but very very likely to just be 2 checks.
+ */
+int cs_ischannelactive(channel *cp, regchan *rcp) {
+ int real_users = 0;
+ int seen_op = 0;
+ nick *np;
+ int i;
+
+ for (i=0;i<cp->users->hashsize;i++) {
+ if(cp->users->content[i]==nouser)
+ continue;
+
+ if((np=getnickbynumeric(cp->users->content[i]))==NULL)
+ continue;
+
+ if(NickOnServiceServer(np)) /* bad snailbot */
+ continue;
+
+ real_users++;
+
+ if(rcp && !seen_op) { /* only look for ops if we haven't seen one yet */
+ reguser *rup = getreguserfromnick(np); /* O(1) */
+ if(rup) {
+ regchanuser *rcup = findreguseronchannel(rcp, rup); /* O(1) */
+ if(rcup && CUHasOpPriv(rcup))
+ seen_op = 1;
+ }
+ }
+
+ /* so once we've seen X real users AND:
+ * - we're not looking for ops as a check had already been done by the caller
+ * - OR we're looking for ops AND we found them
+ * then the channel is active, and we're done
+ */
+ if((real_users >= CLEANUP_MIN_CHAN_SIZE) && (!rcp || (rcp && seen_op)))
+ return 1;
+ }
+
+ return 0;
+}
+
continue;
}
- if (CUKnown(rcup) && rcup->chan->index->channel->users->totalusers >= 3) {
+ if (CUHasOpPriv(rcup) && cs_ischannelactive(rcup->chan->index->channel, NULL)) {
/* This meets the channel use criteria, update. */
rcup->chan->lastactive=time(NULL);
if (!(rcp=cip->exts[chanservext]))
continue;
+ /* there's a bug here... if no joins or modes are done within the threshold
+ * and someone leaves just before the cleanup then the channel will be nuked.
+ */
+
+ /* this is one possible soln but relies on cleanupdb being run more frequently than
+ * the threshold:
+ */
+ if(cip->channel && cs_ischannelactive(cip->channel, rcp)) {
+ rcp->lastactive = t;
+ if (rcp->lastcountersync < (t - COUNTERSYNCINTERVAL)) {
+ csdb_updatechannelcounters(rcp);
+ rcp->lastcountersync=t;
+ }
+ }
+
if(rcp->lastactive < maxchan_age) {
/* don't remove channels with the original founder as an oper */
founder=findreguserbyID(rcp->founder);