A tcl api to everyone's favorite social bookmarking site, by [AF]. See [http://del.icio.us/help/api/] for documentation. package require http package require tls package require tdom package require base64 package require json package require md5 package provide delicious 1.0 ::http::register https 443 [list ::tls::socket] namespace eval delicious { variable user {} variable pass {} namespace export get_posts recent_posts get_all_posts post_dates \ add_post delete_post updated get_tags rename_tag set_bundle \ delete_bundle get_bundles public_network public_tags public_url \ public_posts public_fans } proc ::delicious::_call {url} { variable user variable pass lappend headers Authorization "Basic [base64::encode $user:$pass]" #puts "geturl $url" set t [http::geturl $url -headers $headers] if {[http::ncode $t] != "200"} { #parray $t return -code error "HTTP [http::ncode $t]" } set data [http::data $t] #puts "data: $data" http::cleanup $t return $data } proc ::delicious::_xml_to_list {xml top each} { set data {} set d [[dom parse -simple $xml] getElementsByTagName $top] foreach node [$d getElementsByTagName $each] { lappend data [lindex [$node asList] 1] } return $data } proc ::delicious::_check_result {xml} { if {[regexp { result]} { if {$result != "done"} { return -code error $result } return -code ok } if {[regexp {(.*)} $xml -> result]} { if {$result != "ok" && $result != "done"} { return -code error $result } return -code ok } return -code error "could not parse result" } proc ::delicious::_options {valid in var} { upvar $var blah set query {} foreach x $in { set opt [split $x =] if {[lsearch -exact $valid [lindex $opt 0]] > -1} { if {[lindex $opt 0] == "dt"} { lappend query dt [clock format [clock scan [lindex $opt 1]] -format "%Y-%m-%dT%TZ"] } else { lappend query [lindex $opt 0] [lindex $opt 1] } } } append blah [eval ::http::formatQuery $query] } proc delicious::get_posts {args} { set url https://api.del.icio.us/v1/posts/get? _options {url tag dt} $args url return [_xml_to_list [_call $url] posts post] } proc ::delicious::recent_posts {args} { set url https://api.del.icio.us/v1/posts/recent? _options {tag count} $args url return [_xml_to_list [_call $url] posts post] } proc ::delicious::get_all_posts {args} { set url https://api.del.icio.us/v1/posts/all? _options {tag} $args url return [_xml_to_list [_call $url] posts post] } proc ::delicious::post_dates {args} { set url https://api.del.icio.us/v1/posts/dates? _options {tag} $args url return [_xml_to_list [_call $url] dates date] } proc ::delicious::add_post {args} { set url https://api.del.icio.us/v1/posts/add? _options {url description extended tags dt replace shared} $args url return [_check_result [_call $url]] } proc ::delicious::delete_post {args} { set url https://api.del.icio.us/v1/posts/delete? _options {url} $args url return [_check_result [_call $url]] } proc ::delicious::updated {} { set url https://api.del.icio.us/v1/posts/update set xml [_call $url] regexp { update return [clock scan [string map {T " " Z " UTC"} $update]] } proc ::delicious::get_tags {} { set url https://api.del.icio.us/v1/tags/get return [_xml_to_list [_call $url] tags tag] } proc ::delicious::rename_tag {old new} { set url https://api.del.icio.us/v1/tags/rename? _options {old new} [list old=$old new=$new] url return [_check_result [_call $url]] } proc ::delicious::set_bundle {bundle tags} { set url https://api.del.icio.us/v1/tags/bundles/set? _options {bundle tags} [list bundle=$bundle tags=$tags] url return [_check_result [_call $url]] } proc ::delicious::delete_bundle {bundle} { set url https://api.del.icio.us/v1/tags/bundles/set? _options {old new} [list bundle=$bundle] url return [_check_result [_call $url]] } proc ::delicious::get_bundles {} { set url https://api.del.icio.us/v1/tags/bundles/all return [_xml_to_list [_call $url] bundles bundle] } proc ::delicious::public_network {user} { set url http://del.icio.us/feeds/json/network/$user return [json::json2dict [_call $url]] } proc ::delicious::public_tags {user args} { set url http://del.icio.us/feeds/json/tags/$user? _options {atleast count sort} $args url regexp {Delicious.tags = (.*)} [_call $url] -> json return [json::json2dict $json] } proc ::delicious::public_fans {user} { set url http://del.icio.us/feeds/json/fans/$user return [json::json2dict [_call $url]] } proc ::delicious::public_posts {user args} { set url http://del.icio.us/feeds/json/$user? _options {count} $args url regexp {Delicious.posts = (.*)} [_call $url] -> json return [json::json2dict $json] } proc ::delicious::public_url {urls} { set url http://badges.del.icio.us/feeds/json/url/data? foreach u $urls { append url &hash=[string tolower [md5::md5 -hex $u]] } return [json::json2dict [_call $url]] } ---- An example: package require delicious set delicious::user username set delicious::pass password if [catch {delicious::add_post url=http://wiki.tcl.tk "description=the tclers wiki" tags=tcl} result]} { } ---- I would love to see examples of using this package. Anyone tried it? ---- [LV] 2007-Aug-09 In looking at the api web page mentioned above, I see a few requirements listed for libraries: * one second wait between queries are required * library must watch for http 503 errors and respect them [AF] Well I know it says "library", but I left these up to the ''user'' of the library. Http errors are returned so the user can watch for 503s (or any other error) and do whatever needs to be done. its also up to the user to throttle the requests. ---- [Category Internet]