execute mysql_check only if a query fails.
[NeonServV5.git] / cmd_neonserv_kickban.c
1
2 /*
3 * argv[0]    nick[,*auth[,*!*@mask[...]]]
4 * argv[1-*]  reason
5 */
6 static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup);
7 static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks, char *reason);
8
9 struct neonserv_cmd_kickban_cache {
10     struct ClientSocket *client, *textclient;
11     struct UserNode *user;
12     char *nicks;
13     char *reason;
14 };
15
16 static CMD_BIND(neonserv_cmd_kickban) {
17     struct neonserv_cmd_kickban_cache *cache = malloc(sizeof(*cache));
18     if (!cache) {
19         perror("malloc() failed");
20         return;
21     }
22     cache->client = client;
23     cache->textclient = getTextBot();
24     cache->user = user;
25     cache->nicks = strdup(argv[0]);
26     if(argc > 1) {
27         cache->reason = strdup(merge_argv(argv, 1, argc));
28     } else
29         cache->reason = NULL;
30     get_userlist(chan, neonserv_cmd_kickban_userlist_lookup, cache);
31 }
32
33 static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup) {
34     struct neonserv_cmd_kickban_cache *cache = data;
35     neonserv_cmd_kickban_async1(cache->client, cache->textclient, cache->user, chan, cache->nicks, (cache->reason ? cache->reason : "Bye."));
36     free(cache->nicks);
37     if(cache->reason)
38         free(cache->reason);
39     free(cache);
40 }
41
42 static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks, char *reason) {
43     int i, kicked_users = 0, provided_nicks = 0;
44     char *nick, *nextnick;
45     struct UserNode *cuser;
46     struct ChanUser *chanuser;
47     char usermask[NICKLEN+USERLEN+HOSTLEN+3];
48     nextnick = nicks;
49     while((nick = nextnick)) {
50         nextnick = strstr(nick, ",");
51         if(nextnick) {
52             *nextnick = '\0';
53             nextnick++;
54         }
55         if(!*nick) continue;
56         if(is_ircmask(nick)) {
57             //KICK HOSTMASK
58             struct ChanUser *kickban_chanuser[chan->usercount];
59             int kick_chanuser_pos = 0;
60             for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
61                 cuser = chanuser->user;
62                 sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
63                 if(!match(nick, usermask)) {
64                     provided_nicks++;
65                     if(isNetworkService(chanuser->user)) {
66                         reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
67                         continue;
68                     }
69                     if(isUserProtected(chan, cuser, user)) {
70                         reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
71                         continue;
72                     }
73                     kickban_chanuser[kick_chanuser_pos++] = chanuser;
74                     if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) {
75                         kick_chanuser_pos = 0;
76                         reply(textclient, user, "NS_LAME_MASK", nick);
77                         break;
78                     }
79                 }
80             }
81             for(i = 0; i < kick_chanuser_pos; i++) {
82                 if(i == 0) {
83                     putsock(client, "MODE %s +b %s", chan->name, nick);
84                 }
85                 kicked_users++;
86                 putsock(client, "KICK %s %s :%s", chan->name, kickban_chanuser[i]->user->nick, reason);
87             }
88         } else if(*nick == '*') {
89             //KICK AUTH
90             nick++;
91             cuser = NULL;
92             for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
93                 if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) {
94                     provided_nicks++;
95                     if(isNetworkService(chanuser->user)) {
96                         reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
97                         continue;
98                     }
99                     if(!cuser) {
100                         //check if the user is protected
101                         if(isUserProtected(chan, chanuser->user, user)) {
102                             reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick);
103                             break; //all other users are also protected...
104                         }
105                         cuser = chanuser->user;
106                     }
107                     kicked_users++;
108                     putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask));
109                     putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
110                 }
111             }
112         } else {
113             provided_nicks++;
114             cuser = searchUserByNick(nick);
115             if(!cuser) continue;
116             chanuser = getChanUser(cuser, chan);
117             if(!chanuser) continue;
118             if(isNetworkService(cuser)) {
119                 reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
120                 continue;
121             }
122             if(isUserProtected(chan, cuser, user)) {
123                 reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
124                 continue;
125             }
126             kicked_users++;
127             putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask));
128             putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
129         }
130     }
131     if(kicked_users == provided_nicks)
132         reply(getTextBot(), user, "NS_KICKBAN_DONE", kicked_users, chan->name);
133     else
134         reply(getTextBot(), user, "NS_KICKBAN_FAIL", client->user->nick);
135 }