diff --git a/app/models/jobs/delete_post_from_service.rb b/app/models/jobs/delete_post_from_service.rb new file mode 100644 index 000000000..b5a8302a7 --- /dev/null +++ b/app/models/jobs/delete_post_from_service.rb @@ -0,0 +1,14 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. +# +module Jobs + class DeletePostFromService < Base + @queue = :http_service + + def self.perform(service_id, service_post_id) + service = Service.find_by_id(service_id) + service.delete_post(service_post_id) + end + end +end diff --git a/app/models/post.rb b/app/models/post.rb index 9d3a85423..847f7ddda 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -66,6 +66,7 @@ class Post < ActiveRecord::Base def mentioned_people; []; end def photos; []; end + def self.excluding_blocks(user) people = user.blocks.map{|b| b.person_id} scope = scoped diff --git a/app/models/services/facebook.rb b/app/models/services/facebook.rb index 0cf1b6426..dcdd5fd43 100644 --- a/app/models/services/facebook.rb +++ b/app/models/services/facebook.rb @@ -13,7 +13,10 @@ class Services::Facebook < Service def post(post, url='') Rails.logger.debug("event=post_to_service type=facebook sender_id=#{self.user_id}") - post_to_facebook("https://graph.facebook.com/me/feed", create_post_params(post).to_param) + response = post_to_facebook("https://graph.facebook.com/me/feed", create_post_params(post).to_param) + response = JSON.parse response.body + post.facebook_id = response["id"] + post.save end def post_to_facebook(url, body) @@ -31,5 +34,14 @@ class Services::Facebook < Service def profile_photo_url "https://graph.facebook.com/#{self.uid}/picture?type=large&access_token=#{URI.escape(self.access_token)}" - end + end + + def delete_post(service_post_id) + Rails.logger.debug("event=delete_from_service type=facebook sender_id=#{self.user_id}") + delete_from_facebook("https://graph.facebook.com/#{service_post_id}/", {:access_token => self.access_token}) + end + + def delete_from_facebook(url, body) + Faraday.delete(url, body) + end end diff --git a/app/models/user.rb b/app/models/user.rb index ad4cf3ad4..2ac0408d4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -326,6 +326,7 @@ class User < ActiveRecord::Base if target.is_a?(Post) opts[:additional_subscribers] = target.resharers + opts[:services] = self.services end mailman = Postzord::Dispatcher.build(self, retraction, opts) diff --git a/db/migrate/20130207231310_add_facebook_id_to_post.rb b/db/migrate/20130207231310_add_facebook_id_to_post.rb new file mode 100644 index 000000000..df888dcca --- /dev/null +++ b/db/migrate/20130207231310_add_facebook_id_to_post.rb @@ -0,0 +1,5 @@ +class AddFacebookIdToPost < ActiveRecord::Migration + def change + add_column :posts, :facebook_id, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 53e90f688..11e42a8dd 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120909053122) do +ActiveRecord::Schema.define(:version => 20130207231310) do create_table "account_deletions", :force => true do |t| t.string "diaspora_handle" @@ -297,6 +297,7 @@ ActiveRecord::Schema.define(:version => 20120909053122) do t.datetime "interacted_at" t.string "frame_name" t.boolean "favorite", :default => false + t.string "facebook_id" end add_index "posts", ["author_id", "root_guid"], :name => "index_posts_on_author_id_and_root_guid", :unique => true diff --git a/lib/postzord/dispatcher.rb b/lib/postzord/dispatcher.rb index 7aacf9d86..67032dfd1 100644 --- a/lib/postzord/dispatcher.rb +++ b/lib/postzord/dispatcher.rb @@ -61,6 +61,8 @@ class Postzord::Dispatcher @object end + + protected # @return [Object] @@ -147,6 +149,11 @@ class Postzord::Dispatcher Resque.enqueue(Jobs::PostToService, service.id, @object.id, url) end end + if @object.instance_of?(SignedRetraction) + services.each do |service| + Resque.enqueue(Jobs::DeletePostFromService, service.id, @object.target.facebook_id) + end + end end # @param local_people [Array] diff --git a/spec/lib/postzord/dispatcher_spec.rb b/spec/lib/postzord/dispatcher_spec.rb index dabc95262..2a8c3492b 100644 --- a/spec/lib/postzord/dispatcher_spec.rb +++ b/spec/lib/postzord/dispatcher_spec.rb @@ -312,6 +312,15 @@ describe Postzord::Dispatcher do Resque.should_not_receive(:enqueue).with(Jobs::PostToService, anything, anything, anything) mailman.post end + + it 'queues a job to delete if given retraction' do + retraction = SignedRetraction.build(alice, FactoryGirl.create(:status_message)) + mailman = Postzord::Dispatcher.build(alice, retraction, :url => "http://joindiaspora.com/p/123", :services => [@service]) + + Resque.stub!(:enqueue).with(Jobs::DeletePostFromService, anything, anything) + Resque.should_receive(:enqueue).with(Jobs::DeletePostFromService, anything, anything) + mailman.post + end end describe '#and_notify_local_users' do diff --git a/spec/models/jobs/delete_post_from_service_spec.rb b/spec/models/jobs/delete_post_from_service_spec.rb new file mode 100644 index 000000000..397fcbcdb --- /dev/null +++ b/spec/models/jobs/delete_post_from_service_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe Jobs::DeletePostFromService do + before do + @user = alice + @post = @user.post(:status_message, :text => "hello", :to =>@user.aspects.first.id, :public =>true, :facebook_id => "23456" ) + end + + it 'calls service#delete_post with given service' do + m = mock() + url = "foobar" + m.should_receive(:delete_post) + Service.stub!(:find_by_id).and_return(m) + Jobs::DeletePostFromService.perform("123", @post.id.to_s) + end +end diff --git a/spec/models/services/facebook_spec.rb b/spec/models/services/facebook_spec.rb index b64d0aa7e..1da9d7931 100644 --- a/spec/models/services/facebook_spec.rb +++ b/spec/models/services/facebook_spec.rb @@ -4,7 +4,7 @@ describe Services::Facebook do before do @user = alice - @post = @user.post(:status_message, :text => "hello", :to =>@user.aspects.first.id, :public =>true) + @post = @user.post(:status_message, :text => "hello", :to =>@user.aspects.first.id, :public =>true, :facebook_id => "23456" ) @service = Services::Facebook.new(:access_token => "yeah") @user.services << @service end @@ -12,7 +12,7 @@ describe Services::Facebook do describe '#post' do it 'posts a status message to facebook' do stub_request(:post, "https://graph.facebook.com/me/feed"). - to_return(:status => 200, :body => "", :headers => {}) + to_return(:status => 200, :body => '{"id": "12345"}', :headers => {}) @service.post(@post) end @@ -26,7 +26,7 @@ describe Services::Facebook do it 'should call public message' do stub_request(:post, "https://graph.facebook.com/me/feed"). - to_return(:status => 200) + to_return(:status => 200, :body => '{"id": "12345"}', :headers => {}) url = "foo" @service.should_not_receive(:public_message) @service.post(@post, url) @@ -38,6 +38,13 @@ describe Services::Facebook do post_params = @service.create_post_params(post) post_params[:message].should match "Text with some bolded and italic parts." end + + it 'sets facebook id on post' do + stub_request(:post, "https://graph.facebook.com/me/feed"). + to_return(:status => 200, :body => '{"id": "12345"}', :headers => {}) + @service.post(@post) + @post.facebook_id.should match "12345" + end end @@ -49,4 +56,13 @@ describe Services::Facebook do "https://graph.facebook.com/abc123/picture?type=large&access_token=token123" end end + + describe '#delete_post' do + it 'removes a post from facebook' do + stub_request(:delete, "https://graph.facebook.com/#{@post.facebook_id}/?access_token=#{@service.access_token}"). + to_return(:status => 200) + + @service.delete_post(@post.facebook_id) + end + end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index f167d441d..b0d760da0 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -818,7 +818,7 @@ describe User do @post.reshares << reshare dispatcher = mock - Postzord::Dispatcher.should_receive(:build).with(bob, @retraction, {:additional_subscribers => [person]}).and_return(dispatcher) + Postzord::Dispatcher.should_receive(:build).with(bob, @retraction, {:additional_subscribers => [person], :services => anything}).and_return(dispatcher) dispatcher.should_receive(:post) bob.retract(@post)