| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package WebService::30Boxes::API; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
23738
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
41
|
|
|
4
|
1
|
|
|
1
|
|
5
|
use Carp qw/croak/; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1004
|
|
|
5
|
|
|
|
|
|
|
require WebService::30Boxes::API::Request; |
|
6
|
|
|
|
|
|
|
require WebService::30Boxes::API::Response; |
|
7
|
|
|
|
|
|
|
require WebService::30Boxes::API::Event; |
|
8
|
|
|
|
|
|
|
require WebService::30Boxes::API::Todo; |
|
9
|
|
|
|
|
|
|
require LWP::UserAgent; |
|
10
|
|
|
|
|
|
|
require XML::Simple; |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
our $VERSION = '1.05'; |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub new { |
|
15
|
1
|
|
|
1
|
|
14
|
my ($class, %params) = @_; |
|
16
|
|
|
|
|
|
|
|
|
17
|
1
|
|
33
|
|
|
8
|
my $self = bless ({}, ref ($class) || $class); |
|
18
|
1
|
50
|
|
|
|
4
|
unless($params{'api_key'}) { |
|
19
|
0
|
|
|
|
|
0
|
croak "You need to set your API key before launching a request.\n". |
|
20
|
|
|
|
|
|
|
"See http://30boxes.com/api/api.php?method=getKeyForUser"; |
|
21
|
|
|
|
|
|
|
} |
|
22
|
1
|
|
|
|
|
7
|
$self->{'_apiKey'} = $params{'api_key'}; |
|
23
|
1
|
|
|
|
|
11
|
$self->{'_ua'} = LWP::UserAgent->new( |
|
24
|
|
|
|
|
|
|
'agent' => __PACKAGE__."/".$VERSION, |
|
25
|
|
|
|
|
|
|
); |
|
26
|
|
|
|
|
|
|
|
|
27
|
1
|
|
|
|
|
4714
|
return $self; |
|
28
|
|
|
|
|
|
|
} |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub call { |
|
31
|
0
|
|
|
0
|
|
|
my ($self, $meth, $args) = @_; |
|
32
|
|
|
|
|
|
|
|
|
33
|
0
|
0
|
|
|
|
|
croak "No method specified." unless(defined $meth); |
|
34
|
|
|
|
|
|
|
|
|
35
|
0
|
|
|
|
|
|
my $req = WebService::30Boxes::API::Request->new($meth, $args); |
|
36
|
0
|
0
|
|
|
|
|
if(defined $req) { |
|
37
|
0
|
0
|
|
|
|
|
unless(defined $self->{'_apiKey'}) { |
|
38
|
|
|
|
|
|
|
} |
|
39
|
0
|
|
|
|
|
|
$req->{'_api_args'}->{'apiKey'} = $self->{'_apiKey'}; |
|
40
|
0
|
|
|
|
|
|
$req->encode_args(); |
|
41
|
0
|
|
|
|
|
|
my $response = $self->_execute($req); |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
#adjust |
|
44
|
0
|
0
|
|
|
|
|
if (defined $response->{'_xml'}->{'eventList'}->{'event'}->{'allDayEvent'}){ |
|
45
|
0
|
|
|
|
|
|
_adjust($response, 'event', 'allDayEvent'); |
|
46
|
|
|
|
|
|
|
} |
|
47
|
|
|
|
|
|
|
|
|
48
|
0
|
0
|
|
|
|
|
if (defined $response->{'_xml'}->{'todoList'}->{'todo'}->{'done'}){ |
|
49
|
0
|
|
|
|
|
|
_adjust($response, 'todo', 'done'); |
|
50
|
|
|
|
|
|
|
} |
|
51
|
|
|
|
|
|
|
|
|
52
|
0
|
|
|
|
|
|
my $error_msg = $response->{'error_msg'}; |
|
53
|
0
|
|
|
|
|
|
my $error_code = $response->{'error_code'}; |
|
54
|
|
|
|
|
|
|
|
|
55
|
0
|
0
|
|
|
|
|
if ($meth =~ /^events/){ |
|
|
|
0
|
|
|
|
|
|
|
56
|
0
|
|
|
|
|
|
return new WebService::30Boxes::API::Event($response, $response->{'success'}, $response->{'error_msg'}, $response->{'error_code'}); |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
elsif ($meth =~ /^todos/){ |
|
59
|
0
|
|
|
|
|
|
return new WebService::30Boxes::API::Todo($response, $response->{'success'}, $response->{'error_msg'}, $response->{'error_code'}); |
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
} else { |
|
62
|
0
|
|
|
|
|
|
return; |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub _adjust { |
|
67
|
0
|
|
|
0
|
|
|
my ($response, $method, $identifier) = @_; |
|
68
|
0
|
|
|
|
|
|
my $eventId = $response->{'_xml'}->{$method . 'List'}->{$method}->{$identifier}; |
|
69
|
0
|
|
|
|
|
|
my %temp = %{$response->{'_xml'}->{$method . 'List'}->{$method}}; |
|
|
0
|
|
|
|
|
|
|
|
70
|
0
|
|
|
|
|
|
delete $response->{'_xml'}->{$method . 'List'}->{$method}; |
|
71
|
0
|
|
|
|
|
|
$response->{'_xml'}->{$method . 'List'}->{$method}->{$eventId} = \%temp; |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub request_auth_url { |
|
75
|
0
|
|
|
0
|
|
|
my ($self, $args) = @_; |
|
76
|
0
|
|
|
|
|
|
for my $c (qw/applicationName applicationLogoUrl/) { |
|
77
|
0
|
0
|
|
|
|
|
croak "$c is not defined." unless(defined $args->{$c}); |
|
78
|
|
|
|
|
|
|
} |
|
79
|
|
|
|
|
|
|
|
|
80
|
0
|
|
|
|
|
|
my $req = WebService::30Boxes::API::Request->new('user.Authorize', $args); |
|
81
|
0
|
|
|
|
|
|
$req->{'_api_args'}->{'apiKey'} = $self->{'_apiKey'}; |
|
82
|
0
|
|
|
|
|
|
$req->encode_args(); |
|
83
|
0
|
|
|
|
|
|
return $req->uri .'?'. $req->content; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub _execute { |
|
87
|
0
|
|
|
0
|
|
|
my ($self, $req) = @_; |
|
88
|
|
|
|
|
|
|
|
|
89
|
0
|
|
|
|
|
|
my $resp = $self->{'_ua'}->request($req); |
|
90
|
0
|
|
|
|
|
|
bless $resp, 'WebService::30Boxes::API::Response'; |
|
91
|
|
|
|
|
|
|
|
|
92
|
0
|
0
|
|
|
|
|
if($resp->{'_rc'} != 200){ |
|
93
|
0
|
|
|
|
|
|
$resp->set_error(0, "API returned a non-200 status code ". |
|
94
|
|
|
|
|
|
|
"($resp->{'_rc'})"); |
|
95
|
0
|
|
|
|
|
|
return $resp; |
|
96
|
|
|
|
|
|
|
} |
|
97
|
|
|
|
|
|
|
|
|
98
|
0
|
|
|
|
|
|
my $result = $resp->reply(XML::Simple::XMLin($resp->{'_content'}, |
|
99
|
|
|
|
|
|
|
ForceArray => 0)); |
|
100
|
0
|
0
|
|
|
|
|
if(!defined $result->{'stat'}) { |
|
101
|
0
|
|
|
|
|
|
$resp->set_error(0, "API returned an invalid response"); |
|
102
|
0
|
|
|
|
|
|
return $resp; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
|
|
|
|
|
|
|
|
105
|
0
|
0
|
|
|
|
|
if($result->{'stat'} eq 'fail') { |
|
106
|
0
|
|
|
|
|
|
$resp->set_error($result->{err}{code}, $result->{err}{msg}); |
|
107
|
0
|
|
|
|
|
|
return $resp; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
|
|
110
|
0
|
|
|
|
|
|
$resp->set_success(); |
|
111
|
|
|
|
|
|
|
|
|
112
|
0
|
|
|
|
|
|
return $resp; |
|
113
|
|
|
|
|
|
|
} |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
1; |
|
116
|
|
|
|
|
|
|
#################### main pod documentation begin ################### |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=head1 NAME |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
WebService::30Boxes::API - Perl interface to the 30 Boxes API |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
use WebService::30Boxes::API; |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
#$api_key and $auth_token are defined before |
|
127
|
|
|
|
|
|
|
my $boxes = WebService::30Boxes::API->new(api_key => $api_key); |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
my $events = $boxes->call('events.Get', {authorizedUserToken => $auth_token}); |
|
130
|
|
|
|
|
|
|
#my $todos = $boxes->call('todos.Get', {authorizedUserToken => $auth_token}); |
|
131
|
|
|
|
|
|
|
if($events->{'success'}){ |
|
132
|
|
|
|
|
|
|
print "List start: " . $events->get_listStart . "\n"; |
|
133
|
|
|
|
|
|
|
print "List end: " . $events->get_listEnd . "\n"; |
|
134
|
|
|
|
|
|
|
print "User Id: " . $events->get_userId . "\n\n\n"; |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
#while ($events->nextEventId){ - if you use this, you don't need to specify |
|
137
|
|
|
|
|
|
|
#$_ as an argument |
|
138
|
|
|
|
|
|
|
#foreach (@{$events->get_ref_eventIds}){ |
|
139
|
|
|
|
|
|
|
foreach ($events->get_eventIds){ |
|
140
|
|
|
|
|
|
|
print "Event id: $_\n"; |
|
141
|
|
|
|
|
|
|
print "Title: " . $events->get_title($_) . "\n"; |
|
142
|
|
|
|
|
|
|
print "Repeat end date: " . $events->get_repeatEndDate($_) . "\n"; |
|
143
|
|
|
|
|
|
|
print "Repeat skip dates: "; |
|
144
|
|
|
|
|
|
|
foreach ($events->get_repeatSkipDates($_)){print "$_\n";} |
|
145
|
|
|
|
|
|
|
print "Repeat type: " . $events->get_repeatType($_) . "\n"; |
|
146
|
|
|
|
|
|
|
print "Repeat interval: " . $events->get_repeatInterval($_) . "\n"; |
|
147
|
|
|
|
|
|
|
print "Reminder: " . $events->get_reminder($_) . "\n"; |
|
148
|
|
|
|
|
|
|
print "Tags: "; |
|
149
|
|
|
|
|
|
|
foreach ($events->get_tags($_)){print "$_\n";} |
|
150
|
|
|
|
|
|
|
print "Start date: " . $events->get_startDate($_) . "\n"; |
|
151
|
|
|
|
|
|
|
print "Start time: " . $events->get_startTime($_) . "\n"; |
|
152
|
|
|
|
|
|
|
print "End date: " . $events->get_endDate($_) . "\n"; |
|
153
|
|
|
|
|
|
|
print "End time: " . $events->get_endTime($_) . "\n"; |
|
154
|
|
|
|
|
|
|
print "Is all day event: " . $events->get_isAllDayEvent($_) . "\n"; |
|
155
|
|
|
|
|
|
|
print "Notes: "; |
|
156
|
|
|
|
|
|
|
foreach ($events->get_notes($_)){print "$_\n";} |
|
157
|
|
|
|
|
|
|
print "Privacy: " . $events->get_privacy($_) . "\n\n"; |
|
158
|
|
|
|
|
|
|
} |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
else{ |
|
161
|
|
|
|
|
|
|
print "An error occured (" . $events->{'error_code'} . ": " . |
|
162
|
|
|
|
|
|
|
$events->{'error_msg'} . ")\n"; |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
C - Perl interface to the 30 Boxes API |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=head2 METHODS |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
The following methods can be used |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=head3 new |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
C create a new C object |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head4 options |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=over 5 |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=item api_key |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
The API key is B and this module will croak if you do not set one |
|
184
|
|
|
|
|
|
|
here. A fresh key can be obtained at L |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=back |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=head3 call |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
With this method, you can call one of the available methods as described |
|
191
|
|
|
|
|
|
|
on L. |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
C accepts a method name followed by a hashref with the values to |
|
194
|
|
|
|
|
|
|
pass on to 30Boxes. |
|
195
|
|
|
|
|
|
|
object. |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
It returns an object of type WebService::30Boxes::API::Event or WebService::30Boxes::API::Todo (depending |
|
198
|
|
|
|
|
|
|
which API method was called), which the user can then use to get the desired information. |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head3 request_auth_url |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
Some API methods require authentication (permission by the user). This |
|
203
|
|
|
|
|
|
|
is done by sending the user to a specific URL where permission can be granted |
|
204
|
|
|
|
|
|
|
or denied. This method accepts a hashref with these three values: |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=over 5 |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=item applicationName |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
(B) applicationName sets the well, application name you want to |
|
211
|
|
|
|
|
|
|
show to the user. |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=item applicationLogoUrl |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
(B) The URI to your logo. |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=item returnUrl |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
(B) This is where you want the user to return too after permission |
|
220
|
|
|
|
|
|
|
is granted. |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=back |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
L, L |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
L |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
L |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
L |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
30boxes.pl - this is a Perl script you can find on CPAN under Web that can be run in the terminal |
|
235
|
|
|
|
|
|
|
and it will display the events for a given period of time along with the Todo list. It takes command |
|
236
|
|
|
|
|
|
|
line arguments that specify how many days/weeks worth of events and how many todos will be displayed. |
|
237
|
|
|
|
|
|
|
I use it to display events and todos when I open my terminal. Send me an email with bugs or feature requests. |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=head1 TODO |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Add more error checking. Compact the code and make it more efficient. Please email me for feature requests. |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=head1 BUGS |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
Please email chitoiup@umich.edu with any bugs. |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=head1 AUTHORS |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
M. Blom (main functionality), |
|
250
|
|
|
|
|
|
|
Eblom@cpan.orgE, |
|
251
|
|
|
|
|
|
|
L |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
Robert Chitoiu (integration with Event and Todo) |
|
254
|
|
|
|
|
|
|
Echitoiup@umich.eduE |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
This program is free software; you can redistribute |
|
259
|
|
|
|
|
|
|
it and/or modify it under the same terms as Perl itself. |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
The full text of the license can be found in the |
|
262
|
|
|
|
|
|
|
LICENSE file included with this module. |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=cut |