line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Bot::ChatBots::Telegram::Keyboard; |
2
|
2
|
|
|
2
|
|
73947
|
use strict; |
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
63
|
|
3
|
2
|
|
|
2
|
|
10
|
use warnings; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
85
|
|
4
|
|
|
|
|
|
|
{ our $VERSION = '0.014'; } |
5
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
448
|
use Ouch; |
|
2
|
|
|
|
|
4511
|
|
|
2
|
|
|
|
|
9
|
|
7
|
2
|
|
|
2
|
|
1093
|
use Log::Any qw< $log >; |
|
2
|
|
|
|
|
16626
|
|
|
2
|
|
|
|
|
9
|
|
8
|
2
|
|
|
2
|
|
4822
|
use Data::Dumper; |
|
2
|
|
|
|
|
6852
|
|
|
2
|
|
|
|
|
113
|
|
9
|
|
|
|
|
|
|
|
10
|
2
|
|
|
2
|
|
1171
|
use Moo; |
|
2
|
|
|
|
|
20079
|
|
|
2
|
|
|
|
|
10
|
|
11
|
2
|
|
|
2
|
|
4491
|
use namespace::clean; |
|
2
|
|
|
|
|
23074
|
|
|
2
|
|
|
|
|
15
|
|
12
|
|
|
|
|
|
|
|
13
|
2
|
|
|
2
|
|
789
|
use Exporter qw< import >; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
473
|
|
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
|
|
11
|
$ONE = "\x{200B}"; |
44
|
2
|
|
|
|
|
6
|
$ZERO = "\x{200C}"; |
45
|
2
|
|
|
|
|
2251
|
$BOUNDARY = "\x{200D}"; |
46
|
|
|
|
|
|
|
} ## end BEGIN |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub __encode_uint32 { |
49
|
18
|
|
|
18
|
|
30
|
my $x = shift; |
50
|
18
|
|
|
|
|
81
|
(my $b = unpack 'B32', pack 'N', $x) =~ s/^0+//mxs; |
51
|
18
|
100
|
|
|
|
42
|
$b = '0' unless length $b; |
52
|
18
|
100
|
|
|
|
51
|
return join '', map { $_ ? $ONE : $ZERO } split //, $b; |
|
58
|
|
|
|
|
154
|
|
53
|
|
|
|
|
|
|
} ## end sub __encode_uint32 |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub __decode_uint32 { |
56
|
12
|
|
|
12
|
|
24
|
my $x = shift; |
57
|
12
|
100
|
|
|
|
32
|
my $b = join '', map { $_ eq $ONE ? '1' : '0' } split //, $x; |
|
42
|
|
|
|
|
95
|
|
58
|
12
|
|
|
|
|
33
|
$b = substr(('0' x 32) . $b, -32, 32); |
59
|
12
|
|
|
|
|
58
|
return unpack 'N', pack 'B32', $b; |
60
|
|
|
|
|
|
|
} ## end sub __decode_uint32 |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub __encode { |
63
|
9
|
|
|
9
|
|
19
|
my ($label, $keyboard_id, $code) = @_; |
64
|
9
|
|
|
|
|
19
|
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
|
|
31
|
return unless defined $_[0]; |
72
|
8
|
|
|
|
|
159
|
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
|
|
|
|
28
|
return unless defined $code; |
81
|
6
|
|
|
|
|
15
|
return ($label, __decode_uint32($kid), __decode_uint32($code)); |
82
|
|
|
|
|
|
|
} ## end sub __decode |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub BUILDARGS { |
86
|
3
|
|
|
3
|
1
|
1768
|
my ($class, %args) = @_; |
87
|
3
|
100
|
|
|
|
17
|
ouch 500, 'no input keyboard' unless exists $args{keyboard}; |
88
|
1
|
|
50
|
|
|
4
|
my $id = $args{id} //= 0; |
89
|
1
|
|
|
|
|
5
|
@args{qw} = __keyboard($args{keyboard}, $id); |
90
|
1
|
|
|
|
|
24
|
return \%args; |
91
|
|
|
|
|
|
|
} ## end sub BUILDARGS |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub _decode { |
94
|
13
|
|
|
13
|
|
29
|
my ($self, $x, $name) = @_; |
95
|
13
|
100
|
|
|
|
43
|
if (ref($x) eq 'HASH') { |
|
|
50
|
|
|
|
|
|
96
|
8
|
100
|
|
|
|
24
|
$x = $x->{payload} if exists $x->{payload}; |
97
|
8
|
|
100
|
|
|
30
|
$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
|
|
|
|
|
29
|
return __decode($x); |
104
|
|
|
|
|
|
|
} ## end sub _decode |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub get_value { |
107
|
10
|
|
|
10
|
1
|
11163
|
my ($self, $x) = @_; |
108
|
10
|
|
|
|
|
28
|
my (undef, undef, $code) = $self->_decode($x, 'get_value'); |
109
|
10
|
100
|
|
|
|
39
|
return undef unless defined $code; |
110
|
|
|
|
|
|
|
|
111
|
3
|
|
|
|
|
11
|
my $vf = $self->_value_for; |
112
|
3
|
50
|
|
|
|
8
|
if (!exists($vf->{$code})) { |
113
|
0
|
|
|
|
|
0
|
$log->warn("get_value(): received code $code is unknown"); |
114
|
0
|
|
|
|
|
0
|
return undef; |
115
|
|
|
|
|
|
|
} |
116
|
3
|
|
|
|
|
14
|
return $vf->{$code}; |
117
|
|
|
|
|
|
|
} ## end sub get_value |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub get_keyboard_id { |
120
|
3
|
|
|
3
|
1
|
2523
|
my ($self, $x) = @_; |
121
|
3
|
|
|
|
|
9
|
my (undef, $keyboard_id) = $self->_decode($x, 'get_keyboard_id'); |
122
|
3
|
|
|
|
|
13
|
return $keyboard_id; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub __keyboard { |
126
|
1
|
|
|
1
|
|
4
|
my ($input, $keyboard_id) = @_; |
127
|
1
|
50
|
|
|
|
4
|
ouch 500, 'invalid input keyboard, not an ARRAY' |
128
|
|
|
|
|
|
|
unless ref($input) eq 'ARRAY'; |
129
|
1
|
50
|
|
|
|
5
|
ouch 500, 'invalid empty keyboard' unless @$input; |
130
|
|
|
|
|
|
|
|
131
|
1
|
|
|
|
|
3
|
my $code = 0; |
132
|
1
|
|
|
|
|
2
|
my @display_keyboard; |
133
|
1
|
|
|
|
|
2
|
my (%value_for, %code_for); |
134
|
1
|
|
|
|
|
3
|
for my $row (@$input) { |
135
|
3
|
50
|
|
|
|
10
|
ouch 500, 'invalid input keyboard, not an AoA' |
136
|
|
|
|
|
|
|
unless ref($row) eq 'ARRAY'; |
137
|
|
|
|
|
|
|
|
138
|
3
|
|
|
|
|
5
|
my @display_row; |
139
|
3
|
|
|
|
|
6
|
push @display_keyboard, \@display_row; |
140
|
3
|
|
|
|
|
7
|
for my $item (@$row) { |
141
|
10
|
50
|
|
|
|
23
|
ouch 500, 'invalid input keyboard, not an AoAoH' |
142
|
|
|
|
|
|
|
unless ref($item) eq 'HASH'; |
143
|
|
|
|
|
|
|
|
144
|
10
|
|
|
|
|
32
|
my %display_item = %$item; |
145
|
10
|
|
|
|
|
19
|
push @display_row, \%display_item; |
146
|
|
|
|
|
|
|
|
147
|
10
|
|
|
|
|
21
|
my $command = delete $display_item{_value}; |
148
|
10
|
100
|
|
|
|
22
|
next unless defined $command; |
149
|
9
|
|
66
|
|
|
46
|
my $cc = $code_for{$command} //= $code++; |
150
|
9
|
|
33
|
|
|
42
|
$value_for{$cc} //= $command; |
151
|
|
|
|
|
|
|
$display_item{text} = |
152
|
9
|
|
|
|
|
17
|
__encode($display_item{text}, $keyboard_id, $cc); |
153
|
|
|
|
|
|
|
} ## end for my $item (@$row) |
154
|
|
|
|
|
|
|
} ## end for my $row (@$input) |
155
|
1
|
|
|
|
|
6
|
return (\@display_keyboard, \%value_for); |
156
|
|
|
|
|
|
|
} ## end sub __keyboard |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub keyboard { |
159
|
3
|
|
|
3
|
1
|
3464
|
my %args; |
160
|
3
|
100
|
|
|
|
20
|
if (@_ > 1) { |
|
|
100
|
|
|
|
|
|
161
|
1
|
50
|
|
|
|
4
|
if (ref($_[0])) { |
162
|
0
|
|
|
|
|
0
|
$args{keyboard} = [@_]; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
else { |
165
|
1
|
|
|
|
|
4
|
%args = @_; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
} ## end if (@_ > 1) |
168
|
|
|
|
|
|
|
elsif (@_ == 1) { |
169
|
1
|
|
|
|
|
2
|
my $x = shift; |
170
|
1
|
50
|
|
|
|
4
|
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
|
|
|
|
|
97
|
return Bot::ChatBots::Telegram::Keyboard->new(%args); |
180
|
|
|
|
|
|
|
} ## end sub keyboard |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
1; |