ImgurAPI-Client

 view release on metacpan or  search on metacpan

lib/ImgurAPI/Client.pm  view on Meta::CPAN


package ImgurAPI::Client;

use strict;
use warnings;

use Data::Dumper;
use HTTP::Request::Common;
use JSON qw(decode_json encode_json);
use List::Util qw(first);
use LWP::UserAgent;
use Mozilla::CA;
use Scalar::Util;
use XML::LibXML;

our $VERSION = '1.2.1';

use constant ENDPOINTS => {
    'IMGUR' => 'https://api.imgur.com/3',
    'RAPIDAPI' => 'https://imgur-apiv3.p.rapidapi.com',
    'OAUTH_AUTHORIZE' => 'https://api.imgur.com/oauth2/authorize',
    'OAUTH_TOKEN' => 'https://api.imgur.com/oauth2/token',
};

sub new {
    my $self = shift;
    my $args = shift // {};
    my $vars = {
        'auth' => 1,
        'access_token' => $args->{'access_token'},
        'oauth_cb_state' => $args->{'oauth_cb_state'},
        'client_id' => $args->{'client_id'},
        'client_secret' => $args->{'client_secret'},
        'format_type' => $args->{'format_type'} || 'json',
        'lwp' => LWP::UserAgent->new,
        'rapidapi_key' => $args->{'rapidapi_key'},
        'refresh_token' => $args->{'refresh_token'},
        'response' => undef,
        'ratelimit_hdrs' => {},
        'user_agent' => $args->{'user_agent'} || "ImgurAPI::Client/$VERSION",
    };

    return bless $vars, $self;
}

sub _lwp { shift->{'lwp'} }

sub request {
    my ($self, $uri, $http_method, $data, $hdr, $debug) = @_;

    $http_method = uc($http_method // 'GET');

    my $endpoint = $self->{'rapidapi_key'} ? ENDPOINTS->{'RAPIDAPI'} . $uri : ($uri =~ /^\// ? ENDPOINTS->{'IMGUR'} . $uri : $uri);

    $endpoint .= ($endpoint =~ /\?/ ? '&' : '?') . '_format=' . $self->{'format_type'} . "&_method=$http_method";

    $self->_lwp->default_header('User-Agent' => "ImgurAPI::Client/$VERSION");

    if ($self->{'auth'}) {
        my $access_token = $self->{'access_token'} // die "Missing required access_token";
        $self->_lwp->default_header('Authorization' => "Bearer $access_token");
    } elsif ($self->{'client_id'}) {
        $self->_lwp->default_header('Authorization' => "Client-ID " . $self->{'client_id'});
    }

    if ($http_method =~ /^GET|DELETE$/ && $data && ref($data) eq 'HASH') {
        $endpoint .= "&$_=$data->{$_}" foreach keys %$data;
    }

    my $request;
    if ($http_method eq 'POST') {
        $request = HTTP::Request::Common::POST($endpoint, %{$hdr//{}}, Content => $data);
    } elsif ($http_method eq 'PUT') {
        $request = HTTP::Request::Common::PUT($endpoint, %{$hdr//{}}, Content => $data);
    } else {
        $request = HTTP::Request->new($http_method, $endpoint);
    }

    print Dumper $request if $ENV{'DEBUG'} || ($debug // 0);

    my $response = $self->_lwp->request($request);

    my @ratelimit_headers = qw(userlimit userremaining userreset clientlimit clientremaining);
    foreach my $header (@ratelimit_headers) {
        my $val = $response->header("x-ratelimit-$header");
        $self->{'ratelimit_headers'}->{$header} = $val && $val =~ /^\d+$/ ? int $val : $val;
    }

    $self->{'response'} = $response;
    $self->{'response_content'} = $response->decoded_content;

    print Dumper $response if $ENV{'DEBUG'};

    if ($self->format_type eq 'xml') {
        return XML::LibXML->new->load_xml(string => $response->decoded_content);
    } else {
        my $decoded = eval { decode_json $response->decoded_content };
        if (my $err = $@) {
            die "An error occurred while trying to json decode imgur response: $err\n" . $response->decoded_content;
        }
        return $decoded;
    }
}

sub refresh_access_token {
    my $self = shift;
    my $opts = shift // {};

    my $refresh_token = $opts->{'refresh_token'} || $self->{'refresh_token'} or die "missing required refresh_token";
    my $client_id = $opts->{'client_id'} || $self->{'client_id'} or die "missing required client_id";
    my $client_secret = $opts->{'client_secret'} || $self->{'client_secret'} or die "missing required client_secret";

    my $resp = $self->request(ENDPOINTS->{'OAUTH_TOKEN'}, 'POST', {
        'refresh_token' => $refresh_token,
        'client_id' => $client_id,
        'client_secret' => $client_secret,
        'grant_type' => 'refresh_token',
    });

    $self->{'access_token'} = $resp->{'access_token'};
    $self->{'refresh_token'} = $resp->{'refresh_token'};

    return {
        access_token => $resp->{'access_token'},
        refresh_token => $resp->{'refresh_token'}
    }
}

# Setters
sub set_access_token {
    my ($self, $access_token) = @_;
    $self->{'access_token'} = $access_token;
}

sub set_client_id {
    my ($self, $client_id) = @_;

lib/ImgurAPI/Client.pm  view on Meta::CPAN

        die "file doesnt exist at path: $src" unless -e $src;
        die "provided src file path is not a file" unless -f $src;
        $data->{'image'} = [$src];
        %hdr = (Content_Type => 'form-data');
    }

    return $self->request("/image", 'POST', $data, \%hdr);
}

sub image_delete {
    my $self = shift;
    my $id = shift or die "missing required image id";
    return $self->request("/image/$id", 'DELETE');
}

sub image_favorite {
    my $self = shift;
    my $id = shift or die "missing required image id";
    return $self->request("/image/$id/favorite", 'POST');
}

sub image_update {
    my $self = shift;
    my $id = shift or die "missing required image id";
    my $opts = shift // {};
    return $self->request("/image/$id", 'POST', $opts);
}

# Feed
sub feed {
    my $self = shift;
    return $self->request("/feed");
}

=head1 NAME

ImgurAPI::Client - Imgur API client

=head1 DESCRIPTION

This is a client module for interfacing with the Imgur API.

=head1 SYNOPSIS

=head2 Instantiation

    use ImgurAPI::Client;

    my $client = ImgurAPI::Client->new({
        'client_id' => 'your_client_id',
        'access_token' => 'your_access_token'
    });

    my $upload = $client->image_upload("helloimgur.png", 'file', {title => 'title', description => 'desc'});
    my $image_info = $client->image($upload->{'data'}->{'id'};

=head2 Authorization

Imgur uses OAuth 2.0 for authentication. OAuth 2.0 has four steps: registration, authorization, making authenticated requests and getting new access tokens after the initial one expires using a refresh token and client secret.

After registering a client application with Imgur L<here|https://api.imgur.com/oauth2/addclient>, the user will need to manually authorize it. Generate a authorization url using the C<oauth2_authorize_url> method and redirect the user to the generate...

=head2 Authentication

The client can be authenticated by setting the access token and client id. Those can be set a couple of ways. The first way is to do it is by passing them to the constructor:

    my $client = ImgurAPI::Client->new({
        'client_id' => 'your_client_id',
        'client_secret' => 'your_client_secret'
        'access_token' => 'your_access_token'
    });

The second way is to use the setter methods:

    $client->set_access_token('your_access_token');
    $client->set_client_id('your_client_id');

=head2 Refreshing Access Tokens

Access tokens expire after a period of time. To get a new access token, you can use the C<refresh_access_token> method. This method requires the refresh token, client id and client secret. You can pass these values to the method or set them using the...

    my %args = (
        'refresh_token' => 'your_refresh_token',
        'client_id' => 'your_client_id',
        'client_secret' => 'your_client_secret'
    );
    my $refresh_token = get_refresh_token_from_datastore();

    my $resp = $client->refresh_access_token(\%args);
    my $new_refresh_token = $resp->{'refresh_token'};

    # Store the new refresh token somewhere persistent so it can be used later when the new access token expires.


=head2 METHODS

=head3 new

    $client = ImgurAPI::Client->new(\%args);

Valid constructor arguments are:

=over 4

=item *

C<access_key> - Access token used to authenticate requests.

=item *

C<client_id> - Client identifier used for authorization, refresh token requests and unauthenticated requests.

=item *

C<client_secret> - Client secret used for acquiring a refresh token.

=item *

C<format_type> - Api endpoint response format type. Options are C<json> (default) and C<xml>.

=item *

C<oauth_cb_state> - A parameter that's appended to the OAuth2 authorization callback URL. May be useful if you want to pass along a tracking value to the callback endpoint / collector.

=item *

C<rapidapi_key> - Commercial use api key provided by RapidAPI.

=item *

C<user_agent> - User agent string to use for requests (default: 'ImgurAPI::Client/X.X.X')

=back

A getter and setter method is provided for each constructor arg.

=head3 SETTER METHODS


=head4 set_access_token

    $client->set_access_token('your_access_token');

=head4 set_client_id

    $client->set_client_id('your_client_id');

=head4 set_client_secret

    $client->set_client_secret('your_client_secret');

=head4 set_format_type

    $client->set_format_type('xml');

=head4 set_oauth_cb_state

    $client->set_oauth_cb_state('your_oauth_cb_state');

=head4 set_rapidapi_key

    $client->set_rapidapi_key('rapidapi_key');

=head4 set_user_agent

    $client->set_user_agent('your_user_agent');

=head3 GETTER METHODS

=head4 access_token

    $access_tok = $client->access_token;

=head4 client_id

    $client_id = $client->client_id;

=head4 client_secret

    $client_secret = $client->client_secret;

=head4 format_type

lib/ImgurAPI/Client.pm  view on Meta::CPAN

=over 4

=item *

C<page> - Page number

=back

=head5 account_reply_notifications

    $resp = $client->account_reply_notifications($username, \%opts);

Valid C<\%opts> keys are:

=over 4

=item *

C<new> - Boolean value. True for unviewed notifications and false for viewed notifications.

=back

=head5 account_settings

    $resp = $client->account_settings($username);

Get account settings for a given username.

=head5 account_settings_update

    $resp = $client->account_settings_update($username, \%opts);

Update an account's settings.

Valid C<\%opts> keys are:

=over 4

=item *

C<bio> - A string for the bio.

=item *

C<public_images> - A boolean value to set images to public or not by default.

=item *

C<messaging_enabled> - A boolean value to allow messaging or not.

=item *

C<accepted_gallery_terms> - A boolean value to accept the gallery terms.

=item *

C<username> - A valid username between 4 and 63 alphanumeric characters.

=item *

C<show_mature> - A boolean value to show mature images in gallery list endpoints.

=item *

C<newsletter_subscribed> - A boolean value, true to subscribe to the newsletter, false to unsubscribe from the newsletter.

=back

=head5 account_submissions

    $resp = $client->account_submissions($username, \%opts);

Valid C<\%opts> keys are:

=over 4

=item *

C<page> - Page number

=back

=head5 account_tag_follow

    $resp = $client->account_tag_follow($tag);

Follow a tag.

=head5 account_tag_unfollow

    $resp = $client->account_tag_unfollow($tag);

Unfollow a tag.

=head5 account_verify_email_send

    $resp = $client->account_verify_email_send($username);

Send a verification email.

=head5 account_verify_email_status

    $resp = $client->account_verify_email_status($username);

Get the status of the verification email.

=head4 ALBUM

=head5 album

    $resp = $client->album($album_id);

Get information about a specific album.

=head5 album_create

    $resp = $client->album_create(\%opts);

=over 4

=item *



( run in 1.788 second using v1.01-cache-2.11-cpan-524268b4103 )