diff --git a/app/models/agents/weibo_publish_agent.rb b/app/models/agents/weibo_publish_agent.rb index 1c733c50..073a511f 100644 --- a/app/models/agents/weibo_publish_agent.rb +++ b/app/models/agents/weibo_publish_agent.rb @@ -1,4 +1,4 @@ -# encoding: utf-8 +# encoding: utf-8 module Agents class WeiboPublishAgent < Agent @@ -17,6 +17,8 @@ module Agents You must also specify a `message_path` parameter: a [JSONPaths](http://goessner.net/articles/JsonPath/) to the value to tweet. + You can also specify a `pic_path` parameter: a [JSONPaths](http://goessner.net/articles/JsonPath/) to the picture url to tweet along. + Set `expected_update_period_in_days` to the maximum amount of time that you'd expect to pass between Events being created by this Agent. MD @@ -28,7 +30,7 @@ module Agents end def working? - event_created_within?(interpolated['expected_update_period_in_days']) && most_recent_event.payload['success'] == true && !recent_error_logs? + event_created_within?(interpolated['expected_update_period_in_days']) && most_recent_event && most_recent_event.payload['success'] == true && !recent_error_logs? end def default_options @@ -38,7 +40,8 @@ module Agents 'app_key' => "---", 'app_secret' => "---", 'expected_update_period_in_days' => "10", - 'message_path' => "text" + 'message_path' => "text", + 'pic_path' => "pic" } end @@ -49,14 +52,20 @@ module Agents end incoming_events.each do |event| tweet_text = Utils.value_at(event.payload, interpolated(event)['message_path']) + pic_url = Utils.value_at(event.payload, interpolated(event)['pic_path']) if event.agent.type == "Agents::TwitterUserAgent" tweet_text = unwrap_tco_urls(tweet_text, event.payload) end begin - publish_tweet tweet_text + if valid_image?(pic_url) + publish_tweet_with_pic tweet_text, pic_url + else + publish_tweet tweet_text + end create_event :payload => { 'success' => true, 'published_tweet' => tweet_text, + 'published_pic' => pic_url, 'agent_id' => event.agent_id, 'event_id' => event.id } @@ -65,10 +74,13 @@ module Agents 'success' => false, 'error' => e.message, 'failed_tweet' => tweet_text, + 'failed_pic' => pic_url, 'agent_id' => event.agent_id, 'event_id' => event.id } end + # you can't tweet too fast, give it a minute, i mean... 10 seconds + sleep 10 if incoming_events.length > 1 end end @@ -76,6 +88,24 @@ module Agents weibo_client.statuses.update text end + def publish_tweet_with_pic text, pic + weibo_client.statuses.upload text, open(pic) + end + + def valid_image?(url) + begin + url = URI.parse(url) + http = Net::HTTP.new(url.host, url.port) + http.use_ssl = (url.scheme == "https") + http.start do |http| + # images supported #http://open.weibo.com/wiki/2/statuses/upload + return ['image/gif', 'image/jpeg', 'image/png'].include? http.head(url.request_uri)['Content-Type'] + end + rescue => e + return false + end + end + def unwrap_tco_urls text, tweet_json tweet_json[:entities][:urls].each do |url| text.gsub! url[:url], url[:expanded_url] diff --git a/spec/models/agents/weibo_publish_agent_spec.rb b/spec/models/agents/weibo_publish_agent_spec.rb index 5c599d89..39b84cb8 100644 --- a/spec/models/agents/weibo_publish_agent_spec.rb +++ b/spec/models/agents/weibo_publish_agent_spec.rb @@ -1,4 +1,4 @@ -# encoding: utf-8 +# encoding: utf-8 require 'rails_helper' describe Agents::WeiboPublishAgent do @@ -9,7 +9,8 @@ describe Agents::WeiboPublishAgent do :app_key => "---", :app_secret => "---", :access_token => "---", - :message_path => "text" + :message_path => "text", + :pic_path => "pic" } @checker = Agents::WeiboPublishAgent.new(:name => "Weibo Publisher", :options => @opts) @@ -22,7 +23,9 @@ describe Agents::WeiboPublishAgent do @event.save! @sent_messages = [] + @sent_pictures = [] stub.any_instance_of(Agents::WeiboPublishAgent).publish_tweet { |message| @sent_messages << message} + stub.any_instance_of(Agents::WeiboPublishAgent).publish_tweet_with_pic { |message, picture| @sent_pictures << picture} end describe '#receive' do @@ -52,11 +55,43 @@ describe Agents::WeiboPublishAgent do Agents::WeiboPublishAgent.async_receive(@checker.id, [event.id]) expect(@sent_messages.count).to eq(1) + expect(@sent_pictures.count).to eq(0) expect(@checker.events.count).to eq(1) expect(@sent_messages.first.include?("t.co")).not_to be_truthy end end + describe '#receive payload with picture url' do + before do + stub_request(:head, 'http://valid.image').to_return(status: 200, headers: {"Content-Type" => "image/jpeg"}) + stub_request(:head, 'http://invalid.image').to_return(status: 200, headers: {"Content-Type" => "text/html"}) + end + + it 'should publish a tweet without a picture if image url is not valid' do + event = Event.new + event.agent = agents(:bob_weather_agent) + event.payload = {:text => 'whatever', :pic => 'http://invalid.image'} + event.save! + + Agents::WeiboPublishAgent.async_receive(@checker.id, [event.id]) + expect(@sent_messages.count).to eq(1) + expect(@sent_pictures.count).to eq(0) + expect(@checker.events.count).to eq(1) + end + + it 'should publish a tweet along with a picture if image url is valid' do + event = Event.new + event.agent = agents(:bob_weather_agent) + event.payload = {:text => 'whatever', :pic => 'http://valid.image'} + event.save! + + Agents::WeiboPublishAgent.async_receive(@checker.id, [event.id]) + expect(@sent_messages.count).to eq(0) + expect(@sent_pictures.count).to eq(1) + expect(@checker.events.count).to eq(1) + end + end + describe '#working?' do it 'checks if events have been received within the expected receive period' do expect(@checker).not_to be_working # No events received