/* eggdrop module to handle msg, notice, channel msg, channel notice, and elementary ctcp and ctcp-replies. */ #include #include #include #include #include "eggdrop.h" /* SED and UTC are a big lie, but they'll never know */ #define CLIENTINFO "SED VERSION CLIENTINFO USERINFO ERRMSG FINGER TIME ACTION DCC UTC PING ECHO :Use CLIENTINFO to get more specific information" extern int serv; extern int memused; extern int backgrd; extern int con_chan; extern int term_z; extern char botname[]; extern char helpbot[]; extern char version[]; extern char curchan[]; extern struct dcc_t dcc[]; extern int dcc_total; extern char admin[]; extern int gothelpping; extern char cx_file[]; extern int cx_line; extern int require_x; extern int require_p; extern int telnet_port; /* response to ctcp version requests */ char ctcp_version[121]="me? a bot? no way!"; /* response to ctcp finger requests */ char ctcp_finger[121]="yer gonna lose that finger if you don't stop."; /* ctcp embedded in a privmsg */ void gotctcp(ffrom,to,msg) char *ffrom,*to,*msg; { char from[121],nick[10],code[512]; char *p; strcpy(from,ffrom); split(code,msg); splitnick(nick,from); if (code[0]==0) { strcpy(code,msg); msg[0]=0; } /* unquote if necessary */ p=strchr(msg,'\\'); while (p!=NULL) { if (*(p+1)=='a') *(p+1)=1; strcpy(p,p+1); p=strchr(msg,'\\'); } if (strcmp(code,"FINGER")==0) mprintf(serv,"NOTICE %s :\001FINGER %s %s\001\n",nick,botname,ctcp_finger); else if ((strcmp(code,"PING")==0) || (strcmp(code,"ECHO")==0) || (strcmp(code,"ERRMSG")==0)) mprintf(serv,"NOTICE %s :\001%s %s\001\n",nick,code,msg); else if (strcmp(code,"VERSION")==0) mprintf(serv,"NOTICE %s :\001VERSION %s\001\n",nick,ctcp_version); else if (strcmp(code,"USERINFO")==0) mprintf(serv,"NOTICE %s :\001USERINFO %s\001\n",nick,admin); else if (strcmp(code,"CLIENTINFO")==0) mprintf(serv,"NOTICE %s :\001CLIENTINFO %s\001\n",nick,CLIENTINFO); else if (strcmp(code,"DCC")==0) gotdcc(nick,from,msg); else if (strcmp(code,"TIME")==0) { time_t tm=time(NULL); char tms[81]; strcpy(tms,ctime(&tm)); tms[strlen(tms)-1]=0; mprintf(serv,"NOTICE %s :\001TIME %s\001\n",nick,tms); } else if (strcmp(code,"CHAT")==0) { int atr=get_attr_host(ffrom); if ((atr & (USER_MASTER|USER_PARTY|USER_XFER)) || ((atr&USER_OP) && (!require_x || !require_p))) { if (!telnet_port) mprintf(serv,"NOTICE %s :\001ERROR no telnet port\001\n",nick); else mprintf(serv,"PRIVMSG %s :\001DCC CHAT chat %lu %u\001\n",nick, getmyip(),telnet_port); } } /* don't log DCC or AWAKE */ if ((strcmp(code,"DCC")!=0) && (strcmp(code,"AWAKE")!=0)) { if ((to[0]=='#') || (to[0]=='&') || (to[0]=='+')) { if (strcmp(code,"ACTION")==0) { log(LOG_PUBLIC,"Action: %s %s",nick,msg); } else { log(LOG_PUBLIC,"CTCP %s: %s from %s (%s) to %s",code,msg,nick,from,to); } update_idle(nick); } else { if (strcmp(code,"ACTION")==0) { log(LOG_MSGS,"Action to %s: %s %s",to,nick,msg); } else { log(LOG_MSGS,"CTCP %s: %s from %s (%s)",code,msg,nick,from); } } } } /* ctcp embedded in a notice */ void gotctcpreply(ffrom,to,msg) char *ffrom,*to,*msg; { char from[81],nick[10],code[512]; char *p; strcpy(from,ffrom); split(code,msg); splitnick(nick,from); if (code[0]==0) { strcpy(code,msg); msg[0]=0; } /* unquote if necessary */ p=strchr(msg,'\\'); while (p!=NULL) { if (*(p+1)=='a') *(p+1)=1; strcpy(p,p+1); p=strchr(msg,'\\'); } /* who cares? */ if ((to[0]=='#') || (to[0]=='&') || (to[0]=='+')) { log(LOG_PUBLIC,"CTCP reply %s: %s from %s (%s) to %s",code,msg,nick,from, to); update_idle(nick); } else { if ((strcasecmp(nick,helpbot)==0) && (strcmp(code,"PING")==0)) gothelpping=1; /* ping response from helpbot! */ else log(LOG_MSGS,"CTCP reply %s: %s from %s (%s) to %s",code,msg,nick,from, to); } } /* public msg on channel */ void gotpublic(from,to,msg) char *from,*to,*msg; { char nick[10]; detect_flood(from,_PRIVMSG,1); splitnick(nick,from); #ifdef TCL if (check_tcl_pub(nick,from,msg)) return; check_tcl_pubm(nick,from,msg); #endif if (strcasecmp(curchan,to)==0) log(LOG_PUBLIC,"<%s> %s",nick,msg); else log(LOG_PUBLIC,"<%s:%s> %s",nick,to,msg); update_idle(nick); } /* public notice on channel */ void gotpublicnotice(from,to,msg) char *from,*to,*msg; { char nick[10]; detect_flood(from,_NOTICE,1); splitnick(nick,from); log(LOG_PUBLIC,"-%s:%s- %s",nick,to,msg); update_idle(nick); } /* check for more than 8 control characters in a line */ /* this could indicate: beep flood CTCP avalanche */ int detect_avalanche(msg) char *msg; { int count=0; char *p; for (p=msg; (*p)&&(count<8); p++) if ((*p<32) && (*p!=22) && (*p!=2) && (*p!=31) && (*p!=15)) count++; /* ^ don't penalize for bold/reverse/underline */ if (count>=8) return 1; else return 0; } /* private message */ void gotmsg(from,msg) char *from,*msg; { char to[81],nick[10],ctcp[512]; char *p,*p1; context; split(to,msg); fixcolon(msg); if (detect_avalanche(msg)) { splitnick(nick,from); /* discard -- kick user if it was to the channel */ if ((to[0]=='&') || (to[0]=='#')) { tprintf(serv,"KICK %s %s :that was fun, let's do it again!\n", curchan,nick); } log(LOG_CHAN,"Avalanche from %s!%s - ignoring",nick,from); p=strchr(from,'@'); if (p!=NULL) p++; else p=from; sprintf(ctcp,"*!*@%s",p); prog_ignore(ctcp,time(NULL)); return; } /* check for CTCP: */ p=strchr(msg,1); while (p!=NULL) { p++; p1=p; while ((*p != 1) && (*p != 0)) p++; if (*p==1) { *p=0; strcpy(ctcp,p1); strcpy(p1-1,p+1); } else { strcpy(ctcp,p1); strcpy(p1-1,p); } detect_flood(from,_CTCP,0); gotctcp(from,to,ctcp); p=strchr(msg,1); } if (msg[0]==0) return; /* oh. no msg. well forget it then! */ if ((to[0]=='#') || (to[0]=='&') || (to[0]=='+')) { /* it's a public msg */ gotpublic(from,to,msg); } else { detect_flood(from,_PRIVMSG,0); splitnick(nick,from); gotcmd(nick,from,msg); } } /* private notice */ void gotnotice(from,msg) char *from,*msg; { char to[81],nick[10],ctcp[512]; char *p,*p1; context; split(to,msg); fixcolon(msg); if (detect_avalanche(msg)) { splitnick(nick,from); /* discard -- kick user if it was to the channel */ if ((to[0]=='&') || (to[0]=='#')) { tprintf(serv,"KICK %s %s :that was fun, let's do it again!\n", curchan,nick); } log(LOG_CHAN,"Avalanche from %s!%s",nick,from); return; } /* check for CTCP: */ p=strchr(msg,1); while (p!=NULL) { p++; p1=p; while ((*p != 1) && (*p != 0)) p++; if (*p==1) { *p=0; strcpy(ctcp,p1); strcpy(p1-1,p+1); } else { strcpy(ctcp,p1); strcpy(p1-1,p); } detect_flood(from,_CTCP,0); gotctcpreply(from,to,ctcp); p=strchr(msg,1); } if (msg[0]==0) return; /* oh. no msg. well forget it then! */ if ((to[0]=='#') || (to[0]=='&')) { /* it's a public msg */ gotpublicnotice(from,to,msg); } else { detect_flood(from,_NOTICE,0); splitnick(nick,from); /* server notice? */ if ((from[0]==0) || (nick[0]==0)) log(LOG_MISC|LOG_MSGS,"-NOTICE- %s",msg); else log(LOG_MSGS,"-%s (%s)- %s",nick,from,msg); } } /* error notice */ void goterror(from,msg) void *from,*msg; { fixcolon(msg); log(LOG_MISC|LOG_MSGS,"-ERROR- %s",msg); close(serv); serv=(-1); /* they're gonna disconnect anyway :) */ }