weeter 0.10.0 → 0.11.0

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.
@@ -4,7 +4,7 @@ module Weeter
4
4
 
5
5
  class Configuration
6
6
  include Singleton
7
- attr_accessor :log_path
7
+ attr_accessor :log_path, :subscriptions_limit
8
8
 
9
9
  autoload :ClientAppConfig, 'weeter/configuration/client_app_config'
10
10
  autoload :TwitterConfig, 'weeter/configuration/twitter_config'
@@ -9,11 +9,11 @@ module Weeter
9
9
  class SubscriptionPlugin
10
10
  delegate :get_initial_filters, :to => :configured_plugin
11
11
  delegate :listen_for_filter_update, :to => :configured_plugin
12
-
12
+
13
13
  def initialize(client_app_config)
14
14
  @config = client_app_config
15
15
  end
16
-
16
+
17
17
  protected
18
18
  def configured_plugin
19
19
  @configured_plugin ||= begin
@@ -23,4 +23,4 @@ module Weeter
23
23
  end
24
24
  end
25
25
  end
26
- end
26
+ end
@@ -45,7 +45,7 @@ module Weeter
45
45
  end
46
46
 
47
47
  def tweet_consumer
48
- @tweet_consumer ||= Weeter::Twitter::TweetConsumer.new(@config.twitter, notification_plugin, limiter)
48
+ @tweet_consumer ||= Weeter::Twitter::TweetConsumer.new(@config.twitter, notification_plugin, limiter, @config.subscriptions_limit)
49
49
  end
50
50
  end
51
51
  end
@@ -7,27 +7,37 @@ module Weeter
7
7
 
8
8
  attr_reader :limiter
9
9
 
10
- def initialize(twitter_config, notifier, limiter)
10
+ def initialize(twitter_config, notifier, limiter, subscriptions_limit = nil)
11
11
  @config = twitter_config
12
12
  @notifier = notifier
13
13
  @limiter = limiter
14
+ @subscriptions_limit = subscriptions_limit
14
15
  end
15
16
 
16
17
  def connect(filter_params)
18
+ filter_params = limit_filter_params(filter_params) if @subscriptions_limit
17
19
  filter_params = clean_filter_params(filter_params)
18
- connect_options = {:ssl => true, :params => filter_params, :method => 'POST'}.merge(@config.auth_options)
20
+
21
+ connect_options = {
22
+ ssl: true,
23
+ params: filter_params,
24
+ method: 'POST'
25
+ }.merge(@config.auth_options)
26
+
19
27
  @stream = ::Twitter::JSONStream.connect(connect_options)
20
28
 
21
29
  @stream.each_item do |item|
22
30
  begin
23
31
  tweet_item = TweetItem.new(MultiJson.decode(item))
24
32
 
25
- if limiter.limit?(*tweet_item.limiting_facets)
26
- rate_limit_tweet(tweet_item)
27
- elsif tweet_item.deletion?
33
+ if tweet_item.deletion?
28
34
  @notifier.delete_tweet(tweet_item)
29
35
  elsif tweet_item.publishable?
30
- @notifier.publish_tweet(tweet_item)
36
+ if limiter.limit?(*tweet_item.limiting_facets)
37
+ rate_limit_tweet(tweet_item)
38
+ else
39
+ @notifier.publish_tweet(tweet_item)
40
+ end
31
41
  else
32
42
  ignore_tweet(tweet_item)
33
43
  end
@@ -52,6 +62,37 @@ module Weeter
52
62
 
53
63
  protected
54
64
 
65
+ def limit_filter_params(params)
66
+ result = params.clone
67
+ result.default = []
68
+
69
+ follow_count = result['follow'].length
70
+ track_count = result['track'].length
71
+
72
+ total = follow_count + track_count
73
+
74
+ if total > @subscriptions_limit
75
+ Weeter.logger.error("Twitter Subscriptions are #{total}, but limited to #{@subscriptions_limit} subscriptions")
76
+ end
77
+
78
+ while total > 1000
79
+ if follow_count > track_count
80
+ follow_count -= 1
81
+ elsif track_count > follow_count
82
+ track_count -= 1
83
+ else
84
+ track_count -= 1
85
+ end
86
+
87
+ total = follow_count + track_count
88
+ end
89
+
90
+ result['track'] = result['track'][0...track_count]
91
+ result['follow'] = result['follow'][0...follow_count]
92
+
93
+ result
94
+ end
95
+
55
96
  def clean_filter_params(p)
56
97
  return {} if p.nil?
57
98
  cleaned_params = {}
@@ -1,3 +1,3 @@
1
1
  module Weeter
2
- VERSION = "0.10.0"
2
+ VERSION = "0.11.0"
3
3
  end
@@ -20,6 +20,75 @@ describe Weeter::Twitter::TweetConsumer do
20
20
  end
21
21
  end
22
22
 
23
+ describe '#limit_filter_params' do
24
+
25
+ let(:client_proxy) { mock('NotificationPlugin', :publish_tweet => nil) }
26
+ let(:consumer) do
27
+ Weeter::Twitter::TweetConsumer.new(Weeter::Configuration::TwitterConfig.instance, client_proxy, limiter, 1000)
28
+ end
29
+
30
+ let(:track) {[]}
31
+ let(:follow) {[]}
32
+
33
+ let(:params) do
34
+ {
35
+ 'follow' => follow,
36
+ 'track' => track
37
+ }
38
+ end
39
+
40
+ context 'limit not reached' do
41
+ it 'leaves the values alone' do
42
+ result = consumer.send(:limit_filter_params, params)
43
+ result.fetch('track').length.should == 0
44
+ result.fetch('follow').length.should == 0
45
+ end
46
+ end
47
+
48
+ context 'follow above' do
49
+ let(:follow) { (1..1001).to_a }
50
+
51
+ it 'it limits follows, but not tracks' do
52
+ result = consumer.send(:limit_filter_params, params)
53
+ result.fetch('follow').length.should == 1000
54
+ result.fetch('track').length.should == 0
55
+ end
56
+ end
57
+
58
+ context 'track above' do
59
+ let(:track) { (1..1001).to_a }
60
+
61
+ it 'limits tracks, but not follows' do
62
+ result = consumer.send(:limit_filter_params, params)
63
+ result.fetch('track').length.should == 1000
64
+ result.fetch('follow').length.should == 0
65
+ end
66
+ end
67
+
68
+ context 'they are equally over' do
69
+ let(:track) { (1..600).to_a }
70
+ let(:follow) { (1..600).to_a }
71
+
72
+ it 'limits tracks, but not follows' do
73
+
74
+ result = consumer.send(:limit_filter_params, params)
75
+ result.fetch('track').length.should == 500
76
+ result.fetch('follow').length.should == 500
77
+ end
78
+ end
79
+
80
+ context 'track is more over' do
81
+ let(:track) { (1..800).to_a }
82
+ let(:follow) { (1..300).to_a }
83
+
84
+ it 'limits tracks, but not follows' do
85
+ result = consumer.send(:limit_filter_params, params)
86
+ result.fetch('track').length.should == 700
87
+ result.fetch('follow').length.should == 300
88
+ end
89
+ end
90
+ end
91
+
23
92
  describe "connecting to twitter" do
24
93
 
25
94
  before(:each) do
@@ -9,6 +9,18 @@ Weeter.configure do |conf|
9
9
  # To disable logging:
10
10
  # conf.log_path = false
11
11
 
12
+ # To hard limits number of subscriptions.
13
+ # If the limit has been reached it will log and error, and fairly truncate
14
+ # subscriptions.
15
+ #
16
+ # default: nolimit = nil
17
+ #
18
+ # ** Please Note **
19
+ # - by default, twitter will reject connection attempts
20
+ # with greater then 1000 subscriptions
21
+ #
22
+ # conf.subscriptions_limit = 1000
23
+
12
24
  conf.twitter do |twitter|
13
25
  # For basic auth
14
26
  # twitter.basic_auth = {:username => 'johnny', :password => 'secret'}
metadata CHANGED
@@ -1,151 +1,149 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: weeter
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.11.0
4
5
  prerelease:
5
- version: 0.10.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Luke Melia
9
9
  - Noah Davis
10
10
  - Joey Aghion
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
-
15
- date: 2012-10-24 00:00:00 Z
16
- dependencies:
17
- - !ruby/object:Gem::Dependency
14
+ date: 2012-11-15 00:00:00.000000000Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
18
17
  name: eventmachine
19
- prerelease: false
20
- requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirement: &2154031740 !ruby/object:Gem::Requirement
21
19
  none: false
22
- requirements:
23
- - - ">="
24
- - !ruby/object:Gem::Version
25
- version: "0"
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
26
24
  type: :runtime
27
- version_requirements: *id001
28
- - !ruby/object:Gem::Dependency
29
- name: eventmachine_httpserver
30
25
  prerelease: false
31
- requirement: &id002 !ruby/object:Gem::Requirement
26
+ version_requirements: *2154031740
27
+ - !ruby/object:Gem::Dependency
28
+ name: eventmachine_httpserver
29
+ requirement: &2154030760 !ruby/object:Gem::Requirement
32
30
  none: false
33
- requirements:
34
- - - ">="
35
- - !ruby/object:Gem::Version
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
36
34
  version: 0.2.1
37
35
  type: :runtime
38
- version_requirements: *id002
39
- - !ruby/object:Gem::Dependency
40
- name: em-hiredis
41
36
  prerelease: false
42
- requirement: &id003 !ruby/object:Gem::Requirement
37
+ version_requirements: *2154030760
38
+ - !ruby/object:Gem::Dependency
39
+ name: em-hiredis
40
+ requirement: &2154030240 !ruby/object:Gem::Requirement
43
41
  none: false
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
47
45
  version: 0.1.0
48
46
  type: :runtime
49
- version_requirements: *id003
50
- - !ruby/object:Gem::Dependency
51
- name: multi_json
52
47
  prerelease: false
53
- requirement: &id004 !ruby/object:Gem::Requirement
48
+ version_requirements: *2154030240
49
+ - !ruby/object:Gem::Dependency
50
+ name: multi_json
51
+ requirement: &2154029760 !ruby/object:Gem::Requirement
54
52
  none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
58
56
  version: 1.0.2
59
57
  type: :runtime
60
- version_requirements: *id004
61
- - !ruby/object:Gem::Dependency
62
- name: hashie
63
58
  prerelease: false
64
- requirement: &id005 !ruby/object:Gem::Requirement
59
+ version_requirements: *2154029760
60
+ - !ruby/object:Gem::Dependency
61
+ name: hashie
62
+ requirement: &2154029080 !ruby/object:Gem::Requirement
65
63
  none: false
66
- requirements:
67
- - - ">="
68
- - !ruby/object:Gem::Version
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
69
67
  version: 1.1.0
70
68
  type: :runtime
71
- version_requirements: *id005
72
- - !ruby/object:Gem::Dependency
73
- name: em-http-request
74
69
  prerelease: false
75
- requirement: &id006 !ruby/object:Gem::Requirement
70
+ version_requirements: *2154029080
71
+ - !ruby/object:Gem::Dependency
72
+ name: em-http-request
73
+ requirement: &2154028360 !ruby/object:Gem::Requirement
76
74
  none: false
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
80
78
  version: 1.0.0
81
79
  type: :runtime
82
- version_requirements: *id006
83
- - !ruby/object:Gem::Dependency
84
- name: i18n
85
80
  prerelease: false
86
- requirement: &id007 !ruby/object:Gem::Requirement
81
+ version_requirements: *2154028360
82
+ - !ruby/object:Gem::Dependency
83
+ name: i18n
84
+ requirement: &2154027700 !ruby/object:Gem::Requirement
87
85
  none: false
88
- requirements:
86
+ requirements:
89
87
  - - ~>
90
- - !ruby/object:Gem::Version
88
+ - !ruby/object:Gem::Version
91
89
  version: 0.6.0
92
90
  type: :runtime
93
- version_requirements: *id007
94
- - !ruby/object:Gem::Dependency
95
- name: activesupport
96
91
  prerelease: false
97
- requirement: &id008 !ruby/object:Gem::Requirement
92
+ version_requirements: *2154027700
93
+ - !ruby/object:Gem::Dependency
94
+ name: activesupport
95
+ requirement: &2154027240 !ruby/object:Gem::Requirement
98
96
  none: false
99
- requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
102
100
  version: 3.1.1
103
101
  type: :runtime
104
- version_requirements: *id008
105
- - !ruby/object:Gem::Dependency
106
- name: simple_oauth
107
102
  prerelease: false
108
- requirement: &id009 !ruby/object:Gem::Requirement
103
+ version_requirements: *2154027240
104
+ - !ruby/object:Gem::Dependency
105
+ name: simple_oauth
106
+ requirement: &2154026740 !ruby/object:Gem::Requirement
109
107
  none: false
110
- requirements:
108
+ requirements:
111
109
  - - ~>
112
- - !ruby/object:Gem::Version
110
+ - !ruby/object:Gem::Version
113
111
  version: 0.1.5
114
112
  type: :runtime
115
- version_requirements: *id009
116
- - !ruby/object:Gem::Dependency
117
- name: lukemelia-twitter-stream
118
113
  prerelease: false
119
- requirement: &id010 !ruby/object:Gem::Requirement
114
+ version_requirements: *2154026740
115
+ - !ruby/object:Gem::Dependency
116
+ name: lukemelia-twitter-stream
117
+ requirement: &2154026240 !ruby/object:Gem::Requirement
120
118
  none: false
121
- requirements:
119
+ requirements:
122
120
  - - ~>
123
- - !ruby/object:Gem::Version
121
+ - !ruby/object:Gem::Version
124
122
  version: 0.1.15
125
123
  type: :runtime
126
- version_requirements: *id010
127
- - !ruby/object:Gem::Dependency
128
- name: rspec
129
124
  prerelease: false
130
- requirement: &id011 !ruby/object:Gem::Requirement
125
+ version_requirements: *2154026240
126
+ - !ruby/object:Gem::Dependency
127
+ name: rspec
128
+ requirement: &2154025660 !ruby/object:Gem::Requirement
131
129
  none: false
132
- requirements:
130
+ requirements:
133
131
  - - ~>
134
- - !ruby/object:Gem::Version
132
+ - !ruby/object:Gem::Version
135
133
  version: 2.6.0
136
134
  type: :development
137
- version_requirements: *id011
138
- description: Weeter subscribes to a set of twitter users or search terms using Twitter's streaming API, and notifies your app with each new tweet.
139
- email:
135
+ prerelease: false
136
+ version_requirements: *2154025660
137
+ description: Weeter subscribes to a set of twitter users or search terms using Twitter's
138
+ streaming API, and notifies your app with each new tweet.
139
+ email:
140
140
  - luke@lukemelia.com
141
- executables:
141
+ executables:
142
142
  - weeter
143
143
  - weeter_control
144
144
  extensions: []
145
-
146
145
  extra_rdoc_files: []
147
-
148
- files:
146
+ files:
149
147
  - .gitignore
150
148
  - .travis.yml
151
149
  - Gemfile
@@ -194,32 +192,29 @@ files:
194
192
  - weeter.gemspec
195
193
  homepage: http://github.com/lukemelia/weeter
196
194
  licenses: []
197
-
198
195
  post_install_message:
199
196
  rdoc_options: []
200
-
201
- require_paths:
197
+ require_paths:
202
198
  - lib
203
- required_ruby_version: !ruby/object:Gem::Requirement
199
+ required_ruby_version: !ruby/object:Gem::Requirement
204
200
  none: false
205
- requirements:
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- version: "0"
209
- required_rubygems_version: !ruby/object:Gem::Requirement
201
+ requirements:
202
+ - - ! '>='
203
+ - !ruby/object:Gem::Version
204
+ version: '0'
205
+ required_rubygems_version: !ruby/object:Gem::Requirement
210
206
  none: false
211
- requirements:
212
- - - ">="
213
- - !ruby/object:Gem::Version
214
- version: "0"
207
+ requirements:
208
+ - - ! '>='
209
+ - !ruby/object:Gem::Version
210
+ version: '0'
215
211
  requirements: []
216
-
217
212
  rubyforge_project: weeter
218
213
  rubygems_version: 1.8.10
219
214
  signing_key:
220
215
  specification_version: 3
221
216
  summary: Consume the Twitter stream and notify your app
222
- test_files:
217
+ test_files:
223
218
  - spec/spec_helper.rb
224
219
  - spec/weeter/configuration/client_app_config_spec.rb
225
220
  - spec/weeter/configuration/twitter_config_spec.rb