Compare commits
10 Commits
18c6732f66
...
79cf4fda3d
Author | SHA1 | Date | |
---|---|---|---|
|
79cf4fda3d | ||
|
a7345ae957 | ||
|
b1a4865852 | ||
|
5626a7844b | ||
|
80bea46895 | ||
|
97713e6c29 | ||
|
aa5cfa756f | ||
|
4d025dde85 | ||
|
c4e1ad5af7 | ||
|
3cd8871b24 |
3
Makefile
3
Makefile
@ -21,6 +21,7 @@ main:
|
||||
$(CC) $(CFLAGS) $(SRC)/events.c -o $(OBJ)/events.o
|
||||
$(CC) $(CFLAGS) $(SRC)/module.c -o $(OBJ)/module.o
|
||||
$(CC) $(CFLAGS) $(SRC)/channel.c -o $(OBJ)/channel.o
|
||||
$(CC) $(CFLAGS) $(SRC)/timers.c -o $(OBJ)/timers.o
|
||||
$(CC) -o $(EXEC) $(OBJECTS) $(BINFLAGS)
|
||||
@echo "All Done!"
|
||||
|
||||
@ -29,6 +30,8 @@ mods: $(MODS_DIR)
|
||||
$(MODS_DIR):
|
||||
$(MAKE) -C $@
|
||||
|
||||
all: main mods
|
||||
|
||||
clean:
|
||||
@rm -rf build $(EXEC)
|
||||
@rm -rf mods/*.so
|
||||
|
@ -50,6 +50,8 @@ struct channel
|
||||
struct user *users;
|
||||
};
|
||||
|
||||
extern struct channel *channels[60];
|
||||
|
||||
void add_channel(char *name);
|
||||
void remove_channel(char *name);
|
||||
void add_user_to_channel(char *user, char *host, char *chan);
|
||||
@ -61,6 +63,10 @@ void update_server(char *nick, char *server);
|
||||
void update_realname(char *nick, char *real_name);
|
||||
void user_quit(char *nick);
|
||||
void set_realname(char *nick, char *real_name);
|
||||
struct user *get_user(char *nick);
|
||||
|
||||
MY_API char *get_user_host(char *nick);
|
||||
MY_API char *get_user_user(char *nick);
|
||||
|
||||
#ifdef _WIN32
|
||||
MY_API BOOL is_op(char *chan, char *nick);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define IRC_END_MOTD "376"
|
||||
#define IRC_NAMREPLY "353"
|
||||
#define IRC_WHOREPLY "352"
|
||||
#define TICK "TICK"
|
||||
|
||||
struct ev_handler
|
||||
{
|
||||
@ -33,6 +34,7 @@ struct handler
|
||||
struct ev_handler *evhands;
|
||||
};
|
||||
|
||||
extern struct handler *handlers[512];
|
||||
|
||||
void init_events();
|
||||
MY_API int add_handler(char *type, void *handler);
|
||||
|
10
lib/irc.h
10
lib/irc.h
@ -13,6 +13,8 @@
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#define OUTBUF_SIZE 60000
|
||||
#define INBUF_SIZE 60000
|
||||
|
||||
struct irc_conn
|
||||
{
|
||||
@ -29,8 +31,8 @@ struct irc_conn
|
||||
char real_name[512];
|
||||
|
||||
// I/O Buffers
|
||||
char out[4096];
|
||||
char in[4096];
|
||||
char *out;
|
||||
char *in;
|
||||
};
|
||||
|
||||
typedef struct handler event_handler;
|
||||
@ -53,7 +55,9 @@ MY_API void irc_privmsg(struct irc_conn *bot, char *to, char *fmt, ...);
|
||||
MY_API void irc_raw(struct irc_conn *bot, char *fmt, ...);
|
||||
MY_API void irc_join(struct irc_conn *bot, char *channel);
|
||||
MY_API void irc_part(struct irc_conn *bot, char *channel, char *reason);
|
||||
|
||||
MY_API void irc_ban(struct irc_conn *bot, char *channel, char *nick);
|
||||
MY_API void irc_kick(struct irc_conn *bot, char *channel, char *user, char *reason);
|
||||
MY_API void irc_mode(struct irc_conn *bot, char *channel, char *mode);
|
||||
|
||||
void irc_parse_raw(struct irc_conn *bot, char *raw);
|
||||
|
||||
|
@ -32,12 +32,16 @@ struct mods {
|
||||
struct module *modules;
|
||||
};
|
||||
|
||||
extern struct mods *mods;
|
||||
|
||||
void init_mods();
|
||||
void load_module(struct irc_conn *bot, char *where, char *stype, char *file);
|
||||
void unload_module(struct irc_conn *bot, char *where, char *file);
|
||||
void list_modules(struct irc_conn *bot, char *where);
|
||||
void set_bot(struct irc_conn *b);
|
||||
MY_API void register_module(char *name, char *author, char *version, char *description);
|
||||
MY_API void unregister_module(char *name);
|
||||
MY_API struct mods *get_mods();
|
||||
MY_API struct irc_conn *get_bot();
|
||||
|
||||
#endif
|
||||
|
58
lib/timers.h
Executable file
58
lib/timers.h
Executable file
@ -0,0 +1,58 @@
|
||||
#ifndef TIMERS_H
|
||||
#define TIMERS_H
|
||||
|
||||
#include "irc.h"
|
||||
#include "util.h"
|
||||
#include <time.h>
|
||||
#ifdef _WIN32
|
||||
#include <windef.h>
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
struct timer
|
||||
{
|
||||
int id;
|
||||
char name[50];
|
||||
int interval;
|
||||
int repeat;
|
||||
int repeat_count;
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL active;
|
||||
#else
|
||||
bool active;
|
||||
#endif
|
||||
|
||||
time_t next_run;
|
||||
struct irc_conn *bot;
|
||||
|
||||
void *handler;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct timers
|
||||
{
|
||||
int count;
|
||||
struct timer *timers;
|
||||
};
|
||||
|
||||
extern struct timers *timers;;
|
||||
|
||||
void init_timers();
|
||||
|
||||
MY_API int add_timer(struct irc_conn *bot, int interval, int repeat, void *handler, void *data);
|
||||
MY_API void set_timer_name(int id, char *name);
|
||||
MY_API int get_timer_repeat(int id);
|
||||
MY_API void del_timer(int id);
|
||||
|
||||
#ifdef _WIN32
|
||||
MY_API BOOL active_timers();
|
||||
#else
|
||||
MY_API bool active_timers();
|
||||
#endif
|
||||
|
||||
void add_to_delete_queue(int id);
|
||||
void fire_timers();
|
||||
|
||||
#endif
|
7
mods/chanop/Makefile
Executable file
7
mods/chanop/Makefile
Executable file
@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS=-fPIC -I../../lib
|
||||
OBJ=../chanop.so
|
||||
|
||||
main:
|
||||
$(CC) -shared -o $(OBJ) $(CFLAGS) ./chanop.c
|
||||
@echo "All Done!"
|
108
mods/chanop/chanop.c
Executable file
108
mods/chanop/chanop.c
Executable file
@ -0,0 +1,108 @@
|
||||
#include "channel.h"
|
||||
#define MY_DLL_EXPORTS 1
|
||||
|
||||
#include "util.h"
|
||||
#include "irc.h"
|
||||
#include "events.h"
|
||||
#include "module.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windef.h>
|
||||
BOOL hasAccess(char *user, char *chan)
|
||||
{
|
||||
if (is_op(chan, user) || is_halfop(chan, user))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
bool hasAccess(char *user, char *chan)
|
||||
{
|
||||
if (is_op(chan, user) || is_halfop(chan, user))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MY_API void chanop_privmsg_handler(struct irc_conn *bot, char *user, char *host, char *chan, const char *text)
|
||||
{
|
||||
char *nick;
|
||||
char *buf = (char *)malloc(sizeof(char *) * 500);
|
||||
int sn = 1;
|
||||
|
||||
if (strstr(text, "!kb") != NULL)
|
||||
{
|
||||
if (!hasAccess(user, chan))
|
||||
goto NO_ACCESS;
|
||||
|
||||
nick = skip((char *)text, ' ');
|
||||
sprintf(buf, "Requested by %s", user);
|
||||
|
||||
irc_ban(bot, chan, nick);
|
||||
irc_kick(bot, chan, nick, buf);
|
||||
}
|
||||
else if (strstr(text, "!op") != NULL)
|
||||
{
|
||||
if (!hasAccess(user, chan))
|
||||
goto NO_ACCESS;
|
||||
|
||||
nick = skip((char *)text, ' ');
|
||||
irc_raw(bot, "MODE %s +o %s", chan, nick);
|
||||
}
|
||||
else if (strstr(text, "!deop") != NULL)
|
||||
{
|
||||
if (!hasAccess(user, chan))
|
||||
goto NO_ACCESS;
|
||||
|
||||
nick = skip((char *)text, ' ');
|
||||
irc_raw(bot, "MODE %s -o %s", chan, nick);
|
||||
}
|
||||
else if (strstr(text, "!voice") != NULL)
|
||||
{
|
||||
if (!hasAccess(user, chan))
|
||||
goto NO_ACCESS;
|
||||
|
||||
nick = skip((char *)text, ' ');
|
||||
irc_raw(bot, "MODE %s +v %s", chan, nick);
|
||||
}
|
||||
else if (strstr(text, "!devoice") != NULL)
|
||||
{
|
||||
if (!hasAccess(user, chan))
|
||||
goto NO_ACCESS;
|
||||
|
||||
nick = skip((char *)text, ' ');
|
||||
irc_raw(bot, "MODE %s -v %s", chan, nick);
|
||||
}
|
||||
|
||||
sn = 0;
|
||||
|
||||
NO_ACCESS:
|
||||
if (sn)
|
||||
irc_notice(bot, user, "You do not have access to use that command in %s", chan);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
MY_API void mod_init()
|
||||
{
|
||||
register_module("chanop", "Aaron Blakely", "v0.1", "Channel Operator module");
|
||||
add_handler(PRIVMSG_CHAN, chanop_privmsg_handler);
|
||||
}
|
||||
|
||||
MY_API void mod_unload()
|
||||
{
|
||||
unregister_module("chanop");
|
||||
del_handler(PRIVMSG_CHAN, chanop_privmsg_handler);
|
||||
}
|
@ -1,27 +1,61 @@
|
||||
#define MY_DLL_EXPORTS 1
|
||||
|
||||
#include "util.h"
|
||||
#include "irc.h"
|
||||
#include "events.h"
|
||||
#include "module.h"
|
||||
#include "timers.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct said_hi
|
||||
{
|
||||
int timer_id;
|
||||
int repeat;
|
||||
|
||||
char user[50];
|
||||
char host[150];
|
||||
char chan[70];
|
||||
};
|
||||
|
||||
MY_API void said_h(struct irc_conn *bot, void *data)
|
||||
{
|
||||
struct said_hi *hi = (struct said_hi *)data;
|
||||
|
||||
irc_privmsg(bot, hi->chan, "[timer %d] %d : %s", hi->timer_id, get_timer_repeat(hi->timer_id), hi->user);
|
||||
|
||||
if ((get_timer_repeat(hi->timer_id) + 1) > hi->repeat)
|
||||
{
|
||||
free(hi);
|
||||
}
|
||||
}
|
||||
|
||||
MY_API void hello(struct irc_conn *bot, char *user, char *host, char *chan, const char *text)
|
||||
{
|
||||
struct said_hi *hi;
|
||||
|
||||
char *buf = (char *)malloc(sizeof(char *) * 500);
|
||||
sprintf(buf, "hi %s", bot->nick);
|
||||
|
||||
if (!strcmp(text, buf))
|
||||
{
|
||||
hi = calloc(1, sizeof(struct said_hi));
|
||||
|
||||
irc_privmsg(bot, chan, "hi %s", user);
|
||||
|
||||
printf("%s said hi to me\n", user);
|
||||
sprintf(hi->user, "%s", user);
|
||||
sprintf(hi->host, "%s", host);
|
||||
sprintf(hi->chan, "%s", chan);
|
||||
|
||||
hi->repeat = 3;
|
||||
hi->timer_id = add_timer(bot, 10, hi->repeat, said_h, hi);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
|
||||
MY_API void hello_join(struct irc_conn *bot, char *user, char *host, char *chan)
|
||||
{
|
||||
printf("%s!%s joined %s\n", user, host, chan);
|
||||
|
7
mods/lua/Makefile
Executable file
7
mods/lua/Makefile
Executable file
@ -0,0 +1,7 @@
|
||||
CC=gcc
|
||||
CFLAGS=-g -fPIC -I../../lib -llua
|
||||
OBJ=../lua.so
|
||||
|
||||
main:
|
||||
$(CC) -shared -o $(OBJ) $(CFLAGS) ./wrappers.c ./events.c ./handlers.c ./lua.c
|
||||
@echo "All Done!"
|
272
mods/lua/events.c
Executable file
272
mods/lua/events.c
Executable file
@ -0,0 +1,272 @@
|
||||
#include "lua.h"
|
||||
#include "events.h"
|
||||
#include <lua5.3/lua.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int block = 0;
|
||||
|
||||
void lua_init_events()
|
||||
{
|
||||
lua_register(lua.L, "_add_handler", lua_add_handler);
|
||||
lua_register(lua.L, "_del_handler", lua_del_handler);
|
||||
}
|
||||
|
||||
int lua_add_handler(lua_State *L)
|
||||
{
|
||||
char *event;
|
||||
int lreg;
|
||||
|
||||
if (block)
|
||||
{
|
||||
// return error
|
||||
return !LUA_OK;
|
||||
}
|
||||
|
||||
if (lua_gettop(L) < 2)
|
||||
{
|
||||
printf("Error: add_handler requires 2 arguments\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
luaL_checktype(L, 1, LUA_TSTRING);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
|
||||
lreg = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (lreg == -1)
|
||||
{
|
||||
const char *err = lua_tostring(L, -1);
|
||||
printf("Error: %s\n", err);
|
||||
}
|
||||
|
||||
event = (char *)lua_tostring(L, 1);
|
||||
|
||||
printf("Installing handler for event: %s : %d\n", event, lreg);
|
||||
|
||||
strlcpy(lua.events[lua.event_count].event, event, 25);
|
||||
lua.events[lua.event_count].lreg = lreg;
|
||||
|
||||
lua.event_count++;
|
||||
|
||||
lua_pushinteger(L, lreg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void lua_del_handler(lua_State *L)
|
||||
{
|
||||
char *event;
|
||||
int i;
|
||||
int lreg;
|
||||
|
||||
|
||||
if (lua_gettop(L) < 2)
|
||||
{
|
||||
printf("Error: del_handler requires 2 arguments\n");
|
||||
return;
|
||||
}
|
||||
|
||||
luaL_checktype(L, 1, LUA_TSTRING);
|
||||
luaL_checktype(L, 2, LUA_TNUMBER);
|
||||
|
||||
event = (char *)lua_tostring(L, 1);
|
||||
lreg = (int)lua_tointeger(L, 2);
|
||||
|
||||
for (i = 0; i < lua.event_count; i++)
|
||||
{
|
||||
if (!strcmp(lua.events[i].event, event))
|
||||
{
|
||||
if (lua.events[i].lreg == lreg)
|
||||
{
|
||||
printf("Removing handler for event: %s : %d\n", event, lreg);
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, lua.events[i].lreg);
|
||||
|
||||
while (i < lua.event_count)
|
||||
{
|
||||
lua.events[i] = lua.events[i + 1];
|
||||
i++;
|
||||
}
|
||||
|
||||
lua.event_count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lua_callfunc(int lreg, int argc, ...)
|
||||
{
|
||||
int i;
|
||||
va_list args;
|
||||
|
||||
va_start(args, argc);
|
||||
|
||||
lua_State *L = lua.L;
|
||||
int stackSize = lua_gettop(L);
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, lreg);
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
lua_pushstring(lua.L, va_arg(args, char *));
|
||||
}
|
||||
|
||||
if (lua_pcall(lua.L, argc, 0, 0) != LUA_OK)
|
||||
{
|
||||
const char *err = lua_tostring(L, -1);
|
||||
printf("Error: %s\n", err);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lua_settop(L, stackSize);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void lua_fire_handlers(char *event, ...)
|
||||
{
|
||||
int i;
|
||||
va_list args;
|
||||
|
||||
printf("lua_fire_handlers: %s\n", event);
|
||||
|
||||
char *user, *host, *chan, *text;
|
||||
|
||||
for (i = 0; i < lua.event_count; i++)
|
||||
{
|
||||
if (!lua.events[i].lreg)
|
||||
continue;
|
||||
|
||||
if (!strcmp(lua.events[i].event, event))
|
||||
{
|
||||
if (!strcmp(event, PRIVMSG_CHAN))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
user = va_arg(args, char *);
|
||||
host = va_arg(args, char *);
|
||||
chan = va_arg(args, char *);
|
||||
text = va_arg(args, char *);
|
||||
|
||||
printf("dbug: %s %s %s %s\n", user, host, chan, text);
|
||||
printf("dbug: %s %d %d\n", lua.events[i].event, lua.events[i].lreg, lua.event_count);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 4, user, host, chan, text);
|
||||
}
|
||||
else if (!strcmp(event, PRIVMSG_SELF))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
user = va_arg(args, char *);
|
||||
host = va_arg(args, char *);
|
||||
text = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 3, user, host, text);
|
||||
}
|
||||
else if (!strcmp(event, JOIN))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
user = va_arg(args, char *);
|
||||
host = va_arg(args, char *);
|
||||
chan = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 3, user, host, chan);
|
||||
}
|
||||
else if (!strcmp(event, JOIN_MYSELF))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
chan = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 1, chan);
|
||||
}
|
||||
else if (!strcmp(event, PART))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
user = va_arg(args, char *);
|
||||
host = va_arg(args, char *);
|
||||
chan = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 3, user, host, chan);
|
||||
}
|
||||
else if (!strcmp(event, PART_MYSELF))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
chan = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 1, chan);
|
||||
}
|
||||
else if (!strcmp(event, QUIT))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
user = va_arg(args, char *);
|
||||
host = va_arg(args, char *);
|
||||
text = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 3, user, host, text);
|
||||
}
|
||||
else if (!strcmp(event, NICK))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
user = va_arg(args, char *);
|
||||
host = va_arg(args, char *);
|
||||
text = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 3, user, host, text);
|
||||
}
|
||||
else if (!strcmp(event, NICK_MYSELF))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
text = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 1, text);
|
||||
}
|
||||
else if (!strcmp(event, CTCP))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
user = va_arg(args, char *);
|
||||
host = va_arg(args, char *);
|
||||
text = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 3, user, host, text);
|
||||
}
|
||||
else if (!strcmp(event, IRC_CONNECTED))
|
||||
{
|
||||
lua_callfunc(lua.events[i].lreg, 0);
|
||||
}
|
||||
else if (!strcmp(event, IRC_NAMREPLY))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
chan = va_arg(args, char *);
|
||||
text = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 2, chan, text);
|
||||
}
|
||||
else if (!strcmp(event, IRC_WHOREPLY))
|
||||
{
|
||||
va_start(args, event);
|
||||
|
||||
chan = va_arg(args, char *);
|
||||
text = va_arg(args, char *);
|
||||
|
||||
lua_callfunc(lua.events[i].lreg, 2, chan, text);
|
||||
}
|
||||
else if (!strcmp(event, NICK_INUSE))
|
||||
{
|
||||
lua_callfunc(lua.events[i].lreg, 0);
|
||||
}
|
||||
else if (!strcmp(event, TICK))
|
||||
{
|
||||
lua_callfunc(lua.events[i].lreg, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
128
mods/lua/handlers.c
Executable file
128
mods/lua/handlers.c
Executable file
@ -0,0 +1,128 @@
|
||||
#include "lua.h"
|
||||
#include "events.h"
|
||||
|
||||
void lua_init_handlers()
|
||||
{
|
||||
// see lib/events.h
|
||||
lua_setvar("PRIVMSG_CHAN", PRIVMSG_CHAN);
|
||||
lua_setvar("PRIVMSG_SELF", PRIVMSG_SELF);
|
||||
lua_setvar("TICK", TICK);
|
||||
lua_setvar("JOIN", JOIN);
|
||||
lua_setvar("JOIN_MYSELF", JOIN_MYSELF);
|
||||
lua_setvar("IRC_CONNECTED", IRC_CONNECTED);
|
||||
lua_setvar("NICK_MYSELF", NICK_MYSELF);
|
||||
lua_setvar("NICK_INUSE", NICK_INUSE);
|
||||
lua_setvar("CTCP", CTCP);
|
||||
lua_setvar("IRC_NAMREPLY", IRC_NAMREPLY);
|
||||
lua_setvar("IRC_WHOREPLY", IRC_WHOREPLY);
|
||||
lua_setvar("PART", PART);
|
||||
lua_setvar("PART_MYSELF", PART_MYSELF);
|
||||
lua_setvar("QUIT", QUIT);
|
||||
|
||||
add_handler(PRIVMSG_CHAN, chanprivmsg_handler);
|
||||
add_handler(PRIVMSG_SELF, selfprivmsg_handler);
|
||||
add_handler(TICK, tick_handler);
|
||||
add_handler(JOIN, join_handler);
|
||||
add_handler(JOIN_MYSELF, joinmyself_handler);
|
||||
add_handler(IRC_CONNECTED, ircconnected_handler);
|
||||
add_handler(NICK_MYSELF, nickmyself_handler);
|
||||
add_handler(NICK_INUSE, nickinuse_handler);
|
||||
add_handler(CTCP, ctcp_handler);
|
||||
add_handler(IRC_NAMREPLY, ircnamreply_handler);
|
||||
add_handler(IRC_WHOREPLY, ircwhoreply_handler);
|
||||
add_handler(PART, part_handler);
|
||||
add_handler(PART_MYSELF, partmyself_handler);
|
||||
add_handler(QUIT, quit_handler);
|
||||
}
|
||||
|
||||
void lua_unload_handlers()
|
||||
{
|
||||
del_handler(PRIVMSG_CHAN, chanprivmsg_handler);
|
||||
del_handler(PRIVMSG_SELF, selfprivmsg_handler);
|
||||
del_handler(TICK, tick_handler);
|
||||
del_handler(JOIN, join_handler);
|
||||
del_handler(JOIN_MYSELF, joinmyself_handler);
|
||||
del_handler(IRC_CONNECTED, ircconnected_handler);
|
||||
del_handler(NICK_MYSELF, nickmyself_handler);
|
||||
del_handler(NICK_INUSE, nickinuse_handler);
|
||||
del_handler(CTCP, ctcp_handler);
|
||||
del_handler(IRC_NAMREPLY, ircnamreply_handler);
|
||||
del_handler(IRC_WHOREPLY, ircwhoreply_handler);
|
||||
del_handler(PART, part_handler);
|
||||
del_handler(PART_MYSELF, partmyself_handler);
|
||||
del_handler(QUIT, quit_handler);
|
||||
}
|
||||
|
||||
|
||||
MY_API void chanprivmsg_handler(struct irc_conn *bot, char *user, char *host, char *chan, const char *text)
|
||||
{
|
||||
lua_fire_handlers(PRIVMSG_CHAN, user, host, chan, text);
|
||||
lua_eval(bot, user, host, chan, text);
|
||||
lua_load_script(bot, user, host, chan, text);
|
||||
lua_unload_script(bot, user, host, chan, text);
|
||||
}
|
||||
|
||||
MY_API void selfprivmsg_handler(struct irc_conn *bot, char *user, char *host, const char *text)
|
||||
{
|
||||
lua_fire_handlers(PRIVMSG_SELF, user, host, text);
|
||||
}
|
||||
|
||||
MY_API void tick_handler(struct irc_conn *bot)
|
||||
{
|
||||
lua_fire_handlers(TICK);
|
||||
}
|
||||
|
||||
MY_API void join_handler(struct irc_conn *bot, char *user, char *host, char *chan)
|
||||
{
|
||||
lua_fire_handlers(JOIN, user, host, chan);
|
||||
}
|
||||
|
||||
MY_API void joinmyself_handler(struct irc_conn *bot, char *chan)
|
||||
{
|
||||
lua_fire_handlers(JOIN_MYSELF, chan);
|
||||
}
|
||||
|
||||
MY_API void ircconnected_handler(struct irc_conn *bot)
|
||||
{
|
||||
lua_fire_handlers(IRC_CONNECTED);
|
||||
}
|
||||
|
||||
MY_API void nickmyself_handler(struct irc_conn *bot, char *newnick)
|
||||
{
|
||||
lua_fire_handlers(NICK_MYSELF, newnick);
|
||||
}
|
||||
|
||||
MY_API void nickinuse_handler(struct irc_conn *bot, char *newnick)
|
||||
{
|
||||
lua_fire_handlers(NICK_INUSE, newnick);
|
||||
}
|
||||
|
||||
MY_API void ctcp_handler(struct irc_conn *bot, char *user, char *host, char *chan, const char *text)
|
||||
{
|
||||
lua_fire_handlers(CTCP, user, host, chan, text);
|
||||
}
|
||||
|
||||
MY_API void ircnamreply_handler(struct irc_conn *bot, char *chan, char *nicks)
|
||||
{
|
||||
lua_fire_handlers(IRC_NAMREPLY, chan, nicks);
|
||||
}
|
||||
|
||||
MY_API void ircwhoreply_handler(struct irc_conn *bot, char *chan, char *user, char *host, char *server, char *nick, char *flags, char *hops, char *realname)
|
||||
{
|
||||
lua_fire_handlers(IRC_WHOREPLY, chan, user, host, server, nick, flags, hops, realname);
|
||||
}
|
||||
|
||||
MY_API void part_handler(struct irc_conn *bot, char *user, char *host, char *chan)
|
||||
{
|
||||
lua_fire_handlers(PART, user, host, chan);
|
||||
}
|
||||
|
||||
MY_API void partmyself_handler(struct irc_conn *bot, char *chan)
|
||||
{
|
||||
lua_fire_handlers(PART_MYSELF, chan);
|
||||
}
|
||||
|
||||
MY_API void quit_handler(struct irc_conn *bot, char *user, char *host, const char *text)
|
||||
{
|
||||
lua_fire_handlers(QUIT, user, host, text);
|
||||
}
|
38
mods/lua/init.lua
Executable file
38
mods/lua/init.lua
Executable file
@ -0,0 +1,38 @@
|
||||
-- init.lua: xbot runtime script
|
||||
-- Do not modify this file unless you know what you are doing.
|
||||
--
|
||||
-- Written by Aaron Blakely
|
||||
|
||||
local handlerstore = {}
|
||||
|
||||
function add_handler(type, func)
|
||||
local ret = _add_handler(type, func)
|
||||
|
||||
local callfilename = debug.getinfo(2, "S").source
|
||||
|
||||
if ret then
|
||||
table.insert(handlerstore, {type, func, ret, callfilename})
|
||||
end
|
||||
end
|
||||
|
||||
function del_handler(type, func)
|
||||
local callfilename = debug.getinfo(2, "S").source
|
||||
|
||||
-- loop through the handlerstore and remove the handler
|
||||
for i, v in ipairs(handlerstore) do
|
||||
|
||||
print("called with type: " .. type .. "callfilename: " .. callfilename)
|
||||
print("dbug: type: " .. v[1] .. " func: " .. v[3] .. " callfilename: " .. v[4])
|
||||
if v[2] == func then
|
||||
print("dbug: ref found")
|
||||
end
|
||||
|
||||
if v[1] == type and v[2] == func and v[4] == callfilename then
|
||||
_del_handler(type, v[3])
|
||||
table.remove(handlerstore, i)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
print("Handler not found")
|
||||
end
|
377
mods/lua/lua.c
Executable file
377
mods/lua/lua.c
Executable file
@ -0,0 +1,377 @@
|
||||
#define MY_DLL_EXPORTS 1
|
||||
|
||||
#include "util.h"
|
||||
#include "irc.h"
|
||||
#include "events.h"
|
||||
#include "module.h"
|
||||
#include "timers.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
struct lua_interp lua;
|
||||
struct irc_conn *instance;
|
||||
|
||||
char *scriptsfile = "./mods/lua/scripts";
|
||||
|
||||
int append_script(char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buf = (char *)malloc(sizeof(char *) * 500);
|
||||
|
||||
// check if the file is already in the list
|
||||
struct script_list list = get_scripts();
|
||||
|
||||
for (int i = 0; i < list.count; i++)
|
||||
{
|
||||
if (strcmp(list.scripts[i], fname) == 0)
|
||||
{
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((fp = fopen(scriptsfile, "a")) == NULL)
|
||||
{
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(buf, "%s\n", fname);
|
||||
fputs(buf, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int remove_script(char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buf = (char *)malloc(sizeof(char *) * 500);
|
||||
char *tmpfile = "./mods/lua/scripts.tmp";
|
||||
|
||||
if ((fp = fopen(scriptsfile, "r")) == NULL)
|
||||
{
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *tmp = fopen(tmpfile, "w");
|
||||
|
||||
while (fgets(buf, 500, fp) != NULL)
|
||||
{
|
||||
if (strcmp(buf, fname) != 0)
|
||||
{
|
||||
fputs(buf, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
fclose(tmp);
|
||||
|
||||
remove(scriptsfile);
|
||||
rename(tmpfile, scriptsfile);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct script_list get_scripts()
|
||||
{
|
||||
FILE *fp;
|
||||
char *buf = (char *)malloc(sizeof(char *) * 500);
|
||||
struct script_list list;
|
||||
int i = 0;
|
||||
|
||||
if ((fp = fopen(scriptsfile, "r")) == NULL)
|
||||
{
|
||||
free(buf);
|
||||
|
||||
list.count = 0;
|
||||
return list;
|
||||
}
|
||||
|
||||
while (fgets(buf, 500, fp) != NULL)
|
||||
{
|
||||
list.scripts[i] = (char *)malloc(sizeof(char *) * 150);
|
||||
strlcpy(list.scripts[i], buf, 150);
|
||||
|
||||
// remove newline
|
||||
list.scripts[i][strlen(list.scripts[i]) - 1] = '\0';
|
||||
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
list.count = i;
|
||||
|
||||
free(buf);
|
||||
return list;
|
||||
}
|
||||
|
||||
MY_API void lua_eval(struct irc_conn *bot, char *user, char *host, char *chan, const char *text)
|
||||
{
|
||||
int res;
|
||||
|
||||
block = 1;
|
||||
printf("lua eval called with %s\n", text);
|
||||
if (strstr(text, "!lua") != NULL)
|
||||
{
|
||||
text = skip(text, ' ');
|
||||
printf("lua: %s\n", text);
|
||||
|
||||
res = luaL_loadstring(lua.L, text);
|
||||
|
||||
if (res == LUA_OK)
|
||||
{
|
||||
res = lua_pcall(lua.L, 0, 0, 0);
|
||||
if (res != LUA_OK)
|
||||
{
|
||||
irc_privmsg(bot, chan, "Error: %s", lua_tostring(lua.L, -1));
|
||||
lua_pop(lua.L, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
irc_privmsg(bot, chan, "Error: %s", lua_tostring(lua.L, -1));
|
||||
lua_pop(lua.L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
block = 0;
|
||||
}
|
||||
|
||||
MY_API void lua_load_script(struct irc_conn *bot, char *user, char *host, char *chan, const char *text)
|
||||
{
|
||||
char *name;
|
||||
char *script;
|
||||
char *buf = (char *)malloc(sizeof(char *) * 500);
|
||||
|
||||
if (strstr(text, "!load") != NULL)
|
||||
{
|
||||
text = skip((char *)text, ' ');
|
||||
sprintf(buf, "./scripts/%s", text);
|
||||
|
||||
strlcpy(lua.scripts[lua.script_count].fname, buf, 150);
|
||||
|
||||
if (luaL_loadfile(lua.L, buf) != LUA_OK)
|
||||
{
|
||||
if (!strcmp(chan, "-stdio-"))
|
||||
{
|
||||
printf("Error loading lua script: %s\n", lua_tostring(lua.L, -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
irc_privmsg(bot, chan, "Error loading lua script: %s", lua_tostring(lua.L, -1));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
name = basename(buf);
|
||||
append_script(text);
|
||||
|
||||
// execute the script
|
||||
if (lua_pcall(lua.L, 0, 0, 0) != LUA_OK)
|
||||
{
|
||||
if (!strcmp(chan, "-stdio-"))
|
||||
{
|
||||
printf("Error executing lua script: %s\n", lua_tostring(lua.L, -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
irc_privmsg(bot, chan, "Error executing lua script: %s", lua_tostring(lua.L, -1));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// get a ref to unload function if it exists and store it with luaL_ref
|
||||
lua_getglobal(lua.L, "unload");
|
||||
|
||||
if (lua_isfunction(lua.L, -1))
|
||||
{
|
||||
lua.scripts[lua.script_count].unload = luaL_ref(lua.L, LUA_REGISTRYINDEX);
|
||||
printf("dbg: unload ref: %d\n", lua.scripts[lua.script_count].unload);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua.scripts[lua.script_count].unload = -1;
|
||||
|
||||
if (!strcmp(chan, "-stdio-"))
|
||||
{
|
||||
printf("No unload() function in %s\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
irc_privmsg(bot, chan, "No unload() function in %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
// call the load function if it exists
|
||||
lua_getglobal(lua.L, "load");
|
||||
|
||||
if (lua_isfunction(lua.L, -1))
|
||||
{
|
||||
if (lua_pcall(lua.L, 0, 0, 0) != LUA_OK)
|
||||
{
|
||||
if (!strcmp(chan, "-stdio-"))
|
||||
{
|
||||
printf("Error calling load() in %s: %s\n", buf, lua_tostring(lua.L, -1));
|
||||
}
|
||||
else
|
||||
{
|
||||
irc_privmsg(bot, chan, "Error calling load() in %s: %s", buf, lua_tostring(lua.L, -1));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
lua.script_count++;
|
||||
|
||||
if (!strcmp(chan, "-stdio-"))
|
||||
{
|
||||
printf("Loaded %s\n", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
irc_privmsg(bot, chan, "Loaded %s", name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcmp(chan, "-stdio-"))
|
||||
{
|
||||
printf("Error: No load() function in %s\n", buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
irc_privmsg(bot, chan, "Error: No load() function in %s", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
MY_API void lua_unload_script(struct irc_conn *bot, char *user, char *host, char *chan, const char *text)
|
||||
{
|
||||
char *name;
|
||||
char *script;
|
||||
char *buf = (char *)malloc(sizeof(char *) * 500);
|
||||
|
||||
if (strstr(text, "!unload") != NULL)
|
||||
{
|
||||
text = skip((char *)text, ' ');
|
||||
sprintf(buf, "./scripts/%s", text);
|
||||
|
||||
irc_privmsg(bot, chan, "Unloading %s", buf);
|
||||
|
||||
for (int i = 0; i < lua.script_count; i++)
|
||||
{
|
||||
if (strcmp(lua.scripts[i].fname, buf) == 0)
|
||||
{
|
||||
// call from the ref in .unload
|
||||
lua_rawgeti(lua.L, LUA_REGISTRYINDEX, lua.scripts[i].unload);
|
||||
if (lua_pcall(lua.L, 0, 0, 0) != LUA_OK)
|
||||
{
|
||||
irc_privmsg(bot, chan, "Error calling unload() in %s: %s", buf, lua_tostring(lua.L, -1));
|
||||
return;
|
||||
}
|
||||
|
||||
luaL_unref(lua.L, LUA_REGISTRYINDEX, lua.scripts[i].unload);
|
||||
lua.scripts[i].unload = -1;
|
||||
|
||||
remove_script(text);
|
||||
|
||||
sprintf(buf, "Unloaded %s", text);
|
||||
irc_privmsg(bot, chan, buf);
|
||||
|
||||
while (i < lua.script_count)
|
||||
{
|
||||
lua.scripts[i] = lua.scripts[i + 1];
|
||||
i++;
|
||||
}
|
||||
|
||||
lua.script_count--;
|
||||
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
irc_privmsg(bot, chan, "Error: %s not loaded", text);
|
||||
}
|
||||
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void lua_setvar(char *name, char *value)
|
||||
{
|
||||
lua_pushstring(lua.L, value);
|
||||
lua_setglobal(lua.L, name);
|
||||
}
|
||||
|
||||
MY_API void mod_init()
|
||||
{
|
||||
char *buf = (char *)malloc(sizeof(char *) * 500);
|
||||
struct script_list list = get_scripts();
|
||||
instance = get_bot();
|
||||
|
||||
lua.scripts = calloc(512, sizeof(struct lua_script));
|
||||
lua.events = calloc(1024, sizeof(struct lua_event));
|
||||
|
||||
lua.script_count = 0;
|
||||
lua.event_count = 0;
|
||||
|
||||
lua.L = luaL_newstate();
|
||||
luaL_openlibs(lua.L);
|
||||
lua_init_wrappers();
|
||||
lua_init_events();
|
||||
|
||||
lua_init_handlers();
|
||||
register_module("lua", "Aaron Blakely", "v0.1", "Lua module");
|
||||
|
||||
// load init.lua
|
||||
if (luaL_loadfile(lua.L, "./mods/lua/init.lua") != LUA_OK)
|
||||
{
|
||||
printf("Error loading init.lua: %s\n", lua_tostring(lua.L, -1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (lua_pcall(lua.L, 0, 0, 0) != LUA_OK)
|
||||
{
|
||||
printf("Error executing init.lua: %s\n", lua_tostring(lua.L, -1));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < list.count; i++)
|
||||
{
|
||||
printf("Loading %s\n", list.scripts[i]);
|
||||
|
||||
sprintf(buf, "!load %s", list.scripts[i]);
|
||||
|
||||
lua_load_script(instance, "lua", "localhost", "-stdio-", buf);
|
||||
}
|
||||
|
||||
printf("Lua module loaded\n");
|
||||
free(buf);
|
||||
}
|
||||
|
||||
MY_API void mod_unload()
|
||||
{
|
||||
lua_close(lua.L);
|
||||
|
||||
free(lua.scripts);
|
||||
free(lua.events);
|
||||
|
||||
unregister_module("lua");
|
||||
del_handler(PRIVMSG_CHAN, lua_eval);
|
||||
printf("Lua module unloaded\n");
|
||||
}
|
88
mods/lua/lua.h
Executable file
88
mods/lua/lua.h
Executable file
@ -0,0 +1,88 @@
|
||||
#ifndef LUA_H
|
||||
#define LUA_H
|
||||
|
||||
#include <lua5.3/lua.h>
|
||||
#include <lua5.3/lauxlib.h>
|
||||
#include <lua5.3/lualib.h>
|
||||
#include "irc.h"
|
||||
|
||||
struct lua_script
|
||||
{
|
||||
char name[25];
|
||||
char author[50];
|
||||
char version[10];
|
||||
char description[256];
|
||||
|
||||
char fname[256];
|
||||
int unload;
|
||||
};
|
||||
|
||||
struct lua_event
|
||||
{
|
||||
char event[25];
|
||||
int lreg;
|
||||
};
|
||||
|
||||
struct lua_interp
|
||||
{
|
||||
int script_count;
|
||||
int event_count;
|
||||
|
||||
lua_State *L;
|
||||
|
||||
struct lua_script *scripts;
|
||||
struct lua_event *events;
|
||||
};
|
||||
|
||||
struct script_list
|
||||
{
|
||||
int count;
|
||||
char *scripts[512];
|
||||
};
|
||||
|
||||
extern int block;
|
||||
|
||||
extern struct lua_interp lua;
|
||||
extern struct irc_conn *instance;
|
||||
|
||||
// events.c
|
||||
void lua_init_events();
|
||||
int lua_add_handler(lua_State *L);
|
||||
void lua_del_handler(lua_State *L);
|
||||
void lua_fire_handlers(char *event, ...);
|
||||
|
||||
// wrappers.c
|
||||
void lua_init_wrappers();
|
||||
void raw_wrapper(lua_State *L);
|
||||
void privmsg_wrapper(lua_State *L);
|
||||
|
||||
// handlers.c
|
||||
void lua_init_handlers();
|
||||
void lua_unload_handlers();
|
||||
|
||||
MY_API void chanprivmsg_handler(struct irc_conn *bot, char *user, char *host, char *chan, const char *text);
|
||||
MY_API void selfprivmsg_handler(struct irc_conn *bot, char *user, char *host, const char *text);
|
||||
MY_API void tick_handler(struct irc_conn *bot);
|
||||
MY_API void join_handler(struct irc_conn *bot, char *user, char *host, char *chan);
|
||||
MY_API void joinmyself_handler(struct irc_conn *bot, char *chan);
|
||||
MY_API void ircconnected_handler(struct irc_conn *bot);
|
||||
MY_API void nickmyself_handler(struct irc_conn *bot, char *newnick);
|
||||
MY_API void nickinuse_handler(struct irc_conn *bot, char *newnick);
|
||||
MY_API void ctcp_handler(struct irc_conn *bot, char *user, char *host, char *chan, const char *text);
|
||||
MY_API void ircnamreply_handler(struct irc_conn *bot, char *chan, char *nicks);
|
||||
MY_API void ircwhoreply_handler(struct irc_conn *bot, char *chan, char *user, char *host, char *server, char *nick, char *flags, char *hops, char *realname);
|
||||
MY_API void part_handler(struct irc_conn *bot, char *user, char *host, char *chan);
|
||||
MY_API void partmyself_handler(struct irc_conn *bot, char *chan);
|
||||
MY_API void quit_handler(struct irc_conn *bot, char *user, char *host, const char *text);
|
||||
|
||||
// lua.c
|
||||
void lua_setvar(char *name, char *value);
|
||||
int append_script(char *fname);
|
||||
int remove_script(char *fname);
|
||||
struct script_list get_scripts();
|
||||
|
||||
MY_API void lua_eval(struct irc_conn *bot, char *user, char *host, char *chan, const char *text);
|
||||
MY_API void lua_load_script(struct irc_conn *bot, char *user, char *host, char *chan, const char *text);
|
||||
MY_API void lua_unload_script(struct irc_conn *bot, char *user, char *host, char *chan, const char *text);
|
||||
|
||||
#endif
|
22
mods/lua/wrappers.c
Executable file
22
mods/lua/wrappers.c
Executable file
@ -0,0 +1,22 @@
|
||||
#include "lua.h"
|
||||
|
||||
void lua_init_wrappers()
|
||||
{
|
||||
lua_register(lua.L, "raw", raw_wrapper);
|
||||
lua_register(lua.L, "privmsg", privmsg_wrapper);
|
||||
}
|
||||
|
||||
void raw_wrapper(lua_State *L)
|
||||
{
|
||||
char *text = (char *)lua_tostring(L, 1);
|
||||
|
||||
irc_raw(instance, text);
|
||||
}
|
||||
|
||||
void privmsg_wrapper(lua_State *L)
|
||||
{
|
||||
char *where = (char *)lua_tostring(L, 1);
|
||||
char *text = (char *)lua_tostring(L, 2);
|
||||
|
||||
irc_privmsg(instance, where, text);
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
#define MY_DLL_EXPORTS 1
|
||||
|
||||
#include "irc.h"
|
||||
#include "events.h"
|
||||
#include "module.h"
|
||||
@ -5,13 +7,151 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define BUFFER_SIZE 512
|
||||
#include <windows.h>
|
||||
|
||||
void parseUptime(const char *output, struct irc_conn *bot, const char *where) {
|
||||
const char *keyword = "Statistics since ";
|
||||
const char *uptime_start;
|
||||
int month, day, year, hour, minute;
|
||||
SYSTEMTIME uptime_systemtime, current_time;
|
||||
ULONGLONG uptime_ticks, current_ticks;
|
||||
ULONGLONG uptime_seconds;
|
||||
char buf[BUFFER_SIZE];
|
||||
int days, hours, minutes;
|
||||
|
||||
OSVERSIONINFOEX osInfo;
|
||||
ZeroMemory(&osInfo, sizeof(OSVERSIONINFOEX));
|
||||
osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
|
||||
uptime_start = strstr(output, keyword);
|
||||
if (uptime_start == NULL) {
|
||||
printf("Failed to parse uptime information.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip the "Statistics since " keyword
|
||||
uptime_start += strlen(keyword);
|
||||
|
||||
// Parse the date and time
|
||||
if (sscanf(uptime_start, "%d/%d/%d %d:%d", &month, &day, &year, &hour, &minute) != 5) {
|
||||
printf("Failed to parse date and time.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current time
|
||||
GetLocalTime(¤t_time);
|
||||
|
||||
|
||||
// Calculate the uptime
|
||||
uptime_systemtime.wYear = year;
|
||||
uptime_systemtime.wMonth = month;
|
||||
uptime_systemtime.wDayOfWeek = 0;
|
||||
uptime_systemtime.wDay = day;
|
||||
uptime_systemtime.wHour = hour;
|
||||
uptime_systemtime.wMinute = minute;
|
||||
uptime_systemtime.wSecond = 0;
|
||||
uptime_systemtime.wMilliseconds = 0;
|
||||
|
||||
|
||||
SystemTimeToFileTime(&uptime_systemtime, (FILETIME *)&uptime_ticks);
|
||||
SystemTimeToFileTime(¤t_time, (FILETIME *)¤t_ticks);
|
||||
|
||||
uptime_seconds = (current_ticks - uptime_ticks) / 10000000UL; // Convert to seconds
|
||||
|
||||
uptime_seconds -= 1470;
|
||||
|
||||
days = uptime_seconds / (24 * 3600);
|
||||
hours = (uptime_seconds % (24 * 3600)) / 3600;
|
||||
minutes = (uptime_seconds % 3600) / 60;
|
||||
|
||||
if (GetVersionEx((OSVERSIONINFO*)&osInfo)) {
|
||||
if (osInfo.dwMajorVersion == 10 && osInfo.dwMinorVersion == 0) {
|
||||
sprintf(buf, "Windows 10");
|
||||
} else if (osInfo.dwMajorVersion == 6 && osInfo.dwMinorVersion == 3) {
|
||||
sprintf(buf, "Windows 8.1");
|
||||
} else if (osInfo.dwMajorVersion == 6 && osInfo.dwMinorVersion == 2) {
|
||||
sprintf(buf, "Windows 8");
|
||||
} else if (osInfo.dwMajorVersion == 6 && osInfo.dwMinorVersion == 1) {
|
||||
// detect Windows 7 or Windows Server 2008 R2
|
||||
if (osInfo.wProductType == VER_NT_WORKSTATION) {
|
||||
sprintf(buf, "Windows 7");
|
||||
} else {
|
||||
sprintf(buf, "Windows Server 2008 R2");
|
||||
}
|
||||
} else if (osInfo.dwMajorVersion == 6 && osInfo.dwMinorVersion == 0) {
|
||||
// detect Windows Vista or Windows Server 2008
|
||||
|
||||
if (osInfo.wProductType == VER_NT_WORKSTATION) {
|
||||
sprintf(buf, "Windows Vista");
|
||||
} else {
|
||||
sprintf(buf, "Windows Server 2008");
|
||||
}
|
||||
} else if (osInfo.dwMajorVersion == 5 && osInfo.dwMinorVersion == 1) {
|
||||
// detect Windows XP or Windows Server 2003
|
||||
|
||||
if (osInfo.wProductType == VER_NT_WORKSTATION) {
|
||||
sprintf(buf, "Windows XP");
|
||||
} else {
|
||||
sprintf(buf, "Windows Server 2003");
|
||||
}
|
||||
} else if (osInfo.dwMajorVersion == 5 && osInfo.dwMinorVersion == 0) {
|
||||
sprintf(buf, "Windows 2000");
|
||||
} else {
|
||||
sprintf(buf, "Windows");
|
||||
}
|
||||
}
|
||||
|
||||
irc_privmsg(bot, where, "%s: %d days, %d hours, and %d minutes up\n", buf, days, hours, minutes);
|
||||
}
|
||||
|
||||
char *executeCommand(const char *command)
|
||||
{
|
||||
char buffer[BUFFER_SIZE];
|
||||
char *old_result = NULL;
|
||||
char *result = NULL;
|
||||
FILE *fp;
|
||||
|
||||
fp = _popen(command, "r");
|
||||
if (fp == NULL) {
|
||||
printf("Failed to run command\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
if (result == NULL) {
|
||||
result = _strdup(buffer);
|
||||
} else {
|
||||
old_result = result;
|
||||
result = malloc(strlen(old_result) + strlen(buffer) + 1);
|
||||
strcpy(result, old_result);
|
||||
strcat(result, buffer);
|
||||
free(old_result);
|
||||
}
|
||||
}
|
||||
|
||||
_pclose(fp);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
MY_API void up(struct irc_conn *bot, char *user, char *host, char *chan, char *text)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
char *output;
|
||||
|
||||
if (!strcmp(text, "!uptime"))
|
||||
{
|
||||
output = executeCommand("net statistics server");
|
||||
parseUptime(output, bot, chan);
|
||||
|
||||
free(output);
|
||||
}
|
||||
#else
|
||||
char buf[100];
|
||||
FILE* file;
|
||||
|
||||
printf("dbug up called: %s!%s %s\n", user, host, text);
|
||||
|
||||
if (!strcmp(text, "!uptime"))
|
||||
{
|
||||
file = popen("uptime", "r");
|
||||
@ -20,7 +160,7 @@ MY_API void up(struct irc_conn *bot, char *user, char *host, char *chan, char *t
|
||||
|
||||
irc_privmsg(bot, chan, "%s", buf);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
MY_API void mod_init()
|
||||
|
20
scripts/hello.lua
Executable file
20
scripts/hello.lua
Executable file
@ -0,0 +1,20 @@
|
||||
NAME = "hello"
|
||||
VERSION = "v0.5"
|
||||
AUTHOR = "Aaron Blakely"
|
||||
DESCRIPTION = "A simple hello world script for xbot"
|
||||
|
||||
function hi(nick, host, chan, text)
|
||||
privmsg(chan, "Hello, " .. nick .. " from hello.lua!!!!!")
|
||||
end
|
||||
|
||||
function load()
|
||||
-- register_script(NAME, VERSION, AUTHOR, DESCRIPTION)
|
||||
|
||||
add_handler(PRIVMSG_CHAN, hi)
|
||||
end
|
||||
|
||||
function unload()
|
||||
-- unregister_script(NAME)
|
||||
|
||||
del_handler(PRIVMSG_CHAN, hi)
|
||||
end
|
25
scripts/test.lua
Executable file
25
scripts/test.lua
Executable file
@ -0,0 +1,25 @@
|
||||
local NAME = "hello"
|
||||
local VERSION = "v0.5"
|
||||
local AUTHOR = "Aaron Blakely"
|
||||
local DESCRIPTION = "A simple hello world script for xbot"
|
||||
|
||||
function test(nick, host, chan, text)
|
||||
-- check if text contains "hello"
|
||||
|
||||
|
||||
if string.find(text, "hello") then
|
||||
privmsg(chan, "Hello, " .. nick .. " from test.lua!!!")
|
||||
end
|
||||
end
|
||||
|
||||
function load()
|
||||
-- register_script(NAME, VERSION, AUTHOR, DESCRIPTION)
|
||||
|
||||
add_handler(PRIVMSG_CHAN, test)
|
||||
end
|
||||
|
||||
function unload()
|
||||
-- unregister_script(NAME)
|
||||
|
||||
del_handler(PRIVMSG_CHAN, test)
|
||||
end
|
@ -49,9 +49,28 @@ void remove_channel(char *name)
|
||||
}
|
||||
}
|
||||
|
||||
struct user *get_user(char *nick)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < chan_count; i++)
|
||||
{
|
||||
for (j = 0; j < channels[i]->user_count; j++)
|
||||
{
|
||||
if (!strcmp(channels[i]->users[j].nick, nick))
|
||||
{
|
||||
return &channels[i]->users[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_user_to_channel(char *user, char *host, char *chan)
|
||||
{
|
||||
int i;
|
||||
struct user *u, *uc;
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL is_op, is_voice, is_halfop, is_owner, is_admin;
|
||||
@ -107,6 +126,21 @@ void add_user_to_channel(char *user, char *host, char *chan)
|
||||
{
|
||||
if (!strcmp(channels[i]->name, chan))
|
||||
{
|
||||
if (get_user(user) != NULL)
|
||||
{
|
||||
u = get_user(user);
|
||||
u->is_op = is_op | is_owner | is_admin;
|
||||
u->is_voice = is_voice | is_halfop | is_op | is_owner | is_admin;
|
||||
u->is_halfop = is_halfop;
|
||||
u->is_owner = is_owner;
|
||||
u->is_admin = is_admin;
|
||||
|
||||
channels[i]->users[channels[i]->user_count] = *u;
|
||||
channels[i]->user_count++;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
strlcpy(channels[i]->users[channels[i]->user_count].nick, user, 50);
|
||||
strlcpy(channels[i]->users[channels[i]->user_count].host, host, 256);
|
||||
|
||||
@ -267,6 +301,43 @@ void set_realname(char *nick, char *real_name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MY_API char *get_user_host(char *nick)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < chan_count; i++)
|
||||
{
|
||||
for (j = 0; j < channels[i]->user_count; j++)
|
||||
{
|
||||
if (!strcmp(channels[i]->users[j].nick, nick))
|
||||
{
|
||||
return channels[i]->users[j].host;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *get_user_user(char *nick)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < chan_count; i++)
|
||||
{
|
||||
for (j = 0; j < channels[i]->user_count; j++)
|
||||
{
|
||||
if (!strcmp(channels[i]->users[j].nick, nick))
|
||||
{
|
||||
return channels[i]->users[j].user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
MY_API BOOL is_op(char *chan, char *nick)
|
||||
#else
|
||||
|
18
src/events.c
18
src/events.c
@ -11,13 +11,8 @@
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
struct handler *privmsg_self;
|
||||
struct handler *privmsg_chan;
|
||||
struct handler *chan_join;
|
||||
struct handler *irc_connected;
|
||||
|
||||
int handlers_count = 0;
|
||||
struct handler *handlers[512];
|
||||
int handlers_count = 0;
|
||||
|
||||
void init_event_type(char *type)
|
||||
{
|
||||
@ -31,6 +26,7 @@ void init_event_type(char *type)
|
||||
|
||||
void init_events()
|
||||
{
|
||||
init_event_type(TICK);
|
||||
init_event_type(PRIVMSG_SELF);
|
||||
init_event_type(PRIVMSG_CHAN);
|
||||
init_event_type(JOIN);
|
||||
@ -93,10 +89,10 @@ MY_API void del_handler(char *type, void *handler)
|
||||
void fire_handler(struct irc_conn *bot, char *type, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *usr = calloc(1, 64);
|
||||
char *host = calloc(1, 512);
|
||||
char *chan = calloc(1, 64);
|
||||
char *text = calloc(1, 512);
|
||||
char *usr;
|
||||
char *host;
|
||||
char *chan;
|
||||
char *text;
|
||||
int i, j;
|
||||
void (*handler)();
|
||||
char *cmd, *arg, *modpath;
|
||||
@ -136,7 +132,7 @@ void fire_handler(struct irc_conn *bot, char *type, ...)
|
||||
irc_notice(bot, usr, "You are unauthorized to use this command.");
|
||||
}
|
||||
}
|
||||
else if (!strcmp("PRINT_HANDLERS", cmd))
|
||||
else if (!strcmp("HANDLERS", cmd))
|
||||
{
|
||||
if (!strcmp(bot->admin, usr))
|
||||
{
|
||||
|
41
src/irc.c
41
src/irc.c
@ -142,9 +142,10 @@ void irc_raw(struct irc_conn *bot, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char outbuf[4096];
|
||||
char *p;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(bot->out, sizeof bot->out, fmt, ap);
|
||||
vsnprintf(bot->out, OUTBUF_SIZE, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
sprintf(outbuf, "%s\r\n", bot->out);
|
||||
@ -175,6 +176,29 @@ void irc_part(struct irc_conn *bot, char *chan, char *reason)
|
||||
irc_raw(bot, "PART %s :%s", chan, reason);
|
||||
}
|
||||
|
||||
void irc_ban(struct irc_conn *bot, char *channel, char *user)
|
||||
{
|
||||
char *host = get_user_host(user);
|
||||
char *un = get_user_user(user);
|
||||
|
||||
irc_raw(bot, "MODE %s +b *!%s@%s", channel, un, host);
|
||||
}
|
||||
|
||||
void irc_kick(struct irc_conn *bot, char *channel, char *user, char *reason)
|
||||
{
|
||||
if (!reason)
|
||||
{
|
||||
reason = "";
|
||||
}
|
||||
|
||||
irc_raw(bot, "KICK %s %s :%s", channel, user, reason);
|
||||
}
|
||||
|
||||
void irc_mode(struct irc_conn *bot, char *channel, char *mode)
|
||||
{
|
||||
irc_raw(bot, "MODE %s %s", channel, mode);
|
||||
}
|
||||
|
||||
void irc_ctcp(struct irc_conn *bot, char *to, char *fmt, ...)
|
||||
{
|
||||
char msg_[4096];
|
||||
@ -192,8 +216,6 @@ void irc_parse_raw(struct irc_conn *bot, char *raw)
|
||||
char *user, *host, *par, *text, *chan, *nick, *nicks, *tmp;
|
||||
user = bot->host;
|
||||
|
||||
text = calloc(1, strlen(raw) + 1);
|
||||
|
||||
if (!raw || !*raw)
|
||||
{
|
||||
return;
|
||||
@ -315,7 +337,7 @@ void irc_parse_raw(struct irc_conn *bot, char *raw)
|
||||
#ifdef _WIN32
|
||||
_snprintf(bot->nick, sizeof bot->nick, "%s_", bot->nick);
|
||||
#else
|
||||
snprintf(bot->nick, sizeof bot->nick, "%s_", bot->nick);
|
||||
sprintf(bot->nick, "%s_", bot->nick);
|
||||
#endif
|
||||
irc_raw(bot, "NICK %s", bot->nick);
|
||||
}
|
||||
@ -334,14 +356,20 @@ void irc_parse_raw(struct irc_conn *bot, char *raw)
|
||||
|
||||
while (nick)
|
||||
{
|
||||
add_user_to_channel(nick, "", chan);
|
||||
|
||||
tmp = nick;
|
||||
if (nick[0] == '@' || nick[0] == '+' || nick[0] == '%' || nick[0] == '~' || nick[0] == '&')
|
||||
{
|
||||
tmp++;
|
||||
}
|
||||
|
||||
if (get_user(tmp))
|
||||
{
|
||||
nick = strtok(NULL, " ");
|
||||
continue;
|
||||
}
|
||||
|
||||
add_user_to_channel(nick, "", chan);
|
||||
|
||||
irc_raw(bot, "WHO %s", tmp);
|
||||
nick = strtok(NULL, " ");
|
||||
}
|
||||
@ -376,4 +404,5 @@ void irc_parse_raw(struct irc_conn *bot, char *raw)
|
||||
fire_handler(bot, NICK_MYSELF, user, text);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
32
src/main.c
32
src/main.c
@ -15,6 +15,7 @@
|
||||
#include "events.h"
|
||||
#include "module.h"
|
||||
#include "channel.h"
|
||||
#include "timers.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
@ -22,7 +23,6 @@
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
|
||||
static time_t trespond;
|
||||
|
||||
int main()
|
||||
@ -31,12 +31,20 @@ int main()
|
||||
fd_set rd;
|
||||
struct irc_conn bot;
|
||||
struct timeval tv;
|
||||
struct timeval last_ping;
|
||||
|
||||
|
||||
char *p;
|
||||
|
||||
int bytesRecv;
|
||||
|
||||
bot.in = calloc(INBUF_SIZE, sizeof(char));
|
||||
bot.out = calloc(OUTBUF_SIZE, sizeof(char));
|
||||
|
||||
last_ping.tv_sec = time(NULL);
|
||||
|
||||
set_bot(&bot);
|
||||
init_events();
|
||||
init_timers();
|
||||
init_mods();
|
||||
|
||||
// Read the config
|
||||
@ -46,10 +54,15 @@ int main()
|
||||
printf("Connecting to %s...\n", bot.host);
|
||||
|
||||
irc_connect(&bot);
|
||||
trespond = time(NULL);
|
||||
|
||||
irc_auth(&bot);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
fire_timers();
|
||||
fire_handler(&bot, TICK, NULL);
|
||||
|
||||
FD_ZERO(&rd);
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -58,7 +71,7 @@ int main()
|
||||
FD_SET(0, &rd);
|
||||
FD_SET(fileno(bot.srv_fd), &rd);
|
||||
#endif
|
||||
tv.tv_sec = 120;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -90,13 +103,18 @@ int main()
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (time(NULL) - last_ping.tv_sec >= 120)
|
||||
{
|
||||
last_ping.tv_sec = time(NULL);
|
||||
irc_raw(&bot, "PING %s", bot.host);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
if (FD_ISSET(bot.srv_fd, &rd))
|
||||
{
|
||||
bytesRecv = recv(bot.srv_fd, bot.in, sizeof(bot.in), 0);
|
||||
bytesRecv = recv(bot.srv_fd, bot.in, INBUF_SIZE, 0);
|
||||
if (bytesRecv == SOCKET_ERROR)
|
||||
{
|
||||
eprint("Error receiving data: %d\n", WSAGetLastError());
|
||||
@ -118,7 +136,6 @@ int main()
|
||||
|
||||
// split bot.in into lines by \r\n and parse each one
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
// remove \r
|
||||
@ -131,10 +148,12 @@ int main()
|
||||
irc_parse_raw(&bot, bot.in);
|
||||
memmove(bot.in, p + 1, strlen(p + 1) + 1);
|
||||
}
|
||||
|
||||
free(p);
|
||||
#else
|
||||
if (FD_ISSET(fileno(bot.srv_fd), &rd))
|
||||
{
|
||||
if (fgets(bot.in, sizeof bot.in, bot.srv_fd) == NULL)
|
||||
if (fgets(bot.in, INBUF_SIZE, bot.srv_fd) == NULL)
|
||||
{
|
||||
eprint("xbot: remote host closed connection\n");
|
||||
return 0;
|
||||
@ -145,6 +164,7 @@ int main()
|
||||
#endif
|
||||
trespond = time(NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
45
src/module.c
45
src/module.c
@ -13,6 +13,7 @@
|
||||
#endif
|
||||
|
||||
struct mods *mods;
|
||||
struct irc_conn *instance;
|
||||
|
||||
void init_mods()
|
||||
{
|
||||
@ -23,14 +24,17 @@ void init_mods()
|
||||
|
||||
void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
{
|
||||
char *error = (char *)malloc(sizeof(char *)*1024);
|
||||
strlcpy(mods->modules[mods->count].fname, file, 256);
|
||||
#ifdef _WIN32
|
||||
|
||||
char *error = (char *)malloc(sizeof(char *)*1024);
|
||||
#ifdef _WIN32
|
||||
DWORD err;
|
||||
|
||||
strlcpy(mods->modules[mods->count].fname, file, 256);
|
||||
mods->modules[mods->count].handle = LoadLibrary(file);
|
||||
if (mods->modules[mods->count].handle == NULL)
|
||||
{
|
||||
sprintf(error, "Error loading %s\n", file);
|
||||
err = GetLastError();
|
||||
sprintf(error, "Error loading %s: %lu", file, err);
|
||||
|
||||
if (strcmp("runtime", stype))
|
||||
{
|
||||
@ -39,7 +43,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
}
|
||||
else if (strcmp(PRIVMSG_CHAN, stype))
|
||||
{
|
||||
irc_privmsg(bot, where, error);
|
||||
irc_notice(bot, where, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -63,7 +67,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
}
|
||||
else if (strcmp(PRIVMSG_CHAN, stype))
|
||||
{
|
||||
irc_privmsg(bot, where, error);
|
||||
irc_notice(bot, where, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -89,7 +93,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
}
|
||||
else if (strcmp(PRIVMSG_CHAN, stype))
|
||||
{
|
||||
irc_privmsg(bot, where, error);
|
||||
irc_notice(bot, where, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -101,7 +105,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
|
||||
if (strcmp("runtime", stype))
|
||||
{
|
||||
irc_privmsg(bot, where, "Module '%s' loaded.", file);
|
||||
irc_notice(bot, where, "Module '%s' loaded.", file);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -111,6 +115,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
#else
|
||||
void (*mod_init)();
|
||||
|
||||
strlcpy(mods->modules[mods->count].fname, file, 256);
|
||||
mods->modules[mods->count].handle = dlopen(file, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
|
||||
if (!mods->modules[mods->count].handle)
|
||||
{
|
||||
@ -123,7 +128,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
}
|
||||
else if (strcmp(PRIVMSG_CHAN, stype))
|
||||
{
|
||||
irc_privmsg(bot, where, error);
|
||||
irc_notice(bot, where, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -148,7 +153,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
}
|
||||
else if (strcmp(PRIVMSG_CHAN, stype))
|
||||
{
|
||||
irc_privmsg(bot, where, error);
|
||||
irc_notice(bot, where, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -170,7 +175,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
}
|
||||
else if (strcmp(PRIVMSG_CHAN, stype))
|
||||
{
|
||||
irc_privmsg(bot, where, error);
|
||||
irc_notice(bot, where, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -189,7 +194,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
}
|
||||
else if (strcmp(PRIVMSG_CHAN, stype))
|
||||
{
|
||||
irc_privmsg(bot, where, error);
|
||||
irc_notice(bot, where, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -200,7 +205,7 @@ void load_module(struct irc_conn *bot, char *where, char *stype, char *file)
|
||||
|
||||
if (strcmp("runtime", stype))
|
||||
{
|
||||
irc_privmsg(bot, where, "Module '%s' loaded.", file);
|
||||
irc_notice(bot, where, "Module '%s' loaded.", file);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -229,7 +234,7 @@ void unload_module(struct irc_conn *bot, char *where, char *file)
|
||||
|
||||
if (strcmp(PRIVMSG_CHAN, where))
|
||||
{
|
||||
irc_privmsg(bot, where, "Module '%s' unloaded.", file);
|
||||
irc_notice(bot, where, "Module '%s' unloaded.", file);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -242,6 +247,8 @@ void unload_module(struct irc_conn *bot, char *where, char *file)
|
||||
i++;
|
||||
}
|
||||
|
||||
mods->count--;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -298,3 +305,13 @@ MY_API struct mods *get_mods()
|
||||
{
|
||||
return mods;
|
||||
}
|
||||
|
||||
MY_API struct irc_conn *get_bot()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
MY_API void set_bot(struct irc_conn *b)
|
||||
{
|
||||
instance = b;
|
||||
}
|
||||
|
136
src/timers.c
Executable file
136
src/timers.c
Executable file
@ -0,0 +1,136 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "timers.h"
|
||||
#include "util.h"
|
||||
#include "irc.h"
|
||||
|
||||
struct timers *timers;
|
||||
int delete_queue[512];
|
||||
|
||||
void init_timers()
|
||||
{
|
||||
timers = calloc(1, sizeof(struct timers));
|
||||
|
||||
timers->count = 1;
|
||||
timers->timers = calloc(512, sizeof(struct timer));
|
||||
}
|
||||
|
||||
MY_API int add_timer(struct irc_conn *bot, int interval, int repeat, void *handler, void *data)
|
||||
{
|
||||
timers->timers[timers->count].interval = interval;
|
||||
timers->timers[timers->count].handler = handler;
|
||||
timers->timers[timers->count].id = timers->count;
|
||||
timers->timers[timers->count].bot = bot;
|
||||
timers->timers[timers->count].repeat = repeat;
|
||||
timers->timers[timers->count].repeat_count = 0;
|
||||
timers->timers[timers->count].data = data;
|
||||
timers->timers[timers->count].active = true;
|
||||
timers->timers[timers->count].next_run = time(NULL) + interval;
|
||||
timers->count++;
|
||||
|
||||
return timers->count - 1;
|
||||
}
|
||||
|
||||
MY_API void set_timer_name(int id, char *name)
|
||||
{
|
||||
sprintf(timers->timers[id].name, "%s", name);
|
||||
}
|
||||
|
||||
MY_API int get_timer_repeat(int id)
|
||||
{
|
||||
return timers->timers[id].repeat_count;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
MY_API BOOL active_timers()
|
||||
#else
|
||||
MY_API bool active_timers()
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < timers->count; i++)
|
||||
{
|
||||
if (timers->timers[i].active)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void add_to_delete_queue(int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 512; i++)
|
||||
{
|
||||
if (delete_queue[i] == 0)
|
||||
{
|
||||
delete_queue[i] = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MY_API void del_timer(int id)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < timers->count; i++)
|
||||
{
|
||||
if (timers->timers[i].id == id)
|
||||
{
|
||||
while (i < timers->count)
|
||||
{
|
||||
timers->timers[i] = timers->timers[i + 1];
|
||||
i++;
|
||||
}
|
||||
|
||||
timers->count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fire_timers()
|
||||
{
|
||||
int i;
|
||||
void (*handler)();
|
||||
|
||||
for (i = 0; i < timers->count; i++)
|
||||
{
|
||||
if (timers->timers[i].next_run <= time(NULL))
|
||||
{
|
||||
timers->timers[i].next_run = time(NULL) + timers->timers[i].interval;
|
||||
handler = timers->timers[i].handler;
|
||||
|
||||
if (timers->timers[i].active)
|
||||
(*handler)(timers->timers[i].bot, timers->timers[i].data);
|
||||
|
||||
if (timers->timers[i].repeat > 0)
|
||||
{
|
||||
timers->timers[i].repeat_count++;
|
||||
if (timers->timers[i].repeat_count >= timers->timers[i].repeat)
|
||||
{
|
||||
timers->timers[i].active = false;
|
||||
add_to_delete_queue(timers->timers[i].id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (active_timers() == false)
|
||||
{
|
||||
for (i = 0; i < 512; i++)
|
||||
{
|
||||
if (delete_queue[i] != 0)
|
||||
{
|
||||
del_timer(delete_queue[i]);
|
||||
delete_queue[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
4
xbot.cfg
4
xbot.cfg
@ -3,7 +3,7 @@
|
||||
bot:
|
||||
{
|
||||
verbose = 1;
|
||||
nick = "Lini";
|
||||
nick = "xbot";
|
||||
user = "xbot";
|
||||
admin = "ab3800";
|
||||
};
|
||||
@ -16,7 +16,7 @@ server:
|
||||
|
||||
mods:
|
||||
{
|
||||
autoload = ("autojoin", "hello", "uptime");
|
||||
autoload = ("chanop", "lua", "autojoin", "hello", "uptime");
|
||||
blacklist = ();
|
||||
|
||||
# config option for mods/autojoin.so
|
||||
|
6
xbot.sln
6
xbot.sln
@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xbot", "xbot.vcxproj", "{F9EBC08A-C550-413C-8CC6-81A232859D94}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xbot-mods", "xbot-mods\xbot-mods.vcxproj", "{BB6BFF6F-3972-4F0D-86E9-06FF4EAC5C5A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
@ -15,10 +13,6 @@ Global
|
||||
{F9EBC08A-C550-413C-8CC6-81A232859D94}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{F9EBC08A-C550-413C-8CC6-81A232859D94}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{F9EBC08A-C550-413C-8CC6-81A232859D94}.Release|Win32.Build.0 = Release|Win32
|
||||
{BB6BFF6F-3972-4F0D-86E9-06FF4EAC5C5A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{BB6BFF6F-3972-4F0D-86E9-06FF4EAC5C5A}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{BB6BFF6F-3972-4F0D-86E9-06FF4EAC5C5A}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{BB6BFF6F-3972-4F0D-86E9-06FF4EAC5C5A}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -45,7 +45,7 @@
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Debug\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Debug\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Release\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Release\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</LinkIncremental>
|
||||
@ -108,6 +108,7 @@
|
||||
<ClInclude Include="lib\events.h" />
|
||||
<ClInclude Include="lib\irc.h" />
|
||||
<ClInclude Include="lib\module.h" />
|
||||
<ClInclude Include="lib\timers.h" />
|
||||
<ClInclude Include="lib\util.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -117,6 +118,7 @@
|
||||
<ClCompile Include="src\irc.c" />
|
||||
<ClCompile Include="src\main.c" />
|
||||
<ClCompile Include="src\module.c" />
|
||||
<ClCompile Include="src\timers.c" />
|
||||
<ClCompile Include="src\util.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
Loading…
Reference in New Issue
Block a user