File Coverage

blib/lib/WebService/Mattermost/V4/API/Response.pm
Criterion Covered Total %
statement 130 134 97.0
branch 8 16 50.0
condition 3 6 50.0
subroutine 39 39 100.0
pod 0 1 0.0
total 180 196 91.8


line stmt bran cond sub pod time code
1             package WebService::Mattermost::V4::API::Response;
2:

3: # ABSTRACT: Container for API responses. 4:
5: use Mojo::JSON 'decode_json';
6: use Moo;
7: use Types::Standard qw(Any ArrayRef Bool InstanceOf Int Maybe Object Str);
8:
9: use WebService::Mattermost::V4::API::Object::Analytics::Old;
10: use WebService::Mattermost::V4::API::Object::Application;
11: use WebService::Mattermost::V4::API::Object::Audit;
12: use WebService::Mattermost::V4::API::Object::Bot;
13: use WebService::Mattermost::V4::API::Object::Channel::Member;
14: use WebService::Mattermost::V4::API::Object::Channel;
15: use WebService::Mattermost::V4::API::Object::ChannelStats;
16: use WebService::Mattermost::V4::API::Object::Compliance::Report;
17: use WebService::Mattermost::V4::API::Object::Config;
18: use WebService::Mattermost::V4::API::Object::DataRetentionPolicy;
19: use WebService::Mattermost::V4::API::Object::Emoji;
20: use WebService::Mattermost::V4::API::Object::Error;
21: use WebService::Mattermost::V4::API::Object::File;
22: use WebService::Mattermost::V4::API::Object::Icon;
23: use WebService::Mattermost::V4::API::Object::Job;
24: use WebService::Mattermost::V4::API::Object::Log;
25: use WebService::Mattermost::V4::API::Object::NewLogEntry;
26: use WebService::Mattermost::V4::API::Object::Plugin;
27: use WebService::Mattermost::V4::API::Object::Plugins;
28: use WebService::Mattermost::V4::API::Object::Post;
29: use WebService::Mattermost::V4::API::Object::Reaction;
30: use WebService::Mattermost::V4::API::Object::Response;
31: use WebService::Mattermost::V4::API::Object::Status;
32: use WebService::Mattermost::V4::API::Object::Team;
33: use WebService::Mattermost::V4::API::Object::TeamStats;
34: use WebService::Mattermost::V4::API::Object::Thread;
35: use WebService::Mattermost::V4::API::Object::User::Preference;
36: use WebService::Mattermost::V4::API::Object::User::Session;
37: use WebService::Mattermost::V4::API::Object::User::Status;
38: use WebService::Mattermost::V4::API::Object::User;
39: use WebService::Mattermost::V4::API::Object::WebRTCToken;
40: use WebService::Mattermost::Helper::Alias 'view';
41:
42: ################################################################################
43:
44: has base_url => (is => 'ro', isa => Str, required => 1);
45: has auth_token => (is => 'ro', isa => Str, required => 1);
46: has code => (is => 'ro', isa => Int, required => 1);
47: has headers => (is => 'ro', isa => InstanceOf['Mojo::Headers'], required => 1);
48: has message => (is => 'ro', isa => Str, required => 0);
49: has prev => (is => 'ro', isa => InstanceOf['Mojo::Message::Response'], required => 1);
50: has raw_content => (is => 'ro', isa => Str, required => 0);
51: has item_view => (is => 'ro', isa => Maybe[Str], required => 0);
52: has single_item => (is => 'ro', isa => Bool, required => 0);
53:
54: has is_error => (is => 'ro', isa => Bool, default => 0);
55: has is_success => (is => 'ro', isa => Bool, default => 1);
56:
57: has content => (is => 'rw', isa => Any, default => sub { {} });
58:
59: has item => (is => 'ro', isa => Maybe[Object], lazy => 1, builder => 1);
60: has items => (is => 'ro', isa => Maybe[ArrayRef], lazy => 1, builder => 1);
61:
62: ################################################################################
63:
64: sub BUILD {
65: my $self = shift;
66:
67: if ($self->_looks_like_json($self->raw_content)) {
68: $self->content(decode_json($self->raw_content));
69: }
70:
71: return 1;
72: }
73:
74: ################################################################################
75:
76: sub _looks_like_json {
77: my $self = shift;
78: my $inp = shift;
79:
80: # Rudimentary "is it JSON?" hack
81: return $inp && $inp =~ /^[\{\[]/ ? 1 : 0;
82: }
83:
84: ################################################################################
85:
86: sub _build_item {
87: my $self = shift;
88:
89: my $item;
90:
91: if (scalar @{$self->items}) {
92: $item = $self->items->[0];
93: }
94:
95: return $item;
96: }
97:
98: sub _build_items {
99: my $self = shift;
100:
101: my @ret;
102:
103: if ($self->item_view) {
104: my @init_items = ref $self->content eq 'ARRAY' ? @{$self->content} : ($self->content);
105: my @items;
106:
107: # Sometimes, for example in GET /logs, a JSON string is returned rather
108: # than a hash.
109: foreach (@init_items) {
110: $_ =~ s/\n//sg;
111:
112: if ($self->_looks_like_json($_)) {
113: push @items, decode_json($_);
114: } else {
115: push @items, $_ if $_;
116: }
117: }
118:
119: if ($items[0]->{status_code} && $items[0]->{status_code} != 200) {
120: # The response is actually an error - create an Error view
121: push @ret, view('Error')->new({
122: raw_data => $items[0],
123: auth_token => $self->auth_token,
124: base_url => $self->base_url,
125: });
126: } else {
127: @ret = map {
128: view($self->item_view)->new({
129: auth_token => $self->auth_token,
130: base_url => $self->base_url,
131: raw_data => $_,
132: })
133: } @items;
134: }
135: }
136:
137: return \@ret;
138: }
139:
140: ################################################################################
141:
142: 1;
143:
144: __END__
145:
146: =pod
147:
148: =encoding UTF-8
149:
150: =head1 NAME
151:
152: WebService::Mattermost::V4::API::Response - Container for API responses.
153:
154: =head1 VERSION
155:
156: version 0.28
157:
158: =head1 DESCRIPTION
159:
160: A common container for responses from the Mattermost API.
161:
162: =head2 ATTRIBUTES
163:
164: =over 4
165:
166: =item C<code>
167:
168: The HTTP code returned.
169:
170: =item C<headers>
171:
172: Headers from the C<Mojo::Message::Response> object.
173:
174: =item C<message>
175:
176: A message (or undef) from the API (for example if there is a C<code> of 403,
177: the C<message> will be "Forbidden").
178:
179: =item C<prev>
180:
181: The returned C<Mojo::Message::Response> object.
182:
183: =item C<raw_content>
184:
185: JSON-encoded content or undef.
186:
187: =item C<is_error>
188:
189: =item C<is_success>
190:
191: =item C<content>
192:
193: Decoded content in ArrayRef or HashRef form.
194:
195: =item C<item_view>
196:
197: Whether or not the response should try to create a v4::Object object.
198:
199: =item C<single_item>
200:
201: Whether or not the expected v4::Object should be an ArrayRef.
202:
203: =item C<item>
204:
205: The first v4::Object object.
206:
207: =item C<items>
208:
209: All view objects.
210:
211: =back
212:
213: =head1 AUTHOR
214:
215: Mike Jones <mike@netsplit.org.uk>
216:
217: =head1 COPYRIGHT AND LICENSE
218:
219: This software is Copyright (c) 2020 by Mike Jones.
220:
221: This is free software, licensed under:
222:
223: The MIT (X11) License
224:
225: =cut
226: