diff --git a/app/models/author.rb b/app/models/author.rb
index 8b25ea831d2fb88a4190299b96b171a40f3e76f8..2f50c28cb9175ec302083ab7672d4482a81314bd 100644
--- a/app/models/author.rb
+++ b/app/models/author.rb
@@ -6,6 +6,7 @@ class Author
   key :avatar_thumbnail, String
   key :username, String
   key :profile_url, String
+  key :hub, String
 
   many :ostatus_posts, :class_name => 'OstatusPost', :foreign_key => :author_id
   before_save :set_defaults  
diff --git a/app/models/user.rb b/app/models/user.rb
index e78978d8a28535a3de01d73100566a55fb015e32..e01890dd29abd06529ac963e64932bf9f3507a27 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -85,6 +85,13 @@ class User < Person
     r
   end
 
+  def unsubscribe_from_pubsub(author_id)
+    bad_author = Author.first(:id => author_id)
+    r = Request.instantiate(:to => bad_author.hub, :from => self)
+    r.unsubscribe_from_ostatus(bad_author.feed_url)
+    bad_author.destroy
+  end
+
 
   def send_request(rel_hash)
     puts rel_hash.inspect
diff --git a/lib/common.rb b/lib/common.rb
index 2359b2b706e6f06602beb430a298baf0eb5b40b4..4448a719b9de77d5d1903a2868ac92a70944f64d 100644
--- a/lib/common.rb
+++ b/lib/common.rb
@@ -1,12 +1,15 @@
 module Diaspora
   module OStatusParser
     def self.find_hub(xml)
-      Nokogiri::HTML(xml).xpath('//link[@rel="hub"]').first.attribute("href").value
+      xml = Nokogiri::HTML(xml) if xml.is_a? String
+      xml.xpath('//link[@rel="hub"]').first.attribute("href").value
     end
 
     def self.process(xml)
       doc = Nokogiri::HTML(xml)
       author_hash = parse_author(doc)
+
+      author_hash[:hub] = find_hub(doc) 
       entry_hash = parse_entry(doc)
 
       author = Author.instantiate(author_hash)
@@ -139,6 +142,11 @@ module Diaspora
           @@queue.process
         end
 
+        def unsubscribe_from_ostatus(feed_url)
+          @@queue.add_hub_unsubscribe_request(self.destination_url, self.callback_url+'hubub', feed_url)
+          @@queue.process
+        end
+
         def push_to(recipients)
           @@queue.add_hub_notification(APP_CONFIG[:pubsub_server], User.owner.url + self.class.to_s.pluralize.underscore + '.atom')
           
diff --git a/lib/message_handler.rb b/lib/message_handler.rb
index b1e84524c18565853734d7e7cbb6a4771ca3c66e..1ce4fdad5598c9e7f0e87a24eb9f44146a2488b6 100644
--- a/lib/message_handler.rb
+++ b/lib/message_handler.rb
@@ -30,6 +30,9 @@ class MessageHandler
     @queue.push(Message.new(:hub_subscribe, hub_url, :body => feed_url))
   end
 
+  def add_hub_unsubscribe_request(hub, from, feed_url)
+    @queue.push(Message.new(:hub_unsubscribe, hub, :body => feed_url, :owner_url => from))
+  end
 
   def process_ostatus_subscription(query_object, http)
       hub = Diaspora::OStatusParser::find_hub(http.response)
@@ -37,6 +40,7 @@ class MessageHandler
       Diaspora::OStatusParser::process(http.response)
   end
 
+
   def process
     @queue.pop{ |query|
       case query.type
@@ -59,6 +63,9 @@ class MessageHandler
       when :hub_subscribe
         http = EventMachine::PubSubHubbub.new(query.destination).subscribe query.body, User.owner.url + 'hubbub',  :timeout => TIMEOUT 
         http.callback { process}
+      when :hub_unsubscribe
+        http = EventMachine::PubSubHubbub.new(query.destination).unsubscribe query.body, query.owner_url,  :timeout => TIMEOUT 
+        http.callback {process}
       else
         raise "message is not a type I know!"
       end
@@ -82,9 +89,10 @@ class MessageHandler
   end
 
   class Message
-    attr_accessor :type, :destination, :body, :callback, :try_count
+    attr_accessor :type, :destination, :body, :callback, :owner_url, :try_count
     def initialize(type, dest, opts = {})
       @type = type
+      @owner_url = opts[:owner_url]
       @destination = dest
       @body = opts[:body]
       @callback = opts[:callback] ||= lambda{ process; process }
diff --git a/spec/factories.rb b/spec/factories.rb
index 07baa2488b8a0b9076ce5e4655971a823c2ce95a..4ab541c548daa90ad598051ae98e3f21a662c680 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -26,7 +26,6 @@ Factory.define :user do |u|
   u.key_fingerprint GPGME.list_keys("Smith", true).first.subkeys.first.fingerprint
   u.profile Profile.new( :first_name => "Bob", :last_name => "Smith" )
 end
-
 Factory.define :status_message do |m|
   m.sequence(:message) {|n| "jimmy's #{n} whales"}
 end
@@ -48,4 +47,11 @@ Factory.define :photo do |p|
   p.image File.open( File.dirname(__FILE__) + '/fixtures/bp.jpeg')
 
 end
+
+Factory.define :author do |p|
+  p.hub  "http://pubsubhubub.appspot.com/"
+  p.service  "StatusNet"
+  p.username  "danielgrippi"
+  p.feed_url "http://google.com"
+end
 Factory.define(:comment) {}
diff --git a/spec/models/author_spec.rb b/spec/models/author_spec.rb
index 778c5ac3dd48837b24e80bee2ded0fcdaf7b4b4d..475c60df3ae81a81784a94702be4f78e3ef56c0c 100644
--- a/spec/models/author_spec.rb
+++ b/spec/models/author_spec.rb
@@ -5,7 +5,7 @@ include Diaspora::OStatusParser
 describe Author do
 
   it 'should create from ostatus compliant xml from the parser' do
-    xml_path = File.dirname(__FILE__) + '/../fixtures/ostatus_update.xml'
+    xml_path = File.dirname(__FILE__) + '/../fixtures/identica_feed.atom'
     xml = File.open(xml_path).read
 
     Author.count.should == 0
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 3ad53ceed7ac504f51cf20162d82063698ab8ee6..a6006ed1ddd2c604a0aa24daf8af6a3af258a3bc 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -46,4 +46,15 @@ describe User do
     user.terse_url.should == 'example.com'
   end
 
+  it 'should be able to unsubscribe from a status.net user' do
+    @user = Factory.create(:user)
+    author = Factory.create(:author)
+    Author.all.count.should == 1
+    q = Request.send :class_variable_get, :@@queue
+    q.stub!(:add_hub_unsubscribe_request)
+    q.should_receive(:add_hub_unsubscribe_request)
+
+    @user.unsubscribe_from_pubsub(author.id)  
+    Author.all.count.should == 0
+  end
 end