From: Egor Date: Sun, 8 May 2022 09:55:32 +0000 (+0300) Subject: improve TOPIC and WHOIS X-Git-Url: https://git.patchysicp.xyz/?a=commitdiff_plain;h=dd59470cf4c89878f1beb3fc57075f9036563f5e;p=patchyircd.git improve TOPIC and WHOIS --- diff --git a/common.h b/common.h index 4251edc..a1b0fb5 100644 --- 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 --- 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;