File Coverage

blib/lib/WWW/Picnic.pm
Criterion Covered Total %
statement 18 64 28.1
branch 0 16 0.0
condition 0 6 0.0
subroutine 6 14 42.8
pod 5 8 62.5
total 29 108 26.8


line stmt bran cond sub pod time code
1             package WWW::Picnic;
2             our $AUTHORITY = 'cpan:GETTY';
3             # ABSTRACT: Library to access Picnic Supermarket API
4             $WWW::Picnic::VERSION = '0.001';
5 2     2   72806 use Moo;
  2         23561  
  2         9  
6              
7 2     2   3019 use Carp qw( croak );
  2         4  
  2         89  
8 2     2   485 use JSON::MaybeXS;
  2         8230  
  2         110  
9 2     2   1016 use HTTP::Request;
  2         35068  
  2         68  
10 2     2   1439 use LWP::UserAgent;
  2         52522  
  2         82  
11 2     2   19 use Digest::MD5 qw( md5_hex );
  2         5  
  2         1973  
12              
13             has user => (
14             is => 'ro',
15             required => 1,
16             );
17              
18             has pass => (
19             is => 'ro',
20             required => 1,
21             );
22              
23             has client_id => ( # ???
24             is => 'ro',
25             default => sub { 1 },
26             );
27              
28             has api_version => (
29             isa => sub { $_[0] >= 15 },
30             is => 'ro',
31             default => sub { 15 },
32             );
33              
34             has country => (
35             is => 'ro',
36             default => sub { 'de' },
37             );
38              
39             sub api_endpoint {
40 0     0 0   my ( $self ) = @_;
41 0           return sprintf('https://storefront-prod.%s.picnicinternational.com/api/%s', $self->country, "".$self->api_version."");
42             }
43              
44             has http_agent => (
45             is => 'ro',
46             lazy => 1,
47             default => sub {
48             my $self = shift;
49             my $ua = LWP::UserAgent->new;
50             $ua->agent($self->http_agent_name);
51             return $ua;
52             },
53             );
54              
55             has http_agent_name => (
56             is => 'ro',
57             lazy => 1,
58             default => sub { 'okhttp/3.9.0' },
59             );
60              
61             has json => (
62             is => 'ro',
63             lazy => 1,
64             default => sub { return JSON::MaybeXS->new },
65             );
66              
67             has _auth_cache => (
68             is => 'ro',
69             default => sub {{}},
70             );
71              
72             sub picnic_auth {
73 0     0 0   my ( $self ) = @_;
74 0 0         unless (defined $self->_auth_cache->{auth}) {
75 0           my $url = URI->new(join('/',$self->api_endpoint,'user','login'));
76 0           my $request = HTTP::Request->new( POST => $url );
77 0           $request->header('Accept' => 'application/json');
78 0           $request->header('Content-Type' => 'application/json; charset=UTF-8');
79 0           $request->content($self->json->encode({
80             key => $self->user,
81             secret => md5_hex($self->pass),
82             client_id => $self->client_id,
83             }));
84 0           my $response = $self->http_agent->request($request);
85 0 0         if ($response->is_success) {
86 0           my $auth = $response->header('X-Picnic-Auth');
87 0 0         croak __PACKAGE__.": login success, but no auth token!" unless $auth;
88 0           my $data = $self->json->decode($response->content);
89 0 0 0       croak __PACKAGE__.": login success, but user id!" unless $data and $data->{user_id};
90 0           $self->_auth_cache->{auth} = $auth;
91 0           $self->_auth_cache->{time} = time;
92 0           $self->_auth_cache->{user_id} = $data->{user_id};
93             } else {
94 0           croak __PACKAGE__.": login failed! ".$response->status_line;
95             }
96             }
97 0           return $self->_auth_cache->{auth};
98             }
99              
100             sub request {
101 0     0 0   my ( $self, @original_args ) = @_;
102 0           my ( $method, $path, $data, %params ) = @original_args;
103 0 0 0       $data = [] if $method eq 'PUT' and !$data;
104 0           my $url = URI->new(join('/',$self->api_endpoint,$path));
105 0 0         if (%params) {
106 0           $url->query_form(%params);
107             }
108 0           my $request = HTTP::Request->new( $method => $url );
109 0           $request->header('Accept' => 'application/json');
110 0           $request->header('X-Picnic-Auth' => $self->picnic_auth );
111 0 0         if (defined $data) {
112 0           $request->header('Content-Type' => 'application/json');
113 0           $request->content($self->json->encode($data));
114             }
115 0           my $response = $self->http_agent->request($request);
116 0 0         unless ($response->is_success) {
117 0           croak __PACKAGE__.": request to ".$url->as_string." failed! ".$response->status_line;
118             }
119 0           return $self->json->decode($response->content);
120             }
121              
122             sub get_user {
123 0     0 1   my ( $self ) = @_;
124 0           return $self->request( GET => 'user' );
125             }
126              
127             sub get_cart {
128 0     0 1   my ( $self ) = @_;
129 0           return $self->request( GET => 'cart' );
130             }
131              
132             sub clear_cart {
133 0     0 1   my ( $self ) = @_;
134 0           return $self->request( POST => 'cart/clear' );
135             }
136              
137             sub get_delivery_slots {
138 0     0 1   my ( $self ) = @_;
139 0           return $self->request( GET => 'cart/delivery_slots' );
140             }
141              
142             sub search {
143 0     0 1   my ( $self, $term ) = @_;
144 0           return $self->request( GET => 'search', undef, search_term => $term );
145             }
146              
147             1;
148              
149             __END__