Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Move over implementation

  • Loading branch information...
commit 886ed778282d990c6edbcedaad9cee7cb0af3e57 1 parent b2a34bc
@coreyhaines authored
View
1  .rspec
@@ -0,0 +1 @@
+--color
View
52 lib/tweetbot.rb
@@ -1,5 +1,51 @@
-require "tweetbot/version"
+require 'tweetbot/version'
+require_relative 'tweetbot_talk'
-module Tweetbot
- # Your code goes here...
+class TweetBot
+ include TweetBotTalk
+ attr_accessor :response_frequency
+
+ def self.configure
+ bot = new
+ yield bot if block_given?
+ bot
+ end
+
+ def initialize()
+ self.response_frequency = 20
+ @responses_for_phrases = Hash.new { |hash, key| hash[key] = [] }
+ end
+
+ def phrases_to_search
+ @responses_for_phrases.keys
+ end
+
+ def respond_to_phrase(phrase)
+ responses = []
+ yield responses
+ add_responses_for_phrase(phrase, *responses)
+ end
+
+ def add_responses_for_phrase(phrase, *responses)
+ @responses_for_phrases[phrase.downcase] += responses
+ end
+
+ def response_for(tweet)
+ responses = responses_for_tweet(tweet)
+ "@#{tweet.user.screen_name} #{responses[rand(responses.length)]}"
+ end
+
+ def should_i_respond_to?(tweet)
+ matches = tweet_matches?(tweet)
+ frequency_check = (rand(100) < self.response_frequency)
+ matches && frequency_check
+ end
+
+ def tweet_matches?(tweet)
+ responses_for_tweet(tweet).any?
+ end
+
+ def responses_for_tweet(tweet)
+ @responses_for_phrases.select{|phrase, _| tweet.text =~ /#{phrase}/i}.values[0] || []
+ end
end
View
111 lib/tweetbot_talk.rb
@@ -0,0 +1,111 @@
+if ENV["DEBUG"]
+ module Twitter
+ def self.configure
+ end
+
+ def self.update(status, options = {})
+ puts "DEBUG: #{status}"
+ end
+ end
+end
+module TweetBotTalk
+ def talk
+ require 'twitter'
+ require 'tweetstream'
+ load 'twitter_auth.rb'
+
+
+ TweetStream.configure do |config|
+ config.consumer_key = ConsumerKey
+ config.consumer_secret = ConsumerSecret
+ config.oauth_token = OAuthToken
+ config.oauth_token_secret = OAuthTokenSecret
+ config.auth_method = :oauth
+ end
+ Twitter.configure do |config|
+ config.consumer_key = ConsumerKey
+ config.consumer_secret = ConsumerSecret
+ config.oauth_token = OAuthToken
+ config.oauth_token_secret = OAuthTokenSecret
+ end
+
+ if TwitterAuth.use_apigee?
+ twitter_api_endpoint = if ENV['APIGEE_TWITTER_API_ENDPOINT']
+ ENV['APIGEE_TWITTER_API_ENDPOINT']
+ else
+ # Get this value from Heroku.
+ # Once you have enabled the addon, boot up the 'heroku console' and run the following:
+ # puts ENV['APIGEE_TWITTER_API_ENDPOINT']
+ # this will spit out your correct api endpoint
+ TwitterAuth::ApigeeEnpoint
+ end
+ Twitter.configure do |config|
+ config.gateway = twitter_api_endpoint
+ end
+ end
+
+ bot = self
+
+ puts "Waking up to greet the world... #{Time.now}"
+ begin
+ Twitter.update "Waking up to greet the world... #{Time.now}"
+ rescue Twitter::Forbidden => ex
+ puts "Twitter Forbidden Error while waking up"
+ puts ex
+ puts "Continuing"
+ rescue Twitter::Error => ex
+ puts "Twitter Error while waking up"
+ puts ex
+ exit!(1)
+ rescue => ex
+ puts "Unknown Error while waking up"
+ puts ex
+ exit!(1)
+ end
+ puts "Listening... #{Time.now}"
+
+
+ client = TweetStream::Client.new
+
+ ["INT", "TERM", "STOP"].each do |signal|
+ trap(signal) do
+ puts "Got #{signal}"
+ client.stop
+ exit!(1)
+ end
+ end
+
+ at_exit do
+ puts "Shutting down... #{Time.now}"
+ begin
+ Twitter.update "Going to sleep... #{Time.now}"
+ rescue
+ end
+ end
+
+
+ client.on_error do |message|
+ puts "Error: #{Time.now}"
+ puts message
+ end
+
+ client.track(*bot.phrases_to_search) do |status|
+ if status.user.screen_name == TwitterAuth::MyName
+ puts "#{Time.now} Caught myself saying it"
+ else
+ puts "#{Time.now} #{status.user.screen_name} said #{status.text}"
+ if bot.should_i_respond_to?(status)
+ begin
+ response = bot.response_for(status)
+ Twitter.update "#{response}", :in_reply_to_status_id => status.id
+ rescue Exception => e
+ puts "Exception while sending the reply"
+ puts e
+ end
+ else
+ puts "Bot told me not to respond"
+ end
+ end
+ end
+ end
+end
View
43 spec/tweetbot_config_spec.rb
@@ -0,0 +1,43 @@
+require_relative '../lib/tweetbot'
+
+describe "configuring tweetbot with a config block" do
+
+ context "without a configure block" do
+ it "returns a bot that I can use" do
+ bot = TweetBot.configure
+ bot.response_frequency = 4
+ bot.response_frequency.should == 4
+ end
+ end
+
+ context "configuring frequency" do
+ let(:bot) do
+ TweetBot.configure do |bot|
+ bot.response_frequency = 4
+ end
+ end
+
+ it "saves the response_frequency" do
+ bot.response_frequency.should == 4
+ end
+ end
+
+ context "configuring responses" do
+ let(:bot) do
+ TweetBot.configure do |bot|
+ bot.respond_to_phrase "code and coffee" do |responses|
+ responses << "good times" << "bad times"
+ end
+ end
+ end
+
+ it "saves the response given in block" do
+ bot.stub(:rand) { 0 }
+ response = bot.response_for(stub(:text => "code and coffee", :user => stub.as_null_object))
+ response.should =~ /good times$/
+ bot.stub(:rand) { 1 }
+ response = bot.response_for(stub(:text => "code and coffee", :user => stub.as_null_object))
+ response.should =~ /bad times$/
+ end
+ end
+end
View
115 spec/tweetbot_spec.rb
@@ -0,0 +1,115 @@
+require_relative '../lib/tweetbot'
+
+
+describe TweetBot do
+ let(:bot) { TweetBot.new }
+ let(:tweet) { stub(:text => "hello world", :user => stub(:screen_name => "fun_person")) }
+
+ before do
+ bot.add_responses_for_phrase "hello world", "and hello to you"
+ end
+
+ describe "#phrases_to_search" do
+ it "returns the phrases that have responses associated with them" do
+ bot.add_responses_for_phrase "good night", ""
+ bot.phrases_to_search.should == ["hello world", "good night"]
+ end
+ end
+
+ describe "#tweet_matches?" do
+ before do
+ bot.add_responses_for_phrase "the night", "a dark night"
+ end
+ it "looks to see if any phrases match the tweet" do
+ tweet.stub(:text) { "the night" }
+ bot.tweet_matches?(tweet).should be_true
+ tweet.stub(:text) { "the day" }
+ bot.tweet_matches?(tweet).should be_false
+ end
+
+ it "compares case-insensitive" do
+ tweet.stub(:text) { "The Night"}
+ bot.tweet_matches?(tweet).should be_true
+ end
+
+ it "matches if anywhere in text" do
+ tweet.stub(:text) { "It is cold The Night"}
+ bot.tweet_matches?(tweet).should be_true
+ end
+ end
+
+ describe "#response_for" do
+ it "replies to the user" do
+ tweet.user.stub(:screen_name) { "corey" }
+ bot.response_for(tweet).should =~ /^@corey/
+ end
+
+ it "uses responses associated with phrase" do
+ bot.add_responses_for_phrase("good morning", "morning response")
+ bot.add_responses_for_phrase("good night", "night response")
+
+ tweet.stub(:text) { "good morning" }
+ bot.response_for(tweet).should =~ /morning response/
+ tweet.stub(:text) { "good night" }
+ bot.response_for(tweet).should =~ /night response/
+ end
+
+ it "it randomly uses a phrase from the responses" do
+ tweet.stub(:text) { "good morning" }
+ bot.add_responses_for_phrase("good morning", "response 1")
+ bot.add_responses_for_phrase("good morning", "response 2")
+ bot.stub(:rand) { 0 }
+ bot.response_for(tweet).should =~ /response 1/
+ bot.stub(:rand) { 1 }
+ bot.response_for(tweet).should =~ /response 2/
+ end
+
+ it "uses responses if phrase appears anywhere in tweet (case-insensitive)" do
+ bot.add_responses_for_phrase("good afternoon", "afternoon response")
+ tweet.stub(:text) { "this is a Good Afternoon" }
+ bot.response_for(tweet).should =~ /afternoon response/
+ end
+
+ it "supports adding multiple responses for a phrase in one add_... call" do
+ tweet.stub(:text) { "good day" }
+ bot.add_responses_for_phrase("good day", "and to you", "and again to you")
+ bot.stub(:rand) { 0 }
+ bot.response_for(tweet).should =~ /and to you/
+ bot.stub(:rand) { 1 }
+ bot.response_for(tweet).should =~ /and again to you/
+ end
+
+ end
+
+ describe "#should_i_respond_to?" do
+ before do
+ bot.stub(:rand) { 1 }
+ bot.stub(:tweet_matches?) { true }
+ end
+ it "only responds if rand is less than response_frequency" do
+ bot.response_frequency = 30
+ bot.stub(:rand) { 29 }
+ bot.should_i_respond_to?(stub).should be_true
+ bot.stub(:rand) { 30 }
+ bot.should_i_respond_to?(stub).should be_false
+ bot.stub(:rand) { 31 }
+ bot.should_i_respond_to?(stub).should be_false
+ end
+
+ it "only responds if phrase matches" do
+ bot.stub(:tweet_matches?) { true }
+ bot.should_i_respond_to?(stub).should be_true
+ bot.stub(:tweet_matches?) { false }
+ bot.should_i_respond_to?(stub).should be_false
+ end
+ end
+
+ describe "#respond_to_phrase" do
+ it "stores the given responses" do
+ bot.respond_to_phrase "morning fun" do |responses|
+ responses << "evening delight" << "afternoon rockets"
+ end
+ bot.responses_for_tweet(stub(:text => "morning fun")).should =~ ["evening delight", "afternoon rockets"]
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.