Cmd-Dwarf

 view release on metacpan or  search on metacpan

examples/test-validate-json-body/app/lib/Dwarf/Module/SocialMedia/Weibo.pm  view on Meta::CPAN

package Dwarf::Module::SocialMedia::Weibo;
use Dwarf::Pragma;
use parent 'Dwarf::Module';
use Dwarf::HTTP::Async;
use DateTime;
use DateTime::Format::HTTP;
use HTTP::Request::Common ();
use JSON;
use LWP::UserAgent;

use Dwarf::Accessor qw/
	ua ua_async urls
	key secret
	access_token access_token_secret expires_in
	user_id screen_name name profile_image
	on_error
/;

sub init {
	my $self = shift;

	$self->{ua}       ||= LWP::UserAgent->new;
	$self->{ua_async} ||= Dwarf::HTTP::Async->new;

	$self->{urls} ||= {
		api           => 'https://api.weibo.com/2',
		authorization => 'https://api.weibo.com/oauth2/authorize',
		access_token  => 'https://api.weibo.com/oauth2/access_token',
	};

	$self->{on_error} ||= sub { die @_ };
}

sub _build_screen_name {
	my $self = shift;
	$self->init_user;
	return $self->{screen_name};
}

sub _build_name {
	my $self = shift;
	$self->init_user;
	return $self->{name};
}

sub _build_profile_image {
	my $self = shift;
	$self->init_user;
	return $self->{profile_image};
}

sub init_user {
	my $self = shift;
	my $user = $self->show_user;
	$self->{screen_name}   = $user->{screen_name};
	$self->{name}          = $user->{name};
	$self->{profile_image} = $user->{profile_image_url};
}

sub authorized {
	my ($self, $will_die) = @_;
	$will_die ||= 1;
	my $authorized = defined $self->access_token;
	if ($will_die && !$authorized) {
		$self->on_error("Unauthorized");
	}
	return $authorized;

examples/test-validate-json-body/app/lib/Dwarf/Module/SocialMedia/Weibo.pm  view on Meta::CPAN


	$params{client_id}     ||= $self->key;
	$params{response_type} ||= 'code';

	my $uri = URI->new($self->urls->{authorization});
	$uri->query_form(%params);
	return $uri;
}

sub request_access_token {
	my ($self, %params) = @_;

	die 'key must be specified.' unless defined $self->key;
	die 'secret must be specified.' unless defined $self->secret;
	die "redirect_uri must be specified." unless defined $params{redirect_uri};
	die "code must be specified." unless defined $params{code};

	$params{client_id}     ||= $self->key;
	$params{client_secret} ||= $self->secret;
	$params{grant_type}    ||= 'authorization_code';

	my $uri = URI->new($self->urls->{access_token});
	$uri->query_form(%params);

	my $res = $self->ua->post($uri);
	$self->validate($res);

	my $json = $res->content;
	my $data = eval { decode_json($json) };
	if ($@) {
		warn $data;
	}

	$self->access_token($data->{access_token});
	$self->expires_in($data->{expires_in});
}

sub _make_request {
	my ($self, $command, $method, $params) = @_;

	$method = uc $method;
	$params->{source}       ||= $self->key;
	$params->{access_token} ||= $self->access_token;

	my $uri = URI->new($self->urls->{'api'} . '/' . $command . '.json');
	$uri->query_form(%{ $params }) if $method =~ /^(GET|DELETE)$/;

	my %data = %{ $params };

	if ($method eq 'MULTIPART_POST') {
		$method = 'POST';
		%data = (
			Content_Type => 'multipart/form-data',
			Content      => [ %{ $params} ],
		);
	} elsif ($method eq 'POST') {
		%data = (Content => $params)
	}

	no strict 'refs';
	my $req = &{"HTTP::Request::Common::$method"}($uri, %data);
	$req->header("Content-Length", 0) if $method eq 'DELETE';

	return $req;
}

sub call {
	my ($self, $command, $method, $params) = @_;
	$self->authorized;
	my $req = $self->_make_request($command, $method, $params);
	my $res = $self->ua->request($req);
	return $self->validate($res);
}

sub call_async {
	my $self = shift;
	return if @_ == 0;

	$self->authorized;

	my @requests;
	for my $row (@_) {
		push @requests, $self->_make_request(@{ $row });
	}

	my @responses = $self->ua_async->request_in_parallel(@requests);

	my @contents;
	for my $res (@responses) {
		push @contents, $self->validate($res);
	}

	return @contents;
}

sub validate {
	my ($self, $res) = @_;
	my $content = eval {
		my $ct = $res->content;
		$ct =~ s/0\r\n\r\n$//;
		decode_json($ct);
	};
	if ($@) {
		warn "Couldn't decode JSON: $@";
		$content = $res->content;
	}

	if ($res->code !~ /^2/) {
		if ($content) {
		 	if (ref $content) {
				if ($content->{error} =~ /rate limit/) {
					my $limit = $self->get_rate_limit_status;
					my $reset = DateTime
						->from_epoch(epoch => time + $limit->{reset_time_in_seconds})
						->set_time_zone('Asia/Tokyo');
					$self->on_error->($reset);
				}

				$self->on_error->($content->{error}, $content->{error_code});
			} else {
				$self->on_error->($content);



( run in 0.732 second using v1.01-cache-2.11-cpan-d8267643d1d )