root/del.icio.us.B.B/trunk/del.icio.us.B.B.pl

Revision 2, 8.5 kB (checked in by anonymous, 1 年 ago)

初期配置

Line 
1 #!/usr/bin/perl
2 ########################################################################
3 my $USAGE = <<'PERLHEREDOC';
4 * del.icio.us Best Before - Enable you to time-limited bookmarking
5         Version 1.00 (Release 704)
6         Programmed by Piroli YUKARINOMIYA <piroli at magicvox dot net>
7         Open MagicVox.net - http://www.magicvox.net/
8 PERLHEREDOC
9 ########################################################################
10 $|++;
11 use strict;
12 use warnings;
13 use lib './extlib';
14 use POSIX;
15 use LWP::UserAgent;
16 use XML::Simple;
17
18 ### Set your del.icio.us account
19 use constant DELICIOUS_USERNAME =>  'username';
20 use constant DELICIOUS_PASSWORD =>  'password';
21
22 ###
23 # undef     Delete the post
24 # ''        Delete the Time-Limt tag (not yet implemented)
25 # 'newtag'  Replace the Time-Limit tag with the newly specified tag (not yet implemented)
26 use constant ACTION_WHEN_EXPIRED => undef;
27
28 ### More configurations ...
29 use constant RECENT_POSTS_NUM =>    '10';
30 use constant MARK_DIRNAME =>        './mark';
31 use constant UPDATE_FILENAME =>     'update';
32
33 ### Set some constants definition
34 my $DELICIOUS_DOMAIN =              'api.del.icio.us';
35 my $DELICIOUS_PROTOCOL =            'https';
36 use constant DELICIOUS_PORT =>      '443';
37 use constant DELICIOUS_REALM =>     'del.icio.us API';
38
39 ### Global variables
40 my $ua;
41 my $xmlparser;
42 my $posts = {};
43
44 ########################################################################
45 ### Proceeding
46 ########################################################################
47 showUsage ();
48 setupProgram ();
49 InitUserAgent ();
50 InitXmlParser ();
51 if (isUpdatedPosts ()) {
52     retrieveRecentPosts ();
53 }
54 checkMarkFiles ();
55 updateExpiredPosts ();
56 exit;
57
58 ########################################################################
59 ### Functions
60 ########################################################################
61
62 ### Show usages
63 sub showUsage {
64     printf STDERR $USAGE;
65 }
66
67 ### Setup program
68 sub setupProgram {
69     mkdir MARK_DIRNAME unless -d MARK_DIRNAME;
70 }
71
72 ### Initialize LWP::UserAgent
73 sub InitUserAgent {
74     $ua = new LWP::UserAgent
75         or die 'Failed to create <LWP::UserAgent>';
76     # Setup my credentials
77     $ua->credentials (
78             "$DELICIOUS_DOMAIN:".DELICIOUS_PORT,
79             DELICIOUS_REALM,
80             DELICIOUS_USERNAME, DELICIOUS_PASSWORD
81     );
82 }
83
84 ### Initialize XML::Simple
85 sub InitXmlParser {
86     $xmlparser = new XML::Simple (forcearray => 1)
87         or die 'Failed to create <XML::Simple>';
88 }
89
90 ### Step 0 - Last time
91 sub isUpdatedPosts {
92     my $res = getContent ("$DELICIOUS_PROTOCOL://$DELICIOUS_DOMAIN/v1/posts/update")
93         or return 0;
94     my $data = $xmlparser->XMLin ($res);
95     defined $data->{time}
96         or return 0;
97
98     my $update = read1Line (UPDATE_FILENAME) || '';
99     $update eq $data->{time}
100         and return 0;
101
102     makeMark (UPDATE_FILENAME, $data->{time});
103     1;
104 }
105
106 ### Step 1 - Retrieving the recent posts
107 sub retrieveRecentPosts {
108     printf STDERR "* Retrieving the recent %d post(s) on del.icio.us\n", RECENT_POSTS_NUM;
109     my $res = getContent ("$DELICIOUS_PROTOCOL://$DELICIOUS_DOMAIN/v1/posts/recent?count=". RECENT_POSTS_NUM)
110         or return;
111
112     my $data = $xmlparser->XMLin ($res);
113     my $data_posts = $data->{post};
114     foreach my $data_post (@$data_posts) {
115         foreach my $tag (split /\s+/, $data_post->{tag}) {
116             if (defined tag2timelimit ($tag)) {
117                 # This post is a Time-Limit Bookmark
118                 $posts->{$data_post->{href}} = $data_post;
119
120                 makeMark ($data_post->{hash}, $data_post->{href});
121
122                 printf STDERR ".";
123                 last;
124             }
125         }
126     }
127     printf STDERR "\n";
128 }
129
130 ### Step 2 - Checking the mark files
131 sub checkMarkFiles {
132     printf STDERR "* Checking the mark files - %s\n", MARK_DIRNAME;
133     if (opendir (MARK_DH, MARK_DIRNAME)) {
134         foreach my $filename (readdir MARK_DH) {
135             next unless $filename =~ m!^[0-9a-fA-F]{32}$!;
136             my $href = read1Line ($filename)
137                 or next;
138             # The post in this mark file has not been retrieved
139             if (! defined $posts->{$href}) {
140                 if (! retrievePost ($href)) {
141                     # This post may be deleted
142                     removeMark ($filename);
143                 }
144             }
145         }
146         closedir MARK_DH;
147     }
148     printf STDERR "\n";
149 }
150
151 ### Step 3 - Update the expired posts on del.icio.us
152 sub updateExpiredPosts {
153     printf STDERR "* Updating the expired posts on del.icio.us\n";
154     foreach my $href (keys %$posts) {
155         my $remove_mark = 1;
156         my $data_post = $posts->{$href};
157         foreach my $tag (split /\s+/, $data_post->{tag}) {
158             if (defined (my $expires = tag2timelimit ($tag))) {
159                 if (isExpired ($data_post->{time}, $expires)) {
160                     if (defined ACTION_WHEN_EXPIRED) {
161                         updatePostTags ($href, ACTION_WHEN_EXPIRED);
162                         print "v";
163                     } else {
164                         deletePost ($href);
165                         print "x";
166                     }
167                 } else {
168                     $remove_mark = 0;
169                     print '.';
170                 }
171                 last;
172             }
173         }
174         removeMark ($data_post->{hash})
175             if $remove_mark;
176     }
177     print "\n";
178 }
179
180 ### Get content in the specified URL
181 sub getContent {
182     my $url = shift;
183     my $res = $ua->get ($url);
184     sleep 1;
185     if (! $res->is_success) {
186         printf STDERR "\tFailed to get %s\n\tStatus: %s\n",
187                 $url ,$res->status_line;
188         return undef;
189     }
190     $res->content;
191 }
192
193 ### Update with the latest informatio from del.icio.us
194 sub retrievePost {
195     my $href = shift;
196     my $res = getContent ("$DELICIOUS_PROTOCOL://$DELICIOUS_DOMAIN/v1/posts/get?url=". encode_url ($href))
197         or return;
198
199     my $data = $xmlparser->XMLin ($res);
200     my $data_posts = $data->{post};
201     foreach my $data_post (@$data_posts) {
202         foreach my $tag (split /\s+/, $data_post->{tag}) {
203             if (defined tag2timelimit ($tag)) {
204                 # The post in this mark file has not been retrieved
205                 $posts->{$data_post->{href}} = $data_post;
206
207                 printf STDERR ".";
208                 return 1;
209             }
210         }
211         # only 1 post should be returned.
212     }
213     0;
214 }
215
216 ### Delete a post on del.icio.us
217 sub deletePost {
218     my $href = shift;
219     my $res = getContent ("$DELICIOUS_PROTOCOL://$DELICIOUS_DOMAIN/v1/posts/delete?url=". encode_url ($href))
220         or return;
221     # useless to check the response
222 }
223
224 ### Update a post on del.icio.us
225 sub updatePostTags {
226     # not yet implemented
227 }
228
229 ### Encode for URL
230 sub encode_url {
231     my $str = shift;
232     $str =~ s!([^0-9a-zA-Z_.~-])!sprintf '%%%02X', ord ($1)!eg;
233     $str;
234 }
235
236 ### is expired ?
237 sub isExpired {
238     my $posted = shift;
239     my $expire = shift;
240     $posted le POSIX::strftime ('%Y-%m-%dT%H:%M:%SZ', gmtime (time - $expire));
241 }
242
243 ### Make a mark file for the post
244 sub makeMark {
245     my $hash = shift;
246     my $href = shift;
247     if (open (MARK_FH, ">". MARK_DIRNAME. "/$hash")) {
248         print MARK_FH "$href";
249         close MARK_FH;
250     }
251 }
252
253 ### Remove a mark file for the post
254 sub removeMark {
255     my $hash = shift;
256     my $filepath = MARK_DIRNAME. "/$hash";
257     unlink $filepath
258         if -f $filepath;
259 }
260
261 ### Read 1 line from the file
262 sub read1Line {
263     my $filename = shift;
264     my $ret = undef;
265     if (open (FILE_FH, "<". MARK_DIRNAME. "/$filename")) {
266         $ret = <FILE_FH>;
267         close FILE_FH;
268     }
269     $ret;
270 }
271
272 ### Retrieve the expiring time from tag.
273 sub tag2timelimit {
274     my $tag = shift;
275     if ($tag =~ m!^bb(\d+)s(?:ec(?:onds?)?)?$!i) {
276         return $1; # seconds
277     }
278     elsif ($tag =~ m!^bb(\d+)m(?:in(?:utes?)?)?$!i) {
279         return $1 * 60; # minutes
280     }
281     elsif ($tag =~ m!^bb(\d+)h(?:ours?)?$!i) {
282         return $1 * 60 * 60; # hours
283     }
284     elsif ($tag =~ m!^bb(\d+)d(?:ays?)?$!i) {
285         return $1 * 60 * 60 * 24; # days
286     }
287     elsif ($tag =~ m!^bb(\d+)w(?:eeks?)?$!i) {
288         return $1 * 60 * 60 * 24 * 7; # week
289     }
290     elsif ($tag =~ m!^bb(\d+)m(?:onths?)?$!i) {
291         return $1 * 60 * 60 * 24 * 30; # month
292     }
293     elsif ($tag =~ m!^bb(\d+)y(?:ears?)?$!i) {
294         return $1 * 60 * 60 * 24 * 365; # year
295     }
296     elsif ($tag =~ m!^bb$!i) {
297         return $1 * 60 * 60 * 24 * 3; # (default)
298     }
299     undef;
300 }
301
302 __END__
Note: See TracBrowser for help on using the browser.