123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522 |
- // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
- // For more information, see LICENCE in the main folder
- #include "../common/core.h"
- #include "../common/socket.h"
- #include "../common/malloc.h"
- #include "../common/db.h"
- #include "../common/timer.h"
- #include "../common/strlib.h"
- #include "../common/mmo.h"
- #include "../common/showmsg.h"
- #include "../common/version.h"
- #include "../common/nullpo.h"
- #include "map.h"
- #include "pc.h"
- #include "intif.h" //For GM Broadcast
- #include "irc.h"
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- // configuration
- short use_irc=0;
- short irc_autojoin=0;
- short irc_announce_flag=1;
- short irc_announce_mvp_flag=1;
- short irc_announce_jobchange_flag=1;
- short irc_announce_shop_flag=1;
- char irc_nick[30]="";
- char irc_password[32]="";
- char irc_channel[32]="";
- char irc_channel_pass[32]="";
- char irc_trade_channel[32]="";
- char irc_ip_str[128]="";
- unsigned long irc_ip=0;
- unsigned short irc_port = 6667;
- // variables
- int irc_fd=0;
- IRC_SI *irc_si=NULL;
- struct channel_data cd;
- int last_cd_user=0;
- int irc_connect_timer(int tid, unsigned int tick, int id, int data)
- {
- if(irc_si && session[irc_si->fd])
- return 0;
- //Ok, this ShowInfo and printf are a little ugly, but they are meant to
- //debug just how long the code freezes here. [Skotlex]
- ShowInfo("(IRC) Connecting to %s...\n", irc_ip_str);
- irc_fd = make_connection(irc_ip,irc_port);
- if(irc_fd > 0){
- printf("ok\n");
- session[irc_fd]->func_parse = irc_parse;
- } else
- printf("failed\n");
- return 0;
- }
- void irc_announce(const char* buf)
- {
- char send_string[256];
- sprintf(send_string,"PRIVMSG %s :",irc_channel);
- strcat(send_string, buf);
- irc_send(send_string);
- }
- void irc_announce_jobchange(struct map_session_data *sd)
- {
- char send_string[256];
-
- nullpo_retv(sd);
- sprintf(send_string,"PRIVMSG %s :%s has changed into a %s.",irc_channel,sd->status.name,job_name(sd->status.class_));
- irc_send(send_string);
- }
- void irc_announce_shop(struct map_session_data *sd, int flag)
- {
- char send_string[256];
- char mapname[16];
- int maplen = 0;
- nullpo_retv(sd);
- if(flag){
- strcpy(mapname, map[sd->bl.m].name);
- maplen = strcspn(mapname,".");
- mapname[maplen] = '\0';
- mapname[0]=TOUPPER(mapname[0]);
- sprintf(send_string,"PRIVMSG %s :%s has opened a shop, %s, at <%d,%d> in %s.",irc_trade_channel,sd->status.name,sd->message,sd->bl.x,sd->bl.y,mapname);
- } else
- sprintf(send_string,"PRIVMSG %s :%s has closed their shop.",irc_trade_channel,sd->status.name);
- irc_send(send_string);
- }
- void irc_announce_mvp(struct map_session_data *sd, struct mob_data *md)
- {
- char send_string[256];
- char mapname[16];
- int maplen = 0;
- nullpo_retv(sd);
- nullpo_retv(md);
- strcpy(mapname, map[md->bl.m].name);
- maplen = strcspn(mapname,".");
- mapname[maplen] = '\0';
- mapname[0]=TOUPPER(mapname[0]);
- sprintf(send_string,"PRIVMSG %s :%s the %s has MVP'd %s in %s.",irc_channel,sd->status.name,job_name(sd->status.class_),md->name, mapname);
- irc_send(send_string);
- }
- int irc_parse(int fd)
- {
- if (session[fd]->eof)
- {
- do_close(fd);
- irc_si = NULL;
- add_timer(gettick() + 15000, irc_connect_timer, 0, 0);
- return 0;
- }
- if (session[fd]->session_data == NULL) {
- irc_si = (struct IRC_Session_Info*)aMalloc(sizeof(struct IRC_Session_Info));
- irc_si->fd = fd;
- irc_si->state = 0;
- session[fd]->session_data = irc_si;
- } else if (!irc_si) {
- irc_si = (struct IRC_Session_Info*)session[fd]->session_data;
- irc_si->fd = fd;
- }
- if(RFIFOREST(fd) > 0)
- {
- send_to_parser(fd, (char*)RFIFOP(fd,0), "\n");
- RFIFOSKIP(fd,RFIFOREST(fd));
- }
- return 0;
- }
- int irc_keepalive_timer(int tid, unsigned int tick, int id, int data)
- {
- char send_string[128];
- sprintf(send_string,"PRIVMSG %s : ", irc_nick);
- irc_send(send_string);
- add_timer(gettick() + 30000, irc_keepalive_timer, 0, 0);
- return 0;
- }
- void irc_send(char *buf)
- {
- int len;
- int fd = irc_si->fd;
-
- if(!irc_si || !session[fd])
- return;
- len = strlen(buf) + 1;
- WFIFOHEAD(fd, len);
- sprintf((char*)WFIFOP(fd,0), "%s\n", buf);
- WFIFOSET(fd, len);
- }
- void irc_parse_sub(int fd, char *incoming_string)
- {
- char source[256];
- char command[256];
- char target[256];
- char message[8192];
- char send_string[8192];
- char *source_nick=NULL;
- char *source_ident=NULL;
- char *source_host=NULL;
- char *state_mgr=NULL;
-
- int i=0;
- struct map_session_data **allsd;
-
- memset(source,'\0',256);
- memset(command,'\0',256);
- memset(target,'\0',256);
- memset(message,'\0',8192);
- memset(send_string,'\0',8192);
- sscanf(incoming_string, ":%255s %255s %255s :%4095[^\r\n]", source, command, target, message);
- if (source != NULL)
- {
- if (strstr(source,"!") != NULL)
- {
- source_nick = strtok_r(source,"!",&state_mgr);
- source_ident = strtok_r(NULL,"@",&state_mgr);
- source_host = strtok_r(NULL,"%%",&state_mgr);
- }
- }
- switch (irc_si->state)
- {
- case 0:
- sprintf(send_string, "NICK %s", irc_nick);
- irc_send(send_string);
- sprintf(send_string, "USER eABot 8 * : eABot");
- irc_send(send_string);
- irc_si->state = 1;
- break;
- case 1:
- if(!strcmp(command,"001"))
- {
- ShowStatus("IRC: Connected to IRC.\n");
- sprintf(send_string, "PRIVMSG nickserv :identify %s", irc_password);
- irc_send(send_string);
- sprintf(send_string, "JOIN %s %s", irc_channel, irc_channel_pass);
- irc_send(send_string);
- sprintf(send_string,"NAMES %s",irc_channel);
- irc_send(send_string);
- irc_si->state = 2;
- }
- else
- if(!strcmp(command,"433"))
- {
- ShowError("IRC: Nickname %s is already taken, IRC Client unable to connect.\n", irc_nick);
- sprintf(send_string, "QUIT");
- irc_send(send_string);
- if(session[fd])
- set_eof(fd);
- }
- break;
- case 2:
- if(!strcmp(source, "PING"))
- {
- sprintf(send_string, "PONG %s", command);
- irc_send(send_string);
- }
- else // channel message
- if( strcmpi(target,irc_channel)==0 || strcmpi(target,irc_channel+1)==0 || strcmpi(target+1,irc_channel)==0 )
- { //TODO: why not allow talking to the bot directly? (|| strcmpi(irc_nick,target) == 0)
- // issue a command (usage: say @command <params> into the channel)
- char cmdname[256];
- char cmdargs[256] = "";
- if((strcmpi(command,"privmsg")==0)&&(sscanf(message,"@%255s %255[^\r\n]",cmdname,cmdargs)>0)&&(target[0]=='#'))
- {
- if(strcmpi(cmdname,"kami")==0)
- {
- if(get_access(source_nick) < ACCESS_OP)
- sprintf(send_string,"NOTICE %s :Access Denied",source_nick);
- else
- {
- sprintf(send_string,"%s: %s",source_nick,cmdargs);
- intif_GMmessage(send_string,strlen(send_string)+1,0);
- sprintf(send_string,"NOTICE %s :Message Sent",source_nick);
- }
- irc_send(send_string);
- }
- else // Number of users online
- if(strcmpi(cmdname,"users")==0)
- {
- int users;
- map_getallusers(&users);
- sprintf(send_string, "PRIVMSG %s :Users Online: %d", irc_channel, users);
- irc_send(send_string);
- }
- else // List all users online
- if(strcmpi(cmdname,"who")==0)
- {
- int users;
- allsd = map_getallusers(&users);
- if(users > 0)
- {
- sprintf(send_string,"NOTICE %s :%d Users Online",source_nick,users);
- irc_send(send_string);
- for(i = 0; i < users; i++)
- {
- sprintf(send_string,"NOTICE %s :Name: \"%s\"",source_nick,allsd[i]->status.name);
- irc_send(send_string);
- }
- }
- else
- {
- sprintf(send_string,"NOTICE %s :No Users Online",source_nick);
- irc_send(send_string);
- }
- }
- }
- else // Refresh Names
- if((strcmpi(command,"join")==0)||(strcmpi(command,"part")==0)||(strcmpi(command,"mode")==0)||(strcmpi(command,"nick")==0))
- {
- ShowInfo("IRC: Refreshing User List");
- irc_rmnames();
- printf("...");
- sprintf(send_string,"NAMES %s",irc_channel);
- irc_send(send_string);
- printf("Done\n");
- }
- else // Autojoin on kick
- if((strcmpi(command,"kick")==0)&&(irc_autojoin==1))
- {
- sprintf(send_string, "JOIN %s %s", target, irc_channel_pass);
- irc_send(send_string);
- }
- }
- else // Names Reply
- if((strcmpi(command,"353")==0))
- {
- ShowInfo("IRC: NAMES received\n");
- parse_names_packet(incoming_string);
- }
- break;
- }
- }
- int send_to_parser(int fd, char *input,char key[2])
- {
- char *temp_string=NULL;
- char *state_mgr=NULL;
- int total_loops=0;
- temp_string = strtok_r(input,key,&state_mgr);
- while (temp_string != NULL)
- {
- total_loops = total_loops+1;
- irc_parse_sub(fd,temp_string);
- temp_string = strtok_r(NULL,key,&state_mgr);
- }
- return total_loops;
- }
- //NAMES Packet(353) parser
- int parse_names_packet(char *str)
- {
- char *tok;
- char source[256];
- char numeric[10];
- char target[256];
- char channel[256];
- char names[1024];
- memset(source,'\0',256);
- memset(numeric,'\0',10);
- memset(target,'\0',256);
- memset(channel,'\0',256);
- memset(names,'\0',1024);
- //TODO: fold this
- tok=strtok(str,"\r\n");
- sscanf(tok,":%255s %10s %255s %*1[=@] %255s :%1023[^\r\n]",source,numeric,target,channel,names);
- if(strcmpi(numeric,"353")==0)
- parse_names(names);
- while((tok=strtok(NULL,"\r\n"))!=NULL)
- {
- sscanf(tok,":%255s %10s %255s %*1[=@] %255s :%1023[^\r\n]",source,numeric,target,channel,names);
- if(strcmpi(numeric,"353")==0)
- parse_names(names);
- }
- return 0;
- }
- //User access level prefix parser
- int parse_names(char* str)
- {
- //TODO: fold this copy-pasted junk
- char* tok;
- if (str == NULL) return 0; //Nothing to parse!
- tok = strtok(str, " ");
- switch(tok[0])
- {
- case '~': set_access(tok+1,ACCESS_OWNER); break;
- case '&': set_access(tok+1,ACCESS_SOP); break;
- case '@': set_access(tok+1,ACCESS_OP); break;
- case '%': set_access(tok+1,ACCESS_HOP); break;
- case '+': set_access(tok+1,ACCESS_VOICE); break;
- default : set_access(tok,ACCESS_NORM); break;
- }
- while((tok = strtok(NULL, " ")) != NULL)
- {
- switch(tok[0])
- {
- case '~': set_access(tok+1,ACCESS_OWNER); break;
- case '&': set_access(tok+1,ACCESS_SOP); break;
- case '@': set_access(tok+1,ACCESS_OP); break;
- case '%': set_access(tok+1,ACCESS_HOP); break;
- case '+': set_access(tok+1,ACCESS_VOICE); break;
- default : set_access(tok,ACCESS_NORM); break;
- }
- }
-
- return 1;
- }
- //Store user's access level
- int set_access(char *nick,int newlevel)
- {
- int i;
-
- for(i = 0; i <= MAX_CHANNEL_USERS; i++) {
- if(strcmpi(cd.user[i].name, nick)==0) {
- cd.user[i].level = newlevel;
- return 1;
- }
- }
- strcpy(cd.user[last_cd_user].name, nick);
- cd.user[last_cd_user].level = newlevel;
- last_cd_user++;
- return 0;
- }
- //Returns users access level
- int get_access(char *nick)
- {
- int i;
-
- for(i = 0; i <= MAX_CHANNEL_USERS; i++)
- if(strcmpi(cd.user[i].name, nick)==0)
- return (cd.user[i].level);
- return -1;
- }
- int irc_rmnames()
- {
- int i;
- //TODO: why not just set the max counter to 0?
- for(i = 0; i <= MAX_CHANNEL_USERS; i++)
- cd.user[i].level=0;
- last_cd_user = 0;
- return 0;
- }
- int irc_read_conf(char *file)
- {
- FILE *fp=NULL;
- char w1[256];
- char w2[256];
- char path[256];
- char row[1024];
- memset(w1,'\0',256);
- memset(w2,'\0',256);
- memset(path,'\0',256);
- memset(row,'\0',256);
- sprintf(path,"conf/%s",file);
- if(!(fp=fopen(path,"r"))) {
- ShowError("Cannot find file: %s\n",path);
- return 0;
- }
- while(fgets(row, sizeof(row), fp) != NULL)
- {
- if(row[0]=='/' && row[1]=='/')
- continue;
- sscanf(row,"%[^:]: %255[^\r\n]",w1,w2);
- if(strcmpi(w1,"use_irc")==0)
- use_irc = config_switch(w2);
- else if(strcmpi(w1,"irc_server")==0)
- strcpy(irc_ip_str,w2);
- else if(strcmpi(w1,"irc_port")==0)
- irc_port = atoi(w2);
- else if(strcmpi(w1,"irc_autojoin")==0)
- irc_autojoin = atoi(w2);
- else if(strcmpi(w1,"irc_channel")==0)
- strcpy(irc_channel,w2);
- else if(strcmpi(w1,"irc_channel_pass")==0)
- strcpy(irc_channel_pass,w2);
- else if(strcmpi(w1,"irc_trade_channel")==0)
- strcpy(irc_trade_channel,w2);
- else if(strcmpi(w1,"irc_nick")==0)
- strcpy(irc_nick,w2);
- else if(strcmpi(w1,"irc_pass")==0) {
- if(strcmpi(w2,"0")!=0)
- strcpy(irc_password,w2);
- }
- }
- ShowInfo("IRC Config read successfully\n");
- return 1;
- }
- void do_init_irc(void)
- {
- if(!use_irc)
- return;
- irc_ip = host2ip(irc_ip_str);
- if (!irc_ip)
- {
- ShowError("Unable to resolve %s! Cannot connect to IRC server, disabling irc_bot.\n", irc_ip_str);
- use_irc = 0;
- return;
- }
- irc_connect_timer(0, 0, 0, 0);
- add_timer_func_list(irc_connect_timer, "irc_connect_timer");
- add_timer_func_list(irc_keepalive_timer, "irc_keepalive_timer");
- add_timer(gettick() + 30000, irc_keepalive_timer, 0, 0);
- }
- void do_final_irc(void)
- {
- }
|