a117c18b0c7afa4145ea63a05c42c46a83864d6a
[NeonServV5.git] / event_neonserv_join.c
1
2 struct neonserv_event_join_cache {
3     struct ClientSocket *client;
4     struct ChanUser *chanuser;
5 };
6
7 static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup);
8 static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser);
9 static TIMEQ_CALLBACK(neonserv_event_join_dynlimit);
10
11 static void neonserv_event_join(struct ChanUser *chanuser) {
12     struct UserNode *user = chanuser->user;
13     struct ClientSocket *client = getBotForChannel(chanuser->chan);
14     if(!client) return; //we can't "see" this event
15     if(user->flags & USERFLAG_ISBOT) {
16         putsock(client, "MODE %s +o %s", chanuser->chan->name, chanuser->user->nick);
17         return;
18     }
19     loadChannelSettings(chanuser->chan);
20     if(!(chanuser->chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
21     char *ban;
22     char usermask[NICKLEN+USERLEN+HOSTLEN+3];
23     sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
24     if((ban = getBanAffectingMask(chanuser->chan, usermask)) != NULL && !(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) {
25         MYSQL_RES *res;
26         MYSQL_ROW row;
27         printf_mysql_query("SELECT `ban_reason`, `user_user` FROM `bans` LEFT JOIN `users` ON `ban_owner` = `user_id` WHERE `ban_channel` = '%d' AND `ban_mask` = '%s'", chanuser->chan->channel_id, escape_string(ban));
28         res = mysql_use();
29         if ((row = mysql_fetch_row(res)) != NULL) {
30             putsock(client, "MODE %s +b %s", chanuser->chan->name, ban);
31             putsock(client, "KICK %s %s :(%s) %s", chanuser->chan->name, chanuser->user->nick, (row[1] ? row[1] : client->user->nick), row[0]);
32             return;
33         }
34     }
35     if(!(user->flags & USERFLAG_ISAUTHED)) {
36         struct neonserv_event_join_cache *cache = malloc(sizeof(*cache));
37         if (!cache) {
38             perror("malloc() failed");
39             return;
40         }
41         cache->client = client;
42         cache->chanuser = chanuser;
43         get_userauth(user, neonserv_event_join_nick_lookup, cache);
44     } else
45         neonserv_event_join_async1(client, chanuser);
46 }
47
48 static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup) {
49     struct neonserv_event_join_cache *cache = data;
50     if(user) {
51         neonserv_event_join_async1(cache->client, cache->chanuser);
52     }
53     free(cache);
54 }
55
56 static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser) {
57     struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid));
58     struct ChanNode *chan = chanuser->chan;
59     struct UserNode *user = chanuser->user;
60     struct ModeBuffer *modeBuf;
61     MYSQL_RES *res;
62     MYSQL_ROW row, chanuserrow, defaultrow = NULL;
63     printf_mysql_query("SELECT `channel_maxusers`, `channel_greeting`, `channel_usergreeting`, `channel_getop`, `channel_getvoice`, `channel_userinfo`, `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
64     res = mysql_use();
65     if ((row = mysql_fetch_row(res)) == NULL) return;
66     if(!row[3] || !row[4]) {
67         printf_mysql_query("SELECT `channel_getop`, `channel_getvoice`, `channel_userinfo` FROM `channels` WHERE `channel_name` = 'defaults'");
68         res = mysql_use();
69         defaultrow = mysql_fetch_row(res);
70     }
71     if(chan->usercount > atoi(row[0])) {
72         //update maxusers
73         printf_mysql_query("UPDATE `channels` SET `channel_maxusers` = '%d' WHERE `channel_id` = '%d'", chan->usercount, chan->channel_id);
74     }
75     if((user->flags & USERFLAG_ISAUTHED)) {
76         printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `chanuser_seen`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth));
77         res = mysql_use();
78         chanuserrow = mysql_fetch_row(res);
79     } else
80         chanuserrow = NULL;
81     int userflags = (chanuserrow ? atoi(chanuserrow[1]) : 0);
82     int uaccess = ((chanuserrow && !(userflags & DB_CHANUSER_SUSPENDED)) ? atoi(chanuserrow[0]) : 0);
83     //GREETING
84     char greeting[MAXLEN];
85     int greetingPos = 0;
86     char *a, *b = (chanuserrow && *row[2] ? row[2] : row[1]);
87     do {
88         if(!b) break;
89         a = strstr(b, "$");
90         if(a) *a = '\0';
91         greetingPos += sprintf(greeting + greetingPos, "%s", b);
92         if(!a) break;
93         switch(a[1]) {
94             case '\0':
95                 a = NULL;
96                 break;
97             case 'A':
98                 greetingPos += sprintf(greeting + greetingPos, "%d", uaccess);
99                 break;
100             case 'B':
101                 greetingPos += sprintf(greeting + greetingPos, "%s", client->user->nick);
102                 break;
103             case 'N':
104                 greetingPos += sprintf(greeting + greetingPos, "%s", user->nick);
105                 break;
106             case 'H':
107                 greetingPos += sprintf(greeting + greetingPos, "%s@%s", user->ident, user->host);
108                 break;
109             case 'U':
110                 greetingPos += sprintf(greeting + greetingPos, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*"));
111                 break;
112             default:
113                 greeting[greetingPos++] = '$';
114                 greeting[greetingPos++] = a[1];
115                 break;
116         }
117         if(a)
118             b = a+2;
119     } while(a);
120     if(greetingPos)
121         reply(textclient, user, "[%s] %s", chan->name, greeting);
122     //USER RIGHTS
123     if(!(userflags & DB_CHANUSER_NOAUTOOP)) {
124         int getop = atoi((row[3] ? row[3] : defaultrow[0]));
125         int getvoice = atoi((row[4] ? row[4] : defaultrow[1]));
126         modeBuf = initModeBuffer(client, chan);
127         if(uaccess >= getop && uaccess != 0) { //we disallow auto op for all users
128             modeBufferOp(modeBuf, user->nick);
129         } else if(uaccess >= getvoice) {
130             modeBufferVoice(modeBuf, user->nick);
131         }
132         freeModeBuffer(modeBuf);
133     }
134     //INFOLINE
135     int userinfoaccess = atoi((row[5] ? row[5] : defaultrow[2]));
136     if(chanuserrow && strcmp(chanuserrow[2], "") && uaccess > userinfoaccess) {
137         if(!strcmp(chanuserrow[3], "0") || time(0) - atol(chanuserrow[3]) >= 30) {
138             putsock(client, "PRIVMSG %s :[%s] %s", chan->name, user->nick, chanuserrow[2]);
139         }
140     }
141     //SEEN
142     if(chanuserrow) {
143         printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[4]);
144     }
145     //DYNLIMIT
146     if(row[6] && strcmp(row[6], "0")) {
147         char nameBuf[CHANNELLEN + 10];
148         sprintf(nameBuf, "dynlimit_%s", chan->name);
149         if(!timeq_name_exists(nameBuf)) {
150             //neonserv_event_join_dynlimit
151             timeq_add_name(nameBuf, 30, neonserv_event_join_dynlimit, strdup(chan->name));
152         }
153     }
154     //AUTOINVITE
155     if(chanuserrow && !strcmp(chanuserrow[3], "0") && time(0) - atol(chanuserrow[3]) >= 30) {
156         //TODO: autoinvite
157     }
158 }
159
160 static TIMEQ_CALLBACK(neonserv_event_join_dynlimit) {
161     char *chanName = data;
162     struct ChanNode *chan = getChanByName(chanName);
163     free(chanName);
164     struct ClientSocket *client = getBotForChannel(chan);
165     if(!client) return;
166     loadChannelSettings(chan);
167     if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return;
168     MYSQL_RES *res;
169     MYSQL_ROW row;
170     printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
171     res = mysql_use();
172     if ((row = mysql_fetch_row(res)) == NULL) return;
173     if(row[0] && strcmp(row[0], "0")) {
174         putsock(client, "MODE %s +l %d", chan->name, chan->usercount + atoi(row[0]));
175     }
176 }