| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Bot::ChatBots::Telegram::Keyboard; |
|
2
|
2
|
|
|
2
|
|
55645
|
use strict; |
|
|
2
|
|
|
|
|
11
|
|
|
|
2
|
|
|
|
|
47
|
|
|
3
|
2
|
|
|
2
|
|
8
|
use warnings; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
68
|
|
|
4
|
|
|
|
|
|
|
{ our $VERSION = '0.012'; } |
|
5
|
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
351
|
use Ouch; |
|
|
2
|
|
|
|
|
3453
|
|
|
|
2
|
|
|
|
|
7
|
|
|
7
|
2
|
|
|
2
|
|
820
|
use Log::Any qw< $log >; |
|
|
2
|
|
|
|
|
12707
|
|
|
|
2
|
|
|
|
|
7
|
|
|
8
|
2
|
|
|
2
|
|
3851
|
use Data::Dumper; |
|
|
2
|
|
|
|
|
5195
|
|
|
|
2
|
|
|
|
|
85
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
2
|
|
|
2
|
|
890
|
use Moo; |
|
|
2
|
|
|
|
|
15375
|
|
|
|
2
|
|
|
|
|
8
|
|
|
11
|
2
|
|
|
2
|
|
3204
|
use namespace::clean; |
|
|
2
|
|
|
|
|
18138
|
|
|
|
2
|
|
|
|
|
10
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
2
|
|
|
2
|
|
574
|
use Exporter qw< import >; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
353
|
|
|
14
|
|
|
|
|
|
|
our @EXPORT_OK = qw< keyboard >; |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
has displayable => ( |
|
17
|
|
|
|
|
|
|
is => 'ro', |
|
18
|
|
|
|
|
|
|
required => 1, |
|
19
|
|
|
|
|
|
|
); |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
has id => ( |
|
22
|
|
|
|
|
|
|
is => 'ro', |
|
23
|
|
|
|
|
|
|
default => sub { return 0 }, |
|
24
|
|
|
|
|
|
|
isa => sub { |
|
25
|
|
|
|
|
|
|
my $n = shift; |
|
26
|
|
|
|
|
|
|
my $complaint = 'keyboard_id MUST be an unsigned 32 bits integer'; |
|
27
|
|
|
|
|
|
|
ouch 500, $complaint unless $n =~ m{\A(?: 0 | [1-9]\d* )\z}mxs; |
|
28
|
|
|
|
|
|
|
my $r = unpack 'N', pack 'N', $n; |
|
29
|
|
|
|
|
|
|
ouch 500, $complaint unless $n eq $r; |
|
30
|
|
|
|
|
|
|
return; |
|
31
|
|
|
|
|
|
|
}, |
|
32
|
|
|
|
|
|
|
); |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
has _value_for => ( |
|
35
|
|
|
|
|
|
|
is => 'ro', |
|
36
|
|
|
|
|
|
|
required => 1, |
|
37
|
|
|
|
|
|
|
); |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
{ |
|
40
|
|
|
|
|
|
|
my ($ONE, $ZERO, $BOUNDARY); |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
BEGIN { |
|
43
|
2
|
|
|
2
|
|
7
|
$ONE = "\x{200B}"; |
|
44
|
2
|
|
|
|
|
3
|
$ZERO = "\x{200C}"; |
|
45
|
2
|
|
|
|
|
1781
|
$BOUNDARY = "\x{200D}"; |
|
46
|
|
|
|
|
|
|
} ## end BEGIN |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub __encode_uint32 { |
|
49
|
18
|
|
|
18
|
|
32
|
my $x = shift; |
|
50
|
18
|
|
|
|
|
66
|
(my $b = unpack 'B32', pack 'N', $x) =~ s/^0+//mxs; |
|
51
|
18
|
100
|
|
|
|
35
|
$b = '0' unless length $b; |
|
52
|
18
|
100
|
|
|
|
32
|
return join '', map { $_ ? $ONE : $ZERO } split //, $b; |
|
|
58
|
|
|
|
|
113
|
|
|
53
|
|
|
|
|
|
|
} ## end sub __encode_uint32 |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub __decode_uint32 { |
|
56
|
12
|
|
|
12
|
|
17
|
my $x = shift; |
|
57
|
12
|
100
|
|
|
|
26
|
my $b = join '', map { $_ eq $ONE ? '1' : '0' } split //, $x; |
|
|
42
|
|
|
|
|
71
|
|
|
58
|
12
|
|
|
|
|
26
|
$b = substr(('0' x 32) . $b, -32, 32); |
|
59
|
12
|
|
|
|
|
42
|
return unpack 'N', pack 'B32', $b; |
|
60
|
|
|
|
|
|
|
} ## end sub __decode_uint32 |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub __encode { |
|
63
|
9
|
|
|
9
|
|
13
|
my ($label, $keyboard_id, $code) = @_; |
|
64
|
9
|
|
|
|
|
13
|
return join '', $label, |
|
65
|
|
|
|
|
|
|
$BOUNDARY, __encode_uint32($keyboard_id), |
|
66
|
|
|
|
|
|
|
$BOUNDARY, __encode_uint32($code), |
|
67
|
|
|
|
|
|
|
$BOUNDARY; |
|
68
|
|
|
|
|
|
|
} ## end sub __encode |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
sub __decode { |
|
71
|
13
|
100
|
|
13
|
|
24
|
return unless defined $_[0]; |
|
72
|
8
|
|
|
|
|
113
|
my ($label, $kid, $code) = $_[0] =~ m{ |
|
73
|
|
|
|
|
|
|
\A |
|
74
|
|
|
|
|
|
|
(.*) |
|
75
|
|
|
|
|
|
|
$BOUNDARY ((?:$ZERO|$ONE)+) |
|
76
|
|
|
|
|
|
|
$BOUNDARY ((?:$ZERO|$ONE)+) |
|
77
|
|
|
|
|
|
|
$BOUNDARY |
|
78
|
|
|
|
|
|
|
\z |
|
79
|
|
|
|
|
|
|
}mxs; |
|
80
|
8
|
100
|
|
|
|
21
|
return unless defined $code; |
|
81
|
6
|
|
|
|
|
8
|
return ($label, __decode_uint32($kid), __decode_uint32($code)); |
|
82
|
|
|
|
|
|
|
} ## end sub __decode |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub BUILDARGS { |
|
86
|
3
|
|
|
3
|
1
|
1196
|
my ($class, %args) = @_; |
|
87
|
3
|
100
|
|
|
|
10
|
ouch 500, 'no input keyboard' unless exists $args{keyboard}; |
|
88
|
1
|
|
50
|
|
|
3
|
my $id = $args{id} //= 0; |
|
89
|
1
|
|
|
|
|
2
|
@args{qw} = __keyboard($args{keyboard}, $id); |
|
90
|
1
|
|
|
|
|
17
|
return \%args; |
|
91
|
|
|
|
|
|
|
} ## end sub BUILDARGS |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub _decode { |
|
94
|
13
|
|
|
13
|
|
22
|
my ($self, $x, $name) = @_; |
|
95
|
13
|
100
|
|
|
|
28
|
if (ref($x) eq 'HASH') { |
|
|
|
50
|
|
|
|
|
|
|
96
|
8
|
100
|
|
|
|
28
|
$x = $x->{payload} if exists $x->{payload}; |
|
97
|
8
|
|
100
|
|
|
19
|
$x = $x->{text} // undef; |
|
98
|
|
|
|
|
|
|
} |
|
99
|
|
|
|
|
|
|
elsif (ref($x)) { |
|
100
|
0
|
|
|
|
|
0
|
ouch 500, "$name(): pass either hash references or plain scalars"; |
|
101
|
|
|
|
|
|
|
} |
|
102
|
|
|
|
|
|
|
|
|
103
|
13
|
|
|
|
|
24
|
return __decode($x); |
|
104
|
|
|
|
|
|
|
} ## end sub _decode |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub get_value { |
|
107
|
10
|
|
|
10
|
1
|
8367
|
my ($self, $x) = @_; |
|
108
|
10
|
|
|
|
|
17
|
my (undef, undef, $code) = $self->_decode($x, 'get_value'); |
|
109
|
10
|
100
|
|
|
|
28
|
return undef unless defined $code; |
|
110
|
|
|
|
|
|
|
|
|
111
|
3
|
|
|
|
|
7
|
my $vf = $self->_value_for; |
|
112
|
3
|
50
|
|
|
|
7
|
if (!exists($vf->{$code})) { |
|
113
|
0
|
|
|
|
|
0
|
$log->warn("get_value(): received code $code is unknown"); |
|
114
|
0
|
|
|
|
|
0
|
return undef; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
3
|
|
|
|
|
10
|
return $vf->{$code}; |
|
117
|
|
|
|
|
|
|
} ## end sub get_value |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub get_keyboard_id { |
|
120
|
3
|
|
|
3
|
1
|
1873
|
my ($self, $x) = @_; |
|
121
|
3
|
|
|
|
|
7
|
my (undef, $keyboard_id) = $self->_decode($x, 'get_keyboard_id'); |
|
122
|
3
|
|
|
|
|
10
|
return $keyboard_id; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub __keyboard { |
|
126
|
1
|
|
|
1
|
|
3
|
my ($input, $keyboard_id) = @_; |
|
127
|
1
|
50
|
|
|
|
3
|
ouch 500, 'invalid input keyboard, not an ARRAY' |
|
128
|
|
|
|
|
|
|
unless ref($input) eq 'ARRAY'; |
|
129
|
1
|
50
|
|
|
|
3
|
ouch 500, 'invalid empty keyboard' unless @$input; |
|
130
|
|
|
|
|
|
|
|
|
131
|
1
|
|
|
|
|
2
|
my $code = 0; |
|
132
|
1
|
|
|
|
|
1
|
my @display_keyboard; |
|
133
|
1
|
|
|
|
|
2
|
my (%value_for, %code_for); |
|
134
|
1
|
|
|
|
|
2
|
for my $row (@$input) { |
|
135
|
3
|
50
|
|
|
|
8
|
ouch 500, 'invalid input keyboard, not an AoA' |
|
136
|
|
|
|
|
|
|
unless ref($row) eq 'ARRAY'; |
|
137
|
|
|
|
|
|
|
|
|
138
|
3
|
|
|
|
|
4
|
my @display_row; |
|
139
|
3
|
|
|
|
|
4
|
push @display_keyboard, \@display_row; |
|
140
|
3
|
|
|
|
|
4
|
for my $item (@$row) { |
|
141
|
10
|
50
|
|
|
|
18
|
ouch 500, 'invalid input keyboard, not an AoAoH' |
|
142
|
|
|
|
|
|
|
unless ref($item) eq 'HASH'; |
|
143
|
|
|
|
|
|
|
|
|
144
|
10
|
|
|
|
|
24
|
my %display_item = %$item; |
|
145
|
10
|
|
|
|
|
16
|
push @display_row, \%display_item; |
|
146
|
|
|
|
|
|
|
|
|
147
|
10
|
|
|
|
|
14
|
my $command = delete $display_item{_value}; |
|
148
|
10
|
100
|
|
|
|
16
|
next unless defined $command; |
|
149
|
9
|
|
66
|
|
|
23
|
my $cc = $code_for{$command} //= $code++; |
|
150
|
9
|
|
33
|
|
|
29
|
$value_for{$cc} //= $command; |
|
151
|
|
|
|
|
|
|
$display_item{text} = |
|
152
|
9
|
|
|
|
|
13
|
__encode($display_item{text}, $keyboard_id, $cc); |
|
153
|
|
|
|
|
|
|
} ## end for my $item (@$row) |
|
154
|
|
|
|
|
|
|
} ## end for my $row (@$input) |
|
155
|
1
|
|
|
|
|
4
|
return (\@display_keyboard, \%value_for); |
|
156
|
|
|
|
|
|
|
} ## end sub __keyboard |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub keyboard { |
|
159
|
3
|
|
|
3
|
1
|
2593
|
my %args; |
|
160
|
3
|
100
|
|
|
|
12
|
if (@_ > 1) { |
|
|
|
100
|
|
|
|
|
|
|
161
|
1
|
50
|
|
|
|
2
|
if (ref($_[0])) { |
|
162
|
0
|
|
|
|
|
0
|
$args{keyboard} = [@_]; |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
else { |
|
165
|
1
|
|
|
|
|
3
|
%args = @_; |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
} ## end if (@_ > 1) |
|
168
|
|
|
|
|
|
|
elsif (@_ == 1) { |
|
169
|
1
|
|
|
|
|
2
|
my $x = shift; |
|
170
|
1
|
50
|
|
|
|
3
|
if (@$x > 0) { |
|
171
|
0
|
0
|
|
|
|
0
|
if (ref($x->[0]) eq 'ARRAY') { |
|
172
|
0
|
|
|
|
|
0
|
$args{keyboard} = $x; |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
else { |
|
175
|
0
|
|
|
|
|
0
|
$args{keyboard} = [$x]; # one row only |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
} ## end if (@$x > 0) |
|
178
|
|
|
|
|
|
|
} ## end elsif (@_ == 1) |
|
179
|
3
|
|
|
|
|
45
|
return Bot::ChatBots::Telegram::Keyboard->new(%args); |
|
180
|
|
|
|
|
|
|
} ## end sub keyboard |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
1; |