rubilicious.rb

Path: rubilicious.rb  (CVS)
Last Update: Fri Sep 08 03:38:36 EDT 2006

Rubilicious - Delicious (del.icio.us/) bindings for Ruby. # by Paul Duncan <pabs@pablotron.org> #

                                                                    #
                                                                    #

For the latest version of this software, Please see the Rubilicious # page at pablotron.org/software/rubilicious/. #

                                                                    #
                                                                    #

Copyright (C) 2004-2006 Paul Duncan (pabs@pablotron.org). #

                                                                    #

Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, copy, # modify, merge, publish, distribute, sublicense, and/or sell copies # of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: #

                                                                    #

The above copyright notice and this permission notice shall be # included in all copies of the Software, its documentation and # marketing & publicity materials, and acknowledgment shall be given # in the documentation, materials and software packages that this # Software was used. #

                                                                    #

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #

Required files

cgi   uri   time   net/http   rexml/document   win32/registry  

Methods

add   all   all_bundles   all_posts   bundles   dates   delete   delete_bundle   find_http_proxy   get   h   http_get   new   posts   recent   rename   rename_tag   set_bundle   tags   to_xbel   u   update   update  

Constants

PROXY_ENV_VARS = %w{RUBILICIOUS_HTTP_PROXY HTTP_PROXY http_proxy}   list of environment variables to check for HTTP proxy

Public Class methods

Connect to Delicious with username ‘user’ and password ‘pass’.

Note: if the username or password is incorrect, Rubilicious will not raise an exception until you make an actual call.

Examples:

  # connect to delicious with as 'pabs' with the password 'password'
  r = Rubilicious.new('pabs', 'password')

  # connect to delicious, but never check for an HTTP proxy
  r = Rubilicious.new('pabs', 'password', {'use_proxy' => false})

Options: Rubilicious also accepts several optional parameters in the opt Hash. Here’s a list of the supported keys:

  • use_proxy: Check for HTTP proxy environment variables, and use HTTP proxy if any are set. (default: true)
  • base_uri: URI to Delicious API. Best not to touch this one unless you know what you’re doing. (default: ‘api.del.icio.us/v1’)
  • user_agent: User Agent string to pass to Delicious in each HTTP request. (default: ‘Rubilicious/VERSION Ruby/VERSION’)
  • ssl_verify: Enable SSL certificate validation/verification. Rubilicious will verify the issuer of the server-side certificate against the list of trusted certificates. You can customize this behavior; see below for more information.
  • ssl_cert_path: Override the default SSL certificate directory. If this isn’t set, Rubilicious checks the environment variables RUBILICIOUS_SSL_CERT_DIR and SSL_CERT_DIR. If neither of those are set, Rubilicious uses OpenSSL’s built-in default.
  • ssl_init: Callback proc to use for SSL initialization. See "SSL Options" below for more information.
  • ssl_init_http: Callback proc to use for initializing each HTTPS connection. See "SSL Options" below for more information.

SSL Options: By default, Rubilicious does no server-side certificate validation. This is deliberate; I’m not sure how reasonable each platform’s OpenSSL configuration is, and I’m also not sure how complete each platform’s root certificate list is. If you’re sure your platform is configured properly, you can enable server-side certificate verification using the ‘ssl_verify’ option, like so:

  # enable SSL certificate verification
  r = Rubilicious.new(user, pass, 'ssl_verify' => true)

If you keep your list of root certificates in a directory other than the OpenSSL default, you can override the path by setting the ‘ssl_cert_path’ option, or the RUBILICIOUS_SSL_CERT_DIR or SSL_CERT_DIR environment variables (they’re checked in that order). If none of those are set, Rubilicious falls back to OpenSSL’s built-in certificate directory.

If you need more elaborate SSL verification — to use OSCP or check a CRL, for example — you can use the ‘ssl_init’ and ‘ssl_init_http’ callbacks. The former is called once when an instance of Rubilicious is initialized, and the latter is called for each HTTPS connection. Here’s an example of using the ‘ssl_init’ and ‘ssl_init_http’ callbacks:

# create certificate store, set verify mode x509_store = OpenSSL::X509::Store.new x509_store.add_path(OpenSSL::X509::DEFAULT_CERT_DIR) verify_mode = OpenSSL::SSL::VERIFY_PEER

  # define rubilicious callbacks
  rb_opts = {
    # ssl init callback (called once per instance)
    'ssl_init' => proc { |rb, opt|
      cert_path = opt['ssl_cert_path'] ||
                  ENV['RUBILICIOUS_SSL_CERT_DIR'] ||
                  ENV['SSL_CERT_DIR'] ||
                  OpenSSL::X509::DEFAULT_CERT_DIR
      x509_store.add_path(cert_path)

    },

    # http init callback (called once per HTTPS connection)
    'ssl_init_http' => proc { |rb, http|
      http.use_ssl = true
      http.verify_mode = verify_mode
      http.cert_store = x509_store
    },
  }

  # create rubilicious object
  rb = Rubilicious.new(user, pass, rb_opts)

Public Instance methods

Post a link to delicious, along with an optional extended description, tags (as a space-delimited list), and a timestamp.

Raises an exception on error.

Example:

  # add a link to pablotron to delicious
  r.add('http://pablotron.org/',
        'Pablotron.org : The most popular site on Internet?')

  # add a link to paulduncan.org to delicious with an extended
  # description
  r.add('http://paulduncan.org/', "Paul Duncan", "Damn he's smooth!")

  # add a link with an extended description and some tags
  r.add('http://raggle.org/',
        'Raggle', 'Console RSS Aggregator, written in Ruby.',
        'rss programming ruby console xml')

Return an array of all your posts ever, optionally filtered by tag.

Note: you should check the last update time with Rubilicious#update to see when the last post was made (ie, if calling this is even necessary).

WARNING: This method can generate a large request to Delicious, and should be used sparingly, and at your own risk.

Raises an exception on error.

Example:

  # save all 'art' posts to file "art_posts.txt"
  art_posts = r.all('art')
  File.open('art_posts.txt', 'w') do |file|
    file.puts art_posts.sort do |a, b|
      a['time'] <=> b['time']
    end.map { |post| post['href'] }
  end
all_bundles()

Alias for bundles

all_posts(tag = nil)

Alias for all

Return an array of tag bundles.

Raises an exception on error.

Example:

  # get a list of tag bundles
  bundles = r.bundles

Returns a list of dates with the number of posts at each date. If a tag is given, return a list of dates with the number of posts with the specified tag at each date.

Raises an exception on error.

Examples:

  dates = r.dates
  puts "date,count"
  dates.keys.sort.each do |date|
    puts "#{date},#{dates[date]}"
  end

  # same as above, but only display 'politics' tags
  dates = r.dates('politics')
  puts "date,count",
       dates.map { |args| args.join(',') }.join("\n")

Delete a link from Delicious.

Raises an exception on error.

Example:

  # delete a link to example.com from delicious
  r.delete('http://example.com/')

Delete a tag bundle.

Raises an exception on error.

Example:

  # delete the tag bundle 'testbundle'
  r.delete_bundle('testbundle')

get the HTTP proxy server and port from the environment Returns [nil, nil] if a proxy is not set

This method is private

Get url from Delicious, and optionally parse result and return as an array of hashes as well.

This method is private.

Escape a string to make it XML-friendly.

Low-level HTTP GET.

This method is private.

Returns an array of posts on a given date, filtered by tag. If no date is supplied, most recent date will be used.

Raises an exception on error.

Examples:

  # print out a list of recent links from oldest to newest.
  posts = r.posts
  posts.sort { |a, b| a['time'] <=> b['time'] }.each do |post|
    puts post['href']
  end

  # print out a list of link descriptions from the date '2004-09-22'
  posts = r.posts('2004-09-22')
  posts.sort { |a, b| a['description'] <=> b['description'] }
  posts.each { |post| puts post['description'] }

Returns an array of the most recent posts, optionally filtered by tag.

Raises an exception on error.

Example:

  # get the most recent links
  recent_links = r.recent.map { |post| post['href'] }

  # get the 10 most recent 'music' links
  recent_links = r.recent('music', 10).map { |post| post['href'] }

Renames tags across all posts.

Note: Delicious has currently disabled this feature, so it will not work until they reenable it.

Raises an exception on error.

Example:

  # rename tag "rss" to "xml"
  r.rename('rss', 'xml')
rename_tag(old_tag, new_tag)

Alias for rename

Set (create or replace) a tag bundle.

Raises an exception on error.

Example:

  # set the tags for the tag bundle 'testbundle' to 'ruby programming'.
  r.set_bundle('testbundle', 'ruby programming)

Returns a hash of tags and the number of times they’ve been used.

Raises an exception on error.

Example:

  tags = r.tags
  puts tags.keys.sort.map { |tag| "#{tag},#{tags[tag]}" }.join("\n")

Return an XBEL string of all your posts, optionally filtered by tag.

Note: This is not the same as calling Rubilicious.xbel. Please see the documentation for Rubilicious.xbel for more information.

WARNING: This method can generate a large number of requests to Delicious, and could be construed as abuse. Use sparingly, and at your own risk.

Raises an exception on error.

Example:

  # save all posts ever in XBEL format to file "delicious.xbel"
  File.open('delicious.xbel', 'w') do |file|
    file.puts r.to_xbel
  end

URI-escape a string.

Return the last update time for this user.

Note: this method must be called before you call Rubilicious#all.

Raises an exception on error.

Example:

  # get the last update time for this user
  update_time = r.update

Return the last update time.

Note: this method should be used before calling methods like .posts or .all to conserve on bandwidth.

Example:

 t = r.update  #=> "Fri Mar 11 02:45:51 EST 2005"

[Validate]