Automatically Publish Posts to StumbleUpon with Ruby

Uncovering StumbleUpon's Hidden API

Here’s a Ruby method to automatically submit posts (with tags) to StumbleUpon:

def to_stumble_upon(options = {})
  # fields
  username    = options[:username]
  password    = options[:password]
  title       = options[:title]
  url         = options[:url]
  description = options[:description]
  tags        = options[:tags]

  # crawler
  agent       = Mechanize.new
  agent.user_agent = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; ru-ru) AppleWebKit/533.2+ (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10"

  # login
  page = agent.get("http://www.stumbleupon.com/")
  form = page.form_with(:action => "/login.php")
  form["username"] = username
  form["password"] = password
  form.submit

  # basic info
  page = agent.get("http://www.stumbleupon.com/submit?url=#{url}&title=#{title}")
  form = page.forms.first
  form["topic"] = title
  form["comment"] = description
  form.radiobuttons_with(:name => "sfw").first.check
  page = agent.submit(form)

  # add tags
  page = agent.get("http://www.stumbleupon.com/favorites/")
  # get key properties
  token = page.parser.css("div#wrapperContent").first["class"]
  var = page.parser.css("li.listLi var").first
  comment_id = var["id"]
  public_id   = var["class"]

  # post to hidden api
  url    = "http://www.stumbleupon.com/ajax/edit/comment"
  params = {
    "syndicate_fb"  =>"syndicate_fb",
    "title"         => title,
    "token"         => token,
    "sticky_post"   => "0",
    "review"        => description,
    "tags"          => tags.join(", "),
    "publicid"      => public_id,
    "syndicate_tw"  => "syndicate_tw",
    "commentid"     => comment_id,
    "keep_date"     => "1"
  }

  page   = agent.post(url, params)
end

You can call that like this:

to_stumble_upon(
  :username => "your-username",
  :password => "your-password",
  :title => "A Title",
  :description => "A longer description",
  :tags => ["usability", "ruby", "web services", "open source"],
  :url => "http://your-site.com/a-path"
)

I figured out that ajax call to /ajax/edit/comment by checking in the “Net” menu in Firebug and copy/pasting the request with params. I was able to get a successful response with jQuery in Firebug that looks like this:

$.ajax({
  type:"POST",
  url:"http://www.stumbleupon.com/ajax/edit/comment",
  data:{"syndicate_fb":"syndicate_fb", "title":"title", "token":"asjdflakjfjafdlas", "review":"Imgur is a great service to host images.  It's free, simple, and it gives you neat analytics.  The only problem is, the Imgur interface uses cookies to associate images with a user, but the API does not.  This shows you how to make the API work the same.", "sticky_post":"0", "tags":"usability, ruby, web services, open source", "publicid":"15ylUi", "commentid":"44418172", "syndicate_tw":"syndicate_tw", "keep_date":"1"},
  success:function(data) { alert(data) },
  error:function(data) { alert(data) }
});

And the response looks like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
  <body>
    <p>
      {"commentid":"44418293","review":"Imgur is a great service to host images.  It's free, simple, and it gives you neat analytics.  The only problem is, the Imgur interface uses cookies to associate images with a user, but the API does not.  This shows you how to make the API work the same.","success":true}
    </p>
  </body>
</html>

Super simple.

Lance Pollard (viatropos)
Berkeley CA 94704 United States