1 /* cmd_neonserv_search.c - NeonServ v5.5
2 * Copyright (C) 2011-2012 Philipp Kreil (pk910)
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.
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.
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/>.
18 #include "cmd_neonserv.h"
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 /* state */
25 #define CMD_SEARCH_FLAG_NOT_JOINED 0x020 /* state */
26 #define CMD_SEARCH_FLAG_IS_OPPED 0x040 /* state */
27 #define CMD_SEARCH_FLAG_NOT_OPPED 0x080 /* state */
28 #define CMD_SEARCH_FLAG_IS_VOICED 0x100 /* state */
29 #define CMD_SEARCH_FLAG_NOT_VOICED 0x200 /* state */
30 #define CMD_SEARCH_FLAG_IS_ZOMBIE 0x400
31 #define CMD_SEARCH_FLAG_NOT_ZOMBIE 0x800
33 #define CMD_SEARCH_FLAG_STATES 0x3f0
35 struct neonserv_cmd_search_criteria {
39 unsigned int flags : 16;
40 unsigned int unvisited;
41 unsigned int registered;
42 unsigned int limit : 16;
45 static char neonserv_cmd_search_zombie = 0;
47 CMD_BIND(neonserv_cmd_search) {
48 //ok parse the criterias
49 struct neonserv_cmd_search_criteria criteria;
50 memset(&criteria, 0, sizeof(criteria));
52 int i, show_chans = 0, positive;
53 if(!stricmp(argv[0], "print")) {
56 for(i = 1; i < argc; i += 2) {
58 reply(textclient, user, "MODCMD_LESS_PARAM_COUNT");
61 if(!stricmp(argv[i], "name")) criteria.name = argv[i+1];
62 else if(!stricmp(argv[i], "registrar")) criteria.registrar = argv[i+1];
63 else if(!stricmp(argv[i], "onchan")) criteria.onchan = argv[i+1];
64 else if(!stricmp(argv[i], "unvisited")) criteria.unvisited = strToTime(user, argv[i+1]);
65 else if(!stricmp(argv[i], "registered")) criteria.registered = strToTime(user, argv[i+1]);
66 else if(!stricmp(argv[i], "flags")) {
67 if(argv[i+1][0] == '+') {
70 } else if(argv[i+1][0] == '-') {
75 if(!stricmp(argv[i+1], "nodelete")) {
77 criteria.flags |= CMD_SEARCH_FLAG_HAS_NODELETE;
79 criteria.flags |= CMD_SEARCH_FLAG_NOT_NODELETE;
80 } else if(!stricmp(argv[i+1], "suspended")) {
82 criteria.flags |= CMD_SEARCH_FLAG_HAS_SUSPENDED;
84 criteria.flags |= CMD_SEARCH_FLAG_NOT_SUSPENDED;
85 } else if(!stricmp(argv[i+1], "zombie")) {
87 criteria.flags |= CMD_SEARCH_FLAG_IS_ZOMBIE;
89 criteria.flags |= CMD_SEARCH_FLAG_NOT_ZOMBIE;
92 else if(!stricmp(argv[i], "state")) {
93 if(argv[i+1][0] == '+') {
96 } else if(argv[i+1][0] == '-') {
101 if(!stricmp(argv[i+1], "joined")) {
103 criteria.flags |= CMD_SEARCH_FLAG_IS_JOINED;
105 criteria.flags |= CMD_SEARCH_FLAG_NOT_JOINED;
106 } else if(!stricmp(argv[i+1], "opped")) {
108 criteria.flags |= CMD_SEARCH_FLAG_IS_OPPED;
110 criteria.flags |= CMD_SEARCH_FLAG_NOT_OPPED;
111 } else if(!stricmp(argv[i+1], "voiced")) {
113 criteria.flags |= CMD_SEARCH_FLAG_IS_VOICED;
115 criteria.flags |= CMD_SEARCH_FLAG_NOT_VOICED;
118 else if(!stricmp(argv[i], "limit")) {
119 criteria.limit = atoi(argv[i+1]);
123 if((criteria.flags & (CMD_SEARCH_FLAG_IS_ZOMBIE | CMD_SEARCH_FLAG_NOT_ZOMBIE))) {
124 if(neonserv_cmd_search_zombie) {
125 reply(textclient, user, "NS_SEARCH_ZOMBIE_SCAN_IN_PROGRESS");
128 neonserv_cmd_search_zombie = 1;
131 reply(textclient, user, "NS_SEARCH_HEADER");
132 MYSQL_RES *res, *res2;
134 printf_mysql_query("SELECT `channel_name`, `user_user`, `channel_registered`, `channel_nodelete`, `suspended`, `channel_id` FROM `bot_channels` LEFT JOIN `bots` ON `bots`.`id` = `botid` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botclass` = '%d' AND `active` = '1'", client->botid);
136 struct ChanNode *channel;
137 while ((row = mysql_fetch_row(res)) != NULL) {
138 if((criteria.flags & (CMD_SEARCH_FLAG_IS_ZOMBIE | CMD_SEARCH_FLAG_NOT_ZOMBIE))) {
139 channel = getChanByName(row[0]);
141 channel->flags |= CHANFLAG_SCRIPTFLAG1;
142 if(show_chans && matches == criteria.limit) {
147 if(show_chans && matches == criteria.limit) {
152 if((criteria.flags & CMD_SEARCH_FLAG_IS_ZOMBIE)) continue;
153 if(criteria.name && match(criteria.name, row[0])) continue;
154 if(criteria.registrar && row[1] && match(criteria.registrar, row[1])) continue;
155 if(criteria.unvisited) {
156 printf_mysql_query("SELECT `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%s' ORDER BY `chanuser_seen` DESC LIMIT 1", row[5]);
158 row2 = mysql_fetch_row(res2);
160 if((time(0) - atoi(row2[0])) < criteria.unvisited) continue;
162 if(criteria.registered && (time(0) - atoi(row[2])) < criteria.registered) continue;
164 if((criteria.flags & CMD_SEARCH_FLAG_HAS_NODELETE) && strcmp(row[3], "1")) continue;
165 if((criteria.flags & CMD_SEARCH_FLAG_NOT_NODELETE) && strcmp(row[3], "0")) continue;
166 if((criteria.flags & CMD_SEARCH_FLAG_HAS_SUSPENDED) && strcmp(row[4], "1")) continue;
167 if((criteria.flags & CMD_SEARCH_FLAG_NOT_SUSPENDED) && strcmp(row[4], "0")) continue;
168 if((criteria.flags & CMD_SEARCH_FLAG_STATES) || criteria.onchan) {
169 if(!(criteria.flags & (CMD_SEARCH_FLAG_IS_ZOMBIE | CMD_SEARCH_FLAG_NOT_ZOMBIE)))
170 channel = getChanByName(row[0]);
171 if(criteria.onchan) {
172 if(!channel) continue;
173 struct ChanUser *chanuser = NULL;
174 for(chanuser = getChannelUsers(channel, NULL); chanuser; chanuser = getChannelUsers(channel, chanuser)) {
175 if(!match(criteria.onchan, chanuser->user->nick)) break;
177 if(!chanuser) continue;
179 if((criteria.flags & CMD_SEARCH_FLAG_IS_JOINED) && !channel) continue;
180 if((criteria.flags & CMD_SEARCH_FLAG_NOT_JOINED) && channel) continue;
181 if(channel && (criteria.flags & (CMD_SEARCH_FLAG_IS_OPPED | CMD_SEARCH_FLAG_NOT_OPPED | CMD_SEARCH_FLAG_IS_VOICED | CMD_SEARCH_FLAG_NOT_VOICED))) {
183 struct ClientSocket *bot;
184 for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
185 if(bot->botid == client->botid) {
186 struct ChanUser *chanuser = getChanUser(bot->user, channel);
188 flags = chanuser->flags;
193 if((criteria.flags & CMD_SEARCH_FLAG_IS_OPPED) && !(flags & CHANUSERFLAG_OPPED)) continue;
194 if((criteria.flags & CMD_SEARCH_FLAG_NOT_OPPED) && (flags & CHANUSERFLAG_OPPED)) continue;
195 if((criteria.flags & CMD_SEARCH_FLAG_IS_VOICED) && !(flags & CHANUSERFLAG_VOICED)) continue;
196 if((criteria.flags & CMD_SEARCH_FLAG_NOT_VOICED) && (flags & CHANUSERFLAG_VOICED)) continue;
202 reply(textclient, user, "%s", row[0]);
205 if((criteria.flags & (CMD_SEARCH_FLAG_IS_ZOMBIE | CMD_SEARCH_FLAG_NOT_ZOMBIE))) {
206 struct ChanUser *chanuser;
207 for(chanuser = getUserChannels(client->user, NULL); chanuser; chanuser = getUserChannels(client->user, chanuser)) {
208 channel = chanuser->chan;
209 if(channel->flags & CHANFLAG_SCRIPTFLAG1) {
210 channel->flags &= ~CHANFLAG_SCRIPTFLAG1;
211 } else if((criteria.flags & CMD_SEARCH_FLAG_IS_ZOMBIE)) {
214 reply(textclient, user, "%s", channel->name);
219 neonserv_cmd_search_zombie = 0;
220 reply(textclient, user, "NS_TABLE_COUNT", matches);