WebService-HipChat/lib/WebService/HipChat.pm
package WebService::HipChat;
use Moo;
with 'WebService::Client';
our $VERSION = '0.2001'; # VERSION
use Carp qw(croak);
use MIME::Entity;
use JSON qw(encode_json);
has auth_token => ( is => 'ro', required => 1 );
has '+base_url' => ( default => 'https://api.hipchat.com/v2' );
sub BUILD {
my ($self) = @_;
$self->ua->default_header(Authorization => "Bearer " . $self->auth_token);
}
sub get_rooms {
my ($self, %args) = @_;
return $self->get("/room", $args{query} || {});
}
sub get_room {
my ($self, $room) = @_;
croak '$room is required' unless $room;
return $self->get("/room/$room");
}
sub create_room {
my ($self, $data) = @_;
croak '$data is required' unless 'HASH' eq ref $data;
return $self->post("/room", $data);
}
sub update_room {
my ($self, $room, $data) = @_;
croak '$room is required' unless $room;
croak '$data is required' unless 'HASH' eq ref $data;
return $self->put("/room/$room", $data);
}
sub set_topic {
my ($self, $room, $topic) = @_;
croak '$room is required' unless $room;
croak '$topic is required' unless $topic;
if ( 'HASH' eq ref $topic ) {
$topic = $topic->{topic} or croak '$topic is required';
}
return $self->put("/room/$room/topic", { topic => $topic });
}
sub delete_room {
my ($self, $room) = @_;
croak '$room is required' unless $room;
return $self->delete("/room/$room");
}
sub send_notification {
my ($self, $room, $data) = @_;
croak '$room is required' unless $room;
croak '$data is required' unless 'HASH' eq ref $data;
return $self->post("/room/$room/notification", $data);
}
sub get_webhooks {
my ($self, $room, %args) = @_;
croak '$room is required' unless $room;
return $self->get("/room/$room/webhook", $args{query} || {});
}
sub get_webhook {
my ($self, $room, $webhook_id) = @_;
croak '$room is required' unless $room;
croak '$webhook_id is required' unless $webhook_id;
return $self->get("/room/$room/webhook/$webhook_id")
}
sub create_webhook {
my ($self, $room, $data) = @_;
croak '$room is required' unless $room;
croak '$data is required' unless 'HASH' eq ref $data;
return $self->post("/room/$room/webhook", $data);
}
sub delete_webhook {
my ($self, $room, $webhook_id) = @_;
croak '$room is required' unless $room;
croak '$webhook_id is required' unless $webhook_id;
return $self->delete("/room/$room/webhook/$webhook_id");
}
sub get_members {
my ($self, $room, %args) = @_;
croak '$room is required' unless $room;
return $self->get("/room/$room/member", $args{query} || {});
}
sub add_member {
my ($self, $room, $user) = @_;
croak '$room is required' unless $room;
croak '$user is required' unless $user;
return $self->put("/room/$room/member/$user", {});
}
sub remove_member {
my ($self, $room, $user) = @_;
croak '$room is required' unless $room;
croak '$user is required' unless $user;
return $self->delete("/room/$room/member/$user");
}
sub get_users {
my ($self, %args) = @_;
return $self->get("/user", $args{query} || {});
}
sub get_user {
my ($self, $user) = @_;
croak '$user is required' unless $user;
return $self->get("/user/$user");
}
sub delete_user {
my ($self, $user) = @_;
croak '$user is required' unless $user;
return $self->delete("/user/$user");
}
sub send_private_msg {
my ($self, $user, $data) = @_;
croak '$user is required' unless $user;
croak '$data is required' unless 'HASH' eq ref $data;
return $self->post("/user/$user/message", $data);
}
sub send_room_msg {
my ($self, $room, $data) = @_;
croak '$room is required' unless $room;
croak '$data is required' unless 'HASH' eq ref $data;
return $self->post("/room/$room/message", $data);
}
sub get_private_history {
my ($self, $user, %args) = @_;
croak '$user is required' unless $user;
return $self->get("/user/$user/history", $args{query} || {});
}
sub get_emoticons {
my ($self, %args) = @_;
return $self->get("/emoticon", $args{query} || {});
}
sub get_emoticon {
my ($self, $emoticon) = @_;
croak '$emoticon is required' unless $emoticon;
return $self->get("/emoticon/$emoticon");
}
sub get_room_history {
my ($self, $room, %args) = @_;
croak '$room is required' unless $room;
return $self->get("/room/$room/history/latest", $args{query} || {});
}
sub share_link {
my ($self, $room, $data) = @_;
croak '$room is required' unless $room;
croak '$data is required' unless 'HASH' eq ref $data;
return $self->post("/room/$room/share/link", $data);
}
sub next {
my ($self, $data) = @_;
croak '$data is required' unless 'HASH' eq ref $data;
my $next = $data->{links}{next} or return undef;
return $self->get($next);
}
sub share_file {
my ($self, $destination, $data) = @_;
croak '$destination is required' unless $destination;
croak '$data is required' unless 'HASH' eq ref $data;
# Users may be referenced by '@' name OR email address per
# https://www.hipchat.com/docs/apiv2/method/share_file_with_user
my $api_type = ( $destination =~ /\@/ ) ? 'user' : 'room';
my $msg = $data->{message};
my $file = $data->{file};
if (! -f $file) {
warn "File '$file' doesn't exist\n";
return;
}
my $boundary = 'boundary1234567890';
my $Mime = MIME::Entity->build(
Type => 'multipart/related',
Boundary => $boundary,
);
if ( $msg ) {
my $msg_json = encode_json({ message => $msg });
$Mime->attach(
Type => 'application/json',
Encoding => '7bit',
Data => $msg_json,
);
}
$Mime->attach(
Path => $file,
Disposition => 'attachment; name="file"'
);
$Mime->make_multipart();
return $self->post("/$api_type/$destination/share/file",
$Mime->stringify_body(),
headers => {
'content_type' => "multipart/related; boundary=\"$boundary\"",
},
);
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
WebService::HipChat
=head1 VERSION
version 0.2001
=head1 SYNOPSIS
my $hc = WebService::HipChat->new(auth_token => 'abc');
$hc->send_notification('Room42', { color => 'green', message => 'allo' });
# get paged results:
my $res = $hc->get_emoticons;
my @emoticons = @{ $res->{items} };
while ($res = $hc->next($res)) {
push @emoticons, @{ $res->{items} };
}
=head1 DESCRIPTION
This module provides bindings for the
L<HipChat API v2|https://www.hipchat.com/docs/apiv2>.
It also provides the command line utility L<hipchat-send>.
=head1 METHODS
All methods return a hashref.
The C<$room> param can be the id or name of the room.
The C<$user> param can be the id, email address, or @mention name of the user.
If a resource does not exist for the given parameters, undef is returned.
=head2 get_rooms
get_rooms()
get_rooms(query => { 'start-index' => 0, 'max-results' => 100 });
Example response:
{
items => [
{
id => 2,
links => {
self => "https://hipchat.com/v2/room/2",
webhooks => "https://hipchat.com/v2/room/2/webhook",
},
name => "General Discussion",
},
{
id => 3,
links => {
self => "https://hipchat.com/v2/room/3",
webhooks => "https://hipchat.com/v2/room/3/webhook",
},
name => "Important Stuff",
},
links => { self => "https://hipchat.com/v2/room" },
maxResults => 100,
startIndex => 0,
}
=head2 get_room
get_room($room)
Example response:
{
created => "2014-06-25T02:28:04",
guest_access_url => undef,
id => 2,
is_archived => 0,
is_guest_accessible 0,
last_active => "2014-07-19T02:40:55+00:00",
links => {
self => "https://hipchat.com/v2/room/2",
webhooks => "https://hipchat.com/v2/room/2/webhook",
},
name => "General Discussion",
owner => {
id => 1,
links => { self => "https://hipchat.com/v2/user/1" },
mention_name => "bob",
name => "Bob Williams",
},
participants => [],
privacy => "public",
statistics => {
links => { self => "https://hipchat.com/v2/room/2/statistics" },
},
topic => "hipchat commands",
xmpp_jid => "1_general_discussion\@conf.btf.hipchat.com",
}
=head2 create_room
create_room({ name => 'monkeys' })
Example response:
{
id => 46,
links => { self => "https://hipchat.com/v2/room/46" },
}
=head2 update_room
update_room($room, {
is_archived => JSON::false,
is_guest_accessible => JSON::false,
name => "Jokes",
owner => { id => 17 },
privacy => "public",
topic => "funny jokes",
});
=head2 set_topic
set_topic($room, 'new topic');
=head2 delete_room
delete_room($room)
=head2 send_notification
send_notification($room, { color => 'green', message => 'allo' });
=head2 get_webhooks
get_webhooks($room)
get_webhooks($room, query => { 'start-index' => 0, 'max-results' => 100 });
Example response:
{
items => [
{
event => "room_message",
id => 1,
links => { self => "https://hipchat.com/v2/room/API/webhook/1" },
name => "hook1",
pattern => undef,
url => "http://yourdomain.org/hipchat-webhook",
},
],
links => { self => "https://hipchat.com/v2/room/API/webhook" },
maxResults => 100,
startIndex => 0,
}
=head2 get_webhook
get_webhook($room, $webhook_id);
=head2 create_webhook
create_webhook($room, {
url => 'http://yourdomain.org/hipchat-webhook'
event => 'room_message',
name => 'hook1',
});
=head2 delete_webhook
delete_webhook($room, $webhook_id);
=head2 send_private_msg
send_private_msg($user, { message => 'allo' });
=head2 send_room_msg
send_room_msg($room, { message => 'allo' });
=head2 get_private_history
$hc->get_private_history($user)
$hc->get_private_history($user, query => { 'max-results' => 5 });
Example response:
{
items [
[0] {
date "2014-11-13T10:48:33.322506+00:00",
from {
id 123456,
links {
self "https://api.hipchat.com/v2/user/123456"
},
mention_name "Bob",
name "Bob Williams"
},
id "38988c8c-9120-44ce-87c5-6731a7a3b6",
mentions [],
message "heres a message and a link http://www.sun.com/",
type "message"
},
[1] {
date "2014-11-13T10:49:02.377436+00:00",
from {
id 123456,
links {
self "https://api.hipchat.com/v2/user/123456"
},
mention_name "Bob",
name "Bob Williams"
},
id "c1f47537-6506-4f46-b820-eaade5adc5",
mentions [],
message "A message",
type "message"
}
],
links {
self "https://api.hipchat.com/v2/user/123456/history"
},
maxResults 5,
startIndex 0
}
=head2 get_members
get_members($room);
get_members($room, query => { 'start-index' => 0, 'max-results' => 100 });
Example response:
{
items => [
{
id => 73,
links => { self => "https://hipchat.com/v2/user/73" },
mention_name => "momma",
name => "Yo Momma",
},
{
id => 23,
links => { self => "https://hipchat.com/v2/user/23" },
mention_name => "jackie",
name => "Jackie Chan",
},
],
links => { self => "https://hipchat.com/v2/room/Test/member" },
maxResults => 100,
startIndex => 0,
}
=head2 add_member
Adds a user to a room.
add_member($room, $user);
=head2 remove_member
Removes a user from a room.
remove_member($room, $user);
=head2 get_users
get_users()
get_users(query => { 'start-index' => 0, 'max-results' => 100 });
Example response:
{
items => [
{
id => 1,
links => { self => "https://hipchat.com/v2/user/1" },
mention_name => "magoo",
name => "Matt Wondercookie",
},
{
id => 3,
links => { self => "https://hipchat.com/v2/user/3" },
mention_name => "racer",
name => "Brian Wilson",
},
],
links => { self => "https://hipchat.com/v2/user" },
maxResults => 100,
startIndex => 0,
}
=head2 get_user
get_user($user)
Example response:
{
created => "2014-06-20T03:00:28",
email => 'matt@foo.com',
group => {
id => 1,
links => { self => "https://hipchat.com/v2/group/1" },
name => "Everyone",
},
id => 1,
is_deleted => 0,
is_group_admin => 1,
is_guest => 0,
last_active => 1405718128,
links => { self => "https://hipchat.com/v2/user/1" },
mention_name => "magoo",
name => "Matt Wondercookie",
photo_url => "https://hipchat.com/files/photos/1/abc.jpg",
presence => {
client => {
type => "http://hipchat.com/client/linux",
version => 98,
},
idle => 3853,
is_online => 1,
show => "away",
},
timezone => "America/New_York",
title => "Hacker",
xmpp_jid => '1_1@chat.hipchat.com',
}
=head2 delete_user
delete_user($user)
=head2 get_emoticons
get_emoticons()
get_emoticons(query => { 'start-index' => 0, 'max-results' => 100 });
Example response:
{
items => [
{
id => 166,
links => { self => "https://hipchat.com/v2/emoticon/166" },
shortcut => "dog",
url => "https://hipchat.com/files/img/emoticons/1/dog.png",
},
],
links => { self => "https://hipchat.com/v2/emoticon" },
maxResults => 100,
startIndex => 0,
}
=head2 get_emoticon
get_emoticon()
Example response:
{
creator => {
id => 11,
links => { self => "https://hipchat.com/v2/user/11" },
mention_name => "bob",
name => "Bob Ray",
},
height => 30,
id => 203,
links => { self => "https://hipchat.com/v2/emoticon/203" },
shortcut => "dog",
url => "https://hipchat.com/files/img/emoticons/1/dog.png",
width => 30,
}
=head2 get_room_history
$hc->get_room_history($room)
$hc->get_room_history($room, { 'max-results' => 5 });
Example response:
{
items [
[0] {
date "2014-11-13T10:48:33.322506+00:00",
from {
id 123456,
links {
self "https://api.hipchat.com/v2/user/123456"
},
mention_name "Bob",
name "Bob Williams"
},
id "38988c8c-9120-44ce-87c5-6731a7a3b6",
mentions [],
message "heres a message and a link http://www.sun.com/",
type "message"
},
[1] {
date "2014-11-13T10:49:02.377436+00:00",
from {
id 123456,
links {
self "https://api.hipchat.com/v2/user/123456"
},
mention_name "Bob",
name "Bob Williams"
},
id "c1f47537-6506-4f46-b820-eaade5adc5",
mentions [],
message "A message",
type "message"
}
],
links {
self "https://api.hipchat.com/v2/room/XXX/history/latest"
},
maxResults 2,
startIndex 0
}
=head2 share_link
$hc->share_link($room, { message => 'msg', link => 'http://www.sun.com' });
=head2 share_file
$hc->share_file($destination, { message => 'msg', file => '/tmp/file.png' });
Shares files with $destination, whether that be a room OR a user. If sent to a user, make sure it is their '@' name OR email address. Otherwise we'll think it is a room.
For example: '@JohnQPublic' OR 'johnq@public.test instead of 'SomeRoom'
=head2 next
next($data)
Returns the next page of data for paginated responses.
Example:
my $res = $hc->get_emoticons;
my @emoticons = @{ $res->{items} };
while ($res = $hc->next($res)) {
push @emoticons, @{ $res->{items} };
}
=head1 CONTRIBUTORS
=over
=item *
Andy Baugh <L<https://github.com/troglodyne>>
=item *
Chris C. <L<https://github.com/centreti>>
=item *
Chris Hughes <L<https://github.com/chrisspang>>
=item *
Ken-ichi Mito <L<https://github.com/mittyorz>>
=item *
Tim Man <L<https://github.com/teebszet>>
=back
=head1 AUTHOR
Naveed Massjouni <naveed@vt.edu>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2014 by Naveed Massjouni.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut