tweetganic 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in tweetganic.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 brianpetro
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Tweetganic
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'tweetganic'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install tweetganic
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/MyClass.rb ADDED
@@ -0,0 +1,344 @@
1
+
2
+ require 'tweetstream'
3
+ require 'twitter'
4
+ require 'net/http'
5
+ require 'json'
6
+ require 'uri'
7
+
8
+ # GET's settings from tweetganic server
9
+ def get_user_ctrls
10
+ settings_response = Net::HTTP.get_response('tweetganic.herokuapp.com', "/settings/#{ARGV[0]}.json").body
11
+ JSON.parse(settings_response)
12
+ end
13
+
14
+ # Action On/Off Controls
15
+ def favorite_ctrl(json)
16
+ return false if json['favorite_ctrl'] == "false"
17
+ return true if json['favorite_ctrl'] == "true"
18
+ end
19
+
20
+ def follow_ctrl(json)
21
+ return false if json['follow_ctrl'] == "false"
22
+ return true if json['follow_ctrl'] == "true"
23
+ end
24
+
25
+ def retweet_ctrl(json)
26
+ return false if json['retweet_ctrl'] == "false"
27
+ return true if json['retweet_ctrl'] == "true"
28
+ end
29
+
30
+ # Configure Twitter Connections
31
+ def twitter_config(c_key, c_secret, o_token, o_token_secret)
32
+ TweetStream.configure do |config|
33
+ config.consumer_key = c_key
34
+ config.consumer_secret = c_secret
35
+ config.oauth_token = o_token
36
+ config.oauth_token_secret = o_token_secret
37
+ config.auth_method = :oauth
38
+ end
39
+
40
+ Twitter.configure do |config|
41
+ config.consumer_key = c_key
42
+ config.consumer_secret = c_secret
43
+ config.oauth_token = o_token
44
+ config.oauth_token_secret = o_token_secret
45
+ end
46
+ end
47
+
48
+ class Numeric
49
+ def to_rad
50
+ self * Math::PI / 180
51
+ end
52
+ end
53
+
54
+ # Used to find distance for relativity. loc1 and loc2 are arrays of [latitude, longitude]
55
+ def distance loc1, loc2
56
+ lat1, lon1 = loc1
57
+ lat2, lon2 = loc2
58
+ dLat = (lat2-lat1).to_rad;
59
+ dLon = (lon2-lon1).to_rad;
60
+ a = Math.sin(dLat/2) * Math.sin(dLat/2) +
61
+ Math.cos(lat1.to_rad) * Math.cos(lat2.to_rad) *
62
+ Math.sin(dLon/2) * Math.sin(dLon/2);
63
+ c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
64
+ d = 6371 * c; # Multiply by 6371 to get Kilometers
65
+ end
66
+ # Gets given points difference of distance, returns usable twitter loc geocode
67
+ def get_twit_loc_area(center, selected_radius)
68
+ loc_adjust_by = distance([center[0],center[1]],[center[0]+0.01,center[1]+0.01])
69
+ loc_adjusted = selected_radius/loc_adjust_by
70
+ twitter_loc=[]
71
+ twitter_loc << (center[1] - loc_adjusted/200.0).round(2)
72
+ twitter_loc << (center[0] - loc_adjusted/200.0).round(2)
73
+ twitter_loc << (center[1] + loc_adjusted/200.0).round(2)
74
+ twitter_loc << (center[0] + loc_adjusted/200.0).round(2)
75
+ return twitter_loc
76
+ end
77
+
78
+ # Is user using location?
79
+ def check_using_location(json)
80
+ return false if json['using_location'] == "false"
81
+ return true if json['using_location'] == "true"
82
+ end
83
+
84
+ # To Avoid Tweets with offsite Links
85
+ def check_avoiding_links(json)
86
+ return false if json['avoid_promos'] == "false"
87
+ return true if json['avoid_promos'] == "true"
88
+ end
89
+ # To avoid people you are following
90
+ def check_avoid_people_i_follow(json)
91
+ return false if json['avoid_accounts_i_follow'] == "false"
92
+ return true if json['avoid_accounts_i_follow'] == "true"
93
+ end
94
+ # To avoid tweets containing 'RT' as a word
95
+ def check_avoid_tweets_containing_rt(json)
96
+ return false if json['avoid_tweets_with_rt'] == "false"
97
+ return true if json['avoid_tweets_with_rt'] == "true"
98
+ end
99
+
100
+ def record_data(args)
101
+ Net::HTTP.post_form(URI("http://tweetganic.herokuapp.com/raws.json"), args)
102
+ end
103
+
104
+ # Used to double filter twitters shitty(inaccurate) GPS search
105
+ def is_from_user_set_location(status, gen_coords)
106
+ lat, lon = status.geo.coordinates
107
+ if lat >= gen_coords[1] && lat <= gen_coords[3] && lon >= gen_coords[0] && lon <= gen_coords[2]
108
+ return true
109
+ else
110
+ return false
111
+ end
112
+ end
113
+
114
+ def is_my_friend(user_obj)
115
+ # status.user.following is DEPRECATED
116
+ # write method after array of friends is available
117
+ end
118
+
119
+ # Checks if two word lists contain matching words.
120
+ def matching_keywords(current, ref)
121
+ if (current & ref).empty?
122
+ return false
123
+ else
124
+ return true
125
+ end
126
+ end
127
+
128
+
129
+ ## Twetganic Controller Variables
130
+ json = get_user_ctrls # Get json from tweetganic ctrls db
131
+
132
+ # Set Oauth Keys
133
+ c_key = json['consumer_key']
134
+ c_secret = json['consumer_secret']
135
+ o_token = json['oauth_token']
136
+ o_token_secret = json['oauth_token_secret']
137
+
138
+ avoiding_links=check_avoiding_links(json) # Does Tweet include third party url?
139
+ avoid_tweets_containing_rt=check_avoid_tweets_containing_rt(json) # Does Tweet text include 'RT'?
140
+ min_actions_before_re_engage=json['min_actions_before_re_engage'].to_i # How many other actionable users before a user can become actionable again?
141
+
142
+ keywords_raw = json['track'] # String of keywords extracted from JSON
143
+ keywords = keywords_raw.split(', ') # Parse Keywords into array/list
144
+
145
+ neg_keywords_raw=json['negative_keywords'] # String of negative keywords extracted from JSON
146
+ negative_keywords=neg_keywords_raw.split(', ') # Parse Negative Keywords into array/list
147
+
148
+ using_location=check_using_location(json) # Is user tracking locations?
149
+ if using_location # Set location vars if using location
150
+ set_lat=json['center_lat'].to_f # Center latitude point for location tracking
151
+ set_lon=json['center_lon'].to_f # Center longitude point for location tracking
152
+ set_radius=json['radius_distance'].to_f # Distance from center point for location tracking
153
+ location_keywords=json['location_keywords'].split(', ') # Additional keywords for filtering location tweets
154
+ ## Generated for location tracking
155
+ keyword_ref = location_keywords|keywords # Reference list of keywords and location_keywords, for matching (array)
156
+ gen_coords=get_twit_loc_area([set_lat, set_lon], set_radius) # Generated Twitter location tracking coordinates
157
+ end
158
+
159
+ # Mains Switches for Actions
160
+ favorite_on = favorite_ctrl(json)
161
+ follow_on = follow_ctrl(json)
162
+ retweet_on = retweet_ctrl(json)
163
+
164
+ # Vars for Favoriting Action
165
+ favoriting_friends_min=json['favoriting_friends_min'].to_i
166
+ favoriting_friends_max=json['favoriting_friends_max'].to_i
167
+ favoriting_followers_min=json['favoriting_followers_min'].to_i
168
+ favoriting_followers_max=json['favoriting_followers_max'].to_i
169
+
170
+ # Vars for Following Action
171
+ following_friends_min=json['following_friends_min'].to_i
172
+ following_friends_max=json['following_friends_max'].to_i
173
+ following_followers_min=json['following_followers_min'].to_i
174
+ following_followers_max=json['following_followers_max'].to_i
175
+
176
+ # Vars for Retweeting Action
177
+ rt_friends_min=json['rt_friends_min'].to_i
178
+ rt_friends_max=json['rt_friends_max'].to_i
179
+ rt_followers_min=json['rt_followers_min'].to_i
180
+ rt_followers_max=json['rt_followers_max'].to_i
181
+
182
+ # Get random wait times and convert mins to seconds
183
+ favoriting_wait_min = (json['favoriting_wait_min'].to_i)*60
184
+ favoriting_wait_max = (json['favoriting_wait_max'].to_i)*60
185
+ following_wait_min = (json['following_wait_min'].to_i)*60
186
+ following_wait_max = (json['following_wait_max'].to_i)*60
187
+ rt_wait_min = (json['rt_wait_min'].to_i)*60
188
+ rt_wait_max = (json['rt_wait_max'].to_i)*60
189
+
190
+ ## Generated Variables For Tweet Processing
191
+ twitter_config(c_key, c_secret, o_token, o_token_secret) # Runs config for 'twitter' and 'tweetstream' gems
192
+
193
+ # Gets boundaries for initial filtering
194
+ friends_presets=[favoriting_friends_min, favoriting_friends_max, following_friends_min, following_friends_max, rt_friends_min, rt_friends_max]
195
+ followers_presets=[favoriting_followers_min, favoriting_followers_max, following_followers_min, following_followers_max, rt_followers_min, rt_followers_max]
196
+ min_friends=friends_presets.min
197
+ max_friends=friends_presets.max
198
+ min_followers=followers_presets.min
199
+ max_followers=followers_presets.max
200
+
201
+ start_time=Time.now.to_i # Start time equals run time
202
+ next_favorite_time=start_time # Set to favorite first eligible tweet
203
+ next_follow_time=start_time # Set to follow first eligible tweet
204
+ next_retweet_time=start_time # Set to retweet first eligible tweet
205
+
206
+ ## Vars Set By Twitter API Response
207
+ screen_name = Twitter.user.screen_name
208
+ user_id = Twitter.user.id
209
+
210
+ puts "### Welcome, #{screen_name} ###"
211
+ puts "Tracking:"
212
+ puts keywords
213
+ puts "Location Monitoring: #{using_location}"
214
+ puts "Center: Within #{set_radius}km of #{set_lat}, #{set_lon}" if using_location
215
+ puts "Bounds: #{gen_coords}" if using_location
216
+ puts "Consumer Key: #{c_key}"
217
+ puts "Consumer Secret: #{c_secret}"
218
+ puts "Oauth Token: #{o_token}"
219
+ puts "Oauth Secret: #{o_token_secret}"
220
+ puts "Avoiding Links: #{avoiding_links}"
221
+ puts "Avoiding Tweets Containing 'RT': #{avoid_tweets_containing_rt}"
222
+ puts "Avoids Re-engaging user before #{min_actions_before_re_engage} actions on others"
223
+ puts "Avoiding these negative keywords:"
224
+ puts negative_keywords
225
+ puts "Targets users with between #{min_friends} and #{max_friends} friends"
226
+ puts "Targets users with between #{min_followers} and #{max_followers} followers"
227
+
228
+ ## Fresh for running the script
229
+ i=0 # Tweets analysed this run
230
+ favorited=[] # Stores user_id's of users who were favorited
231
+ followed=[] # Stores user_id's of users who were followed
232
+ retweeted=[] # Stores user_id's of users who were retweeted
233
+ actionabled=[] # Stores user_id's of users who were declared actionable
234
+ recently_engaged=[] # Collection of recently engaged users for re-engage method
235
+
236
+ puts "Stream connecting..."
237
+ client = TweetStream::Client.new
238
+ puts "Stream Connnected."
239
+ client.filter({track: keywords, locations: gen_coords}) do |status|
240
+ tweet_breakdown=status.text.split(' ')
241
+ actionable=true
242
+ favoritable=false
243
+ followable=false
244
+ retweetable=false
245
+ dmable=false
246
+ reportable=true
247
+ tweet_score=0
248
+ i=i+1
249
+ tweeter_user_id=status.user.id
250
+ tweet_id=status.id
251
+ followers_count = status.user.followers_count.to_i
252
+ friends_count = status.user.friends_count.to_i
253
+ tweet_score = followers_count-friends_count
254
+ puts ""
255
+ puts "#{i}"
256
+ puts "#{status.text}"
257
+
258
+ if using_location # Runs 'double check' when running location because of Twitters inferior filtering methods
259
+ if !status.geo.nil?
260
+ actionable=false unless is_from_user_set_location(status, gen_coords)
261
+ end
262
+ # Double check keyword is causing non geoed to stop
263
+ actionable=false unless matching_keywords(tweet_breakdown, keyword_ref)
264
+ end
265
+ ## Initial Validations for Speed, 'actionable=true' if they pass user set validations
266
+ if avoid_tweets_containing_rt
267
+ negative_keywords << "RT"
268
+ end
269
+ if avoiding_links
270
+ actionable=false unless status.urls.empty?
271
+ end
272
+ actionable=false unless friends_count.between?(min_friends, max_friends)
273
+ actionable=false unless followers_count.between?(min_followers, max_followers)
274
+ actionable=false if recently_engaged.include?(tweeter_user_id)
275
+ actionable=false if matching_keywords(tweet_breakdown, negative_keywords)
276
+
277
+ if actionabled.count >=100 # Submit data when able to record 100 data points
278
+ user_followers=Twitter.user.followers_count
279
+ record_data({"data_id" => "1",
280
+ "user_id" => "#{user_id}",
281
+ "user_followers" => "#{user_followers}",
282
+ "favorited" => "#{favorited}",
283
+ "followed" => "#{followed}",
284
+ "retweeted" => "#{retweeted}",
285
+ "actionabled" => "#{actionabled}",
286
+ "keywords" => "#{keywords_raw}",
287
+ "negative_keywords" => "#{neg_keywords_raw}"
288
+ })
289
+ # Resets Lists of user_id's to submit in data
290
+ favorited=[]
291
+ followed=[]
292
+ retweeted=[]
293
+ actionabled=[]
294
+ end
295
+
296
+ if recently_engaged.count >= min_actions_before_re_engage
297
+ recently_engaged=[]
298
+ end
299
+
300
+ if actionable
301
+ puts "Actionable"
302
+ actionabled << tweeter_user_id
303
+ favoritable=true if favorite_on && friends_count.between?(favoriting_friends_min, favoriting_friends_max) && followers_count.between?(favoriting_followers_min, favoriting_followers_max)
304
+ followable=true if follow_on && friends_count.between?(following_friends_min, following_friends_max) && followers_count.between?(following_followers_min, following_followers_max)
305
+ retweetable=true if retweet_on && friends_count.between?(rt_friends_min, rt_friends_max) && followers_count.between?(rt_followers_min, rt_followers_max)
306
+
307
+ if favoritable
308
+ if Time.now.to_i >= next_favorite_time
309
+ Twitter.favorite(tweet_id)
310
+ next_favorite_time=(Time.now.to_i)+rand(favoriting_wait_min..favoriting_wait_max)
311
+ favorited << tweeter_user_id
312
+ recently_engaged << tweeter_user_id
313
+ else
314
+ puts "To Soon To Favorite"
315
+ end
316
+ end
317
+
318
+
319
+ if followable
320
+ if Time.now.to_i >= next_follow_time
321
+ Twitter.follow(tweeter_user_id)
322
+ next_follow_time=(Time.now.to_i)+rand(following_wait_min..following_wait_max)
323
+ followed << tweeter_user_id
324
+ recently_engaged << tweeter_user_id
325
+ else
326
+ puts "To Soon To Follow"
327
+ end
328
+ end
329
+
330
+
331
+ if retweetable
332
+ if Time.now.to_i >= next_retweet_time
333
+ Twitter.retweet(tweet_id)
334
+ next_retweet_time=(Time.now.to_i)+rand(rt_wait_min..rt_wait_max)
335
+ retweeted << tweeter_user_id
336
+ recently_engaged << tweeter_user_id
337
+ else
338
+ puts "To Soon To RT"
339
+ end
340
+ end
341
+ else
342
+ puts "NOT WORTHY"
343
+ end
344
+ end
data/lib/tweetganic.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "tweetganic/version"
2
+
3
+ module Tweetganic
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,3 @@
1
+ module Tweetganic
2
+ VERSION = "0.0.1"
3
+ end
data/tweetganic ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/ruby
2
+ require 'rubygems'
3
+ require 'require_all'
4
+ #make program output in real time so errors visible in VR.
5
+ STDOUT.sync = true
6
+ STDERR.sync = true
7
+
8
+ #everything in these directories will be included
9
+ my_path = File.expand_path(File.dirname(__FILE__))
10
+ require_all Dir.glob(my_path + "/bin/**/*.rb")
11
+
12
+ MyClass.new
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tweetganic/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tweetganic"
8
+ spec.version = Tweetganic::VERSION
9
+ spec.authors = ["brianpetro"]
10
+ spec.email = ["brian@plexm.com"]
11
+ spec.description = %q{Run Tweetganic}
12
+ spec.summary = %q{Runs Tweetganic}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "require"
24
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tweetganic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - brianpetro
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.3'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: require
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Run Tweetganic
63
+ email:
64
+ - brian@plexm.com
65
+ executables:
66
+ - MyClass.rb
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - .gitignore
71
+ - Gemfile
72
+ - LICENSE.txt
73
+ - README.md
74
+ - Rakefile
75
+ - bin/MyClass.rb
76
+ - lib/tweetganic.rb
77
+ - lib/tweetganic/version.rb
78
+ - tweetganic
79
+ - tweetganic.gemspec
80
+ homepage: ''
81
+ licenses:
82
+ - MIT
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 1.8.25
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Runs Tweetganic
105
+ test_files: []