require 'uri' require 'net/http' require 'fusefs' require 'rexml/document' class Twitter User = Struct.new(:user_id, :screen_name, :status) def initialize(username, password) @username, @password = username, password @status = nil @users = {} @friends = nil @followers = nil end attr_reader :followers, :friends, :status def user(s) @users[s] end def crawl @friends = crawl_users('/statuses/friends.xml') @followers = crawl_users('/statuses/followers.xml') end def status=(s) @status = s req = create_request('/statuses/update.json') req.body = 'status=' + URI.encode(@status) post(req) end private def crawl_users(path) result = [] req = create_request(path) doc = REXML::Document.new(post(req)) doc.root.elements.each('/users/user') do |u| ary = (%w(id screen_name status/text).collect do |i| u.elements[i].text end) result << update_user(*ary) end result end def update_user(user_id, screen_name, status) u = @users[screen_name] if u u.status = status else @users[screen_name] = User.new(user_id, screen_name, status) end end def create_request(path) req = Net::HTTP::Post.new(path) req.basic_auth(@username, @password) req end def post(req) result = nil Net::HTTP.start('twitter.com', 80) do |http| resp = http.request(req) result = resp.body end result end end class TwitterFS def initialize(username, password) @twitter = Twitter.new(username, password) @twitter.crawl end def contents(path) case path when '/' %w(me friends followers) when '/friends' @twitter.friends.collect do |f| f.screen_name end when '/followers' @twitter.followers.collect do |f| f.screen_name end end end def file?(path) not directory?(path) end def directory?(path) path == '/friends' or path == '/followers' end def read_file(path) if path =~ %r{^/friends/} or path =~ %r{^/followers/} @twitter.user(File.basename(path)).status elsif path == '/me' @twitter.status else '' end + "\n" end def size(path) read_file(path).length end def can_delete?(path) can_write?(path) end def can_write?(path) path == '/me' end def write_to(path, body) if path == '/me' @twitter.status = body else raise end end end exit if ARGV.length != 3 username, password, path = *ARGV fs = TwitterFS.new(username, password) FuseFS.set_root(fs) FuseFS.mount_under(path) FuseFS.run