LINE-Bot-API
view release on metacpan or search on metacpan
lib/LINE/Bot/API.pm view on Meta::CPAN
package LINE::Bot::API;
use strict;
use warnings;
our $VERSION = '1.21';
use LINE::Bot::API::Builder::SendMessage;
use LINE::Bot::API::Client;
use LINE::Bot::API::Event;
use LINE::Bot::API::Response::Common;
use LINE::Bot::API::Response::Content;
use LINE::Bot::API::Response::Count;
use LINE::Bot::API::Response::FriendDemographics;
use LINE::Bot::API::Response::NumberOfSentMessages;
use LINE::Bot::API::Response::NumberOfMessageDeliveries;
use LINE::Bot::API::Response::Profile;
use LINE::Bot::API::Response::GroupMemberProfile;
use LINE::Bot::API::Response::GroupSummary;
use LINE::Bot::API::Response::RoomMemberProfile;
use LINE::Bot::API::Response::IssueLinkToken;
use LINE::Bot::API::Response::RichMenu;
use LINE::Bot::API::Response::RichMenuList;
use LINE::Bot::API::Response::TargetLimit;
use LINE::Bot::API::Response::TotalUsage;
use LINE::Bot::API::Response::Token;
use LINE::Bot::API::Response::NumberOfFollowers;
use LINE::Bot::API::Response::UserInteractionStatistics;
use LINE::Bot::API::Response::BotInfo;
use LINE::Bot::API::Response::WebhookInformation;
use LINE::Bot::API::Response::WebhookTest;
use LINE::Bot::API::Response::Followers;
use constant {
DEFAULT_MESSAGING_API_ENDPOINT => 'https://api.line.me/v2/bot/',
DEFAULT_SOCIAL_API_ENDPOINT => 'https://api.line.me/v2/oauth/',
DEFAULT_CONTENT_API_ENDPOINT => 'https://api-data.line.me/v2/bot/',
DEFAULT_OAUTH2_API_ENDPOINT => 'https://api.line.me/oauth2/v2.1/',
};
use Furl;
use Carp 'croak';
use URI;
use URI::Escape;
use URI::QueryParam;
sub new {
my($class, %args) = @_;
my $client = LINE::Bot::API::Client->new(%args);
bless {
client => $client,
channel_secret => $args{channel_secret},
channel_access_token => $args{channel_access_token},
messaging_api_endpoint => $args{messaging_api_endpoint} // DEFAULT_MESSAGING_API_ENDPOINT,
social_api_endpoint => $args{social_api_endpoint} // DEFAULT_SOCIAL_API_ENDPOINT,
content_api_endpoint => $args{content_api_endpoint} // DEFAULT_CONTENT_API_ENDPOINT,
oauth_api_endpoint => $args{oauth_api_endpoint} // DEFAULT_OAUTH2_API_ENDPOINT,
}, $class;
}
sub request {
my ($self, $method, $path, @payload) = @_;
return $self->{client}->$method(
$self->{messaging_api_endpoint} . $path,
@payload,
);
}
sub request_content {
my ($self, $method, $path, @payload) = @_;
return $self->{client}->$method(
$self->{content_api_endpoint} . $path,
@payload,
);
}
sub reply_message {
my($self, $reply_token, $messages) = @_;
my $res = $self->request(
post => 'message/reply',
+{
replyToken => $reply_token,
messages => $messages,
}
);
LINE::Bot::API::Response::Common->new(%{ $res });
}
sub push_message {
my($self, $to_id, $messages, $options) = @_;
my @headers = ();
if ($options && defined($options->{'retry_key'})) {
push @headers, 'X-Line-Retry-Key' => $options->{'retry_key'};
}
my $res = $self->request(
post => 'message/push',
\@headers,
+{
to => $to_id,
messages => $messages,
}
);
LINE::Bot::API::Response::Common->new(%{ $res });
}
sub multicast {
my($self, $to_ids, $messages, $options) = @_;
my @headers = ();
if ($options && defined($options->{'retry_key'})) {
push @headers, 'X-Line-Retry-Key' => $options->{'retry_key'};
}
my $res = $self->request(
post => 'message/multicast',
\@headers,
+{
to => $to_ids,
messages => $messages,
}
);
LINE::Bot::API::Response::Common->new(%{ $res });
}
sub broadcast {
my($self, $messages, $options) = @_;
my @headers = ();
lib/LINE/Bot/API.pm view on Meta::CPAN
my ($self, $rich_menu_id) = @_;
my $res = $self->request(post => "user/all/richmenu/${rich_menu_id}", +{});
LINE::Bot::API::Response::RichMenu->new(%{ $res });
}
sub get_default_rich_menu_id {
my ($self) = @_;
my $res = $self->request(get => "user/all/richmenu");
LINE::Bot::API::Response::RichMenu->new(%{ $res });
}
sub cancel_default_rich_menu {
my ($self) = @_;
my $res = $self->request(delete => "user/all/richmenu");
LINE::Bot::API::Response::RichMenu->new(%{ $res });
}
sub link_rich_menu_to_user {
my ($self, $user_id, $rich_menu_id) = @_;
my $res = $self->request(post => "user/${user_id}/richmenu/${rich_menu_id}", +{});
LINE::Bot::API::Response::RichMenu->new(%{ $res });
}
sub link_rich_menu_to_multiple_users {
my ($self, $user_ids, $rich_menu_id) = @_;
my $res = $self->request(post => "richmenu/bulk/link", +{
richMenuId => $rich_menu_id,
userIds => $user_ids,
});
LINE::Bot::API::Response::RichMenu->new(%{ $res });
}
sub get_rich_menu_id_of_user {
my ($self, $user_id, $rich_menu_id) = @_;
my $res = $self->request(get => "user/${user_id}/richmenu");
LINE::Bot::API::Response::RichMenu->new(%{ $res });
}
sub unlink_rich_menu_from_user {
my ($self, $user_id) = @_;
my $res = $self->request(delete => "user/${user_id}/richmenu");
LINE::Bot::API::Response::RichMenu->new(%{ $res });
}
sub unlink_rich_menu_from_multiple_users {
my ($self, $user_ids) = @_;
my $res = $self->request(post => "richmenu/bulk/unlink", +{
userIds => $user_ids,
});
LINE::Bot::API::Response::RichMenu->new(%{ $res });
}
sub upload_rich_menu_image {
my ($self, $rich_menu_id, $content_type, $file_path) = @_;
if (!$content_type) {
croak 'Need content_type';
}
my $res = $self->{client}->post_image(
$self->{content_api_endpoint} . "richmenu/$rich_menu_id/content",
[
'Content-Type' => $content_type,
],
$file_path
);
if ($res->{http_status} eq '200') {
return LINE::Bot::API::Response::Token->new(%{ $res });
} else {
return LINE::Bot::API::Response::Error->new(%{ $res });
}
}
sub download_rich_menu_image {
my ($self, $rich_menu_id) = @_;
return $self->{client}->get_content(
$self->{content_api_endpoint} . "richmenu/$rich_menu_id/content"
);
}
sub validate_rich_menu_object {
my ($self, $rich_menu) = @_;
my $res = $self->request(post => "richmenu/validate", $rich_menu);
LINE::Bot::API::Response::Common->new(%{ $res });
}
sub issue_channel_access_token {
my ($self, $opts) = @_;
my $res = $self->{client}->post_form(
$self->{social_api_endpoint} . 'accessToken',
[
grant_type => 'client_credentials',
client_id => $opts->{client_id},
client_secret => $opts->{client_secret},
]
);
if ($res->{http_status} eq '200') {
return LINE::Bot::API::Response::Token->new(%{ $res });
} else {
return LINE::Bot::API::Response::Error->new(%{ $res });
}
}
sub issue_channel_access_token_v2_1 {
my ($self, $opts) = @_;
my $res = $self->{client}->post_form(
$self->{oauth_api_endpoint} . 'token',
undef,
[
grant_type => 'client_credentials',
client_assertion_type => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
client_assertion => $opts->{jwt},
]
);
if ($res->{http_status} eq '200') {
return LINE::Bot::API::Response::Token->new(%{ $res });
} else {
return LINE::Bot::API::Response::Error->new(%{ $res });
}
}
sub get_valid_channel_access_token_v2_1 {
my ($self, $opts) = @_;
my $jwt = uri_escape($opts->{jwt});
my $assertion_type = uri_escape('urn:ietf:params:oauth:client-assertion-type:jwt-bearer');
my $res = $self->{client}->get(
$self->{oauth_api_endpoint} . 'tokens/kid' . "?client_assertion_type=$assertion_type&client_assertion=$jwt",
);
if ($res->{http_status} eq '200') {
return LINE::Bot::API::Response::Token->new(%{ $res });
} else {
return LINE::Bot::API::Response::Error->new(%{ $res });
}
}
sub revoke_channel_access_token {
my ($self, $opts) = @_;
my $res = $self->{client}->post_form(
$self->{social_api_endpoint} . 'revoke',
[
access_token => $opts->{access_token},
]
);
if ($res->{http_status} eq '200') {
return LINE::Bot::API::Response::Common->new(%{ $res });
} else {
return LINE::Bot::API::Response::Error->new(%{ $res });
}
}
sub get_number_of_followers {
my ($self, $opts) = @_;
my $date = $opts->{date} or croak "get_number_of_followers: Missing a `date` parameter.";
my $res = $self->request(get => "insight/followers?date=${date}");
LINE::Bot::API::Response::NumberOfFollowers->new(%{ $res });
}
sub get_user_interaction_statistics {
my ($self, $opts) = @_;
my $requestId = $opts->{requestId} or croak "get_user_interaction_statistics: Missing a `requestId` parameter.";
my $res = $self->request(get => "insight/message/event?requestId=${requestId}");
LINE::Bot::API::Response::UserInteractionStatistics->new(%{ $res });
}
sub get_bot_info {
my ($self) = @_;
my $res = $self->request(get => "info");
LINE::Bot::API::Response::BotInfo->new(%{ $res });
}
sub set_webhook_url {
my ($self, $opts) = @_;
defined($opts->{endpoint}) or croak "set_webhook_url: Missing a mandatory parameter: `endpoint`";
my $res = $self->request(
'put' => "channel/webhook/endpoint",
[],
+{ endpoint => $opts->{endpoint} },
);
if ($res->{http_status} eq '200') {
return LINE::Bot::API::Response::Common->new(%{ $res });
} else {
return LINE::Bot::API::Response::Error->new(%{ $res });
}
}
sub get_webhook_endpoint_information {
my ($self) = @_;
my $res = $self->request(get => "channel/webhook/endpoint");
LINE::Bot::API::Response::WebhookInformation->new(%{ $res });
}
sub test_webhook_endpoint {
my ($self, $opts) = @_;
my $req_body = {};
if ($opts->{'endpoint'}) {
$req_body->{'endpoint'} = $opts->{'endpoint'};
}
my $res = $self->request(
'post' => "channel/webhook/endpoint",
[],
$req_body,
);
LINE::Bot::API::Response::WebhookTest->new(%{ $res });
}
sub validate_reply_message_objects {
my($self, $messages) = @_;
my $res = $self->request(
post => 'message/validate/reply',
+{
messages => $messages,
}
);
LINE::Bot::API::Response::Common->new(%{ $res });
}
sub validate_push_message_objects {
my($self, $messages) = @_;
my $res = $self->request(
post => 'message/validate/push',
+{
messages => $messages,
}
);
LINE::Bot::API::Response::Common->new(%{ $res });
}
sub validate_multicast_message_objects {
my($self, $messages) = @_;
my $res = $self->request(
post => 'message/validate/multicast',
+{
messages => $messages,
}
);
LINE::Bot::API::Response::Common->new(%{ $res });
}
sub validate_narrowcast_message_objects {
my($self, $messages) = @_;
my $res = $self->request(
post => 'message/validate/narrowcast',
+{
messages => $messages,
}
);
LINE::Bot::API::Response::Common->new(%{ $res });
}
sub validate_broadcast_message_objects {
lib/LINE/Bot/API.pm view on Meta::CPAN
=head2 C<< get_group_member_profile($group_id, $user_id) >>
Get group user profile information.
my $ret = $bot->get_group_member_profile($group_id, $user_id);
if ($ret->is_success) {
say $ret->display_name;
say $ret->user_id;
say $ret->picture_url;
}
See also the LINE Developers API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#get-group-member-profile>
=head2 C<< get_member_in_room_count($room_id) >>
Gets the count of members in a room. You can get the member in room count even if the user hasn't added the LINE Official Account as a friend or has blocked the LINE Official Account.
my $ret = $bot->get_member_in_room_count($room_id);
if ($ret->is_success) {
say $ret->count;
}
See also the LINE Developers API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#get-members-room-count>
=head2 C<< get_member_in_group_count($group_id) >>
Gets the count of members in a group. You can get the member in group count even if the user hasn't added the LINE Official Account as a friend or has blocked the LINE Official Account.
my $ret = $bot->get_member_in_group_count($group_id);
if ($ret->is_success) {
say $ret->count;
}
See also the LINE Developers API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#get-members-group-count>
=head2 C<< get_group_summary($group_id) >>
Gets the group ID, group name, and group icon URL of a group where the LINE Official Account is a member.
my $ret = $bot->get_group_summary($group_id);
if ($ret->is_success) {
say $ret->group_id;
say $ret->group_name;
say $ret->picture_url;
}
See also the LINE Developers API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#get-group-summary>
=head2 C<< get_room_member_profile($room_id, $user_id) >>
Get room user profile information.
A room is like a group without a group name.
The response is similar to get_group_member_profile.
See also the LINE Developers API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#get-room-member-profile>
=head2 C<< get_number_of_sent_reply_messages($date) >>
Gets the number of messages sent with the C<< /bot/message/reply >> endpoint.
The number of messages retrieved by this operation does not include
the number of messages sent from LINE@ Manager.
The C<< $date >> parameter is "yyyyMMdd" format.
=head2 C<< get_number_of_sent_push_messages($date) >>
Gets the number of messages sent with the C<< /bot/message/push >> endpoint.
The number of messages retrieved by this operation does not include the number of messages sent from LINE@ Manager.
=over 4
=item date
Date the messages were sent
Format: yyyyMMdd (Example: 20191231)
Timezone: UTC+9
=back
=head2 C<< get_number_of_sent_multicast_messages($date) >>
Gets the number of messages sent with the C<< /bot/message/multicast >> endpoint.
The number of messages retrieved by this operation does not include the number of messages sent from LINE@ Manager.
=over 4
=item date
Date the messages were sent
Format: yyyyMMdd (Example: 20191231)
Timezone: UTC+9
=back
=head2 C<< get_number_of_send_broadcast_messages($date) >>
Gets the number of messages sent with the C<< /bot/message/broadcast >> endpoint.
The number of messages retrieved by this operation does not include the number of messages sent from LINE Official Account Manager.
=over 4
=item date
Date the messages were sent
Format: yyyyMMdd (Example: 20191231)
Timezone: UTC+9
=back
=head2 C<< create_rich_menu( $rich_menu_object ) >>
This method corresponds to the API of L<Creating rich menu|https://developers.line.biz/en/reference/messaging-api/#create-rich-menu>
One argument is needed: C<$rich_menu_object>, which is a plain HashRef representing L<rich menu object|https://developers.line.biz/en/reference/messaging-api/#rich-menu-object>
=head2 C<< get_rich_menu( $rich_menu_id ) >>
This method corresponds to the API of L<Get rich menu|https://developers.line.biz/en/reference/messaging-api/#get-rich-menu>
One argument is needed: $rich_menu_id -- which correspond to the
richMenuId property of the object returned by C<create_rich_menu>
method.
=head2 C<< delete_rich_menu( $rich_menu_id ) >>
This method corresponds to the API of L<Delete rich menu|https://developers.line.biz/en/reference/messaging-api/#delete-rich-menu>
One argument is needed: $rich_menu_id -- which correspond to the
richMenuId property of the object returned by C<create_rich_menu>
method.
The return value is an empty RichMenu object -- only status code
matters. Upon successful deletion, status code 200 is returned.
=head2 C<< get_rich_menu_list >>
This method corresponds to the API of L<Get rich menu list|https://developers.line.biz/en/reference/messaging-api/#get-rich-menu-list>
No arguments are needed.
=head2 C<< set_default_rich_menu( $rich_menu_id ) >>
This method corresponds to the API of L<Set default rich menu|https://developers.line.biz/en/reference/messaging-api/#set-default-rich-menu>
One argument is needed: $rich_menu_id -- which correspond to the
richMenuId property of the object returned by C<create_rich_menu>
method.
=head2 C<< get_default_rich_menu_id >>
This method corresponds to the API of L<Get default rich menu ID|https://developers.line.biz/en/reference/messaging-api/#get-default-rich-menu-id>
No arguments are needed. The return value is a RichMenu object with only one property: richMenuId.
=head2 C<< cancel_default_rich_menu >>
lib/LINE/Bot/API.pm view on Meta::CPAN
Otherwise, you may examine the "error" attribute and "error_description" attribute for more information about the error.
=head2 C<< get_valid_channel_access_token_v2_1({ jwt => '...' }) >>
This method corresponds to the API of: L<Get all valid channel access token key IDs v2.1|https://developers.line.biz/en/reference/messaging-api/#get-all-valid-channel-access-token-key-ids-v2-1>
The argument is a HashRef with a pair of mandatory key-values:
{
jwt => "...",
}
This method is for getting all valid channel access token key IDs.
When a 200 OK HTTP response is returned, a new token is issued. In this case, you may want to store the values in "key_ids" attributes of the response object for future use.
Otherwise, you may examine the "error" attribute and "error_description" attribute for more information about the error.
=head2 C<< revoke_channel_access_token({ access_token => "..." }) >>
This method corresponds to the API of: L<Revoke channel access token|https://developers.line.biz/en/reference/messaging-api/#revoke-channel-access-token>
The argument is a HashRef with one pair of mandatory key-values;
{ access_token => "..." }
Upon successful revocation, a 200 OK HTTP response is returned. Otherwise, you my examine the "error" attribute and "error_description" attribute for more information about the error.
=head2 C<< get_number_of_followers({ date => "..." }) >>
This method corresponds to the API of: L<Get number of followers|https://developers.line.biz/en/reference/messaging-api/#get-number-of-followers>
The argument is a HashRef with one pair of mandatory key-values;
{ date => "20191231" }
The formate of date is "yyyyMMdd", that is, year in 4 digits, month in
2 digits, and date-of-month in 2 digits.
Upon successful invocation, a 200 OK HTTP response is
returned. Otherwise, you my examine the "error" attribute and
"error_description" attribute for more information about the error.
The return value C<$res> is a response object with the following read-only accessors
(see the API documentation for the meaning of each.)
$res->status(); #=> Str, one of: "ready", "unready", "out_of_service"
$res->followers(); #=> Num
$res->targetedReaches(); #=> Num
$res->blocks(); #=> Num
Notice that the "status" does not mean HTTP status. To inspect actual
HTTP status, invoke C<$res->http_status()>.
=head2 C<< get_user_interaction_statistics({ requestId => "..." }) >>
Returns statistics about how users interact with narrowcast messages or broadcast messages sent from your LINE Official Account.
See also the LINE Developers API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#get-message-event>
=head2 C<< set_webhook_url({ 'endpoint' => "https://example.com/webhook" }) >>
Sets the webhook endpoint to te given C<endpoint>, which should be an URL string.
See also the LINE Developer API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#set-webhook-endpoint-url>
=head2 C<< get_webhook_endpoint_information() >>
Return the information about webhook endpoint as an response object with following accessors:
$res = $api->get_webhook_endpoint_information();
$res->endpoint(); # URL as a string
$res->active(); # true or false
See also the LINE Developer API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#get-webhook-endpoint-information>
=head2 C<< test_webhook_endpoint({ 'endpoint' => "https://example.com/webhook" }) >>
Checks if the configured webhook endpoint can receive a test webhook event.
See also the LINE Developer API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#get-webhook-endpoint-information>
=head2 C<< validate_reply_message_objects([ $message, ... ] ) >>
Validates that an array of message objects is valid as a value for the messages property of the request body for the Send reply message endpoint.
See also the LINE Developer API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#validate-message-objects-of-reply-message>
=head2 C<< validate_push_message_objects([ $message, ... ] ) >>
Validates that an array of message objects is valid as a value for the messages property of the request body for the Send push message endpoint.
See also the LINE Developer API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#validate-message-objects-of-push-message>
=head2 C<< validate_multicast_message_objects([ $message, ... ] ) >>
Validates that an array of message objects is valid as a value for the messages property of the request body for the Send multicast message endpoint.
See also the LINE Developer API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#validate-message-objects-of-multicast-message>
=head2 C<< validate_narrowcast_message_objects([ $message, ... ] ) >>
Validates that an array of message objects is valid as a value for the messages property of the request body for the Send narrowcast message endpoint.
See also the LINE Developer API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#validate-message-objects-of-narrowcast-message>
=head2 C<< validate_broadcast_message_objects([ $message, ... ] ) >>
Validates that an array of message objects is valid as a value for the messages property of the request body for the Send broadcast message endpoint.
See also the LINE Developer API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#validate-message-objects-of-broadcast-message>
=head2 C<< get_followers({ 'limit' => 100, 'start' => "..." }) >>
Gets the list of User IDs of users who have added LINE Official Account as a friend.
See also the LINE Developer API reference of this method: L<https://developers.line.biz/en/reference/messaging-api/#get-follower-ids>
=head1 How to build a send message object
See the LINE Developers API reference about L<Message objects|https://developers.line.biz/en/reference/messaging-api/#message-objects>
When the C<LINE::Bot::API::Builder::SendMessage> class is used, it is possible easily to build a send message object.
That class supports a fluent interface.
my $messages = LINE::Bot::API::Builder::SendMessage->new(
)->add_text(
text => 'Closing the distance',
)->add_image(
image_url => 'http://example.com/image.jpg',
preview_url => 'http://example.com/image_preview.jpg',
);
$bot->reply_message($reply_token, $messages->build);
=head2 Text type
Build a text type object.
my $messages = LINE::Bot::API::Builder::SendMessage->new(
)->add_text(
text => 'Closing the distance',
);
$bot->reply_message($reply_token, $messages->build);
Build a text message with emojis inside:
my $message = LINE::Bot::API::Builder::SendMessage->new();
$message->add_text(
text => '$ LINE Emoji $',
emojis => [
+{
"index" => 0,
"productId" => "5ac1bfd5040ab15980c9b435",
"emojiId" => "001"
},
+{
"index" => 13,
"productId" => "5ac1bfd5040ab15980c9b435",
"emojiId" => "002"
}
]
);
Since 2020/04/16, text messages may contain LINE emojis. They are identified by (productId, emojiId). For more details about possible values as well as how to use these emojis, please read: L<https://developers.line.biz/en/reference/messaging-api/#te...
=head2 Image type
Build an image type object.
( run in 0.462 second using v1.01-cache-2.11-cpan-524268b4103 )