aboutsummaryrefslogtreecommitdiff
path: root/lib/IRC/Client/Grammar/Actions.pm6
blob: b1fcc531c35d2bc9809c0e425aa273e4ef391186 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
unit class IRC::Client::Grammar::Actions;

use IRC::Client::Message;

has $.irc;
has $.server;

method TOP ($/) {
    $/.make: (
        $<message>ยป.made,
        ~( $<left-overs> // '' ),
    );
}

method message ($match) {
    my %args;
    my $pref = $match<prefix>;
    for qw/nick user host/ {
        $pref{$_}.defined or next;
        %args<who>{$_} = ~$pref{$_};
    }
    %args<who><host> = ~$pref<servername> if $pref<servername>.defined;

    my $p = $match<params>;
    loop {
        %args<params>.append: ~$p<middle> if $p<middle>.defined;

        if ( $p<trailing>.defined ) {
            %args<params>.append: ~$p<trailing>;
            last;
        }
        last unless $p<params>.defined;
        $p = $p<params>;
    }

    my %msg-args =
        command  => $match<command>.uc,
        args     => %args<params>,
        host     => %args<who><host>//'',
        irc      => $!irc,
        nick     => %args<who><nick>//'',
        server   => $!server,
        usermask => ~($match<prefix>//''),
        username => %args<who><user>//'';

    my $msg;
    given %msg-args<command> {
        when /^ <[0..9]>**3 $/ {
            $msg = IRC::Client::Message::Numeric.new: |%msg-args;
        }
        when 'JOIN' {
            $msg = IRC::Client::Message::Join.new:
                :channel( %args<params>[0] ),
                |%msg-args;
        }
        when 'PART' {
            $msg = IRC::Client::Message::Part.new:
                :channel( %args<params>[0] ),
                |%msg-args;
        }
        when 'NICK'    {
            $msg = IRC::Client::Message::Nick.new:
                :new-nick( %args<params>[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<params>[0] ~~ /^<[#&]>/
        and return IRC::Client::Message::Privmsg::Channel.new:
            :channel( %args<params>[0] ),
            :text( %args<params>[1] ),
            |%msg-args;

    return IRC::Client::Message::Privmsg::Me.new:
        :text( %args<params>[1] ),
        |%msg-args;
}

sub msg-notice (%args, %msg-args) {
    %args<params>[0] ~~ /^<[#&]>/
        and return IRC::Client::Message::Notice::Channel.new:
            :channel( %args<params>[0] ),
            :text( %args<params>[1] ),
            |%msg-args;

    return IRC::Client::Message::Notice::Me.new:
        :text( %args<params>[1] ),
        |%msg-args;
}

sub msg-mode (%args, %msg-args) {
    if %args<params>[0] ~~ /^<[#&]>/ {
        my @modes;
        for %args<params>[1..*-1].join.comb: /\S/ {
            state $sign;
            /<[+-]>/ and $sign = $_ and next;
            @modes.push: $sign => $_;
        };
        return IRC::Client::Message::Mode::Channel.new:
            :channel( %args<params>[0] ),
            :modes( @modes ),
            |%msg-args;
    }
    else {
        return IRC::Client::Message::Mode::Me.new:
            :modes( %args<params>[1..*-1].join.comb: /<[a..zA..Z]>/ ),
            |%msg-args;
    }
}