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.
- data/lib/weeter/configuration.rb +1 -1
- data/lib/weeter/plugins/subscription_plugin.rb +3 -3
- data/lib/weeter/runner.rb +1 -1
- data/lib/weeter/twitter/tweet_consumer.rb +47 -6
- data/lib/weeter/version.rb +1 -1
- data/spec/weeter/twitter/tweet_consumer_spec.rb +69 -0
- data/weeter.conf.example +12 -0
- metadata +97 -102
data/lib/weeter/configuration.rb
CHANGED
@@ -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
|
data/lib/weeter/runner.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
-
|
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 = {}
|
data/lib/weeter/version.rb
CHANGED
@@ -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
|
data/weeter.conf.example
CHANGED
@@ -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
|
-
|
16
|
-
|
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
|
-
|
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:
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
138
|
-
|
139
|
-
|
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:
|
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:
|
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
|