tweetganic 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []