Created
March 24, 2012 20:27
-
-
Save steveklabnik/2187514 to your computer and use it in GitHub Desktop.
A Shoes hypermedia client for ALPS microblogging
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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" |
inorite
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..
I'm guessing you got @clnclarinet's emails, then. :) I will have to update my code.
yep. exchanged emails w/ her today.
let me know if there is anything i can do for you (or Carol) to help
make ALPS microblogging better.
thanks for all your support/interest; you rock, dude!
…On Fri, Apr 27, 2012 at 17:57, Steve Klabnik ***@***.*** wrote:
I'm guessing you got @clnclarinet's emails, then. :) I will have to update my code.
---
Reply to this email directly or view it on GitHub:
https://gist.github.com/2187514
sorry about that, @steveklabnik ;)
No need to be sorry!
The rel
attribute should also be treated the same way; it could contain multiple white-space separated values.
I decided to make a repo so I can describe the changes I'm making: https://github.com/clnclarinet/shoes-alps-client
excellent.
watched!
ping me any time and i'd be happy to work w/ you to improve the profile.
mca
http://amundsen.com/blog/
http://twitter.com@mamund
http://mamund.com/foaf.rdf#me
…On Tue, May 8, 2012 at 9:34 PM, Carol Nichols ***@***.*** wrote:
I decided to make a repo so I can describe the changes I'm making: https://github.com/clnclarinet/shoes-alps-client
---
Reply to this email directly or view it on GitHub:
https://gist.github.com/2187514
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
zomg 80 chars!!!11!!1!11 ❤️