diff options
Diffstat (limited to 'src/map/irc-bot.c')
-rw-r--r-- | src/map/irc-bot.c | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c new file mode 100644 index 000000000..3e7d7eb06 --- /dev/null +++ b/src/map/irc-bot.c @@ -0,0 +1,272 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Base Author: shennetsind @ http://hercules.ws + +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/strlib.h" +#include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/random.h" + +#include "map.h" +#include "pc.h" +#include "clif.h" +#include "irc-bot.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +char send_string[200]; + +int irc_connect_timer(int tid, unsigned int tick, int id, intptr_t data) { + if( ircbot->fd != -1 || session[ircbot->fd] || ++ircbot->fails >= 3 ) + return 0; + + ircbot->last_try = gettick(); + if( ( ircbot->fd = make_connection(ircbot->ip,hChSys.irc_server_port,true) ) > 0 ){ + session[ircbot->fd]->func_parse = ircbot->parse; + session[ircbot->fd]->flag.server = 1; + add_timer(gettick() + 3000, ircbot->identify_timer, 0, 0); + } + return 0; +} + +int irc_identify_timer(int tid, unsigned int tick, int id, intptr_t data) { + if( ircbot->fd == -1 ) + return 0; + + sprintf(send_string, "USER HerculesWS%d 8 * : Hercules IRC Bridge",rand()%777); + ircbot->send(send_string); + sprintf(send_string, "NICK %s", hChSys.irc_nick); + ircbot->send(send_string); + + add_timer(gettick() + 3000, ircbot->join_timer, 0, 0); + + return 0; +} + +int irc_join_timer(int tid, unsigned int tick, int id, intptr_t data) { + if( ircbot->fd == -1 ) + return 0; + + if( hChSys.irc_nick_pw[0] != '\0' ) { + sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", hChSys.irc_nick_pw); + ircbot->send(send_string); + } + + sprintf(send_string, "JOIN %s", hChSys.irc_channel); + ircbot->send(send_string); + ircbot->isIn = true; + + return 0; +} + +struct irc_func* irc_func_search(char* function_name) { + int i; + for(i = 0; i < ircbot->funcs.size; i++) { + if( strcmpi(ircbot->funcs.list[i]->name, function_name) == 0 ) { + return ircbot->funcs.list[i]; + } + } + return NULL; +} + +int irc_parse(int fd) { + char *parse_string = NULL, *str_safe = NULL; + + if (session[fd]->flag.eof) { + do_close(fd); + ircbot->fd = -1; + ircbot->isIn = false; + ircbot->fails = 0; + ircbot->ip = host2ip(hChSys.irc_server); + add_timer(gettick() + 120000, ircbot->connect_timer, 0, 0); + return 0; + } + + if( !RFIFOREST(fd) ) + return 0; + + parse_string = (char*)RFIFOP(fd,0); + parse_string[ RFIFOREST(fd) - 1 ] = '\0'; + + parse_string = strtok_r(parse_string,"\r\n",&str_safe); + + while (parse_string != NULL) { + ircbot->parse_sub(fd,parse_string); + parse_string = strtok_r(NULL,"\r\n",&str_safe); + } + + RFIFOSKIP(fd, RFIFOREST(fd)); + RFIFOFLUSH(fd); + return 0; +} + +void irc_parse_source(char *source, char *nick, char *ident, char *host) { + int i, len = strlen(source), pos = 0; + unsigned char stage = 0; + + for(i = 0; i < len; i++) { + if( stage == 0 && source[i] == '!' ) { + memcpy(nick, &source[0], len - i); + nick[i] = '\0'; + pos = i+1; + stage = 1; + } else if( stage == 1 && source[i] == '@' ) { + memcpy(ident, &source[pos], i - pos); + ident[i-pos] = '\0'; + memcpy(host, &source[i+1], len); + host[len] = '\0'; + break; + } + } +} +void irc_parse_sub(int fd, char *str) { + char source[180], command[60], target[60], message[200]; + struct irc_func *func; + + source[0] = command[0] = target[0] = message[0] = '\0'; + + if( str[0] == ':' ) + str++; + + sscanf(str, "%179s %59s %59s :%199[^\r\n]", source, command, target, message); + + if( command[0] == '\0' ) + return; + + if( !(func = ircbot->func_search(command)) && !(func = ircbot->func_search(source)) ) { + ShowWarning("Unknown command received %s from %s\n",command,source); + return; + } + func->func(fd,command,source,target,message); + +} + +void irc_send(char *str) { + int len = strlen(str) + 2; + WFIFOHEAD(ircbot->fd, len); + snprintf((char*)WFIFOP(ircbot->fd,0),200, "%s\r\n", str); + WFIFOSET(ircbot->fd, len); +} + +void irc_pong(int fd, char *cmd, char *source, char *target, char *msg) { + sprintf(send_string, "PONG %s", cmd); + ircbot->send(send_string); +} + +void irc_join(int fd, char *cmd, char *source, char *target, char *msg) { + if( ircbot->isIn ) + return; + sprintf(send_string, "JOIN %s", hChSys.irc_channel); + ircbot->send(send_string); + ircbot->isIn = true; +} + +void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) { + if( strcmpi(target,hChSys.irc_nick) == 0 ) { + if( strcmpi(msg,"VERSION") == 0 ) { + sprintf(send_string, "Hercules.ws IRC Bridge"); + ircbot->send(send_string); + return; + } + } else if( strcmpi(target,hChSys.irc_channel) == 0 ) { + char source_nick[40], source_ident[40], source_host[100]; + + source_nick[0] = source_ident[0] = source_host[0] = '\0'; + + if( source[0] != '\0' ) + ircbot->parse_source(source,source_nick,source_ident,source_host); + + snprintf(send_string, 150, "[ #%s ] IRC.%s : %s",ircbot->channel->name,source_nick,msg); + clif->chsys_msg2(ircbot->channel,send_string); + } +} + +void irc_relay (char *name, char *msg) { + if( !ircbot->isIn ) + return; + sprintf(send_string,"PRIVMSG %s :[ %s ] : %s",hChSys.irc_channel,name,msg); + ircbot->send(send_string); +} + +void irc_bot_init(void) { + const struct irc_func irc_func_base[] = { + { "PING" , ircbot->pong }, + { "PRIVMSG", ircbot->privmsg }, + }; + struct irc_func* function; + int i; + + if( !hChSys.irc ) + return; + + if (!(ircbot->ip = host2ip(hChSys.irc_server))) { + ShowError("Unable to resolve '%s' (irc server), disabling irc channel...\n", hChSys.irc_server); + hChSys.irc = false; + return; + } + + ircbot->funcs.size = ARRAYLENGTH(irc_func_base); + + CREATE(ircbot->funcs.list,struct irc_func*,ircbot->funcs.size); + + for( i = 0; i < ircbot->funcs.size; i++ ) { + + CREATE(function, struct irc_func, 1); + + safestrncpy(function->name, irc_func_base[i].name, sizeof(function->name)); + function->func = irc_func_base[i].func; + + ircbot->funcs.list[i] = function; + } + + ircbot->fails = 0; + ircbot->fd = -1; + ircbot->isIn = true; + + add_timer_func_list(ircbot->connect_timer, "irc_connect_timer"); + add_timer(gettick() + 7000, ircbot->connect_timer, 0, 0); +} + +void irc_bot_final(void) { + int i; + + if( !hChSys.irc ) + return; + if( ircbot->fd != -1 ) { + ircbot->send("QUIT :Hercules is shutting down"); + do_close(ircbot->fd); + } + + for( i = 0; i < ircbot->funcs.size; i++ ) { + aFree(ircbot->funcs.list[i]); + } + aFree(ircbot->funcs.list); +} + +void ircbot_defaults(void) { + ircbot = &irc_bot_s; + ircbot->init = irc_bot_init; + ircbot->final = irc_bot_final; + + ircbot->parse = irc_parse; + ircbot->parse_sub = irc_parse_sub; + ircbot->parse_source = irc_parse_source; + + ircbot->func_search = irc_func_search; + + ircbot->connect_timer = irc_connect_timer; + ircbot->identify_timer = irc_identify_timer; + ircbot->join_timer = irc_join_timer; + + ircbot->send = irc_send; + ircbot->relay = irc_relay; + + ircbot->pong = irc_pong; + ircbot->join = irc_join; + ircbot->privmsg = irc_privmsg; +} |