|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Mastodon::Role::UserAgent;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
2905
 | 
 use strict;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
166
 | 
    | 
| 
4
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
36
 | 
 use warnings;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
256
 | 
    | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '0.017';  | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
8
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
63
 | 
 use v5.10.0;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
    | 
| 
9
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
29
 | 
 use Moo::Role;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36
 | 
    | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
1918
 | 
 use Log::Any;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
44
 | 
    | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $log = Log::Any->get_logger( category => 'Mastodon' );  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
14
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
2811
 | 
 use URI::QueryParam;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4090
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
204
 | 
    | 
| 
15
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
38
 | 
 use List::Util qw( any );  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
451
 | 
    | 
| 
16
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
63
 | 
 use Types::Standard qw(  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ArrayRef  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Dict  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     HashRef  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Maybe  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Num  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Optional  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Str  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Undef  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     slurpy  | 
| 
26
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
40
 | 
 );  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
    | 
| 
27
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
 use Mastodon::Types qw(  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     HTTPResponse  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Instance  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     URI  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     UserAgent  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     to_Entity  | 
| 
33
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
10180
 | 
 );  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
34
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
6357
 | 
 use Type::Params qw( compile );  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
    | 
| 
35
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
1233
 | 
 use Carp;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2809
 | 
    | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has instance => (  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   is => 'rw',  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   isa => Instance,  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   default => 'https://mastodon.social',  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   coerce => 1,  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has api_version => (  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   is => 'ro',  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   isa => Num,  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   default => 1,  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has redirect_uri => (  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   is => 'ro',  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   isa => Str,  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   lazy => 1,  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   default => 'urn:ietf:wg:oauth:2.0:oob',  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has user_agent => (  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   is => 'ro',  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   isa => UserAgent,  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   default => sub {  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     require HTTP::Thin;  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     HTTP::Thin->new;  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 has latest_response => (  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     is => 'ro',  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     isa => Maybe[HTTPResponse],  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     init_args => undef,  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub authorization_url {  | 
| 
73
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
0
  
 | 
816
 | 
   my $self = shift;  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
75
 | 
2
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
44
 | 
   unless ($self->client_id and $self->client_secret) {  | 
| 
76
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     croak $log->fatal(  | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       'Cannot get authorization URL without client_id and client_secret'  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
81
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
64
 | 
   state $check = compile( slurpy Dict [ access_code => Optional [Instance] ] );  | 
| 
82
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5957
 | 
   my ($params) = $check->(@_);  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
84
 | 
2
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
101
 | 
   $params->{instance} //= $self->instance;  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
86
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
   my $uri = URI->new('/oauth/authorize')->abs($params->{instance}->uri);  | 
| 
87
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
786
 | 
   $uri->query_param(redirect_uri => $self->redirect_uri);  | 
| 
88
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
462
 | 
   $uri->query_param(response_type => 'code');  | 
| 
89
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
485
 | 
   $uri->query_param(client_id => $self->client_id);  | 
| 
90
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
501
 | 
   $uri->query_param(scope => join q{ }, sort(@{$self->scopes}));  | 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42
 | 
    | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
92
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
674
 | 
   return $uri;  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
95
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
 sub post   { shift->_request( post   => shift, data   => shift, @_ ) }  | 
| 
96
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
 sub patch  { shift->_request( patch  => shift, data   => shift, @_ ) }  | 
| 
97
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
  
0
  
 | 
77
 | 
 sub get    { shift->_request( get    => shift, params => shift, @_ ) }  | 
| 
98
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
0
  
 | 
0
 | 
 sub delete { shift->_request( delete => shift, params => shift, @_ ) }  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _request {  | 
| 
101
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
 
 | 
44
 | 
   my $self   = shift;  | 
| 
102
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
   my $method = shift;  | 
| 
103
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
55
 | 
   my $url    = shift;  | 
| 
104
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
66
 | 
   my $args   = { @_ };  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
106
 | 
22
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
123
 | 
   my $headers = $args->{headers} // {};  | 
| 
107
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
99
 | 
   my $data    = $self->_prepare_data($args->{data});  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
109
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
84
 | 
   $url = $self->_prepare_params($url, $args->{params});  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
111
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
   $method = uc($method);  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
113
 | 
22
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
664
 | 
   if ($self->can('access_token') and $self->access_token) {  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     $headers = {  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       Authorization => 'Bearer ' . $self->access_token,  | 
| 
116
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       %{$headers},  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
120
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2720
 | 
   if ($log->is_trace) {  | 
| 
121
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     require Data::Dumper;  | 
| 
122
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $log->debugf('Method:  %s', $method);  | 
| 
123
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $log->debugf('URL: %s', $url);  | 
| 
124
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $log->debugf('Headers: %s', Data::Dumper::Dumper( $headers ));  | 
| 
125
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $log->debugf('Data:    %s', Data::Dumper::Dumper( $data ));  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
128
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
57
 | 
   use Try::Tiny;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
936
 | 
    | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   return try {  | 
| 
130
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
 
 | 
1135
 | 
     my @args = $url;  | 
| 
131
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
63
 | 
     push @args, [%{$data}] unless $method eq 'GET';  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
132
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
38
 | 
     @args = (@args, %{$headers});  | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
62
 | 
    | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
134
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
140
 | 
     require HTTP::Request::Common;  | 
| 
135
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
60
 | 
     my $type = ($method eq 'PATCH') ? 'POST' : $method;  | 
| 
136
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
249
 | 
     my $request = HTTP::Request::Common->can($type)->( @args );  | 
| 
137
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2184
 | 
     $request->method($method);  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
139
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
880
 | 
     my $response = $self->user_agent->request( $request );  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
141
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
152
 | 
     use JSON::MaybeXS qw( decode_json );  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
345
 | 
    | 
| 
142
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
48
 | 
     use Encode qw( encode );  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3662
 | 
    | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # We want to be able to set it, but do not want the user to do so  | 
| 
145
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
62322
 | 
     $self->{latest_response} = $response;  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
147
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
94
 | 
     die $response->status_line unless $response->is_success;  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
149
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
300
 | 
     my $payload = decode_json encode('utf8', $response->decoded_content);  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Some API calls return empty objects, which cannot be coerced  | 
| 
152
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4544
 | 
     if ($response->decoded_content ne '{}') {  | 
| 
153
 | 
22
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
2860
 | 
       if ($url !~ /(?:apps|oauth)/ and $self->coerce_entities) {  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $payload = (ref $payload eq 'ARRAY')  | 
| 
155
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34
 | 
           ? [ map { to_Entity({ %{$_}, _client => $self }) } @{$payload} ]  | 
| 
 
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
225
 | 
    | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
46
 | 
    | 
| 
156
 | 
22
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
971
 | 
           : to_Entity({ %{$payload}, _client => $self });  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
71
 | 
    | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
       }  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
160
 | 
22
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
172
 | 
     if (ref $payload eq 'ARRAY') {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
161
 | 
17
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
85
 | 
       die $payload->{error} if any { defined $_->{error} } @{$payload};  | 
| 
 
 | 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
    | 
| 
 
 | 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
72
 | 
    | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif (ref $payload eq 'HASH') {  | 
| 
164
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
       die $payload->{error} if defined $payload->{error};  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
167
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
241
 | 
     return $payload;  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   catch {  | 
| 
170
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my $msg = sprintf 'Could not complete request: %s', $_;  | 
| 
171
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $log->fatal($msg);  | 
| 
172
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     croak $msg;  | 
| 
173
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
513
 | 
   };  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _prepare_data {  | 
| 
177
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
 
 | 
76
 | 
   my ($self, $data) = @_;  | 
| 
178
 | 
22
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
116
 | 
   $data //= {};  | 
| 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
180
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
   foreach my $key (keys %{$data}) {  | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
85
 | 
    | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # Array parameters to the API need keys that are marked with []  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # However, HTTP::Request::Common expects an arrayref to encode files  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # for transfer, even though the API does not expect that to be an array  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # So we need to manually skip it, unless we come up with another solution.  | 
| 
185
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     next if $key eq 'file';  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
187
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $val = $data->{$key};  | 
| 
188
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $data->{$key . '[]'} = delete($data->{$key}) if ref $val eq 'ARRAY';  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
191
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
53
 | 
   return $data;  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _prepare_params {  | 
| 
195
 | 
22
 | 
 
 | 
 
 | 
  
22
  
 | 
 
 | 
54
 | 
   my ($self, $url, $params) = @_;  | 
| 
196
 | 
22
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
67
 | 
   $params //= {};  | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
198
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
54
 | 
   croak 'Cannot make a request without a URL' unless $url;  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
200
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
60
 | 
   unless (ref $url eq 'URI') {  | 
| 
201
 | 
22
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
131
 | 
     my $base = $url =~ m{^/oauth/} ? '/' : '/api/v' . $self->api_version . '/';  | 
| 
202
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
80
 | 
     $url = URI->new( $self->instance->uri . $base . $url );  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # Adjust query param format to be Ruby-compliant  | 
| 
206
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3069
 | 
   foreach my $key (keys %{$params}) {  | 
| 
 
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
142
 | 
    | 
| 
207
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     my $val = $params->{$key};  | 
| 
208
 | 
5
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     if (ref $val eq 'ARRAY') { $url->query_param($key . '[]' => @{$val}) }  | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
    | 
| 
209
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     else                     { $url->query_param($key => $val) }  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   }  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
212
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
924
 | 
   return $url;  | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  |