Class: TrumpcareTracker

Inherits:
Object
  • Object
show all
Defined in:
lib/trumpcare_tracker.rb,
lib/trumpcare_tracker/version.rb,
lib/trumpcare_tracker/rake_task.rb,
lib/trumpcare_tracker/reporters.rb,
lib/trumpcare_tracker/tweet_bot.rb

Overview

Track the Twitter mentions of Trumpcare by Democratic US Senators

Defined Under Namespace

Classes: RakeTask, Reporters, TweetBot

Constant Summary collapse

CONSUMER_KEY =
ENV['TCT_CONSUMER_KEY']
CONSUMER_SECRET =
ENV['TCT_CONSUMER_SECRET']
ACCESS_TOKEN =
ENV['TCT_ACCESS_TOKEN']
ACCESS_TOKEN_SECRET =
ENV['TCT_ACCESS_TOKEN_SECRET']
VERSION =
'0.1.11'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user, screen_name, alt_screen_name = '') ⇒ TrumpcareTracker

Returns a new instance of TrumpcareTracker.



33
34
35
36
37
38
39
# File 'lib/trumpcare_tracker.rb', line 33

def initialize(user, screen_name, alt_screen_name = '')
  @audited         = false
  @requests        = 0
  @user            = user
  @screen_name     = screen_name.to_s
  @alt_screen_name = alt_screen_name.to_s
end

Instance Attribute Details

#alt_screen_nameObject (readonly)

Returns the value of attribute alt_screen_name.



14
15
16
# File 'lib/trumpcare_tracker.rb', line 14

def alt_screen_name
  @alt_screen_name
end

#requestsObject (readonly)

Returns the value of attribute requests.



14
15
16
# File 'lib/trumpcare_tracker.rb', line 14

def requests
  @requests
end

#screen_nameObject (readonly)

Returns the value of attribute screen_name.



14
15
16
# File 'lib/trumpcare_tracker.rb', line 14

def screen_name
  @screen_name
end

#userObject (readonly)

Returns the value of attribute user.



14
15
16
# File 'lib/trumpcare_tracker.rb', line 14

def user
  @user
end

Class Method Details

.percentage(numerator, denominator) ⇒ Object



21
22
23
# File 'lib/trumpcare_tracker.rb', line 21

def self.percentage(numerator, denominator)
  (ratio(numerator, denominator) * 100).round(2)
end

.ratio(numerator, denominator) ⇒ Object



16
17
18
19
# File 'lib/trumpcare_tracker.rb', line 16

def self.ratio(numerator, denominator)
  return 0.0 if denominator.zero?
  (numerator / denominator.to_f).round(4)
end

.russia_keyword_regexObject



29
30
31
# File 'lib/trumpcare_tracker.rb', line 29

def self.russia_keyword_regex
  /(russia|comey|sessions|mueller|fbi|flynn|obstruction of justice|collusion|putin|kremlin|kislyak|attorney general| intelligence committee|rosenstein|witch hunt|impeach|perjur|under oath)/
end

.trumpcare_keyword_regexObject



25
26
27
# File 'lib/trumpcare_tracker.rb', line 25

def self.trumpcare_keyword_regex
  /(ahca|trumpcare|healthcare|health|care|drug|medic|prescription|vaccin|obamacare|cbo|premiums|insurance|deductibles|aca.| aca |aca |o-care|a.h.c.a|a.c.a|pre-existing conditions|hhs|showusthebill|show us the bill|opioid)/
end

Instance Method Details

#age_of_tweet_in_days(tweet) ⇒ Object



93
94
95
# File 'lib/trumpcare_tracker.rb', line 93

def age_of_tweet_in_days(tweet)
  (Time.now - tweet.created_at) / 86_400
end

#auditObject



134
135
136
137
# File 'lib/trumpcare_tracker.rb', line 134

def audit
  filter_by_keywords unless audited?
  @audited = true
end

#audited?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/trumpcare_tracker.rb', line 41

def audited?
  @audited
end

#clientObject

Instantiate a Twitter Rest Client with API authorization



46
47
48
49
50
51
52
53
# File 'lib/trumpcare_tracker.rb', line 46

def client
  @_client ||= Twitter::REST::Client.new do |config|
    config.consumer_key        = CONSUMER_KEY
    config.consumer_secret     = CONSUMER_SECRET
    config.access_token        = ACCESS_TOKEN
    config.access_token_secret = ACCESS_TOKEN_SECRET
  end
end

#fetch_older_tweets(timeline, screen_name) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/trumpcare_tracker.rb', line 70

def fetch_older_tweets(timeline, screen_name)
  return timeline if age_of_tweet_in_days(timeline.last) > 7
  @requests += 1
  first_count = timeline.count
  timeline += client.user_timeline(
    screen_name,
    tweet_mode: 'extended',
    max_id: timeline.last.id - 1,
    count: 200
  )
  second_count = timeline.count
  return timeline if second_count == first_count
  fetch_older_tweets(timeline, screen_name)
end

#fetch_timeline(screen_name) ⇒ Object

Make two cursored API calls to fetch the 400 most recent tweets



60
61
62
63
64
65
66
67
68
# File 'lib/trumpcare_tracker.rb', line 60

def fetch_timeline(screen_name)
  return [] if screen_name.to_s.empty?
  @requests += 1
  timeline = client.user_timeline(screen_name, tweet_mode: 'extended', count: 200)
  return timeline if timeline.empty?
  timeline = fetch_older_tweets(timeline, screen_name)
  puts "Fetched #{screen_name}'s timeline"
  timeline
end

#fetch_tweet_with_full_text(tweet) ⇒ Object



109
110
111
112
# File 'lib/trumpcare_tracker.rb', line 109

def fetch_tweet_with_full_text(tweet)
  @requests += 1
  client.status(tweet.id, tweet_mode: 'extended')
end

#filter_by_keywordsObject



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/trumpcare_tracker.rb', line 97

def filter_by_keywords
  recent_tweets.each do |tweet|
    if tweet_match?(tweet, self.class.trumpcare_keyword_regex)
      stats[:trumpcare_tweets] << tweet
    elsif tweet_match?(tweet, self.class.russia_keyword_regex)
      stats[:russia_tweets] << tweet
    end
  end

  stats
end

#recent_tweetsObject

Collect a user’s tweets within the last 7 days



86
87
88
89
90
91
# File 'lib/trumpcare_tracker.rb', line 86

def recent_tweets
  @_recent_tweets ||= timeline.each_with_object([]) do |tweet, memo|
    age_of_tweet_in_days = (Time.now.to_date - tweet.created_at.to_date).to_i
    memo << tweet if age_of_tweet_in_days <= 7
  end
end

#recent_tweets_countObject



147
148
149
# File 'lib/trumpcare_tracker.rb', line 147

def recent_tweets_count
  @_recent_tweets_count ||= recent_tweets.count
end

#russia_tweetsObject



130
131
132
# File 'lib/trumpcare_tracker.rb', line 130

def russia_tweets
  stats[:russia_tweets]
end

#russia_tweets_countObject



162
163
164
# File 'lib/trumpcare_tracker.rb', line 162

def russia_tweets_count
  @_russia_tweets_count ||= russia_tweets.count
end

#russia_tweets_percentageObject



170
171
172
# File 'lib/trumpcare_tracker.rb', line 170

def russia_tweets_percentage
  self.class.percentage(russia_tweets_count, recent_tweets_count)
end

#statsObject



151
152
153
154
155
156
# File 'lib/trumpcare_tracker.rb', line 151

def stats
  @_stats ||= {
    trumpcare_tweets: [],
    russia_tweets: []
  }
end

#timelineObject



55
56
57
# File 'lib/trumpcare_tracker.rb', line 55

def timeline
  @_timeline ||= (fetch_timeline(screen_name) + fetch_timeline(alt_screen_name))
end

#to_hObject



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/trumpcare_tracker.rb', line 178

def to_h
  {
    senator: user,
    official_user_name: screen_name,
    alt_user_name: alt_screen_name,
    tweets_in_last_seven_days: recent_tweets.count,
    trumpcare_tweet_count: trumpcare_tweets.count,
    tct_percentage: trumpcare_tweets_percentage,
    russia_tweet_count: russia_tweets.count,
    rt_percentage: russia_tweets_percentage,
    tct_to_rt_ratio: trumpcare_to_russia_tweets_ratio,
    trumpcare_tweet_urls: trumpcare_tweets.map { |tweet| tweet.uri.to_s },
    russia_tweet_urls: russia_tweets.map { |tweet| tweet.uri.to_s }
  }
end

#to_sObject



139
140
141
142
143
144
145
# File 'lib/trumpcare_tracker.rb', line 139

def to_s
  audit unless audited?
  @_to_s ||= "@#{screen_name}'s last 7 days\n#{recent_tweets_count} tweets\n"\
    "#{trumpcare_tweets_count} TrumpCare - #{trumpcare_tweets_percentage}%\n"\
    "#{russia_tweets_count} Russia - #{russia_tweets_percentage}%\n"\
    "#{trumpcare_to_russia_tweets_ratio} TrumpCare tweets for every Russia tweet"
end

#to_tweet(options = {}) ⇒ Object



194
195
196
197
# File 'lib/trumpcare_tracker.rb', line 194

def to_tweet(options = {})
  @requests += 1
  client.update(".#{self}", options)
end

#trumpcare_to_russia_tweets_ratioObject



174
175
176
# File 'lib/trumpcare_tracker.rb', line 174

def trumpcare_to_russia_tweets_ratio
  self.class.ratio(trumpcare_tweets_count, russia_tweets_count)
end

#trumpcare_tweetsObject



126
127
128
# File 'lib/trumpcare_tracker.rb', line 126

def trumpcare_tweets
  stats[:trumpcare_tweets]
end

#trumpcare_tweets_countObject



158
159
160
# File 'lib/trumpcare_tracker.rb', line 158

def trumpcare_tweets_count
  @_trumpcare_tweets_count ||= trumpcare_tweets.count
end

#trumpcare_tweets_percentageObject



166
167
168
# File 'lib/trumpcare_tracker.rb', line 166

def trumpcare_tweets_percentage
  self.class.percentage(trumpcare_tweets_count, recent_tweets_count)
end

#tweet_match?(tweet, regex) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
117
118
119
120
121
122
123
124
# File 'lib/trumpcare_tracker.rb', line 114

def tweet_match?(tweet, regex)
  full_text = tweet.attrs[:full_text]
  if full_text.downcase.match?(regex)
    true
  elsif tweet.quoted_tweet?
    quoted_tweet = fetch_tweet_with_full_text(tweet.quoted_tweet)
    tweet_match?(quoted_tweet, regex)
  else
    false
  end
end