added states criteria to cmd_search
[NeonServV5.git] / src / cmd_neonserv_search.c
1 /* cmd_neonserv_search.c - NeonServ v5.2
2  * Copyright (C) 2011  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "cmd_neonserv.h"
19
20 #define CMD_SEARCH_FLAG_HAS_NODELETE 0x001
21 #define CMD_SEARCH_FLAG_NOT_NODELETE 0x002
22 #define CMD_SEARCH_FLAG_HAS_SUSPENDED 0x004
23 #define CMD_SEARCH_FLAG_NOT_SUSPENDED 0x008
24 #define CMD_SEARCH_FLAG_IS_JOINED  0x010
25 #define CMD_SEARCH_FLAG_NOT_JOINED 0x020
26 #define CMD_SEARCH_FLAG_IS_OPPED   0x040
27 #define CMD_SEARCH_FLAG_NOT_OPPED  0x080
28 #define CMD_SEARCH_FLAG_IS_VOICED  0x100
29 #define CMD_SEARCH_FLAG_NOT_VOICED 0x200
30 #define CMD_SEARCH_FLAG_STATES     0x3f0
31
32 struct neonserv_cmd_search_criteria {
33     char *name;
34     char *registrar;
35     unsigned int flags : 16;
36     unsigned int unvisited;
37     unsigned int registered;
38     unsigned int limit : 16;
39 };
40
41 CMD_BIND(neonserv_cmd_search) {
42     //ok parse the criterias
43     struct neonserv_cmd_search_criteria *criteria = malloc(sizeof(*criteria));
44     if (!criteria) {
45         perror("malloc() failed");
46         return;
47     }
48     memset(criteria, 0, sizeof(*criteria));
49     criteria->limit = 50;
50     int i, show_chans = 0, positive;
51     if(!stricmp(argv[0], "print")) {
52         show_chans = 1;
53     }
54     for(i = 1; i < argc; i += 2) {
55         if(argc <= i+1) {
56             reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT");
57             return;
58         }
59         if(!stricmp(argv[i], "name")) criteria->name = argv[i+1];
60         else if(!stricmp(argv[i], "registrar")) criteria->registrar = argv[i+1];
61         else if(!stricmp(argv[i], "unvisited")) criteria->unvisited = strToTime(user, argv[i+1]);
62         else if(!stricmp(argv[i], "registered")) criteria->registered = strToTime(user, argv[i+1]);
63         else if(!stricmp(argv[i], "flags")) {
64             if(argv[i+1][0] == '+') {
65                 positive = 1;
66                 argv[i+1]++;
67             } else if(argv[i+1][0] == '-') {
68                 positive = 0;
69                 argv[i+1]++;
70             } else
71                 positive = 1;
72             if(!stricmp(argv[i+1], "nodelete")) {
73                 if(positive)
74                     criteria->flags |= CMD_SEARCH_FLAG_HAS_NODELETE;
75                 else
76                     criteria->flags |= CMD_SEARCH_FLAG_NOT_NODELETE;
77             } else if(!stricmp(argv[i+1], "suspended")) {
78                 if(positive)
79                     criteria->flags |= CMD_SEARCH_FLAG_HAS_SUSPENDED;
80                 else
81                     criteria->flags |= CMD_SEARCH_FLAG_NOT_SUSPENDED;
82             }
83         }
84         else if(!stricmp(argv[i], "state")) {
85             if(argv[i+1][0] == '+') {
86                 positive = 1;
87                 argv[i+1]++;
88             } else if(argv[i+1][0] == '-') {
89                 positive = 0;
90                 argv[i+1]++;
91             } else
92                 positive = 1;
93             if(!stricmp(argv[i+1], "joined")) {
94                 if(positive)
95                     criteria->flags |= CMD_SEARCH_FLAG_IS_JOINED;
96                 else
97                     criteria->flags |= CMD_SEARCH_FLAG_NOT_JOINED;
98             } else if(!stricmp(argv[i+1], "opped")) {
99                 if(positive)
100                     criteria->flags |= CMD_SEARCH_FLAG_IS_OPPED;
101                 else
102                     criteria->flags |= CMD_SEARCH_FLAG_NOT_OPPED;
103             } else if(!stricmp(argv[i+1], "voiced")) {
104                 if(positive)
105                     criteria->flags |= CMD_SEARCH_FLAG_IS_VOICED;
106                 else
107                     criteria->flags |= CMD_SEARCH_FLAG_NOT_VOICED;
108             }
109         }
110         else if(!stricmp(argv[i], "limit")) {
111             criteria->limit = atoi(argv[i+1]);
112         }
113     }
114     int matches = 0;
115     reply(getTextBot(), user, "NS_SEARCH_HEADER");
116     MYSQL_RES *res, *res2;
117     MYSQL_ROW row, row2;
118     printf_mysql_query("SELECT `channel_name`, `user_user`, `channel_registered`, `channel_nodelete`, `suspended`, `channel_id` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botid` = '%d'", client->botid);
119     res = mysql_use();
120     while ((row = mysql_fetch_row(res)) != NULL) {
121         if(show_chans && matches == criteria->limit) {
122             //too many
123             break;
124         }
125         if(criteria->name && match(criteria->name, row[0])) continue;
126         if(criteria->registrar && row[1] && match(criteria->registrar, row[1])) continue;
127         if(criteria->unvisited) {
128             printf_mysql_query("SELECT `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%s' ORDER BY `chanuser_seen` DESC LIMIT 1", row[5]);
129             res2 = mysql_use();
130             row2 = mysql_fetch_row(res);
131             if(!row2) continue;
132             if((time(0) - atoi(row2[0])) < criteria->unvisited) continue;
133         }
134         if(criteria->registered && (time(0) - atoi(row[2])) < criteria->registered) continue;
135         
136         if((criteria->flags & CMD_SEARCH_FLAG_HAS_NODELETE) && strcmp(row[3], "1")) continue;
137         if((criteria->flags & CMD_SEARCH_FLAG_NOT_NODELETE) && strcmp(row[3], "0")) continue;
138         if((criteria->flags & CMD_SEARCH_FLAG_HAS_SUSPENDED) && strcmp(row[4], "1")) continue;
139         if((criteria->flags & CMD_SEARCH_FLAG_NOT_SUSPENDED) && strcmp(row[4], "0")) continue;
140         if(criteria->flags & CMD_SEARCH_FLAG_STATES) {
141             struct ChanNode *channel = getChanByName(row[0]);
142             if((criteria->flags & CMD_SEARCH_FLAG_IS_JOINED) && !channel) continue;
143             if((criteria->flags & CMD_SEARCH_FLAG_NOT_JOINED) && channel) continue;
144             if(channel && (criteria->flags & (CMD_SEARCH_FLAG_IS_OPPED | CMD_SEARCH_FLAG_NOT_OPPED | CMD_SEARCH_FLAG_IS_VOICED | CMD_SEARCH_FLAG_NOT_VOICED))) {
145                 int flags = 0;
146                 struct ClientSocket *bot;
147                 for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
148                     if(bot->botid == client->botid) {
149                         struct ChanUser *chanuser = getChanUser(bot->user, channel);
150                         if(chanuser) {
151                             flags = chanuser->flags;
152                             break;
153                         }
154                     }
155                 }
156                 if((criteria->flags & CMD_SEARCH_FLAG_IS_OPPED) && !(flags & CHANUSERFLAG_OPPED)) continue;
157                 if((criteria->flags & CMD_SEARCH_FLAG_NOT_OPPED) && (flags & CHANUSERFLAG_OPPED)) continue;
158                 if((criteria->flags & CMD_SEARCH_FLAG_IS_VOICED) && !(flags & CHANUSERFLAG_VOICED)) continue;
159                 if((criteria->flags & CMD_SEARCH_FLAG_NOT_VOICED) && (flags & CHANUSERFLAG_VOICED)) continue;
160             }
161         }
162         matches++;
163         //output
164         if(show_chans) {
165             reply(getTextBot(), user, "%s", row[0]);
166         }
167     }
168     reply(getTextBot(), user, "NS_TABLE_COUNT", matches);
169 }