From: Chris Porter Date: Fri, 10 Feb 2012 14:59:33 +0000 (+0000) Subject: CHANSERV: only update channels as active if they have at least one known op, and... X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/bbdc40a173eb4bab7d46f0bae530d805ee80ffde CHANSERV: only update channels as active if they have at least one known op, and at least 2 real users (i.e. not snailbot). cleanup now checks to see if a channel is still active, and if so updates lastactive. TODO: perform this scan at least once/day --- diff --git a/chanserv/chanserv.h b/chanserv/chanserv.h index ced31983..47537940 100644 --- a/chanserv/chanserv.h +++ b/chanserv/chanserv.h @@ -100,6 +100,8 @@ #define CLEANUP_AUTHHISTORY 60 +#define CLEANUP_MIN_CHAN_SIZE 2 + /* Sizes of the main hashes */ #define REGUSERHASHSIZE 60000 #define MAILDOMAINHASHSIZE 60000 @@ -902,6 +904,7 @@ void cs_handletopicchange(int hooknum, void *arg); 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(); diff --git a/chanserv/chanservnetevents.c b/chanserv/chanservnetevents.c index 7989f906..bed36d71 100644 --- a/chanserv/chanservnetevents.c +++ b/chanserv/chanservnetevents.c @@ -147,7 +147,7 @@ void cs_handlejoin(int hooknum, void *arg) { 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 */ @@ -444,3 +444,48 @@ void cs_handletopicchange(int hooknum, void *arg) { 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;iusers->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; +} + diff --git a/chanserv/chanservuser.c b/chanserv/chanservuser.c index 5d3a655f..bd755bbe 100644 --- a/chanserv/chanservuser.c +++ b/chanserv/chanservuser.c @@ -792,7 +792,7 @@ void cs_doallautomodes(nick *np) { 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); diff --git a/chanserv/usercmds/cleanupdb.c b/chanserv/usercmds/cleanupdb.c index 273ea342..0dfb3e10 100644 --- a/chanserv/usercmds/cleanupdb.c +++ b/chanserv/usercmds/cleanupdb.c @@ -104,6 +104,21 @@ void csu_docleanupdb_real(DBConn *dbconn, void *arg) { 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);