From 63c846df17c3d2553faaec3a95cebf8b9ba1e709 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 4 Jun 2021 16:17:09 +0100 Subject: op tracking that actually works --- boha.raku | 103 +++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 55 insertions(+), 48 deletions(-) diff --git a/boha.raku b/boha.raku index 97240ba..28b7263 100644 --- a/boha.raku +++ b/boha.raku @@ -7,85 +7,92 @@ my $config = from-toml( file => (%*ENV // $?FILE.IO.sibling('boha.toml').Str) ); -role TracksOps does IRC::Client::Plugin { - has %!nick-cache; - has $!waiting-for-names = False; - - method !check-op($e) { - return Promise.broken('not a channel message') unless $e.?channel; - # if we already know whether that's an op, the cache will - # contain a kept promise; if we don't, we have to wait for the - # next 353, so we set and return a planned promise - return %!nick-cache{$e.channel}{$e.nick} //= Promise.new(); +class TrackOps does IRC::Client::Plugin { + has %!is-op; + + multi method is-op( + Str() $server, Str() $channel, Str() $nick --> Bool + ) { + return %!is-op{$server}{$channel}{$nick}.so; + } + multi method is-op(IRC::Client::Message $e --> Bool) { + fail 'not a channel message' unless $e.?channel; + return self.is-op($e.server,$e.channel,$e.nick); + } + + method !set-user-mode( + Str() $server, Str() $channel, Str() $nick, Bool $mode + ) { + %!is-op{$server}{$channel}{$nick} = $mode; } # response to /NAMES - method irc-n353($e) { + method irc-n353(IRC::Client::Message $e) { + my $server = $e.server; my ($my-nick,$equal,$channel,$names) = $e.args(); for $names.split(/\s+/) -> $name-str { my $user = $name-str ~~ / ^ $ = [ '@' | '+' ]? $ = [ .+ ] $ /; - # I'm not sure what `+` means - my $is-op = $user eq '@'; - - my $value := %!nick-cache{$channel}{$user}; - if $value ~~ Promise && $value.status ~~ Planned { - # someone called check-op before we saw this nick: - # keep the promise - $value.keep($is-op); - } - else { - # either this nick changed state, or nobody asked - # about it before: set a kept promise - $value = Promise.kept($is-op); - } + self!set-user-mode( + $server, $channel, + $user, + $user eq '@' + ); } - $!waiting-for-names = False; - return $.NEXT; } - method irc-join($e) { - # someone (maybe us) joined the channel: update our ops map - # - # maybe we should do this every few seconds anyway… - Promise.in(5).then: { - unless ($!waiting-for-names) { - $e.irc.send-cmd('NAMES', $e.channel, :server($e.server)); - $!waiting-for-names = True; - } - }; + method irc-mode-channel($e) { + my ($server, $channel) = $e.server, $e.channel; + my $new-mode = ( + $e.mode eq '+o' ?? True !! + $e.mode eq '-o' ?? False !! + return $.NEXT + ); + + for $e.nicks() -> $nick { + self!set-user-mode($server,$channel,$nick,$new-mode); + } + return $.NEXT; } } -class Boha1 does TracksOps { +class Boha1 does IRC::Client::Plugin { + has TrackOps $.ops handles ; + # irc-addressed for in-channel messages # irc-privmsg-me for direct messages method irc-addressed($e) { - return self!check-op($e).then: sub ($promise) { - if ($promise.status ~~ Broken) { - # not a channel message? - return Nil; - } - if (so $promise.result) { - return "you're an op"; + my @words = $e.text.split(/\s+/); + + if @words[0] eq 'op' { + my $nick = @words[1]; + if self.is-op($e.server,$e.channel,$nick) { + return "$nick is op"; } else { - return "you're a normal user"; + return "$nick is a normal user"; } - }; + } + else { + return "I don't know understand '$e.text'"; + } } } +my TrackOps $ops .= new; +my Boha1 $boha .= new(:$ops); + .run with IRC::Client.new( |($config), channels => $config.map(*.), :debug, :plugins( - Boha1.new, + $ops, + $boha, ), ); -- cgit v1.2.3