#define _DBHelper_h
#include "main.h"
+#include "ChanNode.h"
+#include "UserNode.h"
#define DB_CHANUSER_SUSPENDED 0x01
#define DB_CHANUSER_AUTOINVITE 0x02
#define DB_CHANUSER_NOAUTOOP 0x04
-struct ChanNode;
-struct UserNode;
-
void _loadUserSettings(struct UserNode* user);
#define loadUserSettings(USER) if((USER->flags & USERFLAG_ISAUTHED) && !(USER->flags & USERFLAG_LOADED_SETTINGS)) _loadUserSettings(USER)
int isGodMode(struct UserNode *user);
{"NS_ACCESS_OUTRANKED", "You cannot give users access greater than or equal to your own."},
{"NS_USER_OUTRANKED", "\002%s\002 outranks you (command has no effect)."},
{"NS_ACCESS_DENIED", "Access denied."},
+ {"NS_TABLE_NONE", " None"},
{"NS_CLVL_DONE", "%s now has access \002%d\002 in %s."},
{"NS_A_LACKS_ACCESS_BUT_GOD_NICK", "%s lacks access to %s but has \002security override\002 enabled."},
{"NS_A_LACKS_ACCESS_BUT_GOD_AUTH", "%s (%s) lacks access to %s but has \002security override\002 enabled."},
{"NS_A_ACCESS_NICK_GOD", "%s has access \002%d\002 in %s and has \002security override\002 enabled."},
{"NS_A_ACCESS_AUTH_GOD", "%s (%s) has access \002%d\002 in %s and has \002security override\002 enabled."},
{"NS_A_SUSPENDED", "\002%s\002's access to %s has been suspended."},
- {"NS_A_IS_IRCOP", "%s is an \002IRC operator\002." },
+ {"NS_A_IS_IRCOP", "%s is an \002IRC operator\002."},
+ {"NS_USERS_HEADER", "%s users from level %d to %d:"},
+ {"NS_USERS_HEADER_MATCH", "%s users from level %d to %d matching %s:"},
+ {"NS_USERS_HEADER_ACCESS", "Access"},
+ {"NS_USERS_HEADER_ACCOUNT", "Accout"},
+ {"NS_USERS_HEADER_SEEN", "Last Seen"},
+ {"NS_USERS_HEADER_STATE", "Status"},
+ {"NS_USERS_COUNT", "There are \002%d\002 users in %s from level %d to %d."},
+ {"NS_USERS_COUNT_1", "There is \002%d\002 user in %s from level %d to %d."},
+ {"NS_USERS_COUNT_MATCH", "There are \002%d\002 users in %s from level %d to %d. (\002%d\002 matching your request)"},
+ {"NS_USERS_COUNT_MATCH_1", "There is \002%d\002 user in %s from level %d to %d. (\002%d\002 matching your request)"},
+ {"NS_USERS_SEEN_HERE", "Here"},
+ {"NS_USERS_SEEN_NEVER", "Never"},
+ {"NS_USERS_STATE_SUSPENDED", "Suspended"},
+ {"NS_USERS_STATE_NORMAL", "Normal"},
+
{NULL, NULL}
};
void init_NeonServ() {
check_mysql();
- register_command(BOTID, "users", neonserv_cmd_users, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REQUIRE_AUTH);
register_command(BOTID, "modes", neonserv_cmd_modes, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
register_command(BOTID, "adduser", neonserv_cmd_adduser, 2, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
register_command(BOTID, "deluser", neonserv_cmd_deluser, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
register_command(BOTID, "clvl", neonserv_cmd_clvl, 2, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH);
register_command(BOTID, "a", neonserv_cmd_a, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN);
+ register_command(BOTID, "users", neonserv_cmd_users, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN);
start_bots();
bind_bot_ready(neonserv_bot_ready);
+/*
+* argv[0] - usermask
+* argv[1] - min access
+* argv[2] - max access
+*/
+static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup);
+static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access);
+
+struct neonserv_cmd_users_cache {
+ struct ClientSocket *client, *textclient;
+ struct UserNode *user;
+ char *usermask;
+ int min_access;
+ int max_access;
+};
+
static CMD_BIND(neonserv_cmd_users) {
+ int min_access = 1, max_access = 500;
+ char *usermask = NULL;
+ if(argc > 0)
+ usermask = argv[0];
+ if(argc > 2) {
+ min_access = atoi(argv[1]);
+ max_access = atoi(argv[2]);
+ }
+ struct neonserv_cmd_users_cache *cache = malloc(sizeof(*cache));
+ if (!cache) {
+ perror("malloc() failed");
+ return;
+ }
+ cache->client = client;
+ cache->textclient = getTextBot();
+ cache->user = user;
+ cache->usermask = (usermask ? strdup(usermask) : NULL);
+ cache->min_access = min_access;
+ cache->max_access = max_access;
+ get_userlist(chan, neonserv_cmd_users_userlist_lookup, cache);
+}
+
+static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup) {
+ struct neonserv_cmd_users_cache *cache = data;
+ neonserv_cmd_users_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access);
+ if(cache->usermask)
+ free(cache->usermask);
+ free(cache);
+}
+
+static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access) {
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int content_count = 0, cflags, is_here, caccess, i;
+ char seenstr[MAXLEN];
+ struct Table *table;
struct ChanUser *chanuser;
- putsock(client, "PRIVMSG %s :[BOT JOIN] Users on this Channel:", chan->name);
- for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
- putsock(client, "PRIVMSG %s : %s!%s@%s [%s] rights: %d", chan->name, chanuser->user->nick, chanuser->user->ident, chanuser->user->host, ((chanuser->user->flags & USERFLAG_ISAUTHED) ? chanuser->user->auth : "*"), chanuser->flags);
+ printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_seen`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d'", chan->channel_id);
+ res = mysql_use();
+ table = table_init(4, mysql_num_rows(res) + 1, 0);
+ if(usermask)
+ reply(textclient, user, "NS_USERS_HEADER_MATCH", chan->name, min_access, max_access, usermask);
+ else
+ reply(textclient, user, "NS_USERS_HEADER", chan->name, min_access, max_access);
+ char *content[4];
+ content[0] = get_language_string(user, "NS_USERS_HEADER_ACCESS");
+ content[1] = get_language_string(user, "NS_USERS_HEADER_ACCOUNT");
+ content[2] = get_language_string(user, "NS_USERS_HEADER_SEEN");
+ content[3] = get_language_string(user, "NS_USERS_HEADER_STATE");
+ table_add(table, content);
+ while ((row = mysql_fetch_row(res)) != NULL) {
+ caccess = atoi(row[0]);
+ if((!usermask || match(usermask, row[1])) && caccess >= min_access && caccess <= max_access) {
+ content[0] = row[0];
+ content[1] = row[1];
+ is_here = 0;
+ for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+ if((chanuser->user->flags & USERFLAG_ISAUTHED) && !strcmp(chanuser->user->auth, row[1])) {
+ is_here = 1;
+ break;
+ }
+ }
+ if(is_here) {
+ content[2] = get_language_string(user, "NS_USERS_SEEN_HERE");
+ } else if(!strcmp(row[2], "0")) {
+ content[2] = get_language_string(user, "NS_USERS_SEEN_NEVER");
+ } else {
+ timeToStr(user, (time(0) - atoi(row[2])), 2, seenstr);
+ content[2] = seenstr; //generate time
+ }
+ cflags = atoi(row[3]);
+ if(cflags & DB_CHANUSER_SUSPENDED)
+ content[3] = get_language_string(user, "NS_USERS_STATE_SUSPENDED");
+ else
+ content[3] = get_language_string(user, "NS_USERS_STATE_NORMAL");
+ content_count++;
+ table_add(table, content);
+ }
+ }
+ //send the table
+ char **table_lines = table_end(table);
+ for(i = 0; i < table->entrys; i++) {
+ reply(textclient, user, table_lines[i]);
}
+ if(!content_count)
+ reply(textclient, user, "NS_TABLE_NONE");
+ if(usermask || min_access != 1 || max_access != 500)
+ reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_MATCH_1" : "NS_USERS_COUNT_MATCH"), table->length - 1, chan->name, min_access, max_access, content_count);
+ else
+ reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_1" : "NS_USERS_COUNT"), table->length - 1, chan->name, min_access, max_access);
+ table_free(table);
}
}
return NULL;
}
+
+char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...) {
+ char *formatStr = get_language_string(user, msg_ident);
+ if(!formatStr) return NULL;
+ if(buffer == NULL) {
+ buffer = (char *)malloc((MAXLEN+1) * sizeof(char));
+ if (!buffer) {
+ perror("malloc() failed");
+ return NULL;
+ }
+ }
+ int pos;
+ va_list arg_list;
+ buffer[0] = '\0';
+ va_start(arg_list, msg_ident);
+ pos = vsnprintf(buffer, MAXLEN - 2, formatStr, arg_list);
+ va_end(arg_list);
+ if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
+ buffer[pos] = '\n';
+ buffer[pos+1] = '\0';
+ return buffer;
+}
#ifndef _lang_h
#define _lang_h
+#include "main.h"
+
struct UserNode;
struct default_language_entry {
struct language* get_default_language();
void register_default_language_table(const struct default_language_entry *msgtab);
char *get_language_string(struct UserNode *user, const char* msg_ident);
+char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...);
#endif
\ No newline at end of file
#include "mysqlConn.h"
#include "HandleInfoHandler.h"
#include "lang.h"
+#include "tools.h"
void cleanup() {
free_sockets();
init_bind();
init_modcmd();
init_handleinfohandler();
+ init_tools();
init_bots();
time_t socket_wait;
cmdfunc->botid = botid;
cmdfunc->name = strdup(name);
cmdfunc->func = func;
- cmdfunc->flags = 0;
+ cmdfunc->flags = flags;
cmdfunc->paramcount = paramcount;
cmdfunc->next = cmd_functions;
cmd_functions = cmdfunc;
#include "tools.h"
+#include "UserNode.h"
+#include "lang.h"
+
+static const struct default_language_entry msgtab[] = {
+ {"TIME_MASK_2_ITEMS", "%s and %s"},
+ {"TIME_MASK_3_ITEMS", "%s, %s and %s"},
+ {"TIME_YEAR", "%d year"},
+ {"TIME_YEARS", "%d years"},
+ {"TIME_DAY", "%d day"},
+ {"TIME_DAYS", "%d days"},
+ {"TIME_HOUR", "%d hour"},
+ {"TIME_HOURS", "%d hours"},
+ {"TIME_MINUTE", "%d minute"},
+ {"TIME_MINUTES", "%d minutes"},
+ {"TIME_SECOND", "%d second"},
+ {"TIME_SECONDS", "%d seconds"},
+ {NULL, NULL}
+};
/* copied from IRCU 2.10.12 match.c */
/*
struct Table *table = malloc(sizeof(*table));
table->contents = malloc(length * sizeof(*table->contents));
for(row = 0; row < length; row++) {
- table->contents[row] = calloc(width, sizeof(*table->contents));
+ table->contents[row] = calloc(width, sizeof(*table->contents[row]));
}
table->length = length;
table->width = width;
table->flags = flags;
table->col_flags = calloc(length, sizeof(int));
- table->c_entry = 0;
+ table->entrys = 0;
table->maxwidth = calloc(length, sizeof(int));
- table->table = NULL;
+ table->table_lines = NULL;
+ return table;
}
int table_add(struct Table *table, char **entry) {
int col;
+ if(table->entrys == table->length) return 0;
for(col = 0; col < table->width; col++) {
- table->contents[table->c_entry][col] = ((table->flags & TABLE_FLAG_USE_POINTER) ? entry[col] : strdup(entry[col]));
+ table->contents[table->entrys][col] = ((table->flags & TABLE_FLAG_USE_POINTER) ? entry[col] : strdup(entry[col]));
if(strlen(entry[col]) > table->maxwidth[col])
table->maxwidth[col] = strlen(entry[col]);
}
- table->c_entry++;
+ table->entrys++;
+ return 1;
}
int table_set_bold(struct Table *table, int collum, int bold) {
table->col_flags[collum] |= TABLE_FLAG_COL_BOLD;
else
table->col_flags[collum] &= ~TABLE_FLAG_COL_BOLD;
+ return 1;
}
char **table_end(struct Table *table) {
- int row, col, tablewidth, pos,i;
- if(table->table) return table->table;
- table->table = malloc(table->length * sizeof(*table->table));
+ int row, col, tablewidth = 0, pos,i;
+ if(!table->entrys) return NULL;
for(col = 0; col < table->width; col++) {
tablewidth += table->maxwidth[col]+1;
if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
tablewidth += 2;
}
- for(row = 0; row < table->row; row++) {
- table->table[row] = malloc(tablewidth * sizeof(*table->table[row]))
+ table->table_lines = malloc(table->entrys * sizeof(table->table_lines));
+ for(row = 0; row < table->entrys; row++) {
+ table->table_lines[row] = malloc(tablewidth * sizeof(*table->table_lines[row]));
pos = 0;
for(col = 0; col < table->width; col++) {
if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
- table->table[row][pos++] = '\002';
+ table->table_lines[row][pos++] = '\002';
for(i = 0; i < strlen(table->contents[row][col]); i++) {
- table->table[row][pos++] = table->contents[row][col][i];
+ table->table_lines[row][pos++] = table->contents[row][col][i];
}
for(;i < table->maxwidth[col]; i++) {
- table->table[row][pos++] = ' ';
+ table->table_lines[row][pos++] = ' ';
}
if(table->col_flags[col] & TABLE_FLAG_COL_BOLD)
- table->table[row][pos++] = '\002';
+ table->table_lines[row][pos++] = '\002';
if(col < table->width-1)
- table->table[row][pos++] = ' ';
+ table->table_lines[row][pos++] = ' ';
else
- table->table[row][pos++] = '\0';
+ table->table_lines[row][pos++] = '\0';
}
}
- return table->table;
+ return table->table_lines;
}
void table_free(struct Table *table) {
int row, col;
- for(row = 0; row < length; row++) {
- if(!(table->flags & TABLE_FLAG_USE_POINTER)) {
+ for(row = 0; row < table->length; row++) {
+ if(!(table->flags & TABLE_FLAG_USE_POINTER) && table->entrys > row) {
for(col = 0; col < table->width; col++) {
free(table->contents[row][col]);
}
free(table->contents);
free(table->col_flags);
free(table->maxwidth);
- if(table->table) {
- for(row = 0; row < length; row++) {
- free(table->table[row]);
+ if(table->table_lines) {
+ for(row = 0; row < table->entrys; row++) {
+ free(table->table_lines[row]);
}
- free(table->table);
+ free(table->table_lines);
}
free(table);
}
+int timeToStr(struct UserNode *user, int seconds, int items, char *buf) {
+ char *item[items];
+ int tmp, citem = 0;
+ if(citem != items && seconds >= 31536000) { //60*60*24*365 = 31536000
+
+ tmp = seconds / 31536000;
+ item[citem++] = build_language_string(user, NULL, (tmp == 1 ? "TIME_YEAR" : "TIME_YEARS"), tmp);
+ seconds -= tmp * 31536000;
+ }
+ if(citem != items && seconds >= 86400) { //60*60*24 = 86400
+ tmp = seconds / 86400;
+ item[citem++] = build_language_string(user, NULL, (tmp == 1 ? "TIME_DAY" : "TIME_DAYS"), tmp);
+ seconds -= tmp * 86400;
+ }
+ if(citem != items && seconds >= 3600) { //60*60 = 86400
+ tmp = seconds / 3600;
+ item[citem++] = build_language_string(user, NULL, (tmp == 1 ? "TIME_HOUR" : "TIME_HOURS"), tmp);
+ seconds -= tmp * 3600;
+ }
+ if(citem != items && seconds >= 60) {
+ tmp = seconds / 60;
+ item[citem++] = build_language_string(user, NULL, (tmp == 1 ? "TIME_MINUTE" : "TIME_MINUTES"), tmp);
+ seconds -= tmp * 60;
+ }
+ if(citem != items && seconds >= 1) {
+ item[citem++] = build_language_string(user, NULL, (seconds == 1 ? "TIME_SECOND" : "TIME_SECONDS"), seconds);
+ }
+ if(items == 2) {
+ build_language_string(user, buf, "TIME_MASK_2_ITEMS", item[0], item[1]);
+ } else if(items == 3) {
+ build_language_string(user, buf, "TIME_MASK_3_ITEMS", item[0], item[1], item[2]);
+ } else {
+ int i, ii, p = 0;
+ for(i = 0; i < items; i++) {
+ for(ii = 0; ii < strlen(item[i]); ii++) {
+ buf[p++] = item[i][ii];
+ }
+ buf[p++] = ' ';
+ }
+ buf[p-1] = '\0';
+ }
+ return 1;
+}
+
+
+
+
+void init_tools() {
+ register_default_language_table(msgtab);
+}
#define TABLE_FLAG_USE_POINTER 0x01
#define TABLE_FLAG_COL_BOLD 0x02
+struct UserNode;
+
struct Table {
char ***contents;
int length;
int flags;
int *col_flags;
- int c_entry;
+ int entrys;
int *maxwidth;
- char **table; //we just store this to free it in table_free
+ char **table_lines; //we just store this to free it in table_free
};
int match(const char *mask, const char *name);
char **table_end(struct Table *table);
void table_free(struct Table *table);
+int timeToStr(struct UserNode *user, int seconds, int items, char *buf);
+
+void init_tools();
+
#endif
\ No newline at end of file