diff --git a/Makefile b/Makefile index 4e53739..71661b2 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ ifeq ($(DEBUG), 1) CFLAGS += -Wall -Wextra -Wpedantic CFLAGS += -DDEBUG -O0 -ggdb -fno-inline else - CFLAGS += -O3 -fno-stack-protector -fno-exceptions -fno-rtti + CFLAGS += -O3 -fno-stack-protector -fno-rtti endif LDLIBS := -lircclient @@ -17,15 +17,12 @@ OUT := hibot SOURCE.d := source/ SOURCE := main.c SOURCE := $(addprefix ${SOURCE.d}, ${SOURCE}) -HEADER := config.inc log.h bot.h +HEADER := config.inc version.inc log.h bot.h syntax.h HEADER := $(addprefix ${SOURCE.d}, ${HEADER}) -${OUT}: +${OUT}: ${SOURCE} ${HEADER} ${CC} ${CFLAGS} -o $@ ${SOURCE} ${LDLIBS} -static: ${SOURCE} ${HEADER} - ${CC} -static ${CFLAGS} $$(pkg-config --libs openssl) -o $@ ${SOURCE} ${LDLIBS} - run: ${OUT} ${OUT} irc.rizon.net:6665 "#/g/test" diff --git a/source/bot.h b/source/bot.h index 343caf6..142bd39 100644 --- a/source/bot.h +++ b/source/bot.h @@ -4,16 +4,138 @@ #include #include +#include +#include extern syntax_setter_t syntax_functions[]; static irc_session_t * session; static irc_callbacks_t callbacks; +static inline void irc_message(const char * const message) { irc_cmd_msg(session, channel, message); } +static inline +void irc_private_message(const char * const user, const char * const message) { + irc_cmd_msg(session, user, message); +} + +static inline +char * username_root(const char * const fullname){ + char * r = (char *)fullname; + while (*(r++) != '!') { ; } + asprintf(&r, "From %.*s:", (int)(r - fullname)-1, fullname); + return r; +} + +typedef struct { + int is_active; + char * user; + language_t language; + struct itimerval timer; + char * buffer[128]; + unsigned int buffer_head; +} request_t; + +void init_request(request_t * request) { + request->is_active = 0; + request->timer.it_value.tv_sec = 0; + request->timer.it_value.tv_usec = 0; + request->timer.it_interval.tv_sec = 0; + request->timer.it_interval.tv_usec = 0; + request->buffer_head = 0; +} + +request_t * request_queue[message_queue_size]; +unsigned int request_queue_head = 0; + +static inline +void touch_request_timer(request_t * request) { + request->timer.it_value.tv_sec = message_timeout; + setitimer(ITIMER_REAL, &(request->timer), NULL); +} + +void activate_request(request_t * request) { + request->is_active = 1; + + /* message header */ + char * short_name = username_root(request->user); + irc_message(short_name); + free(short_name); +} + +request_t * take_request(const char * const user, language_t language) { + for (unsigned int i = 0; i < request_queue_head; i++) { + if(!strcmp(request_queue[i]->user, user)) { + return request_queue[i]; + } + } + + if (request_queue_head == message_queue_size) { + return NULL; + } + + request_t * request = request_queue[request_queue_head]; + + request->language = language; + request->user = strdup(user); + + if (request_queue_head == 0) { + activate_request(request); + } + + ++request_queue_head; + + char * log_message; + asprintf(&log_message, "Took message: %p (%d)\n", (void*)request, request_queue_head); + log_notice(log_message); + free(log_message); + + return request; +} + +void drop_reqest() { + request_t * request = request_queue[0]; + + if (message_queue_size > 1) { + for (unsigned int i = 0; i < request_queue_head; i++) { + request_queue[i] = request_queue[i+1]; + } + request_queue[request_queue_head] = request; + } + + --request_queue_head; + + request->is_active = 0; + free(request->user); + + if (request_queue_head) { + activate_request(request_queue[0]); + for (unsigned int i = 0; i < request_queue[0]->buffer_head; i++) { + irc_message(request_queue[0]->buffer[i]); + free(request_queue[0]->buffer[i]); + } + request_queue[0]->buffer_head = 0; + touch_request_timer(request_queue[0]); + } + + char * log_message; + asprintf(&log_message, "Dropped message: %p (%d)\n", (void*)request, request_queue_head); + log_notice(log_message); + free(log_message); +} + +void on_message_timeout(int unused) { + (void)unused; + + /* message footer */ + irc_message("--"); + + drop_reqest(request_queue); +} + static language_t translate_language(const char * const language) { if (!strcmp(language, "C") || !strcmp(language, "C++")) { @@ -106,15 +228,18 @@ void event_privmsg(irc_session_t * session, /* Is code */ if (is_code) { - char * buffer = (char *)origin; - while (*(buffer++) != '!') { ; } - asprintf(&buffer, "From %.*s:", (int)(buffer - origin)-1, origin); - irc_message(buffer); - free(buffer); + request_t * request = take_request(origin, language); + if (!request) { + irc_private_message(origin, message_queue_full_message); + goto END; + } - irc_message(syntax_highlight(message)); - - irc_message("--"); + if (request->is_active) { + touch_request_timer(request); + irc_message(syntax_highlight(message)); + } else { + request->buffer[request->buffer_head++] = strdup(syntax_highlight(message)); + } } END: @@ -154,6 +279,12 @@ int connect_bot(const char * const server, const short port) { log_notice("IRC Session initialized."); } + for (unsigned int i = 0; i < message_queue_size; i++) { + request_queue[i] = (request_t*)malloc(sizeof(request_t)); + init_request(request_queue[i]); + } + signal(SIGALRM, on_message_timeout); + irc_connect(session, server, port, diff --git a/source/config.inc b/source/config.inc index d72b594..7331953 100644 --- a/source/config.inc +++ b/source/config.inc @@ -1,7 +1,10 @@ #ifndef CONFIG_INC -const char * const username = PROGRAM_NAME; -const char * const password = ""; +const char * const username = "hibot2"; //PROGRAM_NAME; +const char * const password = ""; +const int message_timeout = 3; +const char * const message_queue_full_message = "Air space too crowded in this area."; +#define message_queue_size 3 #define DEFAULT_LANGUAGE C #define LOG_FILE stdout diff --git a/source/version.inc b/source/version.inc index ea1da60..33e586a 100644 --- a/source/version.inc +++ b/source/version.inc @@ -1 +1 @@ -"1.0" +"1.1"