weeter 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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