File Coverage

blib/lib/LINE/Bot/API.pm
Criterion Covered Total %
statement 295 321 91.9
branch 18 30 60.0
condition 7 14 50.0
subroutine 77 81 95.0
pod 45 51 88.2
total 442 497 88.9


line stmt bran cond sub pod time code
1             package LINE::Bot::API;
2 50     50   6085886 use strict;
  50         494  
  50         1571  
3 50     50   271 use warnings;
  50         97  
  50         2088  
4             our $VERSION = '1.20';
5              
6 50     50   24421 use LINE::Bot::API::Builder::SendMessage;
  50         137  
  50         1587  
7 50     50   17091 use LINE::Bot::API::Client;
  50         128  
  50         1421  
8 50     50   23686 use LINE::Bot::API::Event;
  50         147  
  50         1675  
9 50     50   17267 use LINE::Bot::API::Response::Common;
  50         126  
  50         1278  
10 50     50   22939 use LINE::Bot::API::Response::Content;
  50         148  
  50         1413  
11 50     50   23328 use LINE::Bot::API::Response::Count;
  50         149  
  50         1747  
12 50     50   22290 use LINE::Bot::API::Response::FriendDemographics;
  50         165  
  50         1579  
13 50     50   22504 use LINE::Bot::API::Response::NumberOfSentMessages;
  50         142  
  50         1523  
14 50     50   22460 use LINE::Bot::API::Response::NumberOfMessageDeliveries;
  50         159  
  50         1445  
15 50     50   22538 use LINE::Bot::API::Response::Profile;
  50         154  
  50         1549  
16 50     50   22840 use LINE::Bot::API::Response::GroupMemberProfile;
  50         149  
  50         1443  
17 50     50   22645 use LINE::Bot::API::Response::GroupSummary;
  50         141  
  50         1427  
18 50     50   22125 use LINE::Bot::API::Response::RoomMemberProfile;
  50         148  
  50         1558  
19 50     50   22311 use LINE::Bot::API::Response::IssueLinkToken;
  50         150  
  50         1568  
20 50     50   22656 use LINE::Bot::API::Response::RichMenu;
  50         149  
  50         1613  
21 50     50   22548 use LINE::Bot::API::Response::RichMenuList;
  50         154  
  50         1523  
22 50     50   22635 use LINE::Bot::API::Response::TargetLimit;
  50         149  
  50         1428  
23 50     50   22079 use LINE::Bot::API::Response::TotalUsage;
  50         143  
  50         1418  
24 50     50   22081 use LINE::Bot::API::Response::Token;
  50         167  
  50         1499  
25 50     50   22670 use LINE::Bot::API::Response::NumberOfFollowers;
  50         147  
  50         2557  
26 50     50   23363 use LINE::Bot::API::Response::UserInteractionStatistics;
  50         148  
  50         1395  
27 50     50   22358 use LINE::Bot::API::Response::BotInfo;
  50         191  
  50         1454  
28 50     50   22275 use LINE::Bot::API::Response::WebhookInformation;
  50         204  
  50         1392  
29 50     50   22303 use LINE::Bot::API::Response::WebhookTest;
  50         161  
  50         2178  
30              
31             use constant {
32 50         5280 DEFAULT_MESSAGING_API_ENDPOINT => 'https://api.line.me/v2/bot/',
33             DEFAULT_SOCIAL_API_ENDPOINT => 'https://api.line.me/v2/oauth/',
34             DEFAULT_CONTENT_API_ENDPOINT => 'https://api-data.line.me/v2/bot/',
35             DEFAULT_OAUTH2_API_ENDPOINT => 'https://api.line.me/oauth2/v2.1/',
36 50     50   339 };
  50         100  
37 50     50   19419 use Furl;
  50         190295  
  50         1597  
38 50     50   392 use Carp 'croak';
  50         109  
  50         2609  
39 50     50   20764 use URI::Escape;
  50         63221  
  50         175309  
40              
41             sub new {
42 38     38 1 5104 my($class, %args) = @_;
43              
44 38         440 my $client = LINE::Bot::API::Client->new(%args);
45              
46             bless {
47             client => $client,
48             channel_secret => $args{channel_secret},
49             channel_access_token => $args{channel_access_token},
50             messaging_api_endpoint => $args{messaging_api_endpoint} // DEFAULT_MESSAGING_API_ENDPOINT,
51             social_api_endpoint => $args{social_api_endpoint} // DEFAULT_SOCIAL_API_ENDPOINT,
52             content_api_endpoint => $args{content_api_endpoint} // DEFAULT_CONTENT_API_ENDPOINT,
53 38   50     3424 oauth_api_endpoint => $args{oauth_api_endpoint} // DEFAULT_OAUTH2_API_ENDPOINT,
      50        
      50        
      50        
54             }, $class;
55             }
56              
57             sub request {
58 72     72 0 262 my ($self, $method, $path, @payload) = @_;
59              
60             return $self->{client}->$method(
61 72         704 $self->{messaging_api_endpoint} . $path,
62             @payload,
63             );
64             }
65              
66             sub request_content {
67 0     0 0 0 my ($self, $method, $path, @payload) = @_;
68              
69             return $self->{client}->$method(
70 0         0 $self->{content_api_endpoint} . $path,
71             @payload,
72             );
73             }
74              
75             sub reply_message {
76 11     11 1 39 my($self, $reply_token, $messages) = @_;
77              
78 11         59 my $res = $self->request(
79             post => 'message/reply',
80             +{
81             replyToken => $reply_token,
82             messages => $messages,
83             }
84             );
85              
86 11         39 LINE::Bot::API::Response::Common->new(%{ $res });
  11         75  
87             }
88              
89             sub push_message {
90 25     25 1 105 my($self, $to_id, $messages, $options) = @_;
91              
92 25         58 my @headers = ();
93 25 100 66     113 if ($options && defined($options->{'retry_key'})) {
94 1         3 push @headers, 'X-Line-Retry-Key' => $options->{'retry_key'};
95             }
96              
97 25         172 my $res = $self->request(
98             post => 'message/push',
99             \@headers,
100             +{
101             to => $to_id,
102             messages => $messages,
103             }
104             );
105 25         109 LINE::Bot::API::Response::Common->new(%{ $res });
  25         285  
106             }
107              
108             sub multicast {
109 1     1 1 4 my($self, $to_ids, $messages, $options) = @_;
110              
111 1         2 my @headers = ();
112 1 50 33     5 if ($options && defined($options->{'retry_key'})) {
113 0         0 push @headers, 'X-Line-Retry-Key' => $options->{'retry_key'};
114             }
115              
116 1         6 my $res = $self->request(
117             post => 'message/multicast',
118             \@headers,
119             +{
120             to => $to_ids,
121             messages => $messages,
122             }
123             );
124 1         3 LINE::Bot::API::Response::Common->new(%{ $res });
  1         13  
125             }
126              
127             sub broadcast {
128 2     2 1 8 my($self, $messages, $options) = @_;
129              
130 2         5 my @headers = ();
131 2 100       7 if (defined($options->{'retry_key'})) {
132 1         4 push @headers, 'X-Line-Retry-Key' => $options->{'retry_key'};
133             }
134              
135 2         11 my $res = $self->request(
136             post => 'message/broadcast',
137             \@headers,
138             +{
139             messages => $messages,
140             }
141             );
142 2         7 LINE::Bot::API::Response::Common->new(%{ $res });
  2         17  
143             }
144              
145             sub get_message_content {
146 0     0 1 0 my($self, $message_id, %options) = @_;
147 0         0 my $res = $self->request_content(
148             'contents_download' => "message/$message_id/content",
149             %options
150             );
151 0         0 LINE::Bot::API::Response::Content->new(%{ $res });
  0         0  
152             }
153              
154             sub get_profile {
155 1     1 1 39 my($self, $user_id) = @_;
156 1         6 my $res = $self->request(get => "profile/$user_id");
157 1         3 LINE::Bot::API::Response::Profile->new(%{ $res });
  1         22  
158             }
159              
160             sub get_group_member_profile {
161 1     1 1 40 my($self, $group_id, $user_id) = @_;
162 1         8 my $res = $self->request(get => "group/$group_id/member/$user_id");
163 1         3 LINE::Bot::API::Response::GroupMemberProfile->new(%{ $res });
  1         22  
164             }
165              
166             sub get_room_member_profile {
167 1     1 1 39 my($self, $room_id, $user_id) = @_;
168 1         9 my $res = $self->request(get => "room/$room_id/member/$user_id");
169 1         3 LINE::Bot::API::Response::RoomMemberProfile->new(%{ $res });
  1         22  
170             }
171              
172             sub leave_room {
173 0     0 1 0 my($self, $room_id) = @_;
174 0         0 my $res = $self->request(post => "room/$room_id/leave", +{});
175 0         0 LINE::Bot::API::Response::Common->new(%{ $res });
  0         0  
176             }
177              
178             sub leave_group {
179 0     0 1 0 my($self, $group_id) = @_;
180 0         0 my $res = $self->request(post => "group/$group_id/leave", +{});
181 0         0 LINE::Bot::API::Response::Common->new(%{ $res });
  0         0  
182             }
183              
184             sub get_friend_demographics {
185 1     1 1 29 my($self) = @_;
186 1         4 my $res = $self->request(get => "insight/demographic");
187 1         3 LINE::Bot::API::Response::FriendDemographics->new(%{ $res });
  1         18  
188             }
189              
190             sub get_target_limit_for_additional_messages {
191 1     1 1 38 my($self, $date) = @_;
192 1         5 my $res = $self->request(get => "message/quota");
193 1         3 LINE::Bot::API::Response::TargetLimit->new(%{ $res });
  1         20  
194             }
195              
196             sub get_number_of_messages_sent_this_month {
197 1     1 1 49 my($self, $date) = @_;
198 1         6 my $res = $self->request(get => "message/quota/consumption");
199 1         3 LINE::Bot::API::Response::TotalUsage->new(%{ $res });
  1         18  
200             }
201              
202             sub get_number_of_sent_reply_messages {
203 1     1 1 31 my($self, $date) = @_;
204 1         6 my $res = $self->request(get => "message/delivery/reply?date=${date}");
205 1         3 LINE::Bot::API::Response::NumberOfSentMessages->new(%{ $res });
  1         14  
206             }
207              
208             sub get_number_of_sent_push_messages {
209 1     1 1 684 my($self, $date) = @_;
210 1         7 my $res = $self->request(get => "message/delivery/push?date=${date}", +{});
211 1         3 LINE::Bot::API::Response::NumberOfSentMessages->new(%{ $res });
  1         7  
212             }
213              
214             sub get_number_of_sent_multicast_messages {
215 1     1 1 676 my($self, $date) = @_;
216 1         6 my $res = $self->request(get => "message/delivery/multicast?date=${date}", +{});
217 1         2 LINE::Bot::API::Response::NumberOfSentMessages->new(%{ $res });
  1         7  
218             }
219              
220             sub get_number_of_send_broadcast_messages {
221 1     1 1 692 my($self, $date) = @_;
222 1         6 my $res = $self->request(get => "message/delivery/broadcast?date=${date}", +{});
223 1         4 LINE::Bot::API::Response::NumberOfSentMessages->new(%{ $res });
  1         6  
224             }
225              
226             sub get_number_of_message_deliveries {
227 1     1 1 42 my($self, $opts) = @_;
228 1 50       6 my $date = $opts->{date} or croak "get_number_of_message_deliveries: Missing a `date` parameter.";
229              
230 1         7 my $res = $self->request(get => "insight/message/delivery?date=${date}", +{});
231 1         3 LINE::Bot::API::Response::NumberOfMessageDeliveries->new(%{ $res });
  1         24  
232             }
233              
234             sub get_member_in_room_count {
235 1     1 1 1849 my ($self, $room_id) = @_;
236              
237 1         8 my $res = $self->request(get => "room/${room_id}/members/count", +{});
238 1         4 LINE::Bot::API::Response::Count->new(%{ $res });
  1         20  
239             }
240              
241             sub get_member_in_group_count {
242 1     1 1 1672 my ($self, $group_id) = @_;
243              
244 1         8 my $res = $self->request(get => "group/${group_id}/members/count", +{});
245 1         3 LINE::Bot::API::Response::Count->new(%{ $res });
  1         20  
246             }
247              
248             sub get_group_summary {
249 1     1 1 1884 my ($self, $group_id) = @_;
250              
251 1         6 my $res = $self->request(get => "group/${group_id}/summary", +{});
252 1         3 LINE::Bot::API::Response::GroupSummary->new(%{ $res });
  1         14  
253             }
254              
255             sub validate_signature {
256 2     2 1 6978 my($self, $json, $signature) = @_;
257 2         26 LINE::Bot::API::Event->validate_signature($json, $self->{channel_secret}, $signature);
258             }
259              
260             sub parse_events_from_json {
261 1     1 1 5576 my($self, $json) = @_;
262 1         8 LINE::Bot::API::Event->parse_events_json($json);
263             }
264              
265             sub issue_link_token {
266 1     1 0 33 my($self, $user_id) = @_;
267 1         6 my $res = $self->request(post => "user/${user_id}/linkToken", +{});
268 1         2 LINE::Bot::API::Response::IssueLinkToken->new(%{ $res });
  1         17  
269             }
270              
271             sub create_rich_menu {
272 1     1 1 1663 my ($self, $rich_menu) = @_;
273 1         7 my $res = $self->request(post => "richmenu", $rich_menu);
274 1         2 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         18  
275             }
276              
277             sub get_rich_menu {
278 1     1 1 4103 my ($self, $rich_menu_id) = @_;
279 1         5 my $res = $self->request(get => "richmenu/${rich_menu_id}");
280 1         4 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         5  
281             }
282              
283             sub delete_rich_menu {
284 1     1 1 3584 my ($self, $rich_menu_id) = @_;
285 1         5 my $res = $self->request(delete => "richmenu/${rich_menu_id}");
286 1         3 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         5  
287             }
288              
289             sub get_rich_menu_list {
290 1     1 1 3544 my ($self) = @_;
291 1         4 my $res = $self->request(get => "richmenu/list");
292 1         4 LINE::Bot::API::Response::RichMenuList->new(%{ $res });
  1         14  
293             }
294              
295             sub set_default_rich_menu {
296 1     1 1 3686 my ($self, $rich_menu_id) = @_;
297 1         8 my $res = $self->request(post => "user/all/richmenu/${rich_menu_id}", +{});
298 1         3 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         7  
299             }
300              
301             sub get_default_rich_menu_id {
302 1     1 1 3636 my ($self) = @_;
303 1         5 my $res = $self->request(get => "user/all/richmenu");
304 1         4 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         24  
305             }
306              
307             sub cancel_default_rich_menu {
308 1     1 1 3556 my ($self) = @_;
309 1         4 my $res = $self->request(delete => "user/all/richmenu");
310 1         3 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         8  
311             }
312              
313             sub link_rich_menu_to_user {
314 1     1 1 3557 my ($self, $user_id, $rich_menu_id) = @_;
315 1         10 my $res = $self->request(post => "user/${user_id}/richmenu/${rich_menu_id}", +{});
316 1         4 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         8  
317             }
318              
319             sub link_rich_menu_to_multiple_users {
320 1     1 1 3550 my ($self, $user_ids, $rich_menu_id) = @_;
321 1         8 my $res = $self->request(post => "richmenu/bulk/link", +{
322             richMenuId => $rich_menu_id,
323             userIds => $user_ids,
324             });
325 1         7 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         7  
326             }
327              
328             sub get_rich_menu_id_of_user {
329 1     1 1 3592 my ($self, $user_id, $rich_menu_id) = @_;
330 1         6 my $res = $self->request(get => "user/${user_id}/richmenu");
331 1         5 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         7  
332             }
333              
334             sub unlink_rich_menu_from_user {
335 1     1 1 3554 my ($self, $user_id) = @_;
336 1         10 my $res = $self->request(delete => "user/${user_id}/richmenu");
337 1         3 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         7  
338             }
339              
340             sub unlink_rich_menu_from_multiple_users {
341 1     1 1 3644 my ($self, $user_ids) = @_;
342 1         6 my $res = $self->request(post => "richmenu/bulk/unlink", +{
343             userIds => $user_ids,
344             });
345 1         4 LINE::Bot::API::Response::RichMenu->new(%{ $res });
  1         8  
346             }
347              
348             sub upload_rich_menu_image {
349 1     1 0 1782 my ($self, $rich_menu_id, $content_type, $file_path) = @_;
350              
351 1 50       18 if (!$content_type) {
352 0         0 croak 'Need content_type';
353             }
354              
355             my $res = $self->{client}->post_image(
356 1         14 $self->{content_api_endpoint} . "richmenu/$rich_menu_id/content",
357             [
358             'Content-Type' => $content_type,
359             ],
360             $file_path
361             );
362              
363 1 50       6 if ($res->{http_status} eq '200') {
364 1         3 return LINE::Bot::API::Response::Token->new(%{ $res });
  1         19  
365             } else {
366 0         0 return LINE::Bot::API::Response::Error->new(%{ $res });
  0         0  
367             }
368              
369             }
370              
371             sub download_rich_menu_image {
372 1     1 0 1637 my ($self, $rich_menu_id) = @_;
373              
374             return $self->{client}->get_content(
375 1         10 $self->{content_api_endpoint} . "richmenu/$rich_menu_id/content"
376             );
377             }
378              
379             sub issue_channel_access_token {
380 1     1 1 1742 my ($self, $opts) = @_;
381              
382             my $res = $self->{client}->post_form(
383             $self->{social_api_endpoint} . 'accessToken',
384             [
385             grant_type => 'client_credentials',
386             client_id => $opts->{client_id},
387             client_secret => $opts->{client_secret},
388 1         10 ]
389             );
390              
391 1 50       5 if ($res->{http_status} eq '200') {
392 1         3 return LINE::Bot::API::Response::Token->new(%{ $res });
  1         20  
393             } else {
394 0         0 return LINE::Bot::API::Response::Error->new(%{ $res });
  0         0  
395             }
396             }
397              
398             sub issue_channel_access_token_v2_1 {
399 1     1 1 3831 my ($self, $opts) = @_;
400              
401             my $res = $self->{client}->post_form(
402             $self->{oauth_api_endpoint} . 'token',
403             undef,
404             [
405             grant_type => 'client_credentials',
406             client_assertion_type => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
407             client_assertion => $opts->{jwt},
408 1         13 ]
409             );
410              
411 1 50       8 if ($res->{http_status} eq '200') {
412 1         3 return LINE::Bot::API::Response::Token->new(%{ $res });
  1         10  
413             } else {
414 0         0 return LINE::Bot::API::Response::Error->new(%{ $res });
  0         0  
415             }
416             }
417              
418             sub get_valid_channel_access_token_v2_1 {
419 1     1 1 4534 my ($self, $opts) = @_;
420              
421 1         7 my $jwt = uri_escape($opts->{jwt});
422 1         50 my $assertion_type = uri_escape('urn:ietf:params:oauth:client-assertion-type:jwt-bearer');
423              
424             my $res = $self->{client}->get(
425 1         44 $self->{oauth_api_endpoint} . 'tokens/kid' . "?client_assertion_type=$assertion_type&client_assertion=$jwt",
426             );
427              
428 1 50       6 if ($res->{http_status} eq '200') {
429 1         3 return LINE::Bot::API::Response::Token->new(%{ $res });
  1         9  
430             } else {
431 0         0 return LINE::Bot::API::Response::Error->new(%{ $res });
  0         0  
432             }
433             }
434              
435             sub revoke_channel_access_token {
436 2     2 1 8635 my ($self, $opts) = @_;
437              
438             my $res = $self->{client}->post_form(
439             $self->{social_api_endpoint} . 'revoke',
440             [
441             access_token => $opts->{access_token},
442 2         25 ]
443             );
444              
445 2 100       11 if ($res->{http_status} eq '200') {
446 1         3 return LINE::Bot::API::Response::Common->new(%{ $res });
  1         9  
447             } else {
448 1         3 return LINE::Bot::API::Response::Error->new(%{ $res });
  1         21  
449             }
450             }
451              
452             sub get_number_of_followers {
453 1     1 1 38 my ($self, $opts) = @_;
454 1 50       5 my $date = $opts->{date} or croak "get_number_of_followers: Missing a `date` parameter.";
455              
456 1         7 my $res = $self->request(get => "insight/followers?date=${date}");
457 1         2 LINE::Bot::API::Response::NumberOfFollowers->new(%{ $res });
  1         22  
458             }
459              
460             sub get_user_interaction_statistics {
461 1     1 1 33 my ($self, $opts) = @_;
462 1 50       4 my $requestId = $opts->{requestId} or croak "get_user_interaction_statistics: Missing a `requestId` parameter.";
463              
464 1         6 my $res = $self->request(get => "insight/message/event?requestId=${requestId}");
465 1         3 LINE::Bot::API::Response::UserInteractionStatistics->new(%{ $res });
  1         17  
466             }
467              
468             sub get_bot_info {
469 1     1 0 47 my ($self) = @_;
470 1         5 my $res = $self->request(get => "info");
471 1         2 LINE::Bot::API::Response::BotInfo->new(%{ $res });
  1         17  
472             }
473              
474             sub set_webhook_url {
475 1     1 1 40 my ($self, $opts) = @_;
476 1 50       5 defined($opts->{endpoint}) or croak "set_webhook_url: Missing a mandatory parameter: `endpoint`";
477              
478             my $res = $self->request(
479             'put' => "channel/webhook/endpoint",
480             [],
481             +{ endpoint => $opts->{endpoint} },
482 1         6 );
483              
484 1 50       6 if ($res->{http_status} eq '200') {
485 1         3 return LINE::Bot::API::Response::Common->new(%{ $res });
  1         13  
486             } else {
487 0         0 return LINE::Bot::API::Response::Error->new(%{ $res });
  0         0  
488             }
489             }
490              
491             sub get_webhook_endpoint_information {
492 1     1 1 37 my ($self) = @_;
493 1         5 my $res = $self->request(get => "channel/webhook/endpoint");
494 1         13 LINE::Bot::API::Response::WebhookInformation->new(%{ $res });
  1         20  
495             }
496              
497             sub test_webhook_endpoint {
498 1     1 1 46 my ($self, $opts) = @_;
499              
500 1         3 my $req_body = {};
501 1 50       4 if ($opts->{'endpoint'}) {
502 1         3 $req_body->{'endpoint'} = $opts->{'endpoint'};
503             }
504              
505 1         5 my $res = $self->request(
506             'post' => "channel/webhook/endpoint",
507             [],
508             $req_body,
509             );
510              
511 1         3 LINE::Bot::API::Response::WebhookTest->new(%{ $res });
  1         28  
512             }
513              
514             1;
515              
516             __END__