2 * This is the first client module for newserv :)
4 * A very simple bot which should give people some ideas for how to
5 * implement stuff on this thing
8 #include "../irc/irc_config.h"
9 #include "../parser/parser.h"
10 #include "../localuser/localuser.h"
11 #include "../localuser/localuserchannel.h"
12 #include "../nick/nick.h"
13 #include "../lib/sstring.h"
14 #include "../core/config.h"
15 #include "../irc/irc.h"
16 #include "../lib/splitline.h"
17 #include "../channel/channel.h"
18 #include "../lib/flags.h"
19 #include "../core/schedule.h"
20 #include "../lib/base64.h"
21 #include "../core/modules.h"
32 CommandTree
*controlcmds
;
33 ControlMsg controlreply
;
34 ControlWall controlwall
;
36 void handlemessages(nick
*target
, int messagetype
, void **args
);
37 int controlstatus(void *sender
, int cargc
, char **cargv
);
38 void controlconnect(void *arg
);
39 int controlwhois(void *sender
, int cargc
, char **cargv
);
40 int controlchannel(void *sender
, int cargc
, char **cargv
);
41 int relink(void *sender
, int cargc
, char **cargv
);
42 int die(void *sender
, int cargc
, char **cargv
);
43 int controlinsmod(void *sender
, int cargc
, char **cargv
);
44 int controllsmod(void *sender
, int cargc
, char **cargv
);
45 int controlrehash(void *sender
, int cargc
, char **cargv
);
46 int controlreload(void *sender
, int cargc
, char **cargv
);
47 int controlhelpcmd(void *sender
, int cargc
, char **cargv
);
48 void controlnoticeopers(flag_t permissionlevel
, flag_t noticelevel
, char *format
, ...);
51 controlcmds
=newcommandtree();
52 controlreply
=&controlmessage
;
53 controlwall
=&controlnoticeopers
;
55 registercontrolhelpcmd("status",NO_DEVELOPER
,1,&controlstatus
,"Usage: status ?level?\nDisplays status information, increasing level gives more verbose information.");
56 registercontrolhelpcmd("whois",NO_OPERED
,1,&controlwhois
,"Usage: whois <nickname|#numeric>\nDisplays lots of information about the specified nickname or numeric.");
57 registercontrolhelpcmd("channel",NO_OPER
,1,&controlchannel
,"Usage: channel <#channel>\nDisplays channel information.");
58 registercontrolhelpcmd("relink",NO_DEVELOPER
,1,&relink
,"Usage: relink\nRelinks service to the network.");
59 registercontrolhelpcmd("die",NO_DEVELOPER
,1,&die
,"Usage: die <reason>\nTerminates the service.");
60 registercontrolhelpcmd("insmod",NO_DEVELOPER
,1,&controlinsmod
,"Usage: insmod <module>\nAdds a module to the running instance.");
61 registercontrolhelpcmd("rmmod",NO_DEVELOPER
,1,&controlrmmod
,"Usage: rmmod <module>\nRemoves a module from the running instance.");
62 registercontrolhelpcmd("lsmod",NO_DEVELOPER
,0,&controllsmod
,"Usage: lsmod\nLists currently running modules.");
63 registercontrolhelpcmd("rehash",NO_DEVELOPER
,1,&controlrehash
,"Usage: rehash\nReloads configuration file.");
64 registercontrolhelpcmd("showcommands",NO_ACCOUNT
,0,&controlshowcommands
,"Usage: showcommands\nShows all registered commands.");
65 registercontrolhelpcmd("reload",NO_DEVELOPER
,1,&controlreload
,"Usage: reload <module>\nReloads specified module.");
66 registercontrolhelpcmd("help",NO_ANYONE
,1,&controlhelpcmd
,"Usage: help <command>\nShows help for specified command.");
68 scheduleoneshot(time(NULL
)+1,&controlconnect
,NULL
);
71 void registercontrolhelpcmd(const char *name
, int level
, int maxparams
, CommandHandler handler
, char *help
) {
72 addcommandhelptotree(controlcmds
,name
,level
,maxparams
,handler
,help
);
75 int deregistercontrolcmd(const char *name
, CommandHandler handler
) {
76 return deletecommandfromtree(controlcmds
, name
, handler
);
79 void controlconnect(void *arg
) {
80 sstring
*cnick
, *myident
, *myhost
, *myrealname
, *myauthname
;
83 cnick
=getcopyconfigitem("control","nick","C",NICKLEN
);
84 myident
=getcopyconfigitem("control","ident","control",NICKLEN
);
85 myhost
=getcopyconfigitem("control","hostname",myserver
->content
,HOSTLEN
);
86 myrealname
=getcopyconfigitem("control","realname","NewServ Control Service",REALLEN
);
87 myauthname
=getcopyconfigitem("control","authname","C",ACCOUNTLEN
);
89 mynick
=registerlocaluser(cnick
->content
,myident
->content
,myhost
->content
,myrealname
->content
,myauthname
->content
,UMODE_SERVICE
|UMODE_DEAF
|UMODE_OPER
|UMODE_ACCOUNT
,&handlemessages
);
90 triggerhook(HOOK_CONTROL_REGISTERED
, mynick
);
91 cp
=findchannel("#twilightzone");
93 localcreatechannel(mynick
,"#twilightzone");
95 localjoinchannel(mynick
,cp
);
96 localgetops(mynick
,cp
);
100 freesstring(myident
);
102 freesstring(myrealname
);
103 freesstring(myauthname
);
106 void handlestats(int hooknum
, void *arg
) {
107 controlreply(hooknick
,"%s",(char *)arg
);
110 int controlstatus(void *sender
, int cargc
, char **cargv
) {
111 unsigned int level
=5;
113 hooknick
=(nick
*)sender
;
116 level
=strtoul(cargv
[0],NULL
,10);
119 registerhook(HOOK_CORE_STATSREPLY
,&handlestats
);
120 triggerhook(HOOK_CORE_STATSREQUEST
,(void *)level
);
121 deregisterhook(HOOK_CORE_STATSREPLY
,&handlestats
);
125 int controlrehash(void *sender
, int cargc
, char **cargv
) {
126 nick
*np
=(nick
*)sender
;
128 controlreply(np
,"Rehashing the config file.");
131 triggerhook(HOOK_CORE_REHASH
,(void *)0);
135 void handlewhois(int hooknum
, void *arg
) {
136 controlreply(hooknick
,"%s",(char *)arg
);
139 int controlwhois(void *sender
, int cargc
, char **cargv
) {
148 if (cargv
[0][0]=='#') {
149 if (!(target
=getnickbynumericstr(cargv
[0]+1))) {
150 controlreply(sender
,"Sorry, couldn't find numeric %s",cargv
[0]+1);
154 if ((target
=getnickbynick(cargv
[0]))==NULL
) {
155 controlreply((nick
*)sender
,"Sorry, couldn't find that user");
160 controlreply((nick
*)sender
,"Nick : %s",target
->nick
);
161 controlreply((nick
*)sender
,"Numeric : %s",longtonumeric(target
->numeric
,5));
162 controlreply((nick
*)sender
,"User@Host : %s@%s (%d user(s) on this host)",target
->ident
,target
->host
->name
->content
,target
->host
->clonecount
);
163 if (IsSetHost(target
)) {
164 if (target
->shident
) {
165 controlreply((nick
*)sender
,"Fakehost : %s@%s",target
->shident
->content
, target
->sethost
->content
);
167 controlreply((nick
*)sender
,"Fakehost : %s",target
->sethost
->content
);
170 controlreply((nick
*)sender
,"Timestamp : %lu",target
->timestamp
);
171 controlreply((nick
*)sender
,"IP address: %d.%d.%d.%d",(target
->ipaddress
)>>24,(target
->ipaddress
>>16)&255, (target
->ipaddress
>>8)&255,target
->ipaddress
&255);
172 controlreply((nick
*)sender
,"Realname : %s (%d user(s) have this realname)",target
->realname
->name
->content
,target
->realname
->usercount
);
173 if (target
->umodes
) {
174 controlreply((nick
*)sender
,"Umode(s) : %s",printflags(target
->umodes
,umodeflags
));
176 if (IsAccount(target
)) {
177 controlreply((nick
*)sender
,"Account : %s",target
->authname
);
178 if (target
->accountts
)
179 controlreply((nick
*)sender
,"AccountTS : %ld",target
->accountts
);
182 hooknick
=(nick
*)sender
;
183 registerhook(HOOK_CONTROL_WHOISREPLY
,&handlewhois
);
184 triggerhook(HOOK_CONTROL_WHOISREQUEST
,target
);
185 deregisterhook(HOOK_CONTROL_WHOISREPLY
,&handlewhois
);
187 if (target
->channels
->cursi
==0) {
188 controlreply((nick
*)sender
,"Channels : none");
189 } else if (target
->channels
->cursi
>50) {
190 controlreply((nick
*)sender
,"Channels : - (total: %d)",target
->channels
->cursi
);
193 channels
=(channel
**)target
->channels
->content
;
194 for (i
=0;i
<=target
->channels
->cursi
;i
++) {
195 if (!((i
==target
->channels
->cursi
) || ((70-strlen(buf
))<channels
[i
]->index
->name
->length
&& strlen(buf
)>0))) {
196 strcat(buf
,channels
[i
]->index
->name
->content
);
199 if (strlen(buf
)==0) {
202 controlreply((nick
*)sender
,"Channels : %s",buf
);
213 int controlinsmod(void *sender
, int cargc
, char **cargv
) {
217 switch(insmod(cargv
[0])) {
219 controlreply((nick
*)sender
,"Unable to load module %s",cargv
[0]);
223 controlreply((nick
*)sender
,"Module %s already loaded, or name not valid",cargv
[0]);
227 controlreply((nick
*)sender
,"Module %s loaded.",cargv
[0]);
231 controlreply((nick
*)sender
,"An unknown error occured.");
236 int controlrmmod(void *sender
, int cargc
, char **cargv
) {
240 switch(rmmod(cargv
[0])) {
242 controlreply((nick
*)sender
,"Module %s is not loaded.",cargv
[0]);
246 controlreply((nick
*)sender
,"Module %s unloaded.",cargv
[0]);
250 controlreply((nick
*)sender
,"An unknown error occured.");
255 int controllsmod(void *sender
, int cargc
, char **cargv
) {
259 if (cargc
< 1) { /* list all loaded modules */
261 controlreply((nick
*)sender
,"Module");
262 while (ptr
!= NULL
) {
263 controlreply((nick
*)sender
,"%s", ptr
);
267 ptr
= lsmod(getindex(cargv
[0]));
268 controlreply((nick
*)sender
,"Module \"%s\" %s", cargv
[0], (ptr
? "is loaded." : "is NOT loaded."));
273 int controlreload(void *sender
, int cargc
, char **cargv
) {
277 controlrmmod(sender
, cargc
, cargv
);
278 return controlinsmod(sender
, cargc
, cargv
);
281 int relink(void *sender
, int cargc
, char **cargv
) {
283 controlreply((nick
*)sender
,"You must give a reason.");
287 irc_send("%s SQ %s 0 :%s",mynumeric
->content
,myserver
->content
,cargv
[0]);
293 int die(void *sender
, int cargc
, char **cargv
) {
295 controlreply((nick
*)sender
,"You must give a reason.");
299 irc_send("%s SQ %s 0 :%s",mynumeric
->content
,myserver
->content
,cargv
[0]);
305 int controlchannel(void *sender
, int cargc
, char **cargv
) {
316 if ((cp
=findchannel(cargv
[0]))==NULL
) {
317 controlreply((nick
*)sender
,"Couldn't find channel: %s",cargv
[0]);
322 sprintf(buf2
,"%d",cp
->limit
);
325 controlreply((nick
*)sender
,"Channel : %s",cp
->index
->name
->content
);
327 controlreply((nick
*)sender
,"Topic : %s",cp
->topic
->content
);
328 controlreply((nick
*)sender
,"T-time : %ld [%s]",cp
->topictime
,ctime(&(cp
->topictime
)));
330 controlreply((nick
*)sender
,"Mode(s) : %s %s%s%s",printflags(cp
->flags
,cmodeflags
),IsLimit(cp
)?buf2
:"",
331 IsLimit(cp
)?" ":"",IsKey(cp
)?cp
->key
->content
:"");
332 controlreply((nick
*)sender
,"Users : %d (hash size %d, utilisation %.1f%%); %d unique hosts",
333 cp
->users
->totalusers
,cp
->users
->hashsize
,((float)(100*cp
->users
->totalusers
)/cp
->users
->hashsize
),
334 countuniquehosts(cp
));
338 for (j
=0;j
<=cp
->users
->hashsize
;j
++) {
339 if (i
==4 || j
==cp
->users
->hashsize
) {
341 controlreply((nick
*)sender
,"Users : %s",buf
);
345 if (j
==cp
->users
->hashsize
)
348 if (cp
->users
->content
[j
]!=nouser
) {
349 np
=getnickbynumeric(cp
->users
->content
[j
]);
350 sprintf(&buf
[i
*18],"%c%c%-15s ",cp
->users
->content
[j
]&CUMODE_VOICE
?'+':' ',
351 cp
->users
->content
[j
]&CUMODE_OP
?'@':' ', np
?np
->nick
:"!BUG-NONICK!");
358 for (cbp
=cp
->bans
;cbp
;cbp
=cbp
->next
) {
359 controlreply((nick
*)sender
,"Ban : %s",bantostringdebug(cbp
));
364 int controlshowcommands(void *sender
, int cargc
, char **cargv
) {
365 nick
*np
=(nick
*)sender
;
366 Command
*cmdlist
[100];
369 n
=getcommandlist(controlcmds
,cmdlist
,100);
371 controlreply(np
,"The following commands are registered at present:");
374 controlreply(np
,"%s",cmdlist
[i
]->command
->content
);
377 controlreply(np
,"End of list.");
381 void handlemessages(nick
*target
, int messagetype
, void **args
) {
387 switch(messagetype
) {
390 /* If it's a message, first arg is nick and second is message */
391 sender
=(nick
*)args
[0];
393 Error("control",ERR_INFO
,"From: %s!%s@%s: %s",sender
->nick
,sender
->ident
,sender
->host
->name
->content
, (char *)args
[1]);
395 /* Split the line into params */
396 cargc
=splitline((char *)args
[1],cargv
,50,0);
403 cmd
=findcommandintree(controlcmds
,cargv
[0],1);
405 controlreply(sender
,"Unknown command.");
409 if (cmd
->level
>0 && !IsOper(sender
)) {
410 controlreply(sender
,"You need to be opered to use this command.");
414 /* If we were doing "authed user tracking" here we'd put a check in for authlevel */
416 /* Check the maxargs */
417 if (cmd
->maxparams
<(cargc
-1)) {
418 /* We need to do some rejoining */
419 rejoinline(cargv
[cmd
->maxparams
],cargc
-(cmd
->maxparams
));
420 cargc
=(cmd
->maxparams
)+1;
423 if((cmd
->handler
)((void *)sender
,cargc
-1,&(cargv
[1])) == CMD_USAGE
)
424 controlhelp(sender
, cmd
);
428 /* someone killed me? Bastards */
429 scheduleoneshot(time(NULL
)+1,&controlconnect
,NULL
);
438 void controlmessage(nick
*target
, char *message
, ... ) {
446 va_start(va
,message
);
447 vsnprintf(buf
,512,message
,va
);
450 sendmessagetouser(mynick
,target
,"%s",buf
);
453 void controlchanmsg(channel
*cp
, char *message
, ...) {
461 va_start(va
,message
);
462 vsnprintf(buf
,512,message
,va
);
465 sendmessagetochannel(mynick
,cp
,"%s",buf
);
468 void controlnotice(nick
*target
, char *message
, ... ) {
476 va_start(va
,message
);
477 vsnprintf(buf
,512,message
,va
);
480 sendnoticetouser(mynick
,target
,"%s",buf
);
483 void controlspecialrmmod(void *arg
) {
484 struct specialsched
*a
= (struct specialsched
*)arg
;
487 sstring
*froo
= a
->modulename
;
489 rmmod(froo
->content
);
493 void controlspecialreloadmod(void *arg
) {
494 struct specialsched
*a
= (struct specialsched
*)arg
;
497 sstring
*froo
= a
->modulename
;
499 rmmod(froo
->content
);
500 insmod(froo
->content
);
504 void controlhelp(nick
*np
, Command
*cmd
) {
505 char *cp
= cmd
->help
, *sp
= cp
;
507 controlreply(np
, "Sorry, no help for this command.");
511 if(*cp
== '\0' || *cp
== '\n') {
519 controlreply(np
, "%s", sp
);
532 int controlhelpcmd(void *sender
, int cargc
, char **cargv
) {
534 nick
*np
= (nick
*)sender
;
539 cmd
=findcommandintree(controlcmds
,cargv
[0],1);
541 controlreply(np
,"Unknown command.");
545 controlhelp(np
, cmd
);
549 void controlnoticeopers(flag_t permissionlevel
, flag_t noticelevel
, char *format
, ...) {
555 va_start(va
, format
);
556 vsnprintf(broadcast
, sizeof(broadcast
), format
, va
);
559 for(i
=0;i
<NICKHASHSIZE
;i
++)
560 for(np
=nicktable
[i
];np
;np
=np
->next
)
562 controlnotice(np
, "%s", broadcast
);