]> jfr.im git - irc/quakenet/newserv.git/blobdiff - chanserv/chanserv.c
CHANSERV: add ADDCHAN relay command.
[irc/quakenet/newserv.git] / chanserv / chanserv.c
index 1b2b5d32273becd964094452994726dd64b13ada..bbddf82e086b6466a718cc916bede5d9be901536 100644 (file)
@@ -4,82 +4,38 @@
  */
 
 #include "chanserv.h"
+#include "authlib.h"
 #include "../core/hooks.h"
 #include "../core/schedule.h"
+#include "../lib/version.h"
+
+MODULE_VERSION(QVERSION);
 
-int chanservext;
 int chanservnext;
-int chanservaext;
 
 int chanserv_init_status;
 
 sstring **chantypes;
-
-const flag rcflags[] = {
-  { 'a', QCFLAG_AUTOOP },
-  { 'b', QCFLAG_BITCH },
-  { 'c', QCFLAG_AUTOLIMIT },
-  { 'e', QCFLAG_ENFORCE },
-  { 'f', QCFLAG_FORCETOPIC },
-  { 'g', QCFLAG_AUTOVOICE },
-  { 'i', QCFLAG_INFO },
-  { 'j', QCFLAG_JOINED },
-  { 'k', QCFLAG_KNOWNONLY },
-  { 'p', QCFLAG_PROTECT },
-  { 's', QCFLAG_SPAMPROT },
-  { 't', QCFLAG_TOPICSAVE },
-  { 'v', QCFLAG_VOICEALL },
-  { 'w', QCFLAG_WELCOME },
-  { 'z', QCFLAG_SUSPENDED },
-  { '\0', 0 } };   
-
-const flag rcuflags[] = {
-  { 'a', QCUFLAG_AUTOOP },
-  { 'b', QCUFLAG_BANNED },
-  { 'd', QCUFLAG_DENY },
-  { 'g', QCUFLAG_AUTOVOICE },
-  { 'i', QCUFLAG_HIDEINFO },
-  { 'j', QCUFLAG_AUTOINVITE },
-  { 'k', QCUFLAG_KNOWN },
-  { 'm', QCUFLAG_MASTER },
-  { 'n', QCUFLAG_OWNER },
-  { 'o', QCUFLAG_OP },
-  { 'p', QCUFLAG_PROTECT },
-  { 'q', QCUFLAG_QUIET },
-  { 's', QCUFLAG_SPAMCON },
-  { 't', QCUFLAG_TOPIC },
-  { 'v', QCUFLAG_VOICE },
-  { 'w', QCUFLAG_HIDEWELCOME },
-  { '\0', 0 } };
-
-const flag ruflags[] = {
-  { 'a',  QUFLAG_ADMIN },
-  { 'd',  QUFLAG_DEV },
-  { 'g',  QUFLAG_GLINE },
-  { 'G',  QUFLAG_DELAYEDGLINE },
-  { 'h',  QUFLAG_HELPER },
-  { 'i',  QUFLAG_INFO },
-  { 'l',  QUFLAG_NEEDAUTH },
-  { 'L',  QUFLAG_NOAUTHLIMIT },
-  { 'n',  QUFLAG_NOTICE },
-  { 'o',  QUFLAG_OPER },
-  { 'p',  QUFLAG_PROTECT },
-  { 'r',  QUFLAG_RESTRICTED },
-  { 'z',  QUFLAG_SUSPENDED },
-  { '\0', 0 } };
+sstring *cs_quitreason;
 
 void chanservfreestuff();
 void chanservfinishinit(int hooknum, void *arg);
+static void cs_hourlyfunc(void *arg);
+
+DBModuleIdentifier q9dbid;
 
 void chanservdumpstuff(void *arg) {
   dumplastjoindata("lastjoin.dump");
 }
 
 void _init() {
-  /* Register the extension */
-  chanservext=registerchanext("chanserv");
+  /* Register the nick extension - the others are registered in the db module */
   chanservnext=registernickext("nickserv");
-  chanservaext=registerauthnameext("chanserv");
+
+  chanservcryptoinit();
+  csa_initregex();
+
+  q9dbid = dbgetid();
 
   if (chanservext!=-1 && chanservnext!=-1 && chanservaext!=-1) {
     /* Set up the chantypes */
@@ -91,34 +47,32 @@ void _init() {
     chantypes[4]=getsstring("special",20);
     chantypes[5]=getsstring("gamesite",20);
     chantypes[6]=getsstring("game",20);
-    
-    /* Set up the allocators and the hashes */
-    chanservallocinit();
-    chanservhashinit();
-
-    /* And the messages */
-    initmessages();
+    chantypes[7]=getsstring("upgrade",20);
+    chantypes[8]=getsstring("partner",20);
     
     /* And the log system */
     cs_initlog();
 
-    /* Now load the database */
-    chanserv_init_status = CS_INIT_DB;
-    chanservdbinit();
-
     /* Set up the command handler, and built in commands */
     chanservcommandinit();
-    chanservaddcommand("showcommands", 0, 1, cs_doshowcommands, "Lists available commands.");
-    chanservaddcommand("quit", QCMD_DEV, 1, cs_doquit, "Makes the bot QUIT and \"reconnect\".");
-    chanservaddcommand("rename", QCMD_DEV, 1, cs_dorename, "Changes the bot's name.");
-    chanservaddcommand("rehash", QCMD_DEV, 0, cs_dorehash, "Reloads all text from database.");
-    chanservaddcommand("help", 0, 1, cs_dohelp, "Displays help on a specific command.");
-    
+    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.");
+    chanservaddcommand("quit", QCMD_DEV, 1, cs_doquit, "Makes the bot QUIT and \"reconnect\".","");
+    chanservaddcommand("setquitreason", QCMD_DEV, 1, cs_dosetquitreason, "Sets the reason to be sent when quitting due to an unload.","");
+    chanservaddcommand("rename", QCMD_DEV, 1, cs_dorename, "Changes the bot's name.","");
+    chanservaddcommand("rehash", QCMD_DEV, 0, cs_dorehash, "Reloads all text from database.","");
+    /* 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. */
+    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");
+    chanservaddcommand("version", 0, 1, cs_doversion, "Show Version.","Usage: VERSION\nShows the version number of the running bot.");
+
     chanservaddctcpcommand("ping",cs_doctcpping);
     chanservaddctcpcommand("version",cs_doctcpversion);
     chanservaddctcpcommand("gender",cs_doctcpgender);
 
     registerhook(HOOK_CHANSERV_DBLOADED, chanservfinishinit);
+    
+    /* Now that the database is in a separate module it might be loaded already. */
+    if (chanservdb_ready)
+      chanservfinishinit(HOOK_CHANSERV_DBLOADED, NULL);
   }
 }
 
@@ -131,6 +85,7 @@ void chanservfinishinit(int hooknum, void *arg) {
   
   /* Schedule the dumps */
   schedulerecurring(time(NULL)+DUMPINTERVAL,0,DUMPINTERVAL,chanservdumpstuff,NULL);
+  schedulerecurring(time(NULL)+5,0,5,csdb_flushchannelcounters,NULL);
 
   chanserv_init_status = CS_INIT_NOUSER;
 
@@ -140,12 +95,14 @@ void chanservfinishinit(int hooknum, void *arg) {
   
 void chanserv_finalinit() {
   int i;
-  nick *np;
+  nick *np, *nnp;
 
   /* Scan for users */
   for (i=0;i<NICKHASHSIZE;i++)
-    for (np=nicktable[i];np;np=np->next)
+    for (np=nicktable[i];np;np=nnp) {
+      nnp=np->next;
       cs_checknick(np);
+    }
   
   /* Register core hooks */
   registerhook(HOOK_NICK_NEWNICK, cs_handlenick);
@@ -160,17 +117,29 @@ void chanserv_finalinit() {
   registerhook(HOOK_CHANNEL_BURST, cs_handleburst);
   registerhook(HOOK_CHANNEL_TOPIC, cs_handletopicchange);
   registerhook(HOOK_CHANNEL_LOSTNICK, cs_handlechanlostuser);
-  
+
+  chanserv_init_status = CS_INIT_READY;
+  triggerhook(HOOK_CHANSERV_RUNNING, NULL);  
+
+  /* run every 60 minutes, first one 5 minutes after start */
+  schedulerecurring(time(NULL)+60*5,0,3600,cs_hourlyfunc,NULL);
+
   Error("chanserv",ERR_INFO,"Ready to roll.");
 }
 
 void _fini() {
+  csdb_flushchannelcounters(NULL);
+
+  dbfreeid(q9dbid);
+
+  deleteallschedules(cs_hourlyfunc);
   deleteallschedules(cs_timerfunc);
   deleteallschedules(chanservreguser);
   deleteallschedules(chanservdumpstuff);
   deleteallschedules(chanservdgline);
+  deleteallschedules(csdb_flushchannelcounters);
 
-  if (chanservext>-1 && chanservnext>-1) {
+  if (chanservext>-1 && chanservnext>-1 && chanservaext>-1) {
     int i;
     for (i=0;i<CHANTYPES;i++)
       freesstring(chantypes[i]);
@@ -178,23 +147,15 @@ void _fini() {
     free(chantypes);
   }
     
-  chanservfreestuff();
-
   /* Free everything */
-  if (chanservext!=-1) {
-    releasechanext(chanservext);
-  }
-  
   if (chanservnext!=-1) {
     releasenickext(chanservnext);
   }
-  
-  if (chanservaext!=-1) {
-    releaseauthnameext(chanservaext);
-  }
 
   if (chanservnick)
-    deregisterlocaluser(chanservnick, "Leaving");
+    deregisterlocaluser(chanservnick, cs_quitreason?cs_quitreason->content:"Leaving");
+
+  freesstring(cs_quitreason);
 
   deregisterhook(HOOK_NICK_NEWNICK, cs_handlenick);
   deregisterhook(HOOK_NICK_ACCOUNT, cs_handlenick);
@@ -216,58 +177,48 @@ void _fini() {
 
   chanservremovecommand("showcommands", cs_doshowcommands);
   chanservremovecommand("quit", cs_doquit);
+  chanservremovecommand("setquitreason", cs_dosetquitreason);
   chanservremovecommand("rename", cs_dorename);
   chanservremovecommand("rehash", cs_dorehash);
   chanservremovecommand("help", cs_dohelp);
+  chanservremovecommand("version", cs_doversion);
   chanservremovectcpcommand("ping",cs_doctcpping);
   chanservremovectcpcommand("version",cs_doctcpversion);
   chanservremovectcpcommand("gender",cs_doctcpgender);
   chanservcommandclose();
 
-  cs_closelog();
+  csa_freeregex();
+  chanservcryptofree();
 
-  chanservdbclose();
-  csfreeall();
+  cs_closelog();
 }
 
-void chanservfreestuff() {
-  int i;
+static void cs_hourlyfunc(void *arg) {
+  int i, total = 0, touched = 0, toorecent = 0;
   chanindex *cip, *ncip;
   regchan *rcp;
-  reguser *rup;
-  regchanuser *rcup;
-  regban *rbp;
-  
-  for (i=0;i<REGUSERHASHSIZE;i++) {
-    for (rup=regusernicktable[i];rup;rup=rup->nextbyname) {
-      freesstring(rup->email);
-      freesstring(rup->lastuserhost);
-      freesstring(rup->suspendreason);
-      freesstring(rup->comment);
-      freesstring(rup->info);
-      
-      for (rcup=rup->knownon;rcup;rcup=rcup->nextbyuser)
-       freesstring(rcup->info);
-    }
-  }
+  time_t t = time(NULL);
 
   for (i=0;i<CHANNELHASHSIZE;i++) {
     for (cip=chantable[i];cip;cip=ncip) {
       ncip=cip->next;
-      if ((rcp=cip->exts[chanservext])) {
-       freesstring(rcp->welcome);
-       freesstring(rcp->topic);
-       freesstring(rcp->key);
-       freesstring(rcp->suspendreason);
-       freesstring(rcp->comment);
-       for (rbp=rcp->bans;rbp;rbp=rbp->next) {
-         freesstring(rbp->reason);
-         freechanban(rbp->cbp);
-       }
-       cip->exts[chanservext]=NULL;
-       releasechanindex(cip);
+      if (!(rcp=cip->exts[chanservext]))
+        continue;
+
+      total++;
+
+      if(cip->channel && cs_ischannelactive(cip->channel, rcp)) {
+        rcp->lastactive = t;
+        if (rcp->lastcountersync < (t - COUNTERSYNCINTERVAL)) {
+          csdb_updatechannelcounters(rcp);
+          rcp->lastcountersync=t;
+          touched++;
+        } else {
+          toorecent++;
+        }
       }
+
     }
   }
-
+  cs_log(NULL,"hourly update active completed, %d seen, %d touched, %d too recent to update.",total,touched,toorecent);
 }