twitter_user_agent.rb 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. require "twitter"
  2. module Agents
  3. class TwitterUserAgent < Agent
  4. cannot_receive_events!
  5. description <<-MD
  6. The TwitterUserAgent follows the timeline of a specified Twitter user.
  7. You must set up a Twitter app and provide it's `consumer_key`, `consumer_secret`, `oauth_token` and `oauth_token_secret`, (Also shown as "Access token" on the Twitter developer's site.) along with the `username` of the Twitter user to monitor.
  8. 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.
  9. MD
  10. event_description <<-MD
  11. Events are the raw JSON provided by the Twitter API. Should look something like:
  12. {
  13. :created_at=>"Thu Apr 04 13:27:48 +0000 2013",
  14. :id=>319803490421596160,
  15. :id_str=>"319803490421596160",
  16. :text=>
  17. "In which @jeresig goes to an art gallery and is \"the JavaScript programmer\". http://t.co/gt3PT1d3G1",
  18. :source=>
  19. "<a href=\"http://itunes.apple.com/us/app/twitter/id409789998?mt=12\" rel=\"nofollow\">Twitter for Mac</a>",
  20. :truncated=>false,
  21. :in_reply_to_status_id=>nil,
  22. :in_reply_to_status_id_str=>nil,
  23. :in_reply_to_user_id=>nil,
  24. :in_reply_to_user_id_str=>nil,
  25. :in_reply_to_screen_name=>nil,
  26. :user=>
  27. {:id=>2341001,
  28. :id_str=>"2341001",
  29. :name=>"Albert Sun",
  30. :screen_name=>"albertsun",
  31. :location=>"New York, NY",
  32. :description=>
  33. "News apps developer at NYT, formerly WSJ. graduated Penn 2010, geek, journalist, data-viz, nlp, gis, digital economics =)",
  34. :url=>"http://albertsun.info",
  35. :entities=>
  36. {:url=>
  37. {:urls=>
  38. [{:url=>"http://albertsun.info",
  39. :expanded_url=>nil,
  40. :indices=>[0, 21]}]},
  41. :description=>{:urls=>[]}},
  42. :protected=>false,
  43. :followers_count=>1857,
  44. :friends_count=>798,
  45. :listed_count=>115,
  46. :created_at=>"Mon Mar 26 19:22:05 +0000 2007",
  47. :favourites_count=>9,
  48. :utc_offset=>-18000,
  49. :time_zone=>"Eastern Time (US & Canada)",
  50. :geo_enabled=>false,
  51. :verified=>false,
  52. :statuses_count=>2572,
  53. :lang=>"en",
  54. :contributors_enabled=>false,
  55. :is_translator=>false,
  56. :profile_background_color=>"1B2A2B",
  57. :profile_background_image_url=>
  58. "http://a0.twimg.com/profile_background_images/2802438/twitterbg.jpg",
  59. :profile_background_image_url_https=>
  60. "https://si0.twimg.com/profile_background_images/2802438/twitterbg.jpg",
  61. :profile_background_tile=>false,
  62. :profile_image_url=>
  63. "http://a0.twimg.com/profile_images/110500205/profile-square_normal.jpg",
  64. :profile_image_url_https=>
  65. "https://si0.twimg.com/profile_images/110500205/profile-square_normal.jpg",
  66. :profile_link_color=>"0000FF",
  67. :profile_sidebar_border_color=>"87BC44",
  68. :profile_sidebar_fill_color=>"E0FF92",
  69. :profile_text_color=>"000000",
  70. :profile_use_background_image=>true,
  71. :default_profile=>false,
  72. :default_profile_image=>false,
  73. :following=>false,
  74. :follow_request_sent=>false,
  75. :notifications=>false},
  76. :geo=>nil,
  77. :coordinates=>nil,
  78. :place=>nil,
  79. :contributors=>nil,
  80. :retweet_count=>0,
  81. :favorite_count=>0,
  82. :entities=>
  83. {:hashtags=>[],
  84. :urls=>
  85. [{:url=>"http://t.co/gt3PT1d3G1",
  86. :expanded_url=>
  87. "http://www.nytimes.com/2013/04/04/fashion/art-and-techology-a-clash-of-cultures.html?pagewanted=all",
  88. :display_url=>"nytimes.com/2013/04/04/fas",
  89. :indices=>[77, 99]}],
  90. :user_mentions=>
  91. [{:screen_name=>"jeresig",
  92. :name=>"John Resig",
  93. :id=>752673,
  94. :id_str=>"752673",
  95. :indices=>[9, 17]}]},
  96. :favorited=>false,
  97. :retweeted=>false,
  98. :possibly_sensitive=>false,
  99. :lang=>"en"
  100. }
  101. MD
  102. default_schedule "every_1h"
  103. def validate_options
  104. unless options[:username].present? && options[:expected_update_period_in_days].present? && options[:consumer_key].present? && options[:consumer_secret].present? && options[:oauth_token].present? && options[:oauth_token_secret].present?
  105. errors.add(:base, "expected_update_period_in_days, username, consumer_key, consumer_secret, oauth_token and oauth_token_secret are required")
  106. end
  107. end
  108. def working?
  109. (event = event_created_within(options[:expected_update_period_in_days].to_i.days)) && event.payload.present?
  110. end
  111. def default_options
  112. {
  113. :username => "tectonic",
  114. :expected_update_period_in_days => "2",
  115. :consumer_key => "---",
  116. :consumer_secret => "---",
  117. :oauth_token => "---",
  118. :oauth_token_secret => "---"
  119. }
  120. end
  121. def check
  122. Twitter.configure do |config|
  123. config.consumer_key = options[:consumer_key]
  124. config.consumer_secret = options[:consumer_secret]
  125. config.oauth_token = options[:oauth_token]
  126. config.oauth_token_secret = options[:oauth_token_secret]
  127. end
  128. since_id = memory[:since_id] || nil
  129. opts = {:count => 200, :include_rts => true, :exclude_replies => false, :include_entities => true, :contributor_details => true}
  130. opts.merge! :since_id => since_id unless since_id.nil?
  131. tweets = Twitter.user_timeline(options[:username], opts)
  132. tweets.each do |tweet|
  133. memory[:since_id] = tweet.id if !memory[:since_id] || (tweet.id > memory[:since_id])
  134. create_event :payload => tweet.attrs
  135. end
  136. save!
  137. end
  138. end
  139. end