]> jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chanserv.c
LUA: port luadb to dbapi2 to drop postgres dependency
[irc/quakenet/newserv.git] / chanserv / chanserv.c
1 /*
2 * chanserv.c:
3 * The main chanserv core file.
4 */
5
6 #include "chanserv.h"
7 #include "authlib.h"
8 #include "../core/hooks.h"
9 #include "../core/schedule.h"
10 #include "../lib/version.h"
11
12 MODULE_VERSION(QVERSION);
13
14 int chanservnext;
15
16 int chanserv_init_status;
17
18 sstring **chantypes;
19 sstring *cs_quitreason;
20
21 void chanservfreestuff();
22 void chanservfinishinit(int hooknum, void *arg);
23 static void cs_hourlyfunc(void *arg);
24
25 DBModuleIdentifier q9dbid;
26
27 void chanservdumpstuff(void *arg) {
28 dumplastjoindata("lastjoin.dump");
29 }
30
31 void _init() {
32 /* Register the nick extension - the others are registered in the db module */
33 chanservnext=registernickext("nickserv");
34
35 chanservcryptoinit();
36 csa_initregex();
37
38 q9dbid = dbgetid();
39
40 if (chanservext!=-1 && chanservnext!=-1 && chanservaext!=-1) {
41 /* Set up the chantypes */
42 chantypes=(sstring **)malloc(CHANTYPES*sizeof(sstring *));
43 chantypes[0]=getsstring("(unspecified)",20);
44 chantypes[1]=getsstring("clan",20);
45 chantypes[2]=getsstring("league",20);
46 chantypes[3]=getsstring("private",20);
47 chantypes[4]=getsstring("special",20);
48 chantypes[5]=getsstring("gamesite",20);
49 chantypes[6]=getsstring("game",20);
50 chantypes[7]=getsstring("upgrade",20);
51 chantypes[8]=getsstring("partner",20);
52
53 /* And the log system */
54 cs_initlog();
55
56 /* Set up the command handler, and built in commands */
57 chanservcommandinit();
58 chanservaddcommand("showcommands", 0, 1, cs_doshowcommands, "Lists available commands.","Usage: SHOWCOMMANDS [<mask>]\nPrints a list of commands currently available to you, where:\nmask - Mask of commands to list (* or ? are wildcards). If no mask is specified,\n all available commands are displayed.");
59 chanservaddcommand("quit", QCMD_DEV, 1, cs_doquit, "Makes the bot QUIT and \"reconnect\".","");
60 chanservaddcommand("setquitreason", QCMD_DEV, 1, cs_dosetquitreason, "Sets the reason to be sent when quitting due to an unload.","");
61 chanservaddcommand("rename", QCMD_DEV, 1, cs_dorename, "Changes the bot's name.","");
62 chanservaddcommand("rehash", QCMD_DEV, 0, cs_dorehash, "Reloads all text from database.","");
63 /* Make "HELP" take 2 arguments so things like "HELP chanflags #channel" work. Any junk after the command will go into arg 2 and be ignored. */
64 chanservaddcommand("help", 0, 2, cs_dohelp, "Displays help on a specific command.","Usage: HELP <command>\nShows help for a command, where:\ncommand - the command to show help for.\nFor a list of available commands, see SHOWCOMMANDS.\n");
65 chanservaddcommand("version", 0, 1, cs_doversion, "Show Version.","Usage: VERSION\nShows the version number of the running bot.");
66
67 chanservaddctcpcommand("ping",cs_doctcpping);
68 chanservaddctcpcommand("version",cs_doctcpversion);
69 chanservaddctcpcommand("gender",cs_doctcpgender);
70
71 registerhook(HOOK_CHANSERV_DBLOADED, chanservfinishinit);
72
73 /* Now that the database is in a separate module it might be loaded already. */
74 if (chanservdb_ready)
75 chanservfinishinit(HOOK_CHANSERV_DBLOADED, NULL);
76 }
77 }
78
79 void chanservfinishinit(int hooknum, void *arg) {
80 Error("chanserv",ERR_INFO,"Database loaded, finishing initialisation.");
81
82 deregisterhook(HOOK_CHANSERV_DBLOADED, chanservfinishinit);
83
84 readlastjoindata("lastjoin.dump");
85
86 /* Schedule the dumps */
87 schedulerecurring(time(NULL)+DUMPINTERVAL,0,DUMPINTERVAL,chanservdumpstuff,NULL);
88 schedulerecurring(time(NULL)+5,0,5,csdb_flushchannelcounters,NULL);
89
90 chanserv_init_status = CS_INIT_NOUSER;
91
92 /* Register the user */
93 scheduleoneshot(time(NULL)+1,&chanservreguser,NULL);
94 }
95
96 void chanserv_finalinit() {
97 int i;
98 nick *np, *nnp;
99
100 /* Scan for users */
101 for (i=0;i<NICKHASHSIZE;i++)
102 for (np=nicktable[i];np;np=nnp) {
103 nnp=np->next;
104 cs_checknick(np);
105 }
106
107 /* Register core hooks */
108 registerhook(HOOK_NICK_NEWNICK, cs_handlenick);
109 registerhook(HOOK_NICK_ACCOUNT, cs_handlenick);
110 registerhook(HOOK_NICK_LOSTNICK, cs_handlelostnick);
111 registerhook(HOOK_NICK_SETHOST, cs_handlesethost);
112 registerhook(HOOK_CHANNEL_NEWCHANNEL, cs_handlenewchannel);
113 registerhook(HOOK_CHANNEL_LOSTCHANNEL, cs_handlelostchannel);
114 registerhook(HOOK_CHANNEL_JOIN, cs_handlejoin);
115 registerhook(HOOK_CHANNEL_CREATE, cs_handlejoin);
116 registerhook(HOOK_CHANNEL_MODECHANGE, cs_handlemodechange);
117 registerhook(HOOK_CHANNEL_BURST, cs_handleburst);
118 registerhook(HOOK_CHANNEL_TOPIC, cs_handletopicchange);
119 registerhook(HOOK_CHANNEL_LOSTNICK, cs_handlechanlostuser);
120
121 chanserv_init_status = CS_INIT_READY;
122 triggerhook(HOOK_CHANSERV_RUNNING, NULL);
123
124 /* run every 60 minutes, first one 5 minutes after start */
125 schedulerecurring(time(NULL)+60*5,0,3600,cs_hourlyfunc,NULL);
126
127 Error("chanserv",ERR_INFO,"Ready to roll.");
128 }
129
130 void _fini() {
131 csdb_flushchannelcounters(NULL);
132
133 dbfreeid(q9dbid);
134
135 deleteallschedules(cs_hourlyfunc);
136 deleteallschedules(cs_timerfunc);
137 deleteallschedules(chanservreguser);
138 deleteallschedules(chanservdumpstuff);
139 deleteallschedules(chanservdgline);
140 deleteallschedules(csdb_flushchannelcounters);
141
142 if (chanservext>-1 && chanservnext>-1 && chanservaext>-1) {
143 int i;
144 for (i=0;i<CHANTYPES;i++)
145 freesstring(chantypes[i]);
146
147 free(chantypes);
148 }
149
150 /* Free everything */
151 if (chanservnext!=-1) {
152 releasenickext(chanservnext);
153 }
154
155 if (chanservnick)
156 deregisterlocaluser(chanservnick, cs_quitreason?cs_quitreason->content:"Leaving");
157
158 freesstring(cs_quitreason);
159
160 deregisterhook(HOOK_NICK_NEWNICK, cs_handlenick);
161 deregisterhook(HOOK_NICK_ACCOUNT, cs_handlenick);
162 deregisterhook(HOOK_NICK_LOSTNICK, cs_handlelostnick);
163 deregisterhook(HOOK_NICK_SETHOST, cs_handlesethost);
164 deregisterhook(HOOK_CHANNEL_NEWCHANNEL, cs_handlenewchannel);
165 deregisterhook(HOOK_CHANNEL_LOSTCHANNEL, cs_handlelostchannel);
166 deregisterhook(HOOK_CHANNEL_JOIN, cs_handlejoin);
167 deregisterhook(HOOK_CHANNEL_CREATE, cs_handlejoin);
168 deregisterhook(HOOK_CHANNEL_MODECHANGE, cs_handlemodechange);
169 deregisterhook(HOOK_CHANNEL_BURST, cs_handleburst);
170 deregisterhook(HOOK_CHANNEL_TOPIC, cs_handletopicchange);
171 deregisterhook(HOOK_CHANNEL_LOSTNICK, cs_handlechanlostuser);
172 /* deregisterhook(HOOK_CHANNEL_OPPED, cs_handleopchange);
173 deregisterhook(HOOK_CHANNEL_DEOPPED, cs_handleopchange);
174 deregisterhook(HOOK_CHANNEL_DEVOICED, cs_handleopchange);
175 deregisterhook(HOOK_CHANNEL_BANSET, cs_handlenewban); */
176 deregisterhook(HOOK_CHANSERV_DBLOADED, chanservfinishinit); /* for safety */
177
178 chanservremovecommand("showcommands", cs_doshowcommands);
179 chanservremovecommand("quit", cs_doquit);
180 chanservremovecommand("setquitreason", cs_dosetquitreason);
181 chanservremovecommand("rename", cs_dorename);
182 chanservremovecommand("rehash", cs_dorehash);
183 chanservremovecommand("help", cs_dohelp);
184 chanservremovecommand("version", cs_doversion);
185 chanservremovectcpcommand("ping",cs_doctcpping);
186 chanservremovectcpcommand("version",cs_doctcpversion);
187 chanservremovectcpcommand("gender",cs_doctcpgender);
188 chanservcommandclose();
189
190 csa_freeregex();
191 chanservcryptofree();
192
193 cs_closelog();
194 }
195
196 static void cs_hourlyfunc(void *arg) {
197 int i, total = 0, touched = 0, toorecent = 0;
198 chanindex *cip, *ncip;
199 regchan *rcp;
200 time_t t = time(NULL);
201
202 for (i=0;i<CHANNELHASHSIZE;i++) {
203 for (cip=chantable[i];cip;cip=ncip) {
204 ncip=cip->next;
205 if (!(rcp=cip->exts[chanservext]))
206 continue;
207
208 total++;
209
210 if(cip->channel && cs_ischannelactive(cip->channel, rcp)) {
211 rcp->lastactive = t;
212 if (rcp->lastcountersync < (t - COUNTERSYNCINTERVAL)) {
213 csdb_updatechannelcounters(rcp);
214 rcp->lastcountersync=t;
215 touched++;
216 } else {
217 toorecent++;
218 }
219 }
220
221 }
222 }
223 cs_log(NULL,"hourly update active completed, %d seen, %d touched, %d too recent to update.",total,touched,toorecent);
224 }