]> jfr.im git - irc/quakenet/newserv.git/blame - chanserv/usercmds/cleanupdb.c
CHANSERV: only update channels as active if they have at least one known op, and...
[irc/quakenet/newserv.git] / chanserv / usercmds / cleanupdb.c
CommitLineData
7ac9dbae
P
1/* Automatically generated by refactor.pl.
2 *
3 *
4 * CMDNAME: cleanupdb
85174237 5 * CMDLEVEL: QCMD_DEV
7ac9dbae 6 * CMDARGS: 0
85174237 7 * CMDDESC: Clean up database.
7ac9dbae
P
8 * CMDFUNC: csu_docleanupdb
9 * CMDPROTO: int csu_docleanupdb(void *source, int cargc, char **cargv);
85174237 10 * CMDHELP: Usage: cleanupdb
a6f1f6b6 11 * CMDHELP: Cleans up inactive accounts, unused accounts and inactive channels.
7ac9dbae
P
12 */
13
14#include "../chanserv.h"
15#include "../../lib/irc_string.h"
16#include <stdio.h>
17#include <string.h>
18
511881d6 19unsigned int cleanupdb_active;
20
21void csu_docleanupdb_real(DBConn *dbconn, void *arg) {
22 nick *sender=getnickbynumeric((unsigned long)arg);
a6f1f6b6 23 reguser *vrup, *srup, *founder;
e9484491 24 regchanuser *rcup, *nrcup;
23b85e10 25 authname *anp;
e9484491 26 int i,j;
86a73ca1 27 time_t t, to_age, unused_age, maxchan_age, authhistory_age;
a6f1f6b6
CP
28 int expired = 0, unauthed = 0, chansvaped = 0;
29 chanindex *cip, *ncip;
30 regchan *rcp;
511881d6 31 DBResult *pgres;
32 unsigned int themarker;
33 unsigned int id;
34
cf50e022 35 t = time(NULL);
a6f1f6b6
CP
36 to_age = t - (CLEANUP_ACCOUNT_INACTIVE * 3600 * 24);
37 unused_age = t - (CLEANUP_ACCOUNT_UNUSED * 3600 * 24);
38 maxchan_age = t - (CLEANUP_CHANNEL_INACTIVE * 3600 * 24);
86a73ca1 39 authhistory_age = t - (CLEANUP_AUTHHISTORY * 3600 * 24);
7ac9dbae 40
511881d6 41 themarker=nextauthnamemarker();
42
43 if (!dbconn) {
44 if (sender)
45 chanservsendmessage(sender, "No DB connection, aborting cleanup.");
46 goto out;
47 }
48
49 pgres=dbgetresult(dbconn);
50
51 if (!dbquerysuccessful(pgres)) {
52 Error("chanserv", ERR_ERROR, "Error loading cleanupdb data.");
53 if (sender)
54 chanservsendmessage(sender, "DB error, aborting cleanup.");
55 goto out;
56 }
57
58 while (dbfetchrow(pgres)) {
59 id=strtoul(dbgetvalue(pgres, 0), NULL, 10);
60 anp=findauthname(id);
61 if (anp)
62 anp->marker=themarker;
63 }
64
65 dbclear(pgres);
66
a6f1f6b6
CP
67 cs_log(sender, "CLEANUPDB started");
68
511881d6 69 if (sender)
70 chanservsendmessage(sender, "Scanning regusers...");
7ac9dbae
P
71 for (i=0;i<REGUSERHASHSIZE;i++) {
72 for (vrup=regusernicktable[i]; vrup; vrup=srup) {
73 srup=vrup->nextbyname;
23b85e10 74 if (!(anp=findauthname(vrup->ID)))
75 continue; /* should maybe raise hell instead */
a6f1f6b6 76
511881d6 77 /* If this user has the right marker, this means the authtracker data
78 * indicates that they have been active recently */
79 if (anp->marker == themarker)
80 continue;
81
372e4f1d 82 if(!anp->nicks && !UHasStaffPriv(vrup) && !UIsCleanupExempt(vrup)) {
cf50e022
CP
83 if(vrup->lastauth && (vrup->lastauth < to_age)) {
84 expired++;
fc40d46b 85 cs_log(sender, "CLEANUPDB inactive user %s %u", vrup->username, vrup->ID);
cf50e022
CP
86 } else if(!vrup->lastauth && (vrup->created < unused_age)) {
87 unauthed++;
fc40d46b 88 cs_log(sender, "CLEANUPDB unused user %s %u", vrup->username, vrup->ID);
cf50e022
CP
89 } else {
90 continue;
91 }
92
7ac9dbae 93 cs_removeuser(vrup);
7ac9dbae
P
94 }
95 }
96 }
a6f1f6b6 97
511881d6 98 if (sender)
99 chanservsendmessage(sender, "Scanning chanindicies...");
100
a6f1f6b6
CP
101 for (i=0;i<CHANNELHASHSIZE;i++) {
102 for (cip=chantable[i];cip;cip=ncip) {
103 ncip=cip->next;
104 if (!(rcp=cip->exts[chanservext]))
105 continue;
106
bbdc40a1
CP
107 /* there's a bug here... if no joins or modes are done within the threshold
108 * and someone leaves just before the cleanup then the channel will be nuked.
109 */
110
111 /* this is one possible soln but relies on cleanupdb being run more frequently than
112 * the threshold:
113 */
114 if(cip->channel && cs_ischannelactive(cip->channel, rcp)) {
115 rcp->lastactive = t;
116 if (rcp->lastcountersync < (t - COUNTERSYNCINTERVAL)) {
117 csdb_updatechannelcounters(rcp);
118 rcp->lastcountersync=t;
119 }
120 }
121
a6f1f6b6
CP
122 if(rcp->lastactive < maxchan_age) {
123 /* don't remove channels with the original founder as an oper */
124 founder=findreguserbyID(rcp->founder);
125 if(founder && UHasOperPriv(founder))
126 continue;
127
128 cs_log(sender, "CLEANUPDB inactive channel %s", cip->name?cip->name->content:"??");
41938c9d 129 cs_removechannel(rcp, "Channel deleted due to lack of activity.");
a6f1f6b6
CP
130 chansvaped++;
131 }
374a30be 132
133 /* Get rid of any dead chanlev entries */
134 for (j=0;j<REGCHANUSERHASHSIZE;j++) {
e9484491 135 for (rcup=rcp->regusers[j];rcup;rcup=nrcup) {
374a30be 136 nrcup=rcup->nextbychan;
137
138 if (!rcup->flags) {
511881d6 139 if (sender)
140 chanservsendmessage(sender, "Removing user %s from channel %s (no flags)",rcup->user->username,rcp->index->name->content);
374a30be 141 csdb_deletechanuser(rcup);
142 delreguserfromchannel(rcp, rcup->user);
374a30be 143 }
144 }
145 }
a6f1f6b6
CP
146 }
147 }
7ac9dbae 148
511881d6 149 if (sender)
150 chanservsendmessage(sender, "Starting history database cleanup (will run in background).");
151
86a73ca1 152 csdb_cleanuphistories(authhistory_age);
153
a6f1f6b6 154 cs_log(sender, "CLEANUPDB complete %d inactive accounts %d unused accounts %d channels", expired, unauthed, chansvaped);
511881d6 155 if (sender)
156 chanservsendmessage(sender, "Cleanup complete, %d accounts inactive for %d days, %d accounts weren't used within %d days, %d channels were inactive for %d days.", expired, CLEANUP_ACCOUNT_INACTIVE, unauthed, CLEANUP_ACCOUNT_UNUSED, chansvaped, CLEANUP_CHANNEL_INACTIVE);
157
158out:
159 cleanupdb_active=0;
160}
161
162int csu_docleanupdb(void *source, int cargc, char **cargv) {
163 nick *sender=source;
164 unsigned int to_age;
165
166 to_age = time(NULL) - (CLEANUP_ACCOUNT_INACTIVE * 3600 * 24);
167
168 if (cleanupdb_active) {
169 chanservsendmessage(sender, "Cleanup already in progress.\n");
170 return CMD_ERROR;
171 }
172
173 /* This query returns a single column containing the userids of all users
174 * who have active sessions now, or sessions which ended in the last
175 * CLEANUP_ACCOUNT_INACTIVE days. */
176 q9u_asyncquery(csu_docleanupdb_real, (void *)sender->numeric,
177 "SELECT userID from chanserv.authhistory WHERE disconnecttime=0 OR disconnecttime > %d GROUP BY userID", to_age);
178
179 chanservsendmessage(sender, "Retrieving auth history data, cleanup will proceed when done.");
180
181 cleanupdb_active=1;
182
80d2de64 183 return CMD_OK;
7ac9dbae 184}
511881d6 185