Skip to content

@steveklabnik /http.rb
Created

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
A Shoes hypermedia client for ALPS microblogging
require 'net/http'
require 'open-uri'
require 'hpricot'
# A simple get request should not require this much boilerplate.
def fetch_data(uri)
uri = URI(uri)
req = Net::HTTP::Get.new(uri.request_uri)
req['Accept'] = "application/xhtml+xml"
res = Net::HTTP.start(uri.host, uri.port) {|http|
http.request(req)
}
Hpricot(res.body)
end
# I also like to wrap post requests, too. This is basically taken straight
# from the Net::HTTP docs: http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html
def post_data_with_auth(uri, username, password, data)
uri = URI(uri)
req = Net::HTTP::Post.new(uri.path)
req.basic_auth username, password
req.set_form_data(data)
res = Net::HTTP.start(uri.host, uri.port) do |http|
http.request(req)
end
case res
when Net::HTTPSuccess then
res
when Net::HTTPRedirection then
# We expect a redirect most of the time, and we'll want to
# follow the redirect.
res['location']
else
res.value
end
end
# An ALPS microblogging client.
#
# http://amundsen.com/hypermedia/profiles/
require 'ostruct'
require './http'
# We're going to want to save some configuration options
Config = OpenStruct.new
# The only URI we hard-code. Bonus points for making this configuration, too.
Config.root_uri = "http://alps-microblog.herokuapp.com/"
Config.current_uri = Config.root_uri
class MicroblogClient < Shoes
# We have two basic screens: the preferences setup screen, and our index,
# where all the action happens
url '/', :index
url '/preferences', :preferences
def index
current_data = fetch_data(Config.current_uri)
# We want to make sure that this gets set. We can't post stuff without it!
unless Config.username and Config.password
visit "/preferences"
end
if form = current_data.search("//form[@class='message-post']")
para "What's happening?", :size => "large"
flow do
message_text = edit_line
button "Post" do
uri = form.first['action']
Config.current_uri = post_data_with_auth(uri, Config.username, Config.password, :message => message_text.text)
visit "/"
end
end
end
if messages = current_data.search("//div[@id='messages']/ul[@class='all']")
stack do
para "All messages", :size => "large"
messages.search("li").each do |message|
text = message.search("//span[@class='message-text']").inner_html.strip
user = message.search("//span[@class='user-text']").inner_html
para "'#{text}' - @#{user}"
end
end
end
button "refresh", :right => 10, :top => 5, :align => "right" do
visit "/"
end
end
# This preferences screen will allow us to set our username and password
# so that we don't have to re-authenticate per request
def preferences
para "Account Information", :size => "large"
stack do
user_edit = nil
pass_edit = nil
root_edit = nil
flow do
para "Username:"
user_edit = edit_line
end
flow do
para "Password:"
pass_edit = edit_line :secret => true
end
flow do
para "Root URI:"
root_edit = edit_line :width => 300
root_edit.text = Config.root_uri
end
button "Save" do
Config.username = user_edit.text
Config.password = pass_edit.text
Config.root_uri = root_edit.text
visit "/"
end
end
end
end
Shoes.app :title => "ALPS Microblogging Client"
@carols10cents

zomg 80 chars!!!11!!1!11 :heart:

@steveklabnik
Owner

inorite

@mamund

Good to see this here!

Just a note. The ALPS spec doesn't mean that only certain class names will appear on an element (link, form, etc.). You proly need to use contains() in your XPath queries when checking for a class name on a div, span, form, etc..

@steveklabnik

I'm guessing you got @clnclarinet's emails, then. :) I will have to update my code.

@mamund
@carols10cents

sorry about that, @steveklabnik ;)

@steveklabnik

No need to be sorry!

@mamund

The rel attribute should also be treated the same way; it could contain multiple white-space separated values.

@carols10cents

I decided to make a repo so I can describe the changes I'm making: https://github.com/clnclarinet/shoes-alps-client

@mamund
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.