Delicious client v1.0
Dave Gurnell and Noel Welsh ({dave, noel} at untyped)
1 Introduction
This library provides structures and procedures for accessing the HTTP API of the del.icio.us social bookmarking service. The library handles all connection, encryption and authentication with del.icio.us, allowing the programmer to concentrate on application logic.
This release of the library supports version 1.0 of the del.icio.us API.
2 Configuration
Use the following parameters to configure the library. All API calls within the current scope are affected.
2.1 Basic Configuration
Before making any API calls, the programmer must configure the username and password to use to authenticate with del.icio.us. All communication takes place over SSL, so username and password are secure during transmission over the Internet.
Note that, in the current version of the del.icio.us API, it is only possible to query/manipulate information in the authenticated account.
current-username : (parameter string) |
Sets/retrieves the username to use for subsequent del.icio.us API calls.
current-password : (parameter string) |
Sets/retrieves the password to use for subsequent del.icio.us API calls.
For example:
(parameterize ([username "untyped"] |
[password "password"]) |
; ... authenticated API calls go here ...) |
2.2 Advanced Configuration
current-base-url : (parameter string) |
The base URL of the API. By default this is:
"http://api.del.icio.us:443/v1"
Note the following:
While all communication takes place over SSL, the library does not understand the https:// protocol in the URL. Instead use http:// and specify a port number of 443.
The URL should not end with a / character.
current-throttle : (parameter throttle) |
The throttle control to use to limit the rate at which API requests are made.
del.icio.us can get touchy if you make too many requests too quickly. The documentation states that you must leave a minimum of 1 second between requests, otherwise you will be throttled for up to a few minutes. Experience has shown that persistent use of some of the more "expensive" API requests (such as all-posts) can cause del.icio.us to throttle clients even if they respect this 1 second gap.
The current-throttle parameter takes a throttle structure that is used to rate limit requests. The default value limits the client to the maximum of 1 request per second. You can change this default value if you find you are frequently being throttled by del.icio.us. See Internal Procedures for more information.
2.3 Debug Configuration
The following parameters pare provided to help debug problems with the library:
dump-request-urls? : (parameter boolean) |
If this parameter is set to #t, the URLs of API calls are printed immediately before each call is made.
dump-sxml-responses? : (parameter boolean) |
If this parameter is set to #t, the SXML versions of all responses are printed as they are parsed. Note that this requires the XML response from del.icio.us to be well-formed.
3 API Wrappers
3.1 Special Values
empty : symbol |
The unique symbol empty is used to represent an unspecified argument to an API call (this is because some API calls take optional boolean arguments).
3.2 Result Structures
The following structures are used to encapsulate data returned by API calls. The same structures can also optionally be used as arguments to some API calls:
(struct post (url description extended tags date)) |
url : string |
description : string |
extended : (U string #f) |
tags : (list-of string) |
date : (U srfi-19:date #f) |
A del.icio.us post, comprising a bookmark and some metadata:
url - the bookmarked URL;
description - the one-line title of the post;
extended - extended notes on the post;
tags - tags attached to the post;
date - the date the post was originally made;
(struct bundle (name tags)) |
name : string |
tags : (list-of string) |
A tag bundle: a named collection of tags. Note that bundles may not be used in place of tags, either as members of other bundles or as tag arguments to API calls. This limits their usefulness in the API, although they still appear on the del.icio.us web site.
name - the name of the bundle;
tags - tags in the bundle.
3.3 Exceptions
The following exceptions may be raised by any API procedure call:
(struct (exn:delicious exn) ()) |
Abstract exception supertype. Subtypes of this exception represent failures that are typically the fault of the user, rather than this library or del.icio.us itself.
Applications should respond to exceptions of this type by displaying a "you messed up" style dialog box or feedback message.
(struct (exn:fail:delicious exn) ()) |
Abstract exception supertype. Subtypes of this exception represent failures that are typically the fault of this library or del.icio.us.
Applications should respond to exceptions of this type by displaying an "unexpected error" style dialog box or feedback message.
(struct (exn:delicious:auth exn:delicious) ()) |
Raised if del.icio.us returns an HTTP 403 response. This typically means the username/password were invalid.
(struct (exn:fail:delicious:throttled exn:fail:delicious) ()) |
Raised if del.icio.us returns an HTTP 503 response. del.icio.us is very sensitive to request spamming or over-use. This library contains an auto-throttling element that prevents applications making more than the one permitted request per second, but excessive use of "expensive" requests such as all-posts can still trigger throttling.
Applications should respond to exceptions of this type by backing off for 30 seconds to a few minutes, until del.icio.us switches its throttle protection off again.
(struct (exn:fail:delicious:parse exn:fail:delicious) (fragment)) |
fragment : sxml |
Raised if the library was unable to parse an XML response. This implies the result was well-formed XML with an unexpected structure. The fragment field contains the problematic SXML fragment.
If you get one of these, it’s time to switch on the dump-sxml-responses? parameter and start hunting for bugs in this library. Note that, while bug reports are gratefully received, bug reports and fixes are infinitely preferable.
3.4 API Procedures
The following procedures are wrappers for the various del.icio.us API calls. All calls require the current-username and current-password parameters to be set.
(last-updated) → srfi-19:date |
Returns the (SRFI-19) date of the last post to the account.
(get-tags) → (alist-of string integer) |
Returns an association list of tags to number of uses.
(rename-tag! old-name new-name) → void |
old-name : string |
new-name : string |
Renames a tag and propagates the change to all related posts. For example:
> (length (get-posts "untyped")) |
0 |
> (length (get-posts "un-typed")) |
1 |
> (rename-tag! "un-typed" "untyped") |
> (length (get-posts "untyped")) |
1 |
> (length (get-posts "un-typed")) |
0 |
Returns all posts matching the arguments:
tag - filter by the specified tag (one tag only);
date - filter by the specified post date;
url - filter by the specified URL (must be an exact match).
If all arguments are empty, posts are returned from the most recent day of posting.
(recent-posts [tag count]) → (list-of post) |
Returns a list of the most recent posts:
tag - as above;
count - limit to the specified number of posts: default 15, max 100.
The default value of count is 15.
Returns all posts.
The del.icio.us documentation notes: "Please use sparingly. Call the update function to see if you need to fetch this at all." Frequent use can result in throttling.
(post-dates [tag]) → (alist-of srfi-19:date integer) |
Returns an association list of post dates to number of posts made on that day.
(add-post! post [replace? shared?]) → void |
post : post |
Creates a new post given a post structure.
post - the post to post;
replace? - replace a previous post if the URL has already been posted: default no;
shared? - make the post public: default no.
This procedure delegates to add-post/raw! to do most of the work. Fields in the post are automatically mapped to empty when appropriate.
(add-post/raw! url description [extended tags date replace? shared?]) → void |
url : string |
description : string |
Creates a new post given the constituent parts of a post structure. url, description, extended, tags and date have the same purpose as the relevant fields of post.
(delete-post! post) → void |
post : post |
Deletes an existing post given a post structure.
(delete-post/raw! url) → void |
url : string |
Deletes an existing post given a URL.
(all-bundles) → (list-of bundle) |
Returns a list of tag bundles in the current account.
(update-bundle! bundle) → void |
bundle : bundle |
Creates or updates a tag bundle given a bundle structure. This procedure delegates to update-bundle/raw! to do most of the work.
(update-bundle/raw! name tags) → void |
name : string |
tags : (list-of string) |
Creates or updates a tag bundle given its constituent parts.
name - the name of the tag bundle to create/update;
tags - the (new) contents of the bundle.
(delete-bundle! bundle) → void |
bundle : bundle |
Deletes a bundle given a bundle structure.
(delete-bundle/raw! name) → void |
name : string |
Deletes a bundle given its name.
4 Internal Procedures
4.1 Throttle
The file "throttle.ss" contains procedures that control the rate at which the client sends requests to del.icio.us.
(make-throttle delay) → throttle |
delay : integer |
Creates a throttle structure that manages a queue of requests to run "throttled sections" of code. The throttle responds to requests in the order in which they are received, ensuring that delay milliseconds are allowed to pass between the end of one call and the beginning of the next. This behaviour is enforced in single- and multi-threaded environments.
Use this procedure in conjunction with the current-throttle parameter to change the rate at which the client makes calls to del.icio.us. For example:
(let ([throttle (make-throttle 2000)]) |
(parameterize ([current-throttle throttle]) |
; ... API calls throttled to at most 1 every 2 seconds ...) |
(kill-throttle! throttle)) |
(call-with-throttle throttle thunk) → any |
throttle : throttle |
thunk : (-> any) |
Makes a throttled call to thunk. call-with-throttle sends a message to throttle, asking if it can run the throttled section in thunk. throttle adds the requests to its queue and behaves as described in the documentation for make-throttle above.
(throttle? x) → boolean |
x : any |
Returns #t if x is a throttle, #t otherwise.
(throttle-delay throttle) → integer |
throttle : throttle |
Returns the delay enforced by throttle in milliseconds.
(kill-throttle! throttle) → void |
throttle : throttle |
throttle objects use threads to handle requests. When you have finished using a throttle, you can (and should) call this procedure to kill its thread and free up the system resources it was using. Once a throttle has been killed, it can no longer be used in calls to call-with-throttle.
You can also kill a throttle by shutting down the custodian that was current when it was created.
(throttle-alive? throttle) → boolean |
throttle : throttle |
This procedure determines whether or not a throttle has been killed with the kill-throttle procedure.