weeter 0.9.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.
Files changed (43) hide show
  1. data/.gitignore +8 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +9 -0
  4. data/README.md +98 -0
  5. data/Rakefile +2 -0
  6. data/bin/weeter +6 -0
  7. data/bin/weeter_control +7 -0
  8. data/lib/weeter/.DS_Store +0 -0
  9. data/lib/weeter/cli.rb +24 -0
  10. data/lib/weeter/configuration/client_app_config.rb +12 -0
  11. data/lib/weeter/configuration/twitter_config.rb +21 -0
  12. data/lib/weeter/configuration.rb +22 -0
  13. data/lib/weeter/plugins/lib/oauth_http.rb +40 -0
  14. data/lib/weeter/plugins/lib/redis.rb +17 -0
  15. data/lib/weeter/plugins/notification/http.rb +26 -0
  16. data/lib/weeter/plugins/notification/resque.rb +39 -0
  17. data/lib/weeter/plugins/notification_plugin.rb +26 -0
  18. data/lib/weeter/plugins/subscription/http.rb +45 -0
  19. data/lib/weeter/plugins/subscription/redis.rb +46 -0
  20. data/lib/weeter/plugins/subscription_plugin.rb +26 -0
  21. data/lib/weeter/plugins.rb +4 -0
  22. data/lib/weeter/runner.rb +40 -0
  23. data/lib/weeter/tasks.rb +16 -0
  24. data/lib/weeter/twitter/tweet_consumer.rb +67 -0
  25. data/lib/weeter/twitter/tweet_item.rb +35 -0
  26. data/lib/weeter/twitter.rb +2 -0
  27. data/lib/weeter/version.rb +3 -0
  28. data/lib/weeter.rb +29 -0
  29. data/log/.gitignore +0 -0
  30. data/spec/.DS_Store +0 -0
  31. data/spec/spec_helper.rb +11 -0
  32. data/spec/weeter/configuration/client_app_config_spec.rb +18 -0
  33. data/spec/weeter/configuration/twitter_config_spec.rb +39 -0
  34. data/spec/weeter/configuration_spec.rb +15 -0
  35. data/spec/weeter/plugins/notification_plugin_spec.rb +22 -0
  36. data/spec/weeter/plugins/subscription/update_server_spec.rb +30 -0
  37. data/spec/weeter/plugins/subscription_plugin_spec.rb +23 -0
  38. data/spec/weeter/runner_spec.rb +7 -0
  39. data/spec/weeter/twitter/tweet_consumer_spec.rb +64 -0
  40. data/spec/weeter/twitter/tweet_item_spec.rb +66 -0
  41. data/weeter.conf.example +51 -0
  42. data/weeter.gemspec +34 -0
  43. metadata +228 -0
@@ -0,0 +1,3 @@
1
+ module Weeter
2
+ VERSION = "0.9.0"
3
+ end
data/lib/weeter.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'eventmachine'
2
+ require 'json'
3
+ require 'logger'
4
+
5
+ require 'weeter/configuration'
6
+ require 'weeter/cli'
7
+ require 'weeter/plugins'
8
+ require 'weeter/runner'
9
+ require 'weeter/twitter'
10
+
11
+
12
+ module Weeter
13
+
14
+ def self.configure
15
+ yield Configuration.instance
16
+ end
17
+
18
+ def self.logger
19
+ @logger ||= begin
20
+ if Configuration.instance.log_path == false
21
+ nil
22
+ elsif Configuration.instance.log_path
23
+ Logger.new(Configuration.instance.log_path)
24
+ else
25
+ Logger.new(STDOUT)
26
+ end
27
+ end
28
+ end
29
+ end
data/log/.gitignore ADDED
File without changes
data/spec/.DS_Store ADDED
Binary file
@@ -0,0 +1,11 @@
1
+ require 'rspec'
2
+ require 'multi_json'
3
+
4
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
5
+ require 'weeter'
6
+
7
+ RSpec.configure do |config|
8
+ config.before(:all) do
9
+ Weeter::Configuration.instance.log_path = 'log/test.log'
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Weeter::Configuration::ClientAppConfig do
4
+ %w{delete_url subscriptions_url oauth}.each do |setting|
5
+ it "should accept setting for #{setting}" do
6
+ Weeter.configure do |conf|
7
+ conf.client_app do |app|
8
+ app.send("#{setting}=", "testvalue")
9
+ end
10
+ end
11
+ Weeter::Configuration.instance.client_app.send(setting).should == "testvalue"
12
+ end
13
+ end
14
+
15
+ it "should default subscription_updates_port" do
16
+ Weeter::Configuration.instance.client_app.subscription_updates_port.should == 7337
17
+ end
18
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Weeter::Configuration::TwitterConfig do
4
+ %w{basic_auth oauth}.each do |setting|
5
+ it "should accept setting for #{setting}" do
6
+ Weeter.configure do |conf|
7
+ conf.twitter do |app|
8
+ app.send("#{setting}=", "testvalue")
9
+ end
10
+ end
11
+ Weeter::Configuration::TwitterConfig.instance.send(setting).should == "testvalue"
12
+ end
13
+ end
14
+
15
+ describe "auth_options" do
16
+
17
+ before do
18
+ Weeter::Configuration::TwitterConfig.instance.oauth = nil
19
+ Weeter::Configuration::TwitterConfig.instance.basic_auth = nil
20
+ end
21
+
22
+ it "should return the oauth settings with a oauth credentials" do
23
+ Weeter::Configuration::TwitterConfig.instance.oauth = {:consumer_key => 'consumer_key', :consumer_secret => 'consumer_secret', :access_key => 'acces_key', :access_secret => 'access_secret'}
24
+ Weeter::Configuration::TwitterConfig.instance.auth_options.should == {:oauth => {:consumer_key => 'consumer_key', :consumer_secret => 'consumer_secret', :access_key => 'acces_key', :access_secret => 'access_secret'}}
25
+ end
26
+
27
+ it "should return the basic auth settings separated by a colon" do
28
+ Weeter::Configuration::TwitterConfig.instance.basic_auth = {:username => "bob", :password => "s3cr3t"}
29
+ Weeter::Configuration::TwitterConfig.instance.auth_options.should == {:auth => "bob:s3cr3t"}
30
+ end
31
+
32
+ it "should prefer oauth over basic auth" do
33
+ Weeter::Configuration::TwitterConfig.instance.basic_auth = {:username => "bob", :password => "s3cr3t"}
34
+ Weeter::Configuration::TwitterConfig.instance.oauth = {:consumer_key => 'consumer_key', :consumer_secret => 'consumer_secret', :access_key => 'acces_key', :access_secret => 'access_secret'}
35
+ Weeter::Configuration::TwitterConfig.instance.auth_options.should == {:oauth => {:consumer_key => 'consumer_key', :consumer_secret => 'consumer_secret', :access_key => 'acces_key', :access_secret => 'access_secret'}}
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Weeter::Configuration do
4
+ describe "#twitter" do
5
+ it "should return the instance" do
6
+ Weeter::Configuration.instance.twitter.should == Weeter::Configuration::TwitterConfig.instance
7
+ end
8
+
9
+ it "should yield the instance when a block is provided" do
10
+ Weeter::Configuration.instance.twitter do |twitter_config|
11
+ twitter_config.should == Weeter::Configuration::TwitterConfig.instance
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ module Weeter
4
+ module Plugins
5
+ describe NotificationPlugin do
6
+ describe "#publish_tweet" do
7
+ it "should delegate to the configured plugin" do
8
+ client_app_config = Hashie::Mash.new(:notification_plugin => :http)
9
+ tweet_item = TweetItem.new({})
10
+
11
+ mock_plugin = mock(Notification::Http)
12
+ Notification::Http.should_receive(:new).and_return(mock_plugin)
13
+
14
+ mock_plugin.should_receive(:publish_tweet).with(tweet_item)
15
+
16
+ plugin = NotificationPlugin.new(client_app_config)
17
+ plugin.publish_tweet(tweet_item)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ module Weeter
3
+ module Plugins
4
+ module Subscription
5
+ describe Http::UpdateServer do
6
+ before(:each) do
7
+ @new_ids = [1,2,3]
8
+ @tweet_consumer = mock('TweetConsumer', :reconnect => nil)
9
+ @tweet_server = Http::UpdateServer.new(nil)
10
+ @tweet_server.instance_variable_set('@http_post_content', MultiJson.encode(@new_ids))
11
+ @tweet_server.tweet_consumer = @tweet_consumer
12
+ @response = mock('DelegatedHttpResponse', :send_response => nil)
13
+ EM::DelegatedHttpResponse.stub!(:new).and_return(@response)
14
+ end
15
+
16
+ after(:each) do
17
+ @tweet_server.process_http_request
18
+ end
19
+
20
+ it "should process http request" do
21
+ @tweet_consumer.should_receive(:reconnect).with(@new_ids)
22
+ end
23
+
24
+ it "should send response" do
25
+ @response.should_receive(:send_response)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ module Weeter
4
+ module Plugins
5
+ describe SubscriptionPlugin do
6
+ describe "#get_initial_filters" do
7
+ it "should delegate to the configured plugin" do
8
+ client_app_config = Hashie::Mash.new(:subscription_plugin => :http)
9
+
10
+ mock_plugin = mock(Subscription::Http)
11
+ Subscription::Http.should_receive(:new).and_return(mock_plugin)
12
+
13
+ mock_plugin.should_receive(:get_initial_filters).and_yield([{'foo' => 'bar'}])
14
+
15
+ plugin = SubscriptionPlugin.new(client_app_config)
16
+ plugin.get_initial_filters do |filter_params|
17
+ filter_params.should == [{'foo' => 'bar'}]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Weeter::Runner do
4
+ describe 'start' do
5
+
6
+ end
7
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe Weeter::Twitter::TweetConsumer do
4
+
5
+
6
+ describe "auth" do
7
+ it 'should use connect to JSON stream with auth options for the configuration' do
8
+ @mock_stream = mock('JSONStream', :each_item => nil, :on_error => nil, :on_max_reconnects => nil)
9
+ Twitter::JSONStream.stub!(:connect).and_return(@mock_stream)
10
+
11
+ Weeter::Configuration::TwitterConfig.instance.stub!(:auth_options).and_return(:foo => :bar)
12
+ consumer = Weeter::Twitter::TweetConsumer.new(Weeter::Configuration::TwitterConfig.instance, mock('NotificationPlugin'))
13
+ Twitter::JSONStream.should_receive(:connect).with(hash_including(:foo => :bar))
14
+ consumer.connect({'follow' => ['1','2']})
15
+ end
16
+ end
17
+
18
+ describe "connecting to twitter" do
19
+
20
+ before(:each) do
21
+ @filter_params = {'follow' => ['1','2','3']}
22
+ Weeter::Configuration::TwitterConfig.instance.stub!(:auth_options).and_return(:foo => :bar)
23
+ @tweet_values = {'text' => "Hey", 'id_str' => "123", 'user' => {'id_str' => "1"}}
24
+ @mock_stream = mock('JSONStream', :on_error => nil, :on_max_reconnects => nil)
25
+ @mock_stream.stub!(:each_item).and_yield(MultiJson.encode(@tweet_values))
26
+ Twitter::JSONStream.stub!(:connect).and_return(@mock_stream)
27
+ @client_proxy = mock('NotificationPlugin', :publish_tweet => nil)
28
+ @consumer = Weeter::Twitter::TweetConsumer.new(Weeter::Configuration::TwitterConfig.instance, @client_proxy)
29
+ end
30
+
31
+ after(:each) do
32
+ @consumer.connect(@filter_params)
33
+ end
34
+
35
+ it "should instantiate a TweetItem" do
36
+ tweet_item = Weeter::TweetItem.new(@tweet_values)
37
+ Weeter::TweetItem.should_receive(:new).with({'text' => "Hey", 'id_str' => "123", 'user' => {'id_str' => "1"}}).and_return(tweet_item)
38
+ end
39
+
40
+ it "should connect to a Twitter JSON stream" do
41
+ Twitter::JSONStream.should_receive(:connect).
42
+ with(:ssl => true, :foo => :bar, :params => @filter_params, :method => 'POST')
43
+ end
44
+
45
+ it "should publish new tweet if publishable" do
46
+ mock_tweet = mock('tweet', :deletion? => false, :publishable? => true)
47
+ tweet_item = Weeter::TweetItem.stub!(:new).and_return mock_tweet
48
+ @client_proxy.should_receive(:publish_tweet).with(mock_tweet)
49
+ end
50
+
51
+ it "should not publish unpublishable tweets" do
52
+ mock_tweet = mock('tweet', :deletion? => false, :publishable? => false, :[] => '')
53
+ tweet_item = Weeter::TweetItem.stub!(:new).and_return mock_tweet
54
+ @client_proxy.should_not_receive(:publish_tweet).with(mock_tweet)
55
+ end
56
+
57
+ it "should delete deletion tweets" do
58
+ mock_tweet = mock('tweet', :deletion? => true, :publishable? => false)
59
+ tweet_item = Weeter::TweetItem.stub!(:new).and_return mock_tweet
60
+ @client_proxy.should_receive(:delete_tweet).with(mock_tweet)
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe Weeter::TweetItem do
4
+
5
+ describe "deletion?" do
6
+ it "should be true if it is a deletion request" do
7
+ item = Weeter::TweetItem.new({"delete"=>{"status"=>{"id"=>234, "user_id"=>34555}}})
8
+ item.should be_deletion
9
+ end
10
+
11
+ it "should be false if it is not a deletion request" do
12
+ item = Weeter::TweetItem.new({'text' => "Hey", 'id_str' => "123", 'user' => {'id_str' => "1"}})
13
+ item.should_not be_deletion
14
+ end
15
+ end
16
+
17
+ describe "publishable" do
18
+
19
+ before do
20
+ @tweet_json = {'text' => "Hey", 'id_str' => "123", 'user' => {'id_str' => '1'}}
21
+ end
22
+
23
+ it "should be publishable if not a reply or a retweet" do
24
+ item = Weeter::TweetItem.new(@tweet_json)
25
+ item.should be_publishable
26
+ end
27
+
28
+ it "should not be publishable if implicitly retweeted" do
29
+ item = Weeter::TweetItem.new(@tweet_json.merge({'text' => 'RT @joe Hey'}))
30
+ item.should_not be_publishable
31
+ end
32
+
33
+ it "should not be publishable if explicitly retweeted" do
34
+ item = Weeter::TweetItem.new(@tweet_json.merge('retweeted_status' => {'id_str' => '111', 'text' => 'Hey', 'user' => {'id_str' => "1"}}))
35
+ item.should_not be_publishable
36
+ end
37
+
38
+ it "should not be publishable if implicit reply" do
39
+ item = Weeter::TweetItem.new(@tweet_json.merge('text' => '@joe Hey'))
40
+ item.should_not be_publishable
41
+ end
42
+
43
+ it "should not be publishable if explicit reply" do
44
+ item = Weeter::TweetItem.new(@tweet_json.merge('text' => '@joe Hey', 'in_reply_to_user_id_str' => '1'))
45
+ item.should_not be_publishable
46
+ end
47
+
48
+ end
49
+
50
+ describe "json attributes" do
51
+
52
+ it "should delegate hash calls to its json" do
53
+ item = Weeter::TweetItem.new({'text' => "Hey"})
54
+ item['text'].should == "Hey"
55
+ end
56
+
57
+ it "should retrieve nested attributes" do
58
+ item = Weeter::TweetItem.new({'text' => "Hey", 'id_str' => "123", 'user' => {'id_str' => '1'}})
59
+ item['user']['id_str'].should == "1"
60
+ end
61
+
62
+ end
63
+
64
+
65
+
66
+ end
@@ -0,0 +1,51 @@
1
+ #
2
+ # Customize this configuration file according to your environment.
3
+ #
4
+ Weeter.configure do |conf|
5
+
6
+ # To log to STDOUT, don't specify anything.
7
+ # To log to a specific path:
8
+ # conf.log_path = '/tmp/weeter.log'
9
+ # To disable logging:
10
+ # conf.log_path = false
11
+
12
+ conf.twitter do |twitter|
13
+ # For basic auth
14
+ # twitter.basic_auth = {:username => 'johnny', :password => 'secret'}
15
+
16
+ # Or, for oauth
17
+ twitter.oauth = {:consumer_key => ENV['WEETER_TWITTER_CONSUMER_KEY'],
18
+ :consumer_secret => ENV['WEETER_TWITTER_CONSUMER_SECRET'],
19
+ :access_key => ENV['WEETER_TWITTER_ACCESS_KEY'],
20
+ :access_secret => ENV['WEETER_TWITTER_ACCESS_SECRET']
21
+ }
22
+ end
23
+
24
+ conf.client_app do |client_app|
25
+ client_app.notification_plugin = :http
26
+ client_app.oauth = {
27
+ :consumer_key => ENV['WEETER_CLIENT_CONSUMER_KEY'],
28
+ :consumer_secret => ENV['WEETER_CLIENT_CONSUMER_SECRET'],
29
+ :access_key => ENV['WEETER_CLIENT_ACCESS_KEY'],
30
+ :access_secret => ENV['WEETER_CLIENT_ACCESS_SECRET']
31
+ }
32
+ client_app.publish_url = ENV['WEETER_CLIENT_PUBLISH_URL']
33
+ client_app.delete_url = ENV['WEETER_CLIENT_DELETE_URL']
34
+
35
+ client_app.subscription_plugin = :http
36
+ client_app.subscriptions_url = ENV['WEETER_CLIENT_SUBSCRIPTIONS_URL']
37
+ client_app.subscription_updates_port = 7337 # only effective if running as a daemon
38
+ end
39
+
40
+ # Alternately...
41
+
42
+ # conf.client_app do |client_app|
43
+ # client_app.notification_plugin = :resque
44
+ # client_app.queue = 'weeter'
45
+ # client_app.redis_uri = 'redis://redistogo:abcdef0123456789abcdef0123456789@somehost.redistogo.com:9052/'
46
+ #
47
+ # client_app.subscription_plugin = :redis
48
+ # client_app.subscriptions_key = 'weeter:subscriptions'
49
+ # client_app.subscriptions_changed_channel = 'weeter:subscriptions_changed'
50
+ # end
51
+ end
data/weeter.gemspec ADDED
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "weeter/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "weeter"
7
+ s.version = Weeter::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Luke Melia", "Noah Davis", "Joey Aghion"]
10
+ s.email = ["luke@lukemelia.com"]
11
+ s.homepage = "http://github.com/lukemelia/weeter"
12
+ s.summary = %q{Consume the Twitter stream and notify your app}
13
+ s.description = %q{Weeter subscribes to a set of twitter users or search terms using Twitter's streaming API, and notifies your app with each new tweet.}
14
+
15
+ s.rubyforge_project = "weeter"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency('eventmachine')
23
+ s.add_dependency('eventmachine_httpserver', '>= 0.2.1')
24
+ s.add_dependency('em-hiredis', '>= 0.1.0')
25
+ s.add_dependency('multi_json', '>= 1.0.2')
26
+ s.add_dependency('hashie', '>= 1.1.0')
27
+ s.add_dependency('em-http-request', '>= 1.0.0')
28
+ s.add_dependency('i18n', "~> 0.6.0")
29
+ s.add_dependency('activesupport', ">= 3.1.1")
30
+ s.add_dependency("simple_oauth", '~> 0.1.5')
31
+ s.add_dependency('twitter-stream', '~> 0.1.14')
32
+
33
+ s.add_development_dependency 'rspec', '~> 2.6.0'
34
+ end
metadata ADDED
@@ -0,0 +1,228 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: weeter
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.9.0
6
+ platform: ruby
7
+ authors:
8
+ - Luke Melia
9
+ - Noah Davis
10
+ - Joey Aghion
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+
15
+ date: 2011-11-02 00:00:00 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: eventmachine
19
+ prerelease: false
20
+ requirement: &id001 !ruby/object:Gem::Requirement
21
+ none: false
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: "0"
26
+ type: :runtime
27
+ version_requirements: *id001
28
+ - !ruby/object:Gem::Dependency
29
+ name: eventmachine_httpserver
30
+ prerelease: false
31
+ requirement: &id002 !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 0.2.1
37
+ type: :runtime
38
+ version_requirements: *id002
39
+ - !ruby/object:Gem::Dependency
40
+ name: em-hiredis
41
+ prerelease: false
42
+ requirement: &id003 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.0
48
+ type: :runtime
49
+ version_requirements: *id003
50
+ - !ruby/object:Gem::Dependency
51
+ name: multi_json
52
+ prerelease: false
53
+ requirement: &id004 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 1.0.2
59
+ type: :runtime
60
+ version_requirements: *id004
61
+ - !ruby/object:Gem::Dependency
62
+ name: hashie
63
+ prerelease: false
64
+ requirement: &id005 !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 1.1.0
70
+ type: :runtime
71
+ version_requirements: *id005
72
+ - !ruby/object:Gem::Dependency
73
+ name: em-http-request
74
+ prerelease: false
75
+ requirement: &id006 !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 1.0.0
81
+ type: :runtime
82
+ version_requirements: *id006
83
+ - !ruby/object:Gem::Dependency
84
+ name: i18n
85
+ prerelease: false
86
+ requirement: &id007 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ~>
90
+ - !ruby/object:Gem::Version
91
+ version: 0.6.0
92
+ type: :runtime
93
+ version_requirements: *id007
94
+ - !ruby/object:Gem::Dependency
95
+ name: activesupport
96
+ prerelease: false
97
+ requirement: &id008 !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 3.1.1
103
+ type: :runtime
104
+ version_requirements: *id008
105
+ - !ruby/object:Gem::Dependency
106
+ name: simple_oauth
107
+ prerelease: false
108
+ requirement: &id009 !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ~>
112
+ - !ruby/object:Gem::Version
113
+ version: 0.1.5
114
+ type: :runtime
115
+ version_requirements: *id009
116
+ - !ruby/object:Gem::Dependency
117
+ name: twitter-stream
118
+ prerelease: false
119
+ requirement: &id010 !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 0.1.14
125
+ type: :runtime
126
+ version_requirements: *id010
127
+ - !ruby/object:Gem::Dependency
128
+ name: rspec
129
+ prerelease: false
130
+ requirement: &id011 !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ~>
134
+ - !ruby/object:Gem::Version
135
+ version: 2.6.0
136
+ 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:
140
+ - luke@lukemelia.com
141
+ executables:
142
+ - weeter
143
+ - weeter_control
144
+ extensions: []
145
+
146
+ extra_rdoc_files: []
147
+
148
+ files:
149
+ - .gitignore
150
+ - Gemfile
151
+ - LICENSE
152
+ - README.md
153
+ - Rakefile
154
+ - bin/weeter
155
+ - bin/weeter_control
156
+ - lib/weeter.rb
157
+ - lib/weeter/.DS_Store
158
+ - lib/weeter/cli.rb
159
+ - lib/weeter/configuration.rb
160
+ - lib/weeter/configuration/client_app_config.rb
161
+ - lib/weeter/configuration/twitter_config.rb
162
+ - lib/weeter/plugins.rb
163
+ - lib/weeter/plugins/lib/oauth_http.rb
164
+ - lib/weeter/plugins/lib/redis.rb
165
+ - lib/weeter/plugins/notification/http.rb
166
+ - lib/weeter/plugins/notification/resque.rb
167
+ - lib/weeter/plugins/notification_plugin.rb
168
+ - lib/weeter/plugins/subscription/http.rb
169
+ - lib/weeter/plugins/subscription/redis.rb
170
+ - lib/weeter/plugins/subscription_plugin.rb
171
+ - lib/weeter/runner.rb
172
+ - lib/weeter/tasks.rb
173
+ - lib/weeter/twitter.rb
174
+ - lib/weeter/twitter/tweet_consumer.rb
175
+ - lib/weeter/twitter/tweet_item.rb
176
+ - lib/weeter/version.rb
177
+ - log/.gitignore
178
+ - spec/.DS_Store
179
+ - spec/spec_helper.rb
180
+ - spec/weeter/configuration/client_app_config_spec.rb
181
+ - spec/weeter/configuration/twitter_config_spec.rb
182
+ - spec/weeter/configuration_spec.rb
183
+ - spec/weeter/plugins/notification_plugin_spec.rb
184
+ - spec/weeter/plugins/subscription/update_server_spec.rb
185
+ - spec/weeter/plugins/subscription_plugin_spec.rb
186
+ - spec/weeter/runner_spec.rb
187
+ - spec/weeter/twitter/tweet_consumer_spec.rb
188
+ - spec/weeter/twitter/tweet_item_spec.rb
189
+ - weeter.conf.example
190
+ - weeter.gemspec
191
+ homepage: http://github.com/lukemelia/weeter
192
+ licenses: []
193
+
194
+ post_install_message:
195
+ rdoc_options: []
196
+
197
+ require_paths:
198
+ - lib
199
+ required_ruby_version: !ruby/object:Gem::Requirement
200
+ none: false
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ version: "0"
205
+ required_rubygems_version: !ruby/object:Gem::Requirement
206
+ none: false
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ version: "0"
211
+ requirements: []
212
+
213
+ rubyforge_project: weeter
214
+ rubygems_version: 1.8.10
215
+ signing_key:
216
+ specification_version: 3
217
+ summary: Consume the Twitter stream and notify your app
218
+ test_files:
219
+ - spec/spec_helper.rb
220
+ - spec/weeter/configuration/client_app_config_spec.rb
221
+ - spec/weeter/configuration/twitter_config_spec.rb
222
+ - spec/weeter/configuration_spec.rb
223
+ - spec/weeter/plugins/notification_plugin_spec.rb
224
+ - spec/weeter/plugins/subscription/update_server_spec.rb
225
+ - spec/weeter/plugins/subscription_plugin_spec.rb
226
+ - spec/weeter/runner_spec.rb
227
+ - spec/weeter/twitter/tweet_consumer_spec.rb
228
+ - spec/weeter/twitter/tweet_item_spec.rb