summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2021-05-31 16:43:45 +0100
committerdakkar <dakkar@thenautilus.net>2021-05-31 16:43:45 +0100
commitaf07017fa1a743252d8983d522aca787b05ca342 (patch)
treeeb0894bb4b35ab0d87f36cc1b22a94828a265736
parentfirst stab (diff)
downloadraku-boha-af07017fa1a743252d8983d522aca787b05ca342.tar.gz
raku-boha-af07017fa1a743252d8983d522aca787b05ca342.tar.bz2
raku-boha-af07017fa1a743252d8983d522aca787b05ca342.zip
track who's an op
-rw-r--r--boha.raku80
1 files changed, 75 insertions, 5 deletions
diff --git a/boha.raku b/boha.raku
index 725f00a..97240ba 100644
--- a/boha.raku
+++ b/boha.raku
@@ -7,15 +7,85 @@ my $config = from-toml(
file => (%*ENV<BOHA_CONFIG_FILE> // $?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();
+ }
+
+ # response to /NAMES
+ method irc-n353($e) {
+ my ($my-nick,$equal,$channel,$names) = $e.args();
+
+ for $names.split(/\s+/) -> $name-str {
+ my $user = $name-str ~~ / ^ $<sigil> = [ '@' | '+' ]? $<nick> = [ .+ ] $ /;
+
+ # I'm not sure what `+` means
+ my $is-op = $user<sigil> eq '@';
+
+ my $value := %!nick-cache{$channel}{$user<nick>};
+ 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);
+ }
+ }
+
+ $!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;
+ }
+ };
+ return $.NEXT;
+ }
+}
+
+class Boha1 does TracksOps {
+ # 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";
+ }
+ else {
+ return "you're a normal user";
+ }
+ };
+ }
+}
+
.run with IRC::Client.new(
|($config<server>),
channels => $config<channels>.map(*.<name>),
:debug,
:plugins(
- class :: does IRC::Client::Plugin {
- # irc-addressed for in-channel messages
- # irc-privmsg-me for direct messages
- method irc-to-me($e) { "Boo!" }
- },
+ Boha1.new,
),
);