weibo_publish_agent.rb 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # encoding: utf-8
  2. module Agents
  3. class WeiboPublishAgent < Agent
  4. include WeiboConcern
  5. cannot_be_scheduled!
  6. description <<-MD
  7. The Weibo Publish Agent publishes tweets from the events it receives.
  8. #{'## Include `weibo_2` in your Gemfile to use this Agent!' if dependencies_missing?}
  9. You must first set up a Weibo app and generate an `access_token` for the user that will be used for posting status updates.
  10. You'll use that `access_token`, along with the `app_key` and `app_secret` for your Weibo app. You must also include the Weibo User ID (as `uid`) of the person to publish as.
  11. You must also specify a `message_path` parameter: a [JSONPaths](http://goessner.net/articles/JsonPath/) to the value to tweet.
  12. You can also specify a `pic_path` parameter: a [JSONPaths](http://goessner.net/articles/JsonPath/) to the picture url to tweet along.
  13. 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.
  14. MD
  15. def validate_options
  16. unless options['uid'].present? &&
  17. options['expected_update_period_in_days'].present?
  18. errors.add(:base, "expected_update_period_in_days and uid are required")
  19. end
  20. end
  21. def working?
  22. event_created_within?(interpolated['expected_update_period_in_days']) && most_recent_event && most_recent_event.payload['success'] == true && !recent_error_logs?
  23. end
  24. def default_options
  25. {
  26. 'uid' => "",
  27. 'access_token' => "---",
  28. 'app_key' => "---",
  29. 'app_secret' => "---",
  30. 'expected_update_period_in_days' => "10",
  31. 'message_path' => "text",
  32. 'pic_path' => "pic"
  33. }
  34. end
  35. def receive(incoming_events)
  36. # if there are too many, dump a bunch to avoid getting rate limited
  37. if incoming_events.count > 20
  38. incoming_events = incoming_events.first(20)
  39. end
  40. incoming_events.each do |event|
  41. tweet_text = Utils.value_at(event.payload, interpolated(event)['message_path'])
  42. pic_url = Utils.value_at(event.payload, interpolated(event)['pic_path'])
  43. if event.agent.type == "Agents::TwitterUserAgent"
  44. tweet_text = unwrap_tco_urls(tweet_text, event.payload)
  45. end
  46. begin
  47. if valid_image?(pic_url)
  48. publish_tweet_with_pic tweet_text, pic_url
  49. else
  50. publish_tweet tweet_text
  51. end
  52. create_event :payload => {
  53. 'success' => true,
  54. 'published_tweet' => tweet_text,
  55. 'published_pic' => pic_url,
  56. 'agent_id' => event.agent_id,
  57. 'event_id' => event.id
  58. }
  59. rescue OAuth2::Error => e
  60. create_event :payload => {
  61. 'success' => false,
  62. 'error' => e.message,
  63. 'failed_tweet' => tweet_text,
  64. 'failed_pic' => pic_url,
  65. 'agent_id' => event.agent_id,
  66. 'event_id' => event.id
  67. }
  68. end
  69. # you can't tweet too fast, give it a minute, i mean... 10 seconds
  70. sleep 10 if incoming_events.length > 1
  71. end
  72. end
  73. def publish_tweet text
  74. weibo_client.statuses.update text
  75. end
  76. def publish_tweet_with_pic text, pic
  77. weibo_client.statuses.upload text, open(pic)
  78. end
  79. def valid_image?(url)
  80. begin
  81. url = URI.parse(url)
  82. http = Net::HTTP.new(url.host, url.port)
  83. http.use_ssl = (url.scheme == "https")
  84. http.start do |http|
  85. # images supported #http://open.weibo.com/wiki/2/statuses/upload
  86. return ['image/gif', 'image/jpeg', 'image/png'].include? http.head(url.request_uri)['Content-Type']
  87. end
  88. rescue => e
  89. return false
  90. end
  91. end
  92. def unwrap_tco_urls text, tweet_json
  93. tweet_json[:entities][:urls].each do |url|
  94. text.gsub! url[:url], url[:expanded_url]
  95. end
  96. text
  97. end
  98. end
  99. end