From: Egor Date: Thu, 12 May 2022 08:31:34 +0000 (+0300) Subject: add INVITE command X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=61bbe4c2a27ab2f916e56e099cf17098ec4219e5;p=patchyircd.git add INVITE command --- diff --git a/common.h b/common.h index d786ac9..b3d0c32 100644 --- a/common.h +++ b/common.h @@ -39,6 +39,7 @@ struct client_data { char umode; char regstate; struct trie_node *channels; + struct trie_node *invites; int cookie; time_t signon; time_t lastactivity; @@ -61,6 +62,7 @@ struct channel { struct trie_node *listq; struct trie_node *listwo; struct trie_node *listwv; + struct trie_node *invitees; char *chankey; int member_limit; }; diff --git a/irc.c b/irc.c index 60dbc53..52f54d7 100644 --- a/irc.c +++ b/irc.c @@ -403,6 +403,47 @@ int processPacket(struct client_data *client, char *source, char *command, int a chanlog_time(chan->topic_when); sendbuf_chan(chan); } + } else if(strcmp(command, "INVITE") == 0) { + if (!is_registered(client)) + return err_notregistered(client), sendbuf(client), 0; + if (!args[0]) { + // List pending invites + struct trie_find *f = NULL; + if (trie_findfirst(&f, &client->invites) == 1) + do { + struct channel *chan = f->n->value; + copy_strf(&databuf, ":%s 336 %s %s\n", hostname, client->nick, chan->name); + sendbuf(client); + } while(trie_findnext(&f) == 1); + copy_strf(&databuf, ":%s 337 %s :End of /INVITE list\n", hostname, client->nick); + sendbuf(client); + return 0; + } + if (!args[1]) + return err_needmoreparams(client, command), sendbuf(client), 0; + struct channel *chan = findChannel(args[1]); + if (!chan) + return err_nosuchchannel(client, args[1]), sendbuf(client), 0; + if (chan->dmode & DMODE_INVITEONLY) { + if (!trie_get(&chan->o, client->key)) { + copy_strf(&databuf, ":%s 482 %s :You're not channel operator\r\n", hostname, client->nick, chan->name); + return sendbuf(client), 0; + } + } else { + if (!trie_get(&chan->members, client->key)) + return err_notonchannel(client, chan), sendbuf(client), 0; + } + struct client_data *cl = findClient(args[0]); + if (!cl) + return err_nosuchnick(client, args[0]), sendbuf(client), 0; + if (trie_get(&chan->members, cl->key)) + return err_useronchannel(client, cl->nick, chan), sendbuf(client), 0; + trie_set(&chan->invitees, cl->nick, cl, NULL); + trie_set(&cl->invites, chan->name, chan, NULL); + copy_strf(&databuf, ":%s 341 %s %s %s\r\n", hostname, client->nick, cl->nick, chan->name); + sendbuf(client); + msg_invite(client, cl, chan); + sendbuf(cl); } else if(strcmp(command, "PRIVMSG") == 0 || strcmp(command, "NOTICE") == 0) { if (!is_registered(client)) return err_notregistered(client), sendbuf(client), 0; @@ -420,8 +461,8 @@ int processPacket(struct client_data *client, char *source, char *command, int a return err_cannotsendtochan(client, chan->name), sendbuf(client), 0; if (match_list(client, &chan->listb) && !match_list(client, &chan->liste)) return err_cannotsendtochan(client, chan->name), sendbuf(client), 0; - // TODO: actual invites - if (chan->dmode & DMODE_INVITEONLY && !match_list(client, &chan->listI)) + if (chan->dmode & DMODE_INVITEONLY + && !trie_get(&chan->invitees, client->key) && !match_list(client, &chan->listI)) return err_cannotsendtochan(client, chan->name), sendbuf(client), 0; if (chan->dmode & DMODE_NOEXTERNAL && !trie_get(&chan->members, client->key)) return err_cannotsendtochan(client, chan->name), sendbuf(client), 0; @@ -1184,8 +1225,8 @@ void channel_join(struct client_data *client, const char *channel, const char *c return err_channelisfull(client, chan), sendbuf(client); if (match_list(client, &chan->listb) && !match_list(client, &chan->liste)) return err_bannedfromchan(client, chan), sendbuf(client); - // TODO: actual invites - if (chan->dmode & DMODE_INVITEONLY && !match_list(client, &chan->listI)) + if (chan->dmode & DMODE_INVITEONLY + && !trie_get(&chan->invitees, client->key) && !match_list(client, &chan->listI)) return err_inviteonlychan(client, chan), sendbuf(client); } if (trie_set(&chan->members, client->key, client, NULL) == -1) @@ -1232,6 +1273,12 @@ void channel_part(struct client_data *client, struct channel *chan, const char * chan->member_count--; if (!chan->member_count && !(chan->dmode & DMODE_PERSIST)) { trie_set(&channel_map, chan->key, NULL, NULL); + struct trie_find *f = NULL; + if (trie_findfirst(&f, &chan->invitees) == 1) + do { + struct client_data *cl = f->n->value; + trie_set(&cl->invites, chan->key, NULL, NULL); + } while(trie_findnext(&f) == 1); free(chan->key); free(chan->name); free(chan->topic); @@ -1245,6 +1292,7 @@ void channel_part(struct client_data *client, struct channel *chan, const char * trie_free(&chan->listq); trie_free(&chan->listwo); trie_free(&chan->listwv); + trie_free(&chan->invitees); free(chan->chankey); free(chan); } diff --git a/ircfmt.c b/ircfmt.c index c471471..895d8af 100644 --- a/ircfmt.c +++ b/ircfmt.c @@ -48,12 +48,12 @@ void msg_topic(struct client_data *src, struct channel *chan) src->nick, src->username, src->hostname, chan->name, chan->topic ? chan->topic : ""); } -#if 0 void msg_invite(struct client_data *src, struct client_data *dst, struct channel *chan) { copy_strf(&databuf, ":%s!%s@%s INVITE %s %s\r\n", src->nick, src->username, src->hostname, dst->nick, chan->name); } +#if 0 void msg_kick(struct client_data *src, struct client_data *who, struct channel *chan, const char *reason) { if (reason) @@ -360,12 +360,10 @@ void err_notonchannel(struct client_data *client, struct channel *chan) // 442 { copy_strf(&databuf, ":%s 442 %s %s :You're not on that channel\r\n", hostname, client->nick, chan->name); } -#if 0 void err_useronchannel(struct client_data *client, const char *nick, struct channel *chan) // 443 { copy_strf(&databuf, ":%s 443 %s %s %s :is already on channel\r\n", hostname, client->nick, nick, chan->name); } -#endif void err_notregistered(struct client_data *client) // 451 { (void)client; diff --git a/net.c b/net.c index 86aefce..951b46c 100644 --- a/net.c +++ b/net.c @@ -50,8 +50,15 @@ void killConnection(struct client_data *cl, bool byChoice) { channel_part(cl, chan, NULL); } while(trie_findfirst(&f, &cl->channels) == 1); free(f); - if (cl->key) + if (cl->key) { trie_set(&client_map, cl->key, NULL, NULL); + struct trie_find *f = NULL; + if (trie_findfirst(&f, &cl->invites) == 1) + do { + struct channel *chan = f->n->value; + trie_set(&chan->invitees, cl->key, NULL, NULL); + } while(trie_findnext(&f) == 1); + } free(cl->nick); free(cl->key); free(cl->username);