lizmat / IRC-Client

Raku module for building IRC (Internet Relay Chat) clients
Artistic License 2.0
14 stars 7 forks source link

See who is present on the channel #29

Open AlexDaniel opened 7 years ago

AlexDaniel commented 7 years ago

I was expecting IRC::Client to provide something like $message.channel.people, so that I can see who is on the channel.

I thought about other ways of achieving that, but all of them are quite painful.

Any ideas?

zoffixznet commented 7 years ago

That's quite a bit of work to implement in core, as the client would have to keep track of all the joins, parts, quits, bans, and kicks after joining the channel.

One of the alternative methods is to use .send-cmd method (I think I forgot to document it) and issue a NAMES command to the server, and subscribe to the numeric events for the response.

So it'd be $.irc.send-cmd: 'NAMES', '#channel'

Successful responses will be sent in 353 numerical message, ending with a 366 message:

353    RPL_NAMREPLY
              "( "=" / "*" / "@" ) <channel>
               :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
         - "@" is used for secret channels, "*" for private
           channels, and "=" for others (public channels).

       366    RPL_ENDOFNAMES
              "<channel> :End of NAMES list"

         - To reply to a NAMES message, a reply pair consisting
           of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
           server back to the client.  If there is no channel
           found as in the query, then only RPL_ENDOFNAMES is

Sample from my local server:

    NAMES #zofbot
    :irc.local 353 Zoffix2 = #zofbot :@zoffix Zoffix2 
    :irc.local 366 Zoffix2 #zofbot :End of /NAMES list.

so it'd be something like:

my @users; # something saner than this
method irc-353 ($e) {
    @users.append: $e.args[1].words;
}
method irc-366 ($) {
     say "Users in channel: @users[]";
}
AlexDaniel commented 7 years ago

/o\

zoffixznet commented 7 years ago

I've added a working example: https://github.com/zoffixznet/perl6-IRC-Client/blob/master/examples/08-numeric-bot.p6

This won't be core feature, but a plugin (that may be shipped with a core distro). The core (if required) needs to provide all of the facilities that would make it possible for other plugins to interface with the names tracking and run queries on it.

AlexDaniel commented 7 years ago

Yeah. I did it already: https://github.com/perl6/whateverable/blob/master/Evalable.p6#L109. But of course, I wish I did not have that stuff in the code.

Not sure why it can't be in core, but whatever. Your house, your rules :)

BenGoldberg1 commented 7 years ago

If you want to maintain a list of everyone who is on a particular channel, you will need to keep track of people joining, changing nicks, and leaving the channel.

Considering how some channels have absurd numbers of people on them, it might be more desirable to provide an interface that lets the plugin's user specify a list of nicks to keep track of, and the bot will then pay attention to whether or not those nicks are present/absent on whichever channels the bot is on.

In this case, the bot would not need to issue a NAMES command, but rather a WHOIS command for each monitored nick, and parse the RPL_WHOISCHANNELS part of each reply. After that, it would still need to pay attention to JOIN, PART, and NICK messages, but only ones which involve the particular nicks.

For example, the Evalable bot only cares whether camelia is present on #perl6, and shouldn't need a full list of #perl6's users.

Similarly, the Unicodable bot only cares about whether yoleaux or yoleaux2 is present.

AlexDaniel commented 7 years ago

@BenGoldberg1, that's an interesting idea!