]> PatchyGit - patchyircd.git/commitdiff
improve TOPIC and WHOIS
authorEgor <egor@patchysicp.xyz>
Sun, 8 May 2022 09:55:32 +0000 (12:55 +0300)
committerEgor <egor@patchysicp.xyz>
Sun, 8 May 2022 09:55:32 +0000 (12:55 +0300)
common.h
irc.c

index 4251edc..a1b0fb5 100644 (file)
--- a/common.h
+++ b/common.h
@@ -32,6 +32,8 @@ struct client_data {
        char   regstate;
        struct trie_node *channels;
        int    cookie;
+       time_t signon;
+       time_t lastactivity;
 };
 struct channel {
        char *key;
diff --git a/irc.c b/irc.c
index 1f8af04..f384baa 100644 (file)
--- a/irc.c
+++ b/irc.c
@@ -295,7 +295,9 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                        // TODO: +s
                        channel_sendtopic(client, chan, 0);
                } else {
-                       // TODO: +t check, membership check
+                       // TODO: membership check, maybe?
+                       if (chan->dmode & DMODE_TOPICPROT && !trie_get(&chan->o, client->key))
+                               return 0; // error 482
                        free(chan->topic);
                        free(chan->topic_who);
                        if (!*args[1]) {
@@ -317,6 +319,7 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                        return err_notregistered(client), sendbuf(client), 0;
                if (argc < 2) // FIXME: error message
                        return 0;
+               client->lastactivity = time(NULL);
                (command[0] == 'P' ? msg_privmsg : msg_notice)(client, args[0], args[1]);
                // TODO: extra target forms such as nick@server #hostmask $servermask
                int is_modmsg = !!strchr("@+", args[0][0]);
@@ -696,19 +699,37 @@ int processPacket(struct client_data *client, char *source, char *command, int a
                char *nick = args[1] ? args[1] : args[0];
                struct client_data *cl = findClient(nick);
                if (cl) {
-                       copy_strf(&databuf, ":%s 311 %s %s %s %s * :%s\n", hostname, client->nick, cl->nick, cl->username, cl->hostname, cl->realname);
+                       copy_strf(&databuf, ":%s 311 %s %s %s %s * :%s\r\n", hostname, client->nick, cl->nick, cl->username, cl->hostname, cl->realname);
                        sendbuf(client);
-                       copy_strf(&databuf, ":%s 312 %s %s %s :Patchy server\n", hostname, client->nick, cl->nick, hostname);
+                       copy_strf(&databuf, ":%s 312 %s %s %s :Patchy server\r\n", hostname, client->nick, cl->nick, hostname);
                        sendbuf(client);
                        if (cl->umode & UMODE_OPER) {
-                               copy_strf(&databuf, ":%s 313 %s %s :is an IRC operator\n", hostname, client->nick, cl->nick);
+                               copy_strf(&databuf, ":%s 313 %s %s :is an IRC operator\r\n", hostname, client->nick, cl->nick);
                                sendbuf(client);
                        }
+                       // FIXME: 64-bit time_t
+                       copy_strf(&databuf, ":%s 317 %s %s %u %u :seconds idle, signon time\r\n",
+                                       hostname, client->nick, cl->nick, (unsigned)(time(NULL)-cl->lastactivity), (unsigned)cl->signon);
+                       sendbuf(client);
                        if (cl->away) {
-                               copy_strf(&databuf, ":%s 301 %s %s :%s\n", hostname, client->nick, cl->nick, cl->away);
+                               copy_strf(&databuf, ":%s 301 %s %s :%s\r\n", hostname, client->nick, cl->nick, cl->away);
                                sendbuf(client);
                        }
-                       copy_strf(&databuf, ":%s 318 %s %s :End of /WHOIS list\n", hostname, client->nick, cl->nick);
+                       struct trie_find *f = NULL;
+                       if (trie_findfirst(&f, &cl->channels) == 1)
+                               do {
+                                       struct channel *chan = f->n->value;
+                                       if ((cl->umode & UMODE_INVISIBLE || chan->dmode & DMODE_SECRET) && !trie_get(&chan->members, client->key))
+                                               continue;
+                                       char prefix[2] = {0,0};
+                                       if (trie_get(&chan->o, cl->key))
+                                               prefix[0] = '@';
+                                       else if (trie_get(&chan->v, cl->key))
+                                               prefix[0] = '+';
+                                       copy_strf(&databuf, ":%s 319 %s %s :%s%s\r\n", hostname, client->nick, cl->nick, prefix, chan->name);
+                                       sendbuf(client);
+                               } while (trie_findnext(&f) == 1);
+                       copy_strf(&databuf, ":%s 318 %s %s :End of /WHOIS list\r\n", hostname, client->nick, cl->nick);
                        sendbuf(client);
                } else {
                        err_nosuchnick(client, nick);
@@ -742,6 +763,7 @@ void newUser(struct client_data *client) {
        setNick(client, client->nick_reg);
        free(client->nick_reg);
        client->nick_reg = NULL;
+       client->signon = client->lastactivity = time(NULL);
        if (!client->nick)
                return;
        client->regstate = REG_REGISTERED;