]> PatchyGit - patchyircd.git/commitdiff
add INVITE command
authorEgor <egor@patchysicp.xyz>
Thu, 12 May 2022 08:31:34 +0000 (11:31 +0300)
committerEgor <egor@patchysicp.xyz>
Thu, 12 May 2022 08:31:34 +0000 (11:31 +0300)
common.h
irc.c
ircfmt.c
net.c

index d786ac9..b3d0c32 100644 (file)
--- 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 (file)
--- 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);
        }
index c471471..895d8af 100644 (file)
--- 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 (file)
--- 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);