added timeToStr and cmd_users
authorpk910 <philipp@zoelle1.de>
Sun, 21 Aug 2011 04:19:14 +0000 (06:19 +0200)
committerpk910 <philipp@zoelle1.de>
Sun, 21 Aug 2011 05:58:00 +0000 (07:58 +0200)
DBHelper.h
bot_NeonServ.c
cmd_neonserv_users.c
lang.c
lang.h
main.c
modcmd.c
tools.c
tools.h

index cb99bc3393b8c403fff3a3dc965b5653607e685a..5c68b90f5967f9ed1b3c50a735c9f5b678e23c51 100644 (file)
@@ -2,14 +2,13 @@
 #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);
index feb16168bd36386698c12d3aa7156055336a136f..4cc7bded8e972acddcf671c7753593be2ea43a4a 100644 (file)
@@ -29,6 +29,7 @@ static const struct default_language_entry msgtab[] = {
     {"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."},
@@ -37,7 +38,22 @@ static const struct default_language_entry msgtab[] = {
     {"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}
 };
 
@@ -112,13 +128,13 @@ static void start_bots() {
 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);
index 30112592a5ebe348ed4289a460e84c00ad9ebc07..a87aca55d6ee4be60d8636c0fbddd9a959812ba9 100644 (file)
@@ -1,8 +1,110 @@
 
+/*
+* 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);
 }
diff --git a/lang.c b/lang.c
index f10292dd462cc041276fc80c93aa5e0020345859..2c186485f7bbada8ef37ac6a082d62897f99acdf 100644 (file)
--- a/lang.c
+++ b/lang.c
@@ -103,3 +103,25 @@ char *get_language_string(struct UserNode *user, const char* msg_ident) {
     }
     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;
+}
diff --git a/lang.h b/lang.h
index b909bd7e7e78f4224808f08d6c3e630f62083de3..f2dd4af9b41a196cb7478b831f92c9cb04ee05b1 100644 (file)
--- a/lang.h
+++ b/lang.h
@@ -1,6 +1,8 @@
 #ifndef _lang_h
 #define _lang_h
 
+#include "main.h"
+
 struct UserNode;
 
 struct default_language_entry {
@@ -28,5 +30,6 @@ struct language* get_language_by_name(char *name);
 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
diff --git a/main.c b/main.c
index 0fd282d189d447a260b4c6dc401ae7da5499018d..681f69140703b1ccb53e722afcc14f12125d0aca 100644 (file)
--- a/main.c
+++ b/main.c
@@ -11,6 +11,7 @@
 #include "mysqlConn.h"
 #include "HandleInfoHandler.h"
 #include "lang.h"
+#include "tools.h"
 
 void cleanup() {
     free_sockets();
@@ -36,6 +37,7 @@ int main(void)
     init_bind();
        init_modcmd();
     init_handleinfohandler();
+    init_tools();
     init_bots();
     
     time_t socket_wait;
index 5c07fb4e4828011040b799d0ec5dd05729ec3a38..03e56ac0bc6282ea2bccca3b2f59c905db5fb0c5 100644 (file)
--- a/modcmd.c
+++ b/modcmd.c
@@ -299,7 +299,7 @@ int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, un
     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;
diff --git a/tools.c b/tools.c
index 7911e5497eebd773aa63036c31aa2e65fc810254..cb00985435eb4142e9b130aa908e024e93fd14d5 100644 (file)
--- a/tools.c
+++ b/tools.c
@@ -1,4 +1,22 @@
 #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 */
 /*
@@ -77,25 +95,28 @@ struct Table *table_init(int width, int length, int flags) {
     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) {
@@ -103,44 +124,45 @@ 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]);
             }
@@ -150,12 +172,62 @@ void table_free(struct Table *table) {
     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);
+}
diff --git a/tools.h b/tools.h
index 22c1301ef0f236512ce32f8f3ade670238bdaa20..f34787d6d0efbb4d452a3299af7095284ee93eba 100644 (file)
--- a/tools.h
+++ b/tools.h
@@ -6,6 +6,8 @@
 #define TABLE_FLAG_USE_POINTER 0x01
 #define TABLE_FLAG_COL_BOLD    0x02
 
+struct UserNode;
+
 struct Table {
     char ***contents;
     int length;
@@ -13,10 +15,10 @@ struct Table {
     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);
@@ -27,4 +29,8 @@ int table_set_bold(struct Table *table, int collum, int bold);
 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