diff --git a/app/models/service.rb b/app/models/service.rb index 93bd741cb..cb1d776ac 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -4,7 +4,8 @@ class Service include MongoMapper::Document - + include ActionView::Helpers::TextHelper + belongs_to :user key :provider, String @@ -14,10 +15,15 @@ class Service key :nickname, String timestamps! - def public_message(length, url = "") + def public_message(post, length, url = "") space_for_url = url.blank? ? 0 : (url.length + 1) - truncated = truncate(self.message, :length => (length - space_for_url)) + truncated = truncate(post.message, :length => (length - space_for_url)) truncated = "#{truncated} #{url}" unless url.blank? return truncated end + + + def post + raise "NotImplementedError: you must instantiate a subclass" + end end diff --git a/app/models/services/facebook.rb b/app/models/services/facebook.rb index 338416e6b..69abb4caa 100644 --- a/app/models/services/facebook.rb +++ b/app/models/services/facebook.rb @@ -1,10 +1,17 @@ class Services::Facebook < Service - def post(message) + MAX_CHARACTERS = 420 + + def post(post, url='') Rails.logger.debug("event=post_to_service type=facebook sender_id=#{self.user_id}") + message = public_message(post, url) begin RestClient.post("https://graph.facebook.com/me/feed", :message => message, :access_token => self.access_token) rescue Exception => e Rails.logger.info("#{e.message} failed to post to facebook") end end + + def public_message(post, url) + super(post, MAX_CHARACTERS, url) + end end diff --git a/app/models/services/twitter.rb b/app/models/services/twitter.rb index 373dbdf23..aeecf8c0c 100644 --- a/app/models/services/twitter.rb +++ b/app/models/services/twitter.rb @@ -1,6 +1,9 @@ class Services::Twitter < Service - def post(message) - Rails.logger.debug("event=post_to_service type=twitter sender_id=#{self.user_id}") + MAX_CHARACTERS = 140 + + def post(post, url='') + Rails.logger.debug("event=post_to_service type=twitter sender_id=#{self.user_id}") + message = public_message(post, url) twitter_key = SERVICES['twitter']['consumer_key'] twitter_consumer_secret = SERVICES['twitter']['consumer_secret'] @@ -15,7 +18,15 @@ class Services::Twitter < Service config.oauth_token = self.access_token config.oauth_token_secret = self.access_secret end - - Twitter.update(message) + + begin + Twitter.update(message) + rescue Exception => e + Rails.logger.info e.message + end + end + + def public_message(post, url) + super(post, MAX_CHARACTERS, url) end end diff --git a/app/models/user.rb b/app/models/user.rb index b6d2af2c4..e2fac1364 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -151,22 +151,15 @@ class User def dispatch_post(post, opts = {}) aspect_ids = opts.delete(:to) - #socket post Rails.logger.info("event=dispatch user=#{diaspora_handle} post=#{post.id.to_s}") push_to_aspects(post, aspects_from_ids(aspect_ids)) + post_to_services(post, opts[:url]) + end - if post.public && post.respond_to?(:message) - - if opts[:url] && post.photos.count > 0 - - message = truncate(post.message, :length => (140 - (opts[:url].length + 1))) - message = "#{message} #{opts[:url]}" - else - message = post.message - end - + def post_to_services(post, url) + if post.public && post.respond_to?(:message) self.services.each do |service| - service.post(message) + service.post(post.message) end end end diff --git a/app/views/services/index.html.haml b/app/views/services/index.html.haml index 8a593179e..883ae1eba 100644 --- a/app/views/services/index.html.haml +++ b/app/views/services/index.html.haml @@ -21,7 +21,7 @@ = t('.logged_in_as') %b = service.nickname - = link_to t('.disconnect'), service, :confirm => t('.really_disconnect', :service => service.provider), :method => :delete + = link_to t('.disconnect'), service_path(service), :confirm => t('.really_disconnect', :service => service.provider), :method => :delete %h4= link_to image_tag('services/twitter_sign_in.png'), "/auth/twitter" if SERVICES['twitter']['consumer_key']!= "" %h4= link_to image_tag('services/facebook_sign_in.png'), "/auth/facebook" if SERVICES['facebook']['app_id'] !="" diff --git a/spec/controllers/status_message_controller_spec.rb b/spec/controllers/status_message_controller_spec.rb index 3915bd5ec..83ad36017 100644 --- a/spec/controllers/status_message_controller_spec.rb +++ b/spec/controllers/status_message_controller_spec.rb @@ -55,6 +55,7 @@ describe StatusMessagesController do post :create, status_message_hash.merge(:format => 'js') response.status.should == 201 end + it "doesn't overwrite person_id" do new_user = make_user status_message_hash[:status_message][:person_id] = new_user.person.id @@ -85,45 +86,7 @@ describe StatusMessagesController do user.should_receive(:dispatch_post).exactly(3).times post :create, hash end - - context "posting out to facebook" do - let!(:service2) { s = Factory(:service, :provider => 'facebook'); user.services << s; s } - - it 'should post to facebook when public is set' do - user.should_receive(:post_to_facebook) - post :create, status_message_hash - end - - it 'should not post to facebook when public is not set' do - status_message_hash[:status_message][:public] = 'false' - user.should_not_receive(:post_to_facebook) - post :create, status_message_hash - end - - it 'should include the permalink to the post' do - pending - end - end - - context "posting to twitter" do - let!(:service1) { s = Factory(:service, :provider => 'twitter'); user.services << s; s } - - it 'should post to twitter if public is set' do - user.should_receive(:post_to_twitter).and_return(true) - post :create, status_message_hash - end - - it 'should not post to twitter when public in not set' do - status_message_hash[:status_message][:public] = 'false' - user.should_not_receive(:post_to_twitter) - post :create, status_message_hash - end - - it 'should include a permalink to the post' do - end - end end - describe '#destroy' do let!(:message) {user.post(:status_message, :message => "hey", :to => aspect.id)} let!(:message2) {user2.post(:status_message, :message => "hey", :to => aspect2.id)} diff --git a/spec/factories.rb b/spec/factories.rb index 0b30ddd4d..ef90d99a4 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -67,6 +67,9 @@ Factory.define :service do |service| service.sequence(:uid) { |token| "00000#{token}" } service.sequence(:access_token) { |token| "12345#{token}" } service.sequence(:access_secret) { |token| "98765#{token}" } + service.after_build do |s| + s._type = "Services::#{s.provider.camelize}" + end end Factory.define(:comment) {} diff --git a/spec/models/services/facebook_spec.rb b/spec/models/services/facebook_spec.rb index b239b4ac5..19385c935 100644 --- a/spec/models/services/facebook_spec.rb +++ b/spec/models/services/facebook_spec.rb @@ -13,11 +13,30 @@ describe Services::Facebook do describe '#post' do it 'posts a status message to facebook' do RestClient.should_receive(:post).with("https://graph.facebook.com/me/feed", :message => @post.message, :access_token => @service.access_token) - @service.post(@post.message) + @service.post(@post) end it 'swallows exception raised by facebook always being down' do RestClient.should_receive(:post).and_raise - @service.post(@post.message) + @service.post(@post) + end + + it 'should call public message' do + RestClient.stub!(:post) + url = "foo" + @service.should_receive(:public_message).with(@post, url) + @service.post(@post, url) + end + end + + + describe '.public_message' do + it 'calls super with MAX_CHARACTERS' do + pending "i guess you cant test this?" + message = mock() + message.should_receive(:message).and_return("foo") + service = Services::Facebook.new + service.should_receive(:super).with(message, Services::Facebook::MAX_CHARACTERS, "url") + service.public_message(message, "url") end end end diff --git a/spec/models/services/twitter_spec.rb b/spec/models/services/twitter_spec.rb index 63720a350..de4cc008b 100644 --- a/spec/models/services/twitter_spec.rb +++ b/spec/models/services/twitter_spec.rb @@ -13,7 +13,19 @@ describe Services::Twitter do describe '#post' do it 'posts a status message to twitter' do Twitter.should_receive(:update).with(@post.message) - @service.post(@post.message) + @service.post(@post) + end + + it 'swallows exception raised by twitter always being down' do + Twitter.should_receive(:update).and_raise + @service.post(@post) + end + + it 'should call public message' do + Twitter.stub!(:update) + url = "foo" + @service.should_receive(:public_message).with(@post, url) + @service.post(@post, url) end end end diff --git a/spec/models/user/posting_spec.rb b/spec/models/user/posting_spec.rb index f587886ad..047fd2b05 100644 --- a/spec/models/user/posting_spec.rb +++ b/spec/models/user/posting_spec.rb @@ -71,23 +71,20 @@ describe User do end - describe 'services' + describe '#post_to_services' do + it 'only iterates through services if the post is public' do + user.should_receive(:services).and_return([]) + user.post(:status_message, :message => "foo", :public => true, :to => user.aspects.first.id) + end + end describe '#dispatch_post' do - include Rails.application.routes.url_helpers let(:status) {user.build_post(:status_message, @status_opts)} before do @message = "hello, world!" @status_opts = {:to => "all", :message => @message} end - it "posts to services if post is public" do - @status_opts[:public] = true - status.save - user.should_receive(:post_to_twitter).with(service1, @message).once - user.should_receive(:post_to_facebook).with(service2, @message).once - user.dispatch_post(status, :to => "all") - end it "posts to a pubsub hub if enabled" do EventMachine::PubSubHubbub.should_receive(:new).and_return(FakeHttpRequest.new(:success)) @@ -101,57 +98,17 @@ describe User do } end - it "does not post to services if post is not public" do - @status_opts[:public] = false - status.save - user.should_not_receive(:post_to_twitter) - user.should_not_receive(:post_to_facebook) + it "calls post_to_services" do + user.should_receive(:post_to_services) user.dispatch_post(status, :to => "all") end - it 'does not include a permalink' do - @status_opts[:public] = true - status.save - user.should_receive(:post_to_twitter).with(service1, @message).once - user.should_receive(:post_to_facebook).with(service2, @message).once - user.dispatch_post(status, :to => "all", :url => post_path(status)) + it 'pushes to aspects' do + user.should_receive(:push_to_aspects) + user.dispatch_post(status, :to => "all") end - - it 'includes a permalink' do - fixture_filename = 'button.png' - fixture_name = File.join(File.dirname(__FILE__), '..', '..', 'fixtures', fixture_filename) - - photo1 = user.build_post(:photo, :user_file=> File.open(fixture_name), :to => aspect.id) - photo1.save! - - @status_opts[:public] = true - @status_opts[:photo_id] = photo1.id - status.save - - user.should_receive(:post_to_twitter).with(service1, @message).once - user.should_receive(:post_to_facebook).with(service2, @message).once - user.dispatch_post(status, :to => "all", :url => post_path(status)) - end - - it 'only pushes to services if it is a status message' do - photo = Photo.new() - photo.public = true - user.stub!(:push_to_aspects) - user.should_not_receive(:post_to_twitter) - user.should_not_receive(:post_to_facebook) - user.dispatch_post(photo, :to =>"all") - end end - describe '#post' do - it 'should not create a post with invalid aspect' do - pending "this would just cause db polution" - proc { - user.post(:status_message, :message => "hey", :to => aspect2.id) - }.should_not change(Post, :count) - end - end - describe '#update_post' do it 'should update fields' do photo = user.post(:photo, :user_file => uploaded_photo, :caption => "Old caption", :to => aspect.id)