unit class IRC::Client::Grammar::Actions; use IRC::Client::Message; has $.irc; has $.server; method TOP ($/) { $/.make: ( $ยป.made, ~( $ // '' ), ); } method message ($match) { my %args; my $pref = $match; for qw/nick user host/ { $pref{$_}.defined or next; %args{$_} = ~$pref{$_}; } %args = ~$pref if $pref.defined; my $p = $match; loop { %args.append: ~$p if $p.defined; if ( $p.defined ) { %args.append: ~$p; last; } last unless $p.defined; $p = $p; } my %msg-args = command => $match.uc, args => %args, host => %args//'', irc => $!irc, nick => %args//'', server => $!server, usermask => ~($match//''), username => %args//''; my $msg; given %msg-args { when /^ <[0..9]>**3 $/ { $msg = IRC::Client::Message::Numeric.new: |%msg-args; } when 'JOIN' { $msg = IRC::Client::Message::Join.new: :channel( %args[0] ), |%msg-args; } when 'PART' { $msg = IRC::Client::Message::Part.new: :channel( %args[0] ), |%msg-args; } when 'NICK' { $msg = IRC::Client::Message::Nick.new: :new-nick( %args[0] ), |%msg-args; } when 'NOTICE' { $msg = msg-notice %args, %msg-args } when 'MODE' { $msg = msg-mode %args, %msg-args } when 'PING' { $msg = IRC::Client::Message::Ping.new: |%msg-args } when 'PRIVMSG' { $msg = msg-privmsg %args, %msg-args } when 'QUIT' { $msg = IRC::Client::Message::Quit.new: |%msg-args } default { $msg = IRC::Client::Message::Unknown.new: |%msg-args } } $match.make: $msg; } sub msg-privmsg (%args, %msg-args) { %args[0] ~~ /^<[#&]>/ and return IRC::Client::Message::Privmsg::Channel.new: :channel( %args[0] ), :text( %args[1] ), |%msg-args; return IRC::Client::Message::Privmsg::Me.new: :text( %args[1] ), |%msg-args; } sub msg-notice (%args, %msg-args) { %args[0] ~~ /^<[#&]>/ and return IRC::Client::Message::Notice::Channel.new: :channel( %args[0] ), :text( %args[1] ), |%msg-args; return IRC::Client::Message::Notice::Me.new: :text( %args[1] ), |%msg-args; } sub msg-mode (%args, %msg-args) { if %args[0] ~~ /^<[#&]>/ { my @modes; for %args[1..*-1].join.comb: /\S/ { state $sign; /<[+-]>/ and $sign = $_ and next; @modes.push: $sign => $_; }; return IRC::Client::Message::Mode::Channel.new: :channel( %args[0] ), :modes( @modes ), |%msg-args; } else { return IRC::Client::Message::Mode::Me.new: :modes( %args[1..*-1].join.comb: /<[a..zA..Z]>/ ), |%msg-args; } }