added cmd_unregister and cmd_recover
[NeonServV5.git] / cmd_neonserv_register.c
1
2 /*
3 * argv[0] - channel
4 * argv[0/1] - nick / *auth
5 */
6 static AUTHLOOKUP_CALLBACK(neonserv_cmd_register_auth_lookup);
7 static USERAUTH_CALLBACK(neonserv_cmd_register_nick_lookup);
8 static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *channel, char *auth);
9
10 struct neonserv_cmd_register_cache {
11     struct ClientSocket *client, *textclient;
12     struct UserNode *user;
13     struct ChanNode *chan;
14     char *nick;
15     char *channel;
16 };
17
18 static CMD_BIND(neonserv_cmd_register) {
19     MYSQL_RES *res;
20     MYSQL_ROW row;
21     char *channel = argv[0];
22     if(!is_valid_chan(channel)) {
23         reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]);
24         return;
25     }
26     printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid);
27     res = mysql_use();
28     if ((row = mysql_fetch_row(res)) != NULL) {
29         reply(getTextBot(), user, "NS_REGISTER_ALREADY", argv[0], client->user->nick);
30         return;
31     }
32     //check own access
33     if(argv[0][0] == '*') {
34         //we've got an auth
35         argv[0]++;
36         printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[0]));
37         res = mysql_use();
38         if ((row = mysql_fetch_row(res)) != NULL) {
39             neonserv_cmd_register_async1(client, getTextBot(), user, chan, channel, row[0]);
40         } else {
41             //we need to create a new user...
42             //but first lookup the auth to check if it really exists
43             struct neonserv_cmd_register_cache *cache = malloc(sizeof(*cache));
44             if (!cache) {
45                 perror("malloc() failed");
46                 return;
47             }
48             cache->client = client;
49             cache->textclient = getTextBot();
50             cache->user = user;
51             cache->chan = chan;
52             cache->nick = strdup(argv[0]);
53             cache->channel = strdup(channel);
54             lookup_authname(argv[0], neonserv_cmd_register_auth_lookup, cache);
55         }
56     } else {
57         struct UserNode *cuser = getUserByNick(argv[0]);
58         if(!cuser) {
59             cuser = createTempUser(argv[0]);
60             cuser->flags |= USERFLAG_ISTMPUSER;
61         }
62         if(cuser->flags & USERFLAG_ISAUTHED) {
63             neonserv_cmd_register_async1(client, getTextBot(), user, chan, channel, cuser->auth);
64         } else {
65             struct neonserv_cmd_register_cache *cache = malloc(sizeof(*cache));
66             if (!cache) {
67                 perror("malloc() failed");
68                 return;
69             }
70             cache->client = client;
71             cache->textclient = getTextBot();
72             cache->user = user;
73             cache->chan = chan;
74             cache->nick = strdup(argv[0]);
75             cache->channel = strdup(channel);
76             get_userauth(cuser, neonserv_cmd_register_nick_lookup, cache);
77         }
78     }
79 }
80
81 static AUTHLOOKUP_CALLBACK(neonserv_cmd_register_auth_lookup) {
82     struct neonserv_cmd_register_cache *cache = data;
83     if(!exists) {
84         //AUTH_DOES_NOT_EXIST
85         reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick);
86     } else
87         neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->channel, auth);
88     free(cache->channel);
89     free(cache->nick);
90     free(cache);
91 }
92
93 static USERAUTH_CALLBACK(neonserv_cmd_register_nick_lookup) {
94     struct neonserv_cmd_register_cache *cache = data;
95     if(!user) {
96         //USER_DOES_NOT_EXIST
97         reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick);
98     }
99     else if(!(user->flags & USERFLAG_ISAUTHED)) {
100         //USER_NOT_AUTHED
101         reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick);
102     }
103     else
104         neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->channel, user->auth);
105     free(cache->channel);
106     free(cache->nick);
107     free(cache);
108 }
109
110 static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *channel, char *auth) {
111     //we've got a valid auth now...
112     MYSQL_RES *res;
113     MYSQL_ROW row, row2;
114     int userid, adminid;
115     printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth));
116     res = mysql_use();
117     if ((row = mysql_fetch_row(res)) != NULL)
118         adminid = atoi(row[0]);
119     else
120         adminid = 0;
121     printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth));
122     res = mysql_use();
123     if ((row = mysql_fetch_row(res)) != NULL) {
124         userid = atoi(row[0]);
125     } else {
126         printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth));
127         userid = (int) mysql_insert_id(mysql_conn);
128     }
129     printf_mysql_query("SELECT `botid`, `max_channels`, `defaulttrigger` FROM `bots` WHERE `botclass` = '%d' ORDER BY `register_priority` DESC", client->botid);
130     res = mysql_use();
131     int botid = 0;
132     char *bottrigger;
133     while ((row = mysql_fetch_row(res)) != NULL) {
134         //check channel count
135         printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]);
136         row2 = mysql_fetch_row(mysql_use());
137         if(atoi(row2[0]) < atoi(row[1])) {
138             botid = atoi(row[0]);
139             bottrigger = row[2];
140             break;
141         }
142     }
143     if(!botid) {
144         reply(textclient, user, "NS_REGISTER_FULL");
145         return;
146     }
147     int chanid;
148     printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel));
149     res = mysql_use();
150     if ((row = mysql_fetch_row(res)) != NULL) {
151         chanid = atoi(row[0]);
152         printf_mysql_query("UPDATE `channels` SET `channel_registered` = UNIX_TIMESTAMP(), `channel_registrator` = '%d' WHERE `channel_id` = '%d'", adminid, chanid);
153     } else {
154         printf_mysql_query("INSERT INTO `channels` (`channel_name`, `channel_registered`, `channel_registrator`) VALUES ('%s', UNIX_TIMESTAMP(), '%d')", escape_string(channel), adminid);
155         chanid = (int) mysql_insert_id(mysql_conn);
156     }
157     struct ClientSocket *bot;
158     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
159         if(bot->clientid == botid)
160             break;
161     }
162     if(bot) {
163         putsock(bot, "JOIN %s", channel);
164     } else
165         reply(textclient, user, "NS_REGISTER_DISCONNECTED");
166     printf_mysql_query("INSERT INTO `bot_channels` (`botid`, `chanid`, `trigger`) VALUES ('%d', '%d', '%s')", botid, chanid, bottrigger);
167     printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_cid` = '%d'", chanid);
168     printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`) VALUES ('%d', '%d', '%d')", chanid, userid, 500);
169     reply(textclient, user, "NS_REGISTER_DONE", channel, auth);
170 }