source: trunk/tools/piwigo_remote.pl @ 20355

Last change on this file since 20355 was 15327, checked in by plg, 12 years ago

piwigo_remote.pl: simplified use of pwg.images.add, no longer need thumb and high

  • Property svn:eol-style set to LF
File size: 9.7 KB
RevLine 
[2463]1#!/usr/bin/perl
2
[3193]3####
4# Usage examples
5#
[15327]6# perl piwigo_remote.pl --action=pwg.images.add --file=erwann_rocher-web.jpg --define categories=9
[3193]7
[2463]8use strict;
9use warnings;
10
11use JSON;
12use LWP::UserAgent;
[4347]13# LWP::Debug::level('+');
[2463]14use Getopt::Long;
[2670]15use Encode qw/is_utf8 decode/;
[3193]16use POSIX qw(ceil floor);
[2463]17
18my %opt = ();
19GetOptions(
20    \%opt,
[3454]21    qw/
22          action=s
23          file=s
24          original=s
25          categories=s
26          chunk_size=i
27          base_url=s
28          username=s
29          password=s
30          define=s%
31      /
[2463]32);
33
34our $ua = LWP::UserAgent->new;
[4347]35$ua->agent('Mozilla/piwigo_remote.pl 1.25');
[2463]36$ua->cookie_jar({});
37
38my %conf;
39$conf{response_format} = 'json';
40$conf{limit} = 10;
41
[3454]42my %conf_default = (
43    base_url => 'http://localhost/piwigo/2.0',
44    username => 'plg',
45    password => 'plg',
46    chunk_size => 500_000,
47);
48foreach my $conf_key (keys %conf_default) {
49    $conf{$conf_key} = defined $opt{$conf_key} ? $opt{$conf_key} : $conf_default{$conf_key}
50}
51
[4347]52$ua->default_headers->authorization_basic(
53    $conf{username},
54    $conf{password}
55);
56
[2463]57my $result = undef;
58my $query = undef;
59
60binmode STDOUT, ":encoding(utf-8)";
61
62# TODO : don't connect at each script call, use the session duration instead.
63my $form = {
64    method => 'pwg.session.login',
65    username => $conf{username},
66    password => $conf{password},
67};
68
69$result = $ua->post(
[2519]70    $conf{base_url}.'/ws.php?format=json',
[2463]71    $form
72);
73
74# print "\n", $ua->cookie_jar->as_string, "\n";
75
76if ($opt{action} eq 'pwg.images.add') {
77    use Digest::MD5::File qw/file_md5_hex/;
78
[3193]79    $form = {};
[4348]80    $form->{method} = $opt{action};
[3193]81
[15327]82    my $original = $opt{file};
83    if (defined $opt{original}) {
84        $original = $opt{original};
85    }
86
87    my $original_sum = file_md5_hex($original);
[3193]88    $form->{original_sum} = $original_sum;
[3065]89
[3193]90    send_chunks(
91        filepath => $opt{file},
92        type => 'file',
93        original_sum => $original_sum,
94    );
95    $form->{file_sum} = file_md5_hex($opt{file});
[2463]96
[2569]97    foreach my $key (keys %{ $opt{define} }) {
98        $form->{$key} = $opt{define}{$key};
99    }
100
[2500]101    my $response = $ua->post(
[2519]102        $conf{base_url}.'/ws.php?format=json',
[2463]103        $form
104    );
[2500]105
106    print "-" x 50, "\n";
107    printf("response code    : %u\n", $response->code);
108    printf("response message : %s\n", $response->message);
109    print "-" x 50, "\n";
110    print "\n";
111
112#     use Data::Dumper;
[3065]113#     print Dumper($response->content);
114#     print Dumper(from_json($response->content));
[2500]115
116    if ($response->is_success) {
117        print "upload successful\n";
118    }
119    else {
[4347]120        print Dumper($response);
[2500]121        warn 'A problem has occured during upload', "\n";
122        warn $response->decoded_content, "\n";
123        die $response->status_line;
124    }
[2463]125}
126
[4348]127if ($opt{action} eq 'pwg.images.addFile') {
128    use Digest::MD5::File qw/file_md5_hex/;
129
130    if (not defined $opt{define}{image_id}) {
131        die '--define image_id=1234 is missing';
132    }
133
134    # which file type are we going to add/update?
135    my $type = undef;
136
137    foreach my $test_type (qw/thumbnail file high/) {
138        if (defined $opt{$test_type}) {
139            $type = $test_type;
140            last;
141        }
142    }
143
144    if (not defined $type) {
145        die 'at least one of file/thumbnail/high parameters must be set';
146    }
147
148    my $type_code = typecode_from_typename($type);
149
150    send_chunks(
151        filepath => $opt{$type},
152        type => $type_code,
153        original_sum => file_md5_hex($opt{original}),
154    );
155
156    $form = {};
157    $form->{method} = $opt{action};
158    $form->{type}   = $type_code;
159    $form->{sum}    = file_md5_hex($opt{$type});
160
161    foreach my $key (keys %{ $opt{define} }) {
162        $form->{$key} = $opt{define}{$key};
163    }
164
165    my $response = $ua->post(
166        $conf{base_url}.'/ws.php?format=json',
167        $form
168    );
169
170    print "-" x 50, "\n";
171    printf("response code    : %u\n", $response->code);
172    printf("response message : %s\n", $response->message);
173    print "-" x 50, "\n";
174    print "\n";
175
176#     use Data::Dumper;
177#     print Dumper($response->content);
178#     print Dumper(from_json($response->content));
179
180    if ($response->is_success) {
181        print "upload successful\n";
182    }
183    else {
184        print Dumper($response);
185        warn 'A problem has occured during upload', "\n";
186        warn $response->decoded_content, "\n";
187        die $response->status_line;
188    }
189}
190
[2463]191if ($opt{action} eq 'pwg.tags.list') {
192    use Text::ASCIITable;
193
194    $query = pwg_ws_get_query(
195        method => 'pwg.tags.getList',
196        sort_by_counter => 'true',
197    );
198
199    $result = $ua->get($query);
200    my $tag_result = from_json($result->content);
201    my $t = Text::ASCIITable->new({ headingText => 'Tags' });
202    $t->setCols('id','counter','name');
203
204    my $tag_number = 1;
205    foreach my $tag_href (@{ $tag_result->{result}{tags} }) {
206        $t->addRow(
207            $tag_href->{id},
208            $tag_href->{counter},
209            $tag_href->{name}
210        );
211
212        last if $tag_number++ >= $conf{limit};
213    }
214    print $t;
215}
216
[2584]217if ($opt{action} eq 'pwg.tags.getAdminList') {
218    $query = pwg_ws_get_query(
219        method => 'pwg.tags.getAdminList'
220    );
221
222    $result = $ua->get($query);
[4347]223    print Dumper($result);
[2584]224    my $tags = from_json($result->content)->{result}{tags};
225
226    foreach my $tag (@{$tags}) {
227        # print join(',', keys %{$tag}), "\n"; exit();
228        printf(
229            '{%u} %s ',
230            $tag->{id},
231            $tag->{name}
232        );
233    }
234
235    print "\n";
236}
237
[2583]238if ($opt{action} eq 'pwg.categories.add') {
239    $form = {
240        method => 'pwg.categories.add',
241        name => $opt{define}{name},
242        parent => $opt{define}{parent},
243    };
244
245    my $response = $ua->post(
246        $conf{base_url}.'/ws.php?format=json',
247        $form
248    );
249
250    use Data::Dumper;
251    print Dumper(from_json($response->content));
252}
253
[2634]254if ($opt{action} eq 'pwg.tags.add') {
255    $form = {
256        method => 'pwg.tags.add',
257        name => $opt{define}{name},
258    };
259
260    my $response = $ua->post(
261        $conf{base_url}.'/ws.php?format=json',
262        $form
263    );
264
265    use Data::Dumper;
266    print Dumper(from_json($response->content));
267}
268
[2683]269if ($opt{action} eq 'pwg.images.exist') {
270    $form = {
271        method => $opt{action},
272    };
273
274    foreach my $key (keys %{ $opt{define} }) {
275        $form->{$key} = $opt{define}{$key};
276    }
277
278    my $response = $ua->post(
279        $conf{base_url}.'/ws.php?format=json',
280        $form
281    );
282
283    use Data::Dumper;
284    print Dumper(from_json($response->content)->{result});
285    # print Dumper($response);
286}
287
[4347]288if ($opt{action} eq 'pwg.images.checkFiles') {
289    use Digest::MD5::File qw/file_md5_hex/;
290
291    $form = {};
292    $form->{method} = $opt{action};
293
294    foreach my $type (qw/thumbnail file high/) {
295        if (defined $opt{$type}) {
296            $form->{$type.'_sum'} = file_md5_hex($opt{$type});
297        }
298    }
299
300    foreach my $key (keys %{ $opt{define} }) {
301        $form->{$key} = $opt{define}{$key};
302    }
303
304    my $response = $ua->post(
305        $conf{base_url}.'/ws.php?format=json',
306        $form
307    );
308
309    print "-" x 50, "\n";
310    printf("response code    : %u\n", $response->code);
311    printf("response message : %s\n", $response->message);
312    print "-" x 50, "\n";
313    print "\n";
314
315    use Data::Dumper;
316    print Dumper(from_json($response->content));
317}
318
[3454]319if ($opt{action} eq 'pwg.images.setInfo' or $opt{action} eq 'pwg.categories.setInfo') {
[2919]320    $form = {
321        method => $opt{action},
322    };
323
324    foreach my $key (keys %{ $opt{define} }) {
325        $form->{$key} = $opt{define}{$key};
326    }
327
328    my $response = $ua->post(
329        $conf{base_url}.'/ws.php?format=json',
330        $form
331    );
332
333    use Data::Dumper;
334    # print Dumper(from_json($response->content)->{result});
335    print Dumper($response);
336}
337
[4347]338if ($opt{action} eq 'pwg.categories.getList') {
339    $form = {
340        method => $opt{action},
341    };
342
343    foreach my $key (keys %{ $opt{define} }) {
344        $form->{$key} = $opt{define}{$key};
345    }
346
347    my $response = $ua->post(
348        $conf{base_url}.'/ws.php?format=json',
349        $form
350    );
351
352    use Data::Dumper;
353    print Dumper($response->content);
354    print Dumper(from_json($response->content)->{result});
355    print Dumper($response);
356}
357
358
[2463]359$query = pwg_ws_get_query(
360    method => 'pwg.session.logout'
361);
362$ua->get($query);
363
364sub pwg_ws_get_query {
365    my %params = @_;
366
367    my $query = $conf{base_url}.'/ws.php?format='.$conf{response_format};
368
369    foreach my $key (keys %params) {
370        $query .= '&'.$key.'='.$params{$key};
371    }
372
373    return $query;
374}
[3193]375
376sub send_chunks {
377    my %params = @_;
378
[4348]379    use MIME::Base64 qw(encode_base64);
[4347]380    use File::Slurp;
381
[3240]382    my $content = read_file($params{filepath});
[3193]383    my $content_length = length($content);
384    my $nb_chunks = ceil($content_length / $conf{chunk_size});
385
386    my $chunk_pos = 0;
387    my $chunk_id = 1;
388    while ($chunk_pos < $content_length) {
389        my $chunk = substr(
390            $content,
391            $chunk_pos,
392            $conf{chunk_size}
393        );
394        $chunk_pos += $conf{chunk_size};
395
396        my $response = $ua->post(
397            $conf{base_url}.'/ws.php?format=json',
398            {
399                method => 'pwg.images.addChunk',
[3240]400                data => encode_base64($chunk),
[3193]401                original_sum => $params{original_sum},
402                position => $chunk_id,
403                type => $params{type},
404            }
405        );
406
407        printf(
408            'chunk %05u of %05u for %s "%s"'."\n",
409            $chunk_id,
410            $nb_chunks,
411            $params{type},
412            $params{filepath}
413        );
414        if ($response->code != 200) {
415            printf("response code    : %u\n", $response->code);
416            printf("response message : %s\n", $response->message);
417        }
418
419        $chunk_id++;
420    }
421}
[4348]422
423sub typecode_from_typename {
424    my ($typename) = @_;
425
426    my $typecode = $typename;
427
428    if ('thumbnail' eq $typename) {
429        $typecode = 'thumb';
430    }
431
432    return $typecode;
433}
Note: See TracBrowser for help on using the repository browser.