API-Instagram

 view release on metacpan or  search on metacpan

CHANGES  view on Meta::CPAN

  Date : 2014-08-19 22:37:32 +0000

    Many bug fixes; Better cache management; Starting version 0.008' 

  Change: 3d4f7c2554f544dfbf1607279d96ad908ec7a483
  Author: Gabriel Vieira <gabriel.vieira@gmail.com>
  Date : 2014-08-17 11:26:38 +0000

    Fixed profile_picture method on API::Instagram::User. Objects
    creation returns undef when Instagram returns an error during
    request. API::Instagram::User keeps user previous data when attempt
    to reload fails. Starting version 0.007. 

  Change: ee143d09d124ba0f37b4710008b43d79d786ff73
  Author: Gabriel Vieira <gabriel.vieira@gmail.com>
  Date : 2014-08-17 01:37:20 +0000

    Removed use API::Instagram::Direct request 

  Change: 905fe6e5d9a8c1a161372a85a297e785f11113b0
  Author: Gabriel Vieira <gabriel.vieira@gmail.com>

lib/API/Instagram.pm  view on Meta::CPAN



sub get_access_token {
	my $self = shift;

	my @access_token_fields = qw(client_id redirect_uri grant_type client_secret code);
	for ( @access_token_fields ) {
		carp "ERROR: $_ required for generating access token." and return unless defined $self->$_;
	}

	my $data = { map { $_ => $self->$_ } @access_token_fields };
	my $json = $self->_request( 'post', $self->_access_token_url, $data, { token_not_required => 1 } );

	wantarray ? ( $json->{access_token}, $self->user( $json->{user} ) ) : $json->{access_token};
}


sub media { shift->_get_obj( 'Media', 'id', shift ) }

sub user { shift->_get_obj( 'User', 'id', shift // 'self' ) }

sub location { shift->_get_obj( 'Location', 'id', shift, 1 ) }

lib/API/Instagram.pm  view on Meta::CPAN

}

sub _comment { shift->_get_obj( 'Media::Comment', 'id', shift ) }

#####################################################
# Returns cached wanted object or creates a new one #
#####################################################
sub _get_obj {
	my ( $self, $type, $key, $code, $optional_code ) = @_;

	my $data = { $key => $code };
	$data = $code if ref $code eq 'HASH';
	$code = $data->{$key};

	# Returns if CODE is not optional and not defined or if it's not a string
	return if (!$optional_code and !defined $code) or ref $code;

	# Code used as cache key
	my $cache_code = md5_hex( $code // $data);

	# Returns cached value or creates a new object
	my $return = $self->_cache($type)->{$cache_code} //= ("API::Instagram::$type")->new( $data );

	# Deletes cache if no-cache is set
	delete $self->_cache($type)->{$cache_code} if $self->no_cache;

	return $return;
}

###################################
# Returns a list of Media Objects #
###################################

lib/API/Instagram.pm  view on Meta::CPAN

	my $self   = shift;
	my $params = shift;
	my $opts   = shift;

	my $url      = delete $params->{url} || return [];
	my $count    = $params->{count} // 999_999_999;
	$count       = 999_999_999 if $count < 0;
	$params->{count} = $count;

	my $request = $self->_request( 'get', $url, $params, $opts );
	my $data    = $request->{data};

	# Keeps requesting if total items is less than requested
	# and still there is pagination
	while ( my $pagination = $request->{pagination} ){

		last if     @$data >= $count;
		last unless $pagination->{next_url};

		$opts->{prepared_url} = 1;
		$request = $self->_request( 'get', $pagination->{next_url}, $params, $opts );
		push @$data, @{ $request->{data} };
	}

	return @$data;
}

##############################################################
# Requests the data from the given URL with QUERY parameters #
##############################################################
sub _request {
	my ( $self, $method, $url, $params, $opts ) = @_;

	# Verifies access requirements
	unless ( defined $self->access_token ) {
		if ( !$opts->{token_not_required} or !defined $self->client_id ) {
			carp "A valid access_token is required";
			return {}
		}

lib/API/Instagram.pm  view on Meta::CPAN


	# Verifies meta node
	my $meta = $res->{meta};
	carp "$meta->{error_type}: $meta->{error_message}" if $meta->{code} ne '200';

use Data::Dumper;
# die Dumper $res;
	$res;
}

sub _request_data { shift->_request(@_)->{data} || {} }

sub _del  { shift->_request_data( 'delete', @_ ) }
sub _get  { shift->_request_data( 'get',    @_ ) }
sub _post { shift->_request_data( 'post',   @_ ) }

################################
# Returns requested cache hash #
################################
sub _cache { shift->_obj_cache->{ shift() } }


1;

__END__

lib/API/Instagram/Location.pm  view on Meta::CPAN


# ABSTRACT: Instagram Location Object

use Moo;
use Carp;

has id        => ( is => 'ro', predicate => 1 );
has latitude  => ( is => 'lazy' );
has longitude => ( is => 'lazy' );
has name      => ( is => 'lazy' );
has _data     => ( is => 'rwp', lazy => 1, builder => 1, clearer => 1 );


sub recent_medias {
	my $self = shift;

	carp "Not available for location with no ID." and return [] unless $self->has_id;

	my $url  = sprintf "locations/%s/media/recent", $self->id;
	API::Instagram->instance->_medias( $url, { @_%2?():@_ } );
}

sub _build_name      { shift->_data->{name}      }
sub _build_latitude  { shift->_data->{latitude}  }
sub _build_longitude { shift->_data->{longitude} }

sub _build__data {
	my $self = shift;
	carp "Not available for location with no ID." and return {} unless $self->has_id;
	my $url  = sprintf "locations/%s", $self->id;
	API::Instagram->instance->_get( $url );
}

1;

__END__

lib/API/Instagram/Media.pm  view on Meta::CPAN

has filter         => ( is => 'lazy' );
has images         => ( is => 'lazy' );
has videos         => ( is => 'lazy' );
has user           => ( is => 'lazy', coerce => \&_coerce_user           );
has tags           => ( is => 'lazy', coerce => \&_coerce_tags           );
has location       => ( is => 'lazy', coerce => \&_coerce_location       );
has users_in_photo => ( is => 'lazy', coerce => \&_coerce_users_in_photo );
has caption        => ( is => 'lazy', coerce => sub { $_[0]->{text} if $_[0] and ref $_[0] eq 'HASH' } );
has created_time   => ( is => 'lazy', coerce => sub { Time::Moment->from_epoch( $_[0] ) } );
has _api           => ( is => 'lazy' );
has _data          => ( is => 'rwp', lazy => 1, builder => 1, clearer => 1 );

sub likes {
	my $self = shift;
	$self->_clear_data if shift;
	$self->_data->{likes}->{count}
}

sub last_likes {
	my $self = shift;
	$self->_clear_data if shift;
	my $api  = $self->_api;
	[ map { $api->user($_) } @{ $self->_data->{likes}->{data} } ]
}

sub get_likes {
	my $self = shift;
	my %opts = @_;
	my $url  = sprintf "media/%s/likes", $self->id;
	my $api  = $self->_api;
	[ map { $api->user($_) } $api->_get_list( { %opts, url => $url } ) ]
}

lib/API/Instagram/Media.pm  view on Meta::CPAN

}

sub dislike {
	my $self = shift;
	my $url  = sprintf "media/%s/likes", $self->id;
	$self->_api->_del( $url )
}

sub comments {
	my $self = shift;
	$self->_clear_data if shift;
	$self->_data->{comments}->{count}
}

sub last_comments {
	my $self = shift;
	$self->_clear_data if shift;
	my $api  = $self->_api;
	[ map { $api->_comment( { %$_, media => $self } ) } @{ $self->_data->{comments}->{data} } ]
}

sub get_comments {
	my $self = shift;
	my %opts = @_;
	my $url  = sprintf "media/%s/comments", $self->id;
	my $api  = $self->_api;
	[ map { $api->_comment( { %$_, media => $self } ) } $api->_get_list( { %opts, url => $url } ) ]
}

sub comment {
	my $self = shift;
	my $text = shift;
	my $url  = sprintf "media/%s/comments", $self->id;
	$self->_api->_post( $url, { text => $text } )
}


sub _build__api           { API::Instagram->instance       }
sub _build_user           { shift->_data->{user}           }
sub _build_tags           { shift->_data->{tags}           }
sub _build_location       { shift->_data->{location}       }
sub _build_users_in_photo { shift->_data->{users_in_photo} }
sub _build_type           { shift->_data->{type}           }
sub _build_link           { shift->_data->{link}           }
sub _build_filter         { shift->_data->{filter}         }
sub _build_images         { shift->_data->{images}         }
sub _build_videos         { shift->_data->{videos}         }
sub _build_caption        { shift->_data->{caption }       }
sub _build_created_time   { shift->_data->{created_time}   }

sub _build__data {
	my $self = shift;
	my $url  = sprintf "media/%s", $self->id;
	$self->_api->_get( $url );
}

############################################################
# Attributes coercion that API::Instagram object reference #
############################################################
sub _coerce_user     { API::Instagram->instance->user    ( $_[0] ) };
sub _coerce_location { API::Instagram->instance->location( $_[0] ) if $_[0] };

sub _coerce_tags {
	my $data = $_[0];
	return if ref $data ne 'ARRAY';
	[ map { API::Instagram->instance->tag($_) } @$data ]
};
	
sub _coerce_users_in_photo {
	my $data = $_[0];
	return if ref $data ne 'ARRAY';
	[
		map {{
			user     => API::Instagram->instance->user( $_->{user} ),
			position => $_->{position},
		}} @$data
	]
};


1;

__END__

=pod

lib/API/Instagram/Media.pm  view on Meta::CPAN


=head2 likes

	printf "Total Likes: %d\n", $media->likes; # Total likes when object was created

	or

	printf "Total Likes: %d\n", $media->likes(1); # Up to date total likes

Returns media total likes.
If you set C<1> as parameter it will renew all media data and return an up-do-date total likes.

Note: C<1> as parameter also updates total comments, last likes and last comments.

=head2 last_likes

	for my $user ( @{ $media->last_likes } ) {
		say $user->username;
	}

Returns a list of C<API::Instagram::User> of the last users who liked the media.
If you set C<1> as parameter it will renew all media data and return an up-do-date list.

Note: C<1> as parameter also updates total likes, total comments and last comments.

=head2 get_likes

	my @likers = $media->get_likes( count => 5 );

Returns a list of L<API::Instagram::User> objects of users who liked the media.

Accepts C<count>.

lib/API/Instagram/Media.pm  view on Meta::CPAN


=head2 comments

	printf "Total Comments: %d\n", $media->comments; # Total comments when object was created

	or

	printf "Total Comments: %d\n", $media->comments(1); # Up to date total comments

Returns media total comments.
If you set C<1> as parameter it will renew all media data and return an up-do-date total comments.

Note: C<1> as parameter also updates total likes, last likes and last comments.

=head2 last_comments

	for my $comment ( @{ $media->last_comments } ) {
		printf "%s: %s\n", $comment->from->username, $comment->text;
	}

Returns a list of C<API::Instagram::Media::Comment> of the last comments on the media.
If you set C<1> as parameter it will renew all media data and return an up-do-date list.

Note: C<1> as parameter also updates total likes, total comments and last likes.

=head2 get_comments

	my @comments = $media->get_comments( count => 5 );

Returns a list of L<API::Instagram::Media::Comment> objects of the media.

Accepts C<count>.

lib/API/Instagram/Tag.pm  view on Meta::CPAN

package API::Instagram::Tag;

# ABSTRACT: Instagram Tag Object

use Moo;

has name  => ( is => 'ro', required => 1 );
has _data => ( is => 'rwp', lazy => 1, builder => 1, clearer => 1 );

sub media_count {
	my $self = shift;
	$self->_clear_data if shift;
	$self->_data->{media_count}
}


sub recent_medias {
	my $self = shift;
	my $url  = sprintf "tags/%s/media/recent", $self->name;
	API::Instagram->instance->_medias( $url, { @_%2?():@_ } );
}

sub _build__data {
	my $self = shift;
	my $url  = sprintf "tags/%s", $self->name;
	API::Instagram->instance->_get( $url );
}

1;

__END__

=pod

lib/API/Instagram/User.pm  view on Meta::CPAN

use Moo;
use Carp;

has id              => ( is => 'ro', required => 1 );
has username        => ( is => 'lazy' );
has full_name       => ( is => 'lazy' );
has bio             => ( is => 'lazy' );
has website         => ( is => 'lazy' );
has profile_picture => ( is => 'lazy' );
has _api            => ( is => 'lazy' );
has _data           => ( is => 'rwp', lazy => 1, builder => 1, clearer => 1 );

sub media {
	my $self = shift;
	$self->_clear_data if shift;
	return $_->{media} for $self->_data->{counts}
}

sub follows {
	my $self = shift;
	$self->_clear_data if shift;
	return $_->{follows} for $self->_data->{counts}
}

sub followed_by {
	my $self = shift;
	$self->_clear_data if shift;
	return $_->{followed_by} for $self->_data->{counts}
}


sub feed {
	my $self = shift;
	my @list = $self->_self_requests( 'feed', '/users/self/feed', @_ ) or return;
	[ map { $self->_api->media($_) } @list ];
}


lib/API/Instagram/User.pm  view on Meta::CPAN

	my $self = shift;
	my $opts = shift;

	$opts->{profile_picture} //= delete $opts->{profile_pic_url} if exists $opts->{profile_pic_url};

	return $opts;
}


sub _build__api            { API::Instagram->instance        }
sub _build_username        { shift->_data->{username}        }
sub _build_full_name       { shift->_data->{full_name}       }
sub _build_bio             { shift->_data->{bio}             }
sub _build_website         { shift->_data->{website}         }
sub _build_profile_picture { shift->_data->{profile_picture} }

sub _build__data {
	my $self = shift;
	my $url  = sprintf "users/%s", $self->id;
	$self->_api->_get( $url );
}



1;

__END__

t/00-comment.t  view on Meta::CPAN


my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
            no_cache      => 1,
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });

my $media = $api->media(123);
isa_ok( $media, 'API::Instagram::Media' );

my $get_comments = $media->get_comments;
is ref $get_comments, 'ARRAY';

my $comment = $get_comments->[0];
isa_ok( $comment, 'API::Instagram::Media::Comment' );

t/00-comment.t  view on Meta::CPAN

is $time->year, 2010;

is $comment->media->id, 123;
ok $comment->remove;

__DATA__
{
    "meta": {
        "code": 200
    },
    "data": [
        {
            "created_time": "1280780324",
            "text": "Really amazing photo!",
            "from": {
                "username": "snoopdogg",
                "profile_picture": "http://images.instagram.com/profiles/profile_16_75sq_1305612434.jpg",
                "id": "1574083",
                "full_name": "Snoop Dogg"
            },
            "id": "420"

t/00-instagram.t  view on Meta::CPAN

use Test::MockObject::Extends; 

use JSON;
use Furl;
use Furl::Response;
use Inline::Files;

use API::Instagram;
use Test::More tests => 17;

my $data = join '', <DATA>;
my $ua   = Test::MockObject::Extends->new( Furl->new() );
my $res  = Test::MockObject::Extends->new( Furl::Response->new( 1, 200, 'OK', {}, $data) );

$ua->mock('get',  sub { $res });
$ua->mock('post', sub { $res });

my $api = API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
            no_cache      => 1,
            _ua           => $ua,

t/00-instagram.t  view on Meta::CPAN

is $api2->popular_medias->[0]->user->username, 'cocomiin';

__DATA__
{
    "meta": {
        "code": 200
    },
    "pagination": {
        "next_url": "http://localhost"
    },
    "data":[1],
    "access_token": 123456789,
    "user": {
        "id": "1574083",
        "username": "snoopdogg",
        "full_name": "Snoop Dogg",
        "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1574083_75sq_1295469061.jpg",
        "bio": "This is my bio",
        "website": "http://snoopdogg.com",
        "counts": {
            "media": 1320,

t/00-instagram.t  view on Meta::CPAN

            "followed_by": 3410
        }
    }
}

__POPULAR__
{
    "meta": {
        "code": 200
    },
    "data": [{
            "type": "image",
            "users_in_photo": [],
            "filter": "Gotham",
            "tags": [],
            "comments": {},
            "caption": {
                "created_time": "1296656006",
                "text": "ハート♥アプリ始めて使ってみたょ(^^)",
                "from": {
                    "username": "cocomiin",
                    "full_name": "",
                    "type": "user",
                    "id": "1127272"
                },
                "id": "26329105"
            },
            "likes": {
                "count": 35,
                "data": [{
                    "username": "mikeyk",
                    "full_name": "Kevin S",
                    "id": "4",
                    "profile_picture": "..."
                }]
            },
            "link": "http://instagr.am/p/BV5v_/",
            "user": {
                "username": "cocomiin",
                "full_name": "Cocomiin",

t/00-instagram.t  view on Meta::CPAN

                },
                "standard_resolution": {
                    "url": "http://distilleryvesper9-13.ak.instagram.com/090d06dad9cd11e2aa0912313817975d_101.mp4",
                    "width": 640,
                    "height": 640
                },
                "users_in_photo": null,
                "filter": "Vesper",
                "tags": [],
                "comments": {
                    "data": [{
                        "created_time": "1279332030",
                        "text": "Love the sign here",
                        "from": {
                            "username": "mikeyk",
                            "full_name": "Mikey Krieger",
                            "id": "4",
                            "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1242695_75sq_1293915800.jpg"
                        },
                        "id": "8"
                    }, {

t/00-instagram.t  view on Meta::CPAN

                            "id": "3",
                            "profile_picture": "..."
                        },
                        "id": "3"
                    }],
                    "count": 2
                },
                "caption": null,
                "likes": {
                    "count": 1,
                    "data": [{
                        "username": "mikeyk",
                        "full_name": "Mikeyk",
                        "id": "4",
                        "profile_picture": "..."
                    }]
                },
                "link": "http://instagr.am/p/D/",
                "user": {
                    "username": "kevin",
                    "full_name": "Kevin S",

t/00-location.t  view on Meta::CPAN

use Test::More tests => 6;

my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_get_list', sub { [] });

my $location = $api->location('1');
isa_ok( $location, 'API::Instagram::Location' );

is $location->id, 1;
is $location->name, 'Dogpatch Labs';
is $location->latitude, 37.782;
is $location->longitude, -122.387;
is ref $location->recent_medias, 'ARRAY';

__DATA__
{
    "data": {
        "id": "1",
        "name": "Dogpatch Labs",
        "latitude": 37.782,
        "longitude": -122.387
    }
}

t/00-media.t  view on Meta::CPAN


use JSON;
use API::Instagram;
use Test::More tests => 27;

my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123', client_secret => '456', redirect_uri  => 'http://localhost', no_cache      => 1, })
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_get_list', sub { {} });

# First Object
my $media = $api->media(3);
isa_ok( $media, 'API::Instagram::Media' );

is $media->id, 3;
is $media->type, 'video';
is $media->filter, 'Vesper';

t/00-media.t  view on Meta::CPAN

is ref $tags, 'ARRAY';
isa_ok( $tags->[0], 'API::Instagram::Tag' );

my $location = $media->location;
isa_ok( $location, 'API::Instagram::Location');
is $location->latitude, 0.2;

isa_ok( $media->created_time, 'Time::Moment' );
is $media->created_time->year, 2010;

$json = decode_json $data;
is $media->likes(1), 1;
is $media->comments(1), 2;

is ref $media->last_likes(1), 'ARRAY';
is ref $media->last_comments(1), 'ARRAY';


__DATA__
{
    "data": {
        "type": "video",
        "videos": {
            "low_resolution": {
                "url": "http://distilleryvesper9-13.ak.instagram.com/090d06dad9cd11e2aa0912313817975d_102.mp4",
                "width": 480,
                "height": 480
            },
            "standard_resolution": {
                "url": "http://distilleryvesper9-13.ak.instagram.com/090d06dad9cd11e2aa0912313817975d_101.mp4",
                "width": 640,
                "height": 640
            }
        },
        "users_in_photo": null,
        "filter": "Vesper",
        "tags": ["test"],
        "comments": {
            "data": [{
                "created_time": "1279332030",
                "text": "Love the sign here",
                "from": {
                    "username": "mikeyk",
                    "full_name": "Mikey Krieger",
                    "id": "4",
                    "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1242695_75sq_1293915800.jpg"
                },
                "id": "8"
            },

t/00-media.t  view on Meta::CPAN

                    "id": "3",
                    "profile_picture": "..."
                },
                "id": "3"
            }],
            "count": 2
        },
        "caption": null,
        "likes": {
            "count": 1,
            "data": [{
                "username": "mikeyk",
                "full_name": "Mikeyk",
                "id": "4",
                "profile_picture": "..."
            }]
        },
        "link": "http://instagr.am/p/D/",
        "user": {
            "username": "kevin",
            "full_name": "Kevin S",

t/00-search.t  view on Meta::CPAN

use Test::More tests => 4;

my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });

my $search = $api->search('tag');
isa_ok( $search, 'API::Instagram::Search' );

my $tags = $search->find( q => 'x' );
is ref $tags, 'ARRAY';

isa_ok( $tags->[0], 'API::Instagram::Tag' );
is $tags->[3]->name, 'snowydays';

__DATA__
{
    "data": [
        {
            "media_count": 43590,
            "name": "snowy"
        },
        {
            "media_count": 3264,
            "name": "snowyday"
        },
        {
            "media_count": 1880,

t/00-tag.t  view on Meta::CPAN

use Test::More tests => 5;

my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_get_list', sub { [] });

my $tag = $api->tag('nofilter');
isa_ok( $tag, 'API::Instagram::Tag' );

is $tag->name, 'nofilter';
is $tag->media_count, 472;
is $tag->media_count(1), 472;
is ref $tag->recent_medias, 'ARRAY';

__DATA__
{
    "data": {
        "media_count": 472,
        "name": "nofilter"
    }
}

t/00-user.t  view on Meta::CPAN


my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
            no_cache      => 1
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_get_list', sub { [] });

my $user = $api->user("1574083");
isa_ok( $user, 'API::Instagram::User' );

is $user->id, 1574083;
is $user->username, 'snoopdogg';
is $user->full_name, 'Snoop Dogg';
is $user->bio, 'This is my bio';

t/00-user.t  view on Meta::CPAN

is ref $user->get_follows, 'ARRAY';
is ref $user->get_followers, 'ARRAY';
is ref $user->recent_medias, 'ARRAY';

is $user->feed, undef;
is $user->liked_media, undef;
is $user->requested_by, undef;

__DATA__
{
    "data": {
        "id": "1574083",
        "username": "snoopdogg",
        "full_name": "Snoop Dogg",
        "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1574083_75sq_1295469061.jpg",
        "bio": "This is my bio",
        "website": "http://snoopdogg.com",
        "counts": {
            "media": 1320,
            "follows": 420,
            "followed_by": 3410

t/01-location.t  view on Meta::CPAN

use Test::More tests => 4;

my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_get_list', sub { [] });

my $location = $api->location( $json->{data} );
isa_ok( $location, 'API::Instagram::Location' );

is $location->id, undef;
is $location->name, undef;
is ref $location->recent_medias, 'ARRAY';

__DATA__
{
    "data": {
        "latitude": 37.782,
        "longitude": -122.387
    }
}

t/01-media.t  view on Meta::CPAN


my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
            no_cache      => 1,
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_get_list', sub { [] });

my $media = $api->media( $json->{data} );
isa_ok( $media, 'API::Instagram::Media' );

is $media->location, undef;
is ref $media->tags, 'ARRAY';
is $media->tags->[0], undef;

my $uip = $media->users_in_photo;
is ref $uip, 'ARRAY';

my $item = $uip->[0];

t/01-media.t  view on Meta::CPAN

is ref $item_pos, 'HASH';
is $item_pos->{y}, 0.9111;

is ref $media->like,    'HASH';
is ref $media->dislike, 'HASH';

ok $media->comment("Nice pic!");

__DATA__
{
    "data": {
        "type": "video",
        "videos": {
            "low_resolution": {
                "url": "http://distilleryvesper9-13.ak.instagram.com/090d06dad9cd11e2aa0912313817975d_102.mp4",
                "width": 480,
                "height": 480
            },
            "standard_resolution": {
                "url": "http://distilleryvesper9-13.ak.instagram.com/090d06dad9cd11e2aa0912313817975d_101.mp4",
                "width": 640,

t/01-media.t  view on Meta::CPAN

                },
                "position": {
                    "x": 0.315,
                    "y": 0.9111
                }
            }
        ],
        "filter": "Vesper",
        "tags": [],
        "comments": {
            "data": [{
                "created_time": "1279332030",
                "text": "Love the sign here",
                "from": {
                    "username": "mikeyk",
                    "full_name": "Mikey Krieger",
                    "id": "4",
                    "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1242695_75sq_1293915800.jpg"
                },
                "id": "8"
            }, {

t/01-media.t  view on Meta::CPAN

                    "id": "3",
                    "profile_picture": "..."
                },
                "id": "3"
            }],
            "count": 2
        },
        "caption": null,
        "likes": {
            "count": 1,
            "data": [{
                "username": "mikeyk",
                "full_name": "Mikeyk",
                "id": "4",
                "profile_picture": "..."
            }]
        },
        "link": "http://instagr.am/p/D/",
        "user": {
            "username": "kevin",
            "full_name": "Kevin S",

t/01-search.t  view on Meta::CPAN

use Test::More tests => 1;

my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });

my $search = eval { $api->search('car') };
is $search, undef;

__DATA__
{
    "data": [
        {
            "media_count": 43590,
            "name": "snowy"
        },
        {
            "media_count": 3264,
            "name": "snowyday"
        },
        {
            "media_count": 1880,

t/01-user.t  view on Meta::CPAN


my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
            no_cache      => 1
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_get_list', sub { [] });

my $user = $api->user( $json->{data} );
isa_ok( $user, 'API::Instagram::User' );

is $user->id, 'self';
is $user->profile_picture, 'http://distillery.s3.amazonaws.com/profiles/profile_1574083_75sq_1295469061.jpg';
is ref $user->feed, 'ARRAY';
is ref $user->liked_media, 'ARRAY';
is ref $user->requested_by, 'ARRAY';

__DATA__
{
    "data": {
        "id": "self",
        "username": "snoopdogg",
        "full_name": "Snoop Dogg",
        "profile_pic_url": "http://test.com/picture.jpg",
        "profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1574083_75sq_1295469061.jpg",
        "bio": "This is my bio",
        "website": "http://snoopdogg.com",
        "counts": {
            "media": 1320,
            "follows": 420,

t/02-user.t  view on Meta::CPAN


my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
            no_cache      => 1
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_get_list', sub { [] });

my $user = $api->user( $json->{data} );
isa_ok( $user, 'API::Instagram::User' );

is $user->id, 123;
is $user->profile_picture, 'http://test.com/picture.jpg';
is $user->feed, undef;
is $user->liked_media, undef;
is $user->requested_by, undef;

__DATA__
{
    "data": {
        "id": "123",
        "username": "snoopdogg",
        "full_name": "Snoop Dogg",
        "profile_pic_url": "http://test.com/picture.jpg",
        "bio": "This is my bio",
        "website": "http://snoopdogg.com",
        "counts": {
            "media": 1320,
            "follows": 420,
            "followed_by": 3410

t/03-user.t  view on Meta::CPAN


my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
            no_cache      => 1
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_get_list', sub { [] });

my $user = $api->user( $json->{data} );
isa_ok( $user, 'API::Instagram::User' );

is $user->profile_picture, undef;

__DATA__
{
    "data": {
        "id": "1574083",
        "username": "snoopdogg",
        "full_name": "Snoop Dogg",
        "profile_pic_url": null,
        "profile_picture": null,
        "bio": "This is my bio",
        "website": "http://snoopdogg.com",
        "counts": {
            "media": 1320,
            "follows": 420,

t/04-user.t  view on Meta::CPAN


my $api = Test::MockObject::Extends->new(
	API::Instagram->new({
			client_id     => '123',
			client_secret => '456',
			redirect_uri  => 'http://localhost',
            no_cache      => 1
	})
);

my $data = join '', <DATA>;
my $json = decode_json $data;
$api->mock('_request', sub { $json });
$api->mock('_post',    sub { $json });

my $user = $api->user( 123 );
isa_ok( $user, 'API::Instagram::User' );

is ref $user->relationship, 'HASH';
is $user->relationship->{incoming_status}, 'requested_by';
is ref $user->relationship('block'), 'HASH';
is ref $user->relationship('undef'), 'HASH';

__DATA__
{
    "meta": {
        "code": 200
    }, 
    "data": {
        "outgoing_status": "none", 
        "incoming_status": "requested_by"
    }
}



( run in 1.096 second using v1.01-cache-2.11-cpan-6b5c3043376 )