chatterbot 0.2.8 → 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/{README.rdoc → README.markdown} +86 -62
- data/bin/chatterbot-blacklist +1 -1
- data/bin/chatterbot-register +113 -0
- data/bin/chatterbot-status +53 -0
- data/chatterbot.gemspec +2 -2
- data/lib/chatterbot.rb +0 -1
- data/lib/chatterbot/blacklist.rb +1 -8
- data/lib/chatterbot/bot.rb +4 -0
- data/lib/chatterbot/client.rb +23 -9
- data/lib/chatterbot/config.rb +36 -2
- data/lib/chatterbot/dsl.rb +47 -13
- data/lib/chatterbot/helpers.rb +31 -5
- data/lib/chatterbot/reply.rb +1 -1
- data/lib/chatterbot/search.rb +13 -1
- data/lib/chatterbot/tweet.rb +3 -1
- data/lib/chatterbot/version.rb +1 -1
- data/spec/config_spec.rb +50 -0
- data/spec/dsl_spec.rb +20 -1
- data/spec/helpers_spec.rb +51 -3
- data/spec/reply_spec.rb +11 -1
- data/spec/search_spec.rb +24 -6
- data/spec/spec_helper.rb +7 -5
- metadata +23 -19
data/Gemfile
CHANGED
@@ -7,11 +7,12 @@ gemspec
|
|
7
7
|
# Add dependencies to develop your gem here.
|
8
8
|
# Include everything needed to run rake, tests, features, etc.
|
9
9
|
group :development do
|
10
|
+
gem 'simplecov', :require => false, :group => :test
|
11
|
+
|
10
12
|
gem "shoulda", ">= 0"
|
11
13
|
gem "rspec"
|
12
14
|
|
13
15
|
gem "bundler", "~> 1.0.0"
|
14
|
-
gem "rcov"
|
15
16
|
gem "watchr"
|
16
17
|
end
|
17
18
|
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
Chatterbot
|
2
|
+
===========
|
2
3
|
|
3
4
|
Chatterbot is a Ruby library for making bots on Twitter. It is basic
|
4
5
|
enough that you can put it into use quickly, but can be used to make
|
@@ -6,49 +7,62 @@ pretty involved bots. It handles searches, replies and tweets, and has
|
|
6
7
|
a simple blacklist system to help keep you from spamming people who
|
7
8
|
don't want to hear from your bot.
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
Features
|
11
|
+
--------
|
11
12
|
* Works via Twitter's OAuth system.
|
12
13
|
* Handles search queries and replies to your bot
|
13
14
|
* Use a simple DSL, or extend a Bot class if you need it
|
14
15
|
* Simple blacklistling system to limit your annoyance of users
|
15
16
|
* Optionally log tweets to the database for metrics and tracking purposes
|
16
17
|
|
17
|
-
|
18
|
+
Using Chatterbot
|
19
|
+
================
|
18
20
|
|
19
|
-
|
21
|
+
Make a Twitter account
|
22
|
+
----------------------
|
20
23
|
|
21
24
|
First thing you'll need to do is create an account for your bot on
|
22
25
|
Twitter. That's the easy part.
|
23
26
|
|
24
|
-
|
27
|
+
Run the generator
|
28
|
+
-----------------
|
29
|
+
|
30
|
+
Chatterbot comes with a script named `chatterbot-register` which will
|
31
|
+
handle two tasks -- it will authorize your bot with Twitter and it
|
32
|
+
will generate a skeleton script, which you use to implement your
|
33
|
+
actual bot.
|
34
|
+
|
35
|
+
Write your bot
|
36
|
+
--------------
|
25
37
|
|
26
38
|
Chatterbot has a very simple DSL inspired by Sinatra and Twibot, an
|
27
|
-
earlier Twitter bot framework. Here's an example, based on
|
28
|
-
|
39
|
+
earlier Twitter bot framework. Here's an example, based on
|
40
|
+
[@dr_rumack](http://twitter.com/#!/Dr_Rumack), an actual bot running
|
41
|
+
on Twitter:
|
29
42
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
43
|
+
require 'chatterbot/dsl'
|
44
|
+
search("'surely you must be joking'") do |tweet|
|
45
|
+
reply "@#{tweet_user(tweet)} I am serious, and don't call me Shirley!", tweet
|
46
|
+
end
|
34
47
|
|
35
|
-
Or, you can create a bot object yourself, extend it if needed, and use
|
36
|
-
it like so:
|
48
|
+
Or, you can create a bot object yourself, extend it if needed, and use it like so:
|
37
49
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
50
|
+
bot = Chatterbot::Bot.new
|
51
|
+
bot.search("'surely you must be joking'") do |tweet|
|
52
|
+
bot.reply "@#{tweet_user(tweet)} I am serious, and don't call me Shirley!", tweet
|
53
|
+
end
|
42
54
|
|
43
55
|
That's it!
|
44
56
|
|
45
|
-
|
57
|
+
Authorization
|
58
|
+
-------------
|
46
59
|
|
47
60
|
If you only want to use Chatterbot to search for tweets, it will work
|
48
61
|
out of the box without any authorization. However, if you want to
|
49
62
|
reply to tweets, or check for replies to your bot, you will have to
|
50
|
-
jump through a few authorization hoops with Twitter.
|
51
|
-
|
63
|
+
jump through a few authorization hoops with Twitter.
|
64
|
+
|
65
|
+
Before you setup a bot for the first time, you will need to register an
|
52
66
|
application with Twitter. Twitter requires all API communication to be via an
|
53
67
|
app which is registered on Twitter. I would set one up and make it
|
54
68
|
part of Chatterbot, but unfortunately Twitter doesn't allow developers
|
@@ -56,29 +70,29 @@ to publicly post the OAuth consumer key/secret that you would need to
|
|
56
70
|
use. If you're planning to run more than one bot, you only need to do
|
57
71
|
this step once -- you can use the same app setup for other bots too.
|
58
72
|
|
59
|
-
|
73
|
+
The helper script `chatterbot-register` will walk you through most of
|
74
|
+
this without too much hand-wringing. And, if you write a bot without
|
75
|
+
`chatterbot-register`, you'll still be sent through the authorization
|
76
|
+
process the first time you run your script. But if you prefer, here's
|
77
|
+
the instructions if you want to do it yourself:
|
60
78
|
|
79
|
+
1. [Setup your own app](https://twitter.com/apps/new) on Twitter.
|
61
80
|
|
81
|
+
2. Choose 'Client' as the app type.
|
62
82
|
|
83
|
+
3. Choose 'Read & Write' access unless you don't need to send tweets.
|
63
84
|
|
64
|
-
|
65
|
-
|
66
|
-
|
85
|
+
4. Take the consumer key/consumer secret values, and either run your bot, and enter them
|
86
|
+
in when prompted, or store them in a config file for your bot. (See
|
87
|
+
below for details on this). It should look like this:
|
67
88
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
4. Take the consumer key/consumer secret values, and either run your
|
72
|
-
bot, and enter them in when prompted, or store them in a config
|
73
|
-
file for your bot. (See below for details on this). It should look
|
74
|
-
like this:
|
89
|
+
---
|
90
|
+
:consumer_secret: CONSUMER SECRET GOES HERE
|
91
|
+
:consumer_key: CONSUMER KEY GOES HERE
|
75
92
|
|
76
|
-
---
|
77
|
-
:consumer_secret: CONSUMER SECRET GOES HERE
|
78
|
-
:consumer_key: CONSUMER KEY GOES HERE
|
79
93
|
|
80
|
-
|
81
|
-
same values as in Step #4.
|
94
|
+
When you do this via the helper script, chatterbot will point you at
|
95
|
+
the URL in Step #1, then ask you to paste the same values as in Step #4.
|
82
96
|
|
83
97
|
Once this is done, you will need to setup authorization for the actual
|
84
98
|
bot with Twitter. At the first run, you'll get a message asking you to go
|
@@ -90,30 +104,32 @@ bot. Hit return, and you should be all set.
|
|
90
104
|
This is obviously a bunch of effort, but once you're done, you're
|
91
105
|
ready to go!
|
92
106
|
|
93
|
-
|
107
|
+
Configuration
|
108
|
+
-------------
|
94
109
|
|
95
110
|
Chatterbot offers a couple different methods of storing the config for
|
96
111
|
your bot:
|
97
112
|
|
98
113
|
1. In a YAML file with the same name as the bot, so if you have
|
99
114
|
botname.rb or a Botname class, store your config in botname.yaml
|
100
|
-
2. In a global config file at
|
115
|
+
2. In a global config file at `/etc/chatterbot.yml` -- values stored here
|
101
116
|
will apply to any bots you run.
|
102
117
|
3. In another global config file specified in the environment variable
|
103
|
-
|
104
|
-
4. In a
|
118
|
+
`'chatterbot_config'`.
|
119
|
+
4. In a `global.yml` file in the same directory as your bot. This
|
105
120
|
gives you the ability to have a global configuration file, but keep
|
106
121
|
it with your bots if desired.
|
107
122
|
5. In a database. You can store your configuration in a DB, and then
|
108
123
|
specify the connection string either in one of the global config
|
109
|
-
files, or on the command-line by using the
|
124
|
+
files, or on the command-line by using the `--db="db_uri"`
|
110
125
|
configuration option. Any calls to the database are handled by the
|
111
126
|
Sequel gem, and MySQL and Sqlite should work. The DB URI should
|
112
|
-
be in the form of
|
127
|
+
be in the form of `mysql://username:password@host/database` -- see
|
113
128
|
http://sequel.rubyforge.org/rdoc/files/doc/opening_databases_rdoc.html
|
114
129
|
for details.
|
115
130
|
|
116
|
-
|
131
|
+
Running Your Bot
|
132
|
+
----------------
|
117
133
|
|
118
134
|
There's a couple ways of running your bot:
|
119
135
|
|
@@ -121,51 +137,58 @@ Run it on the command-line whenever you like. Whee!
|
|
121
137
|
|
122
138
|
Run it via cron. Here's an example of running a bot every two minutes
|
123
139
|
|
124
|
-
|
140
|
+
*/2 * * * * . ~/.bash_profile; cd /path/to/bot/; ./bot.rb
|
125
141
|
|
126
142
|
Run it as a background process. Just put the guts of your bot in a loop like this:
|
127
|
-
loop do
|
128
|
-
replies do |tweet|
|
129
|
-
# do stuff
|
130
|
-
end
|
131
143
|
|
132
|
-
|
133
|
-
|
144
|
+
loop do
|
145
|
+
replies do |tweet|
|
146
|
+
# do stuff
|
147
|
+
end
|
134
148
|
|
135
|
-
|
149
|
+
sleep 60
|
150
|
+
end
|
151
|
+
|
152
|
+
Database logging
|
153
|
+
----------------
|
136
154
|
|
137
155
|
Chatterbot can log tweet activity to the database if desired. This
|
138
156
|
can be handy for tracking what's going on with your bot. See
|
139
|
-
|
157
|
+
`Chatterbot::Logging` for details on this.
|
140
158
|
|
141
159
|
|
142
|
-
|
160
|
+
Blacklists
|
161
|
+
----------
|
143
162
|
|
144
163
|
Not everyone wants to hear from your bot. To keep annoyances to a
|
145
164
|
minimum, Chatterbot has a global blacklist option, as well as
|
146
165
|
bot-specific blacklists if desired. The global blacklist is stored in
|
147
166
|
the database, and you can add entries to it by using the
|
148
|
-
|
167
|
+
`chatterbot-blacklist` script included with the gem.
|
149
168
|
|
150
169
|
You can also specify users to skip as part of the DSL:
|
151
170
|
|
152
|
-
|
153
|
-
|
171
|
+
require 'chatterbot'
|
172
|
+
blacklist "mean_user, private_user"
|
173
|
+
|
174
|
+
You should really respect the wishes of users who don't want to hear
|
175
|
+
from your bot, and add them to your blacklist whenever requested.
|
154
176
|
|
155
177
|
There's also an 'exclude' method which can be used to add
|
156
178
|
words/phrases you might want to ignore -- for example, if you wanted
|
157
179
|
to ignore tweets with links, you could do something like this:
|
158
180
|
|
159
|
-
|
181
|
+
exclude "http://"
|
160
182
|
|
161
|
-
|
183
|
+
TODO
|
184
|
+
====
|
162
185
|
|
163
|
-
* A skeleton bot generator
|
164
186
|
* web-based frontend for tracking bot activity
|
165
187
|
* opt-out system that adds people to blacklist if they reply to a bot
|
166
188
|
in the right way
|
167
189
|
|
168
|
-
|
190
|
+
Contributing to Chatterbot
|
191
|
+
--------------------------
|
169
192
|
|
170
193
|
Since this code is based off of actual Twitter bots, it's mostly
|
171
194
|
working the way I want it to, and I might prefer to keep it that way.
|
@@ -174,7 +197,8 @@ fork the project and hack away. I'll pull anything back that makes
|
|
174
197
|
sense if requested.
|
175
198
|
|
176
199
|
|
177
|
-
|
200
|
+
Copyright/License
|
201
|
+
-----------------
|
178
202
|
|
179
203
|
Copyright (c) 2011 Colin Mitchell. Chatterbot is distributed under a
|
180
204
|
modified WTFPL licence -- it's the 'Do what the fuck you want to --
|
data/bin/chatterbot-blacklist
CHANGED
@@ -0,0 +1,113 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
|
4
|
+
require 'chatterbot'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
include Chatterbot::Helpers
|
8
|
+
include Chatterbot::Config
|
9
|
+
include Chatterbot::DB
|
10
|
+
include Chatterbot::Logging
|
11
|
+
|
12
|
+
@force = false
|
13
|
+
|
14
|
+
|
15
|
+
#
|
16
|
+
# pull in any arguments and set them as env variables
|
17
|
+
#
|
18
|
+
opts = OptionParser.new
|
19
|
+
opts.banner = <<-EOS
|
20
|
+
|
21
|
+
Register a bot with Twitter, and generate a script to run
|
22
|
+
it. This script will walk you through the whole process.
|
23
|
+
|
24
|
+
Usage: #{File.basename($0)} [options]
|
25
|
+
EOS
|
26
|
+
|
27
|
+
opts.separator ""
|
28
|
+
opts.separator "Options:"
|
29
|
+
|
30
|
+
opts.on('-d', '--db [ARG]', "Specify a DB connection URI") { |d| ENV["chatterbot_db"] = d }
|
31
|
+
opts.on('-c', '--config [ARG]', "Specify a config file to load") { |c| ENV["chatterbot_config"] = c }
|
32
|
+
opts.on('-b', '--bot [ARG]', "Name of the bot you want to register. If you don't specify this, it will be grabbed from twitter when you authenticate") { |b| @botname = b }
|
33
|
+
opts.on('-f', '--force', "Overwrite existing config values") { @force = true }
|
34
|
+
|
35
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
36
|
+
puts opts
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# skeleton code for a bot -- pretty basic but covers the bases
|
42
|
+
#
|
43
|
+
skeleton = <<'EOF'
|
44
|
+
#!/usr/bin/env ruby
|
45
|
+
|
46
|
+
require 'rubygems'
|
47
|
+
require 'chatterbot/dsl'
|
48
|
+
|
49
|
+
# remove this to send out tweets
|
50
|
+
debug_mode
|
51
|
+
|
52
|
+
# remove this to update the db
|
53
|
+
no_update
|
54
|
+
# remove this to get less output when running
|
55
|
+
verbose
|
56
|
+
|
57
|
+
# here's a list of users to ignore
|
58
|
+
blacklist "abc", "def"
|
59
|
+
|
60
|
+
# here's a list of things to exclude from searches
|
61
|
+
exclude "hi", "spammer", "junk"
|
62
|
+
|
63
|
+
search "keyword" do |tweet|
|
64
|
+
reply "Hey #USER# nice to meet you!", tweet
|
65
|
+
end
|
66
|
+
|
67
|
+
replies do |tweet|
|
68
|
+
reply "Yes #USER#, you are very kind to say that!", tweet
|
69
|
+
end
|
70
|
+
|
71
|
+
EOF
|
72
|
+
|
73
|
+
extra = opts.parse!(ARGV)
|
74
|
+
|
75
|
+
|
76
|
+
if @botname.nil?
|
77
|
+
@botname = "tmp_bot_name"
|
78
|
+
end
|
79
|
+
|
80
|
+
@bot = Chatterbot::Bot.new(:name => @botname)
|
81
|
+
|
82
|
+
if ! @bot.needs_auth_token? && @force == false
|
83
|
+
puts "Looks like your bot has already been authorized."
|
84
|
+
puts "If something went wrong, run #{File.basename($0)} again with the '-f' flag."
|
85
|
+
end
|
86
|
+
|
87
|
+
@bot.config.delete(:token)
|
88
|
+
@bot.require_login(false)
|
89
|
+
|
90
|
+
if @bot.client.authorized?
|
91
|
+
if @botname == "tmp_bot_name"
|
92
|
+
puts "change botname to #{@bot.access_token.params[:screen_name]}"
|
93
|
+
@bot.botname = @bot.access_token.params[:screen_name]
|
94
|
+
end
|
95
|
+
|
96
|
+
puts "Storing config info"
|
97
|
+
@bot.update_config
|
98
|
+
|
99
|
+
skel_dest = File.join(Dir.getwd, "#{@bot.botname}.rb")
|
100
|
+
if File.exist?(skel_dest)
|
101
|
+
puts "#{skel_dest} exists already, not doing anything"
|
102
|
+
else
|
103
|
+
puts "writing skeleton to #{skel_dest}"
|
104
|
+
|
105
|
+
f = File.new(skel_dest, "w")
|
106
|
+
f.write(skeleton)
|
107
|
+
f.close
|
108
|
+
|
109
|
+
File.chmod(0740, skel_dest)
|
110
|
+
end
|
111
|
+
else
|
112
|
+
puts "Looks like something went wrong, better luck next time!"
|
113
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
|
4
|
+
require 'chatterbot'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
include Chatterbot::Helpers
|
8
|
+
include Chatterbot::Config
|
9
|
+
include Chatterbot::DB
|
10
|
+
|
11
|
+
@tweet_count = 5
|
12
|
+
|
13
|
+
#
|
14
|
+
# pull in any arguments and set them as env variables
|
15
|
+
#
|
16
|
+
opts = OptionParser.new
|
17
|
+
opts.banner = "Usage: #{File.basename($0)} [options]"
|
18
|
+
|
19
|
+
opts.separator ""
|
20
|
+
opts.separator "Specific options:"
|
21
|
+
|
22
|
+
opts.on('-d', '--db [ARG]', "Specify a DB connection URI") { |d| ENV["chatterbot_db"] = d }
|
23
|
+
opts.on('-c', '--config [ARG]', "Specify a config file to use") { |c| ENV["chatterbot_config"] = c }
|
24
|
+
opts.on('-t', '--tweets [ARG]', "How many tweets to display") { |t| @tweet_count = t.to_i }
|
25
|
+
|
26
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
27
|
+
puts opts
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
|
31
|
+
extra = opts.parse!(ARGV)
|
32
|
+
|
33
|
+
#
|
34
|
+
# will only work if user is tracking tweets in a db
|
35
|
+
#
|
36
|
+
if ! has_db?
|
37
|
+
puts "You need to specify a db connection!"
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# return total number of tweets sent in last 'days' days
|
43
|
+
#
|
44
|
+
def count_for_period(bot, days=1)
|
45
|
+
db[:tweets].filter(:bot => bot[:id]).filter{created_at > (Time.now - (days*86400))}.count
|
46
|
+
end
|
47
|
+
|
48
|
+
db[:config].each do |bot|
|
49
|
+
puts "Tweets from #{bot[:id]} #{[1,7,30].collect{|d| count_for_period(bot, d)}.join("/")}"
|
50
|
+
db[:tweets].filter(:bot => bot[:id]).order(:created_at.desc).limit(@tweet_count).each do |t|
|
51
|
+
puts "#{t[:created_at]}: #{t[:txt]} (#{t[:source_tweet]})"
|
52
|
+
end
|
53
|
+
end
|
data/chatterbot.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.add_development_dependency(%q<rspec>, [">= 0"])
|
30
30
|
s.add_development_dependency(%q<rdoc>, [">= 0"])
|
31
31
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
32
|
-
s.add_development_dependency(%q<
|
32
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
33
33
|
s.add_development_dependency(%q<watchr>, [">= 0"])
|
34
34
|
else
|
35
35
|
s.add_dependency(%q<twitter_oauth>, [">= 0"])
|
@@ -37,7 +37,7 @@ Gem::Specification.new do |s|
|
|
37
37
|
s.add_dependency(%q<rspec>, [">= 0"])
|
38
38
|
s.add_dependency(%q<rdoc>, [">= 0"])
|
39
39
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
40
|
-
s.add_dependency(%q<
|
40
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
41
41
|
s.add_dependency(%q<watchr>, [">= 0"])
|
42
42
|
end
|
43
43
|
else
|
data/lib/chatterbot.rb
CHANGED
data/lib/chatterbot/blacklist.rb
CHANGED
@@ -25,18 +25,11 @@ module Chatterbot
|
|
25
25
|
search = s.is_a?(Hash) ? s[:text] : s
|
26
26
|
exclude.detect { |e| search.downcase.include?(e) } != nil
|
27
27
|
end
|
28
|
-
|
29
|
-
#
|
30
|
-
# Pull the username from a tweet hash -- this is different depending on
|
31
|
-
# if we're doing a search, or parsing through replies/mentions.
|
32
|
-
def tweet_user(s)
|
33
|
-
s.has_key?(:from_user) ? s[:from_user] : s[:user][:screen_name]
|
34
|
-
end
|
35
28
|
|
36
29
|
#
|
37
30
|
# Is this tweet from a user on our blacklist?
|
38
31
|
def on_blacklist?(s)
|
39
|
-
search = (s.is_a?(Hash) ?
|
32
|
+
search = (s.is_a?(Hash) ? from_user(s) : s).downcase
|
40
33
|
blacklist.any? { |b| search.include?(b.downcase) } ||
|
41
34
|
on_global_blacklist?(search)
|
42
35
|
end
|
data/lib/chatterbot/bot.rb
CHANGED
data/lib/chatterbot/client.rb
CHANGED
@@ -7,13 +7,18 @@ module Chatterbot
|
|
7
7
|
# the Twitter client
|
8
8
|
attr_accessor :client
|
9
9
|
|
10
|
+
# track the access token so we can get screen name when
|
11
|
+
# registering new bots
|
12
|
+
attr_accessor :access_token
|
13
|
+
|
10
14
|
#
|
11
15
|
# default options when querying twitter -- this could be extended
|
12
16
|
# with a language, etc.
|
13
17
|
def default_opts
|
14
18
|
return {} if since_id <= 0
|
15
19
|
{
|
16
|
-
:since_id => since_id
|
20
|
+
:since_id => since_id,
|
21
|
+
:result_type => "recent"
|
17
22
|
}
|
18
23
|
end
|
19
24
|
|
@@ -34,9 +39,9 @@ module Chatterbot
|
|
34
39
|
#
|
35
40
|
# Call this before doing anything that requires an authorized Twitter
|
36
41
|
# connection.
|
37
|
-
def require_login
|
42
|
+
def require_login(do_update_config=true)
|
38
43
|
init_client
|
39
|
-
login
|
44
|
+
login(do_update_config)
|
40
45
|
end
|
41
46
|
|
42
47
|
#
|
@@ -49,6 +54,8 @@ module Chatterbot
|
|
49
54
|
|
50
55
|
puts "Paste your PIN and hit enter when you have completed authorization."
|
51
56
|
STDIN.readline.chomp
|
57
|
+
rescue Interrupt => e
|
58
|
+
|
52
59
|
end
|
53
60
|
|
54
61
|
#
|
@@ -87,13 +94,16 @@ module Chatterbot
|
|
87
94
|
# error message for auth
|
88
95
|
def display_oauth_error
|
89
96
|
debug "Oops! Looks like something went wrong there, please try again!"
|
90
|
-
# exit
|
91
97
|
end
|
92
98
|
|
93
99
|
#
|
94
100
|
# handle oauth for this request. if the client isn't authorized, print
|
95
101
|
# out the auth URL and get a pin code back from the user
|
96
|
-
|
102
|
+
# If +do_update_config+ is false, don't udpate the bots config
|
103
|
+
# file after authorization. This defaults to true but
|
104
|
+
# chatterbot-register will pass in false because it does some
|
105
|
+
# other work before saving.
|
106
|
+
def login(do_update_config=true)
|
97
107
|
if needs_api_key?
|
98
108
|
get_api_key
|
99
109
|
end
|
@@ -102,16 +112,20 @@ module Chatterbot
|
|
102
112
|
request_token = client.request_token
|
103
113
|
|
104
114
|
pin = get_oauth_verifier(request_token)
|
105
|
-
|
115
|
+
return false if pin.nil?
|
116
|
+
|
117
|
+
@access_token = client.authorize(
|
106
118
|
request_token.token,
|
107
119
|
request_token.secret,
|
108
120
|
:oauth_verifier => pin
|
109
121
|
)
|
110
122
|
|
123
|
+
|
111
124
|
if client.authorized?
|
112
|
-
config[:token] = access_token.token
|
113
|
-
config[:secret] = access_token.secret
|
114
|
-
|
125
|
+
config[:token] = @access_token.token
|
126
|
+
config[:secret] = @access_token.secret
|
127
|
+
|
128
|
+
update_config unless do_update_config == false
|
115
129
|
else
|
116
130
|
display_oauth_error
|
117
131
|
return false
|
data/lib/chatterbot/config.rb
CHANGED
@@ -35,6 +35,13 @@ module Chatterbot
|
|
35
35
|
has_sequel? && config.has_key?(:db_uri)
|
36
36
|
end
|
37
37
|
|
38
|
+
def debug_mode=(d)
|
39
|
+
config[:debug_mode] = d
|
40
|
+
end
|
41
|
+
def no_update=(d)
|
42
|
+
config[:no_update] = d
|
43
|
+
end
|
44
|
+
|
38
45
|
#
|
39
46
|
# are we in debug mode?
|
40
47
|
def debug_mode?
|
@@ -53,6 +60,10 @@ module Chatterbot
|
|
53
60
|
has_config? && config.has_key?(:log_dest)
|
54
61
|
end
|
55
62
|
|
63
|
+
def verbose=(v)
|
64
|
+
config[:verbose] = v
|
65
|
+
end
|
66
|
+
|
56
67
|
def verbose?
|
57
68
|
config[:verbose] || false
|
58
69
|
end
|
@@ -132,10 +143,32 @@ module Chatterbot
|
|
132
143
|
config[:token].nil?
|
133
144
|
end
|
134
145
|
|
146
|
+
#
|
147
|
+
# determine if we're being called by one of our internal scripts
|
148
|
+
#
|
149
|
+
def chatterbot_helper?
|
150
|
+
File.basename($0).include?("chatterbot-")
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# if we are called by a bot, we want to use the directory of that
|
155
|
+
# script. If we are called by chatterbot-register or another
|
156
|
+
# helper script, we want to use the current working directory
|
157
|
+
#
|
158
|
+
def working_dir
|
159
|
+
if chatterbot_helper?
|
160
|
+
Dir.getwd
|
161
|
+
else
|
162
|
+
File.dirname($0)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
135
166
|
#
|
136
167
|
# figure out what config file to load based on the name of the bot
|
137
168
|
def config_file
|
138
|
-
|
169
|
+
dest = working_dir
|
170
|
+
|
171
|
+
x = File.join(File.expand_path(dest), "#{botname}.yml")
|
139
172
|
end
|
140
173
|
|
141
174
|
#
|
@@ -164,7 +197,7 @@ module Chatterbot
|
|
164
197
|
ENV["chatterbot_config"],
|
165
198
|
|
166
199
|
# 'global' config file local to the path of the ruby script
|
167
|
-
File.join(
|
200
|
+
File.join(working_dir, "global.yml")
|
168
201
|
].compact
|
169
202
|
end
|
170
203
|
|
@@ -172,6 +205,7 @@ module Chatterbot
|
|
172
205
|
# get any config from our global config files
|
173
206
|
def global_config
|
174
207
|
tmp = {}
|
208
|
+
|
175
209
|
global_config_files.each { |f|
|
176
210
|
tmp.merge!(slurp_file(f) || {})
|
177
211
|
}
|
data/lib/chatterbot/dsl.rb
CHANGED
@@ -41,29 +41,63 @@ module Chatterbot
|
|
41
41
|
@bot = Chatterbot::Bot.new(params)
|
42
42
|
end
|
43
43
|
|
44
|
+
#
|
45
|
+
# should we send tweets?
|
46
|
+
#
|
47
|
+
def debug_mode(d=nil)
|
48
|
+
d = true if d.nil?
|
49
|
+
bot.debug_mode = d
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# should we update the db with a new since_id?
|
54
|
+
#
|
55
|
+
def no_update(d=nil)
|
56
|
+
d = true if d.nil?
|
57
|
+
bot.no_update = d
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# turn on/off verbose output
|
62
|
+
#
|
63
|
+
def verbose(d=nil)
|
64
|
+
d = true if d.nil?
|
65
|
+
bot.verbose = d
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# take a variable list of strings and possibly arrays and turn
|
70
|
+
# them into a single flat array of strings
|
71
|
+
#
|
72
|
+
def flatten_list_of_strings(args)
|
73
|
+
args.collect do |b|
|
74
|
+
if b.is_a?(String)
|
75
|
+
# string, split on commas and turn into array
|
76
|
+
b.split(",").collect { |s| s.strip }
|
77
|
+
else
|
78
|
+
# presumably an array
|
79
|
+
b
|
80
|
+
end
|
81
|
+
end.flatten
|
82
|
+
end
|
83
|
+
|
44
84
|
#
|
45
85
|
# specify a bot-specific blacklist of users. accepts an array, or a
|
46
86
|
# comma-delimited string
|
47
|
-
def blacklist(
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
if b.nil? || b.empty?
|
87
|
+
def blacklist(*args)
|
88
|
+
list = flatten_list_of_strings(args)
|
89
|
+
|
90
|
+
if list.nil? || list.empty?
|
53
91
|
bot.blacklist = []
|
54
92
|
else
|
55
|
-
bot.blacklist +=
|
93
|
+
bot.blacklist += list
|
56
94
|
end
|
57
|
-
|
58
95
|
end
|
59
96
|
|
60
97
|
#
|
61
98
|
# specify list of strings we will check when deciding to respond to a tweet or not
|
62
|
-
def exclude(
|
63
|
-
|
64
|
-
e = e.split(",").collect { |s| s.strip }
|
65
|
-
end
|
66
|
-
|
99
|
+
def exclude(*args)
|
100
|
+
e = flatten_list_of_strings(args)
|
67
101
|
if e.nil? || e.empty?
|
68
102
|
bot.exclude = []
|
69
103
|
else
|
data/lib/chatterbot/helpers.rb
CHANGED
@@ -3,27 +3,53 @@ module Chatterbot
|
|
3
3
|
#
|
4
4
|
# a bunch of helper routines for bots
|
5
5
|
module Helpers
|
6
|
+
def botname=(b)
|
7
|
+
@botname = b
|
8
|
+
end
|
6
9
|
|
7
10
|
#
|
8
11
|
# The name of the currently running bot
|
9
12
|
def botname
|
10
|
-
if
|
13
|
+
if !@botname.nil?
|
14
|
+
@botname
|
15
|
+
elsif self.class < Bot
|
11
16
|
self.class.to_s.downcase
|
12
17
|
else
|
13
18
|
File.basename($0,".rb")
|
14
19
|
end
|
15
20
|
end
|
16
21
|
|
22
|
+
#
|
23
|
+
# Pull the username from a tweet hash -- this is different depending on
|
24
|
+
# if we're doing a search, or parsing through replies/mentions.
|
25
|
+
def from_user(s)
|
26
|
+
return s if s.is_a?(String)
|
27
|
+
s.has_key?(:from_user) ? s[:from_user] : s[:user][:screen_name]
|
28
|
+
end
|
29
|
+
|
30
|
+
|
17
31
|
#
|
18
32
|
# Take the incoming tweet/user name, and turn it into something suitable for replying
|
19
33
|
# to a user. Basically, get their handle and add a '@' to it.
|
20
34
|
def tweet_user(tweet)
|
21
|
-
|
22
|
-
|
35
|
+
base = from_user(tweet)
|
36
|
+
base =~ /^@/ ? base : "@#{base}"
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
#
|
41
|
+
# do some simple variable substitution. for now, it only handles
|
42
|
+
# replacing #USER# with the screen of the incoming tweet, but it
|
43
|
+
# could do more if needed
|
44
|
+
#
|
45
|
+
def replace_variables(txt, original = nil)
|
46
|
+
if ! original.nil? && txt.include?("#USER#")
|
47
|
+
username = tweet_user(original)
|
48
|
+
txt.gsub("#USER#", username)
|
23
49
|
else
|
24
|
-
|
50
|
+
txt
|
25
51
|
end
|
26
|
-
base =~ /^@/ ? base : "@#{base}"
|
27
52
|
end
|
53
|
+
|
28
54
|
end
|
29
55
|
end
|
data/lib/chatterbot/reply.rb
CHANGED
data/lib/chatterbot/search.rb
CHANGED
@@ -4,6 +4,13 @@ module Chatterbot
|
|
4
4
|
# handle Twitter searches
|
5
5
|
module Search
|
6
6
|
|
7
|
+
#
|
8
|
+
# modify a query string to exclude retweets from searches
|
9
|
+
#
|
10
|
+
def exclude_retweets(q)
|
11
|
+
q.include?("include:retweets") ? q : q += " -include:retweets"
|
12
|
+
end
|
13
|
+
|
7
14
|
# internal search code
|
8
15
|
def search(queries, opts = {}, &block)
|
9
16
|
return unless init_client
|
@@ -18,13 +25,18 @@ module Chatterbot
|
|
18
25
|
# search twitter
|
19
26
|
#
|
20
27
|
queries.each { |query|
|
21
|
-
search
|
28
|
+
debug "search: #{query} #{opts.merge(default_opts)}"
|
29
|
+
|
30
|
+
search = client.search(exclude_retweets(query), opts.merge(default_opts))
|
22
31
|
update_since_id(search)
|
23
32
|
|
24
33
|
if search != nil
|
25
34
|
search["results"].each { |s|
|
26
35
|
s.symbolize_keys!
|
36
|
+
debug s[:text]
|
37
|
+
#if s[:text].downcase.include?(query.downcase)
|
27
38
|
yield s unless ! block_given? || on_blacklist?(s) || skip_me?(s)
|
39
|
+
#end
|
28
40
|
}
|
29
41
|
end
|
30
42
|
}
|
data/lib/chatterbot/tweet.rb
CHANGED
@@ -3,11 +3,13 @@ module Chatterbot
|
|
3
3
|
#
|
4
4
|
# routines for sending tweets
|
5
5
|
module Tweet
|
6
|
-
|
6
|
+
|
7
7
|
# simple wrapper for sending a message
|
8
8
|
def tweet(txt, params = {}, original = nil)
|
9
9
|
return if require_login == false
|
10
10
|
|
11
|
+
txt = replace_variables(txt, original)
|
12
|
+
|
11
13
|
if debug_mode?
|
12
14
|
debug "I'm in debug mode, otherwise I would tweet: #{txt}"
|
13
15
|
else
|
data/lib/chatterbot/version.rb
CHANGED
data/spec/config_spec.rb
CHANGED
@@ -75,6 +75,28 @@ describe "Chatterbot::Config" do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
describe "debug_mode=" do
|
79
|
+
it "works" do
|
80
|
+
@bot.debug_mode = true
|
81
|
+
@bot.config[:debug_mode].should == true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "no_update=" do
|
86
|
+
it "works" do
|
87
|
+
@bot.no_update = true
|
88
|
+
@bot.config[:no_update].should == true
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "verbose=" do
|
93
|
+
it "works" do
|
94
|
+
@bot.verbose = true
|
95
|
+
@bot.config[:verbose].should == true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
78
100
|
describe "debug_mode?" do
|
79
101
|
it "works when debug_mode isn't set" do
|
80
102
|
@bot.debug_mode?.should == false
|
@@ -181,7 +203,19 @@ describe "Chatterbot::Config" do
|
|
181
203
|
end
|
182
204
|
end
|
183
205
|
|
206
|
+
|
207
|
+
describe "working_dir" do
|
208
|
+
it "returns getwd for chatterbot scripts" do
|
209
|
+
@bot.should_receive(:chatterbot_helper?).and_return(true)
|
210
|
+
@bot.working_dir.should == Dir.getwd
|
211
|
+
end
|
184
212
|
|
213
|
+
it "returns calling dir for non-chatterbot scripts" do
|
214
|
+
@bot.should_receive(:chatterbot_helper?).and_return(false)
|
215
|
+
@bot.working_dir.should == File.dirname($0)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
185
219
|
describe "file I/O" do
|
186
220
|
it "loads in some YAML" do
|
187
221
|
tmp = {:since_id => 0}
|
@@ -216,5 +250,21 @@ describe "Chatterbot::Config" do
|
|
216
250
|
@bot.update_config
|
217
251
|
end
|
218
252
|
end
|
253
|
+
|
254
|
+
describe "store_local_config" do
|
255
|
+
before(:each) do
|
256
|
+
tmp = {:x => 123, :foo => :bar}
|
257
|
+
|
258
|
+
@src = Tempfile.new("config")
|
259
|
+
|
260
|
+
@bot.stub!(:config_file).and_return(@src.path)
|
261
|
+
@bot.stub!(:config_to_save).and_return(tmp)
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should work" do
|
265
|
+
@bot.store_local_config
|
266
|
+
@bot.slurp_file(@src.path).should == { :x => 123, :foo => :bar }
|
267
|
+
end
|
268
|
+
end
|
219
269
|
|
220
270
|
end
|
data/spec/dsl_spec.rb
CHANGED
@@ -25,7 +25,26 @@ describe "Chatterbot::DSL" do
|
|
25
25
|
blacklist "foo, bar"
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
|
+
[:no_update, :debug_mode, :verbose].each do |method|
|
30
|
+
describe method.to_s do
|
31
|
+
it "#{method.to_s} with nil passes along true to bot object" do
|
32
|
+
@bot.should_receive("#{method.to_s}=").with(true)
|
33
|
+
send method
|
34
|
+
end
|
35
|
+
|
36
|
+
it "#debug_mode with false is passed" do
|
37
|
+
@bot.should_receive("#{method.to_s}=").with(false)
|
38
|
+
send method, false
|
39
|
+
end
|
40
|
+
|
41
|
+
it "#debug_mode with true is passed" do
|
42
|
+
@bot.should_receive("#{method.to_s}=").with(true)
|
43
|
+
send method, true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
29
48
|
describe "exclude" do
|
30
49
|
it "#exclude passes along to bot object" do
|
31
50
|
@bot.should_receive(:exclude=).with(["foo"])
|
data/spec/helpers_spec.rb
CHANGED
@@ -18,15 +18,39 @@ describe "Chatterbot::Helpers" do
|
|
18
18
|
bot.tweet_user("foo").should == "@foo"
|
19
19
|
bot.tweet_user("@foo").should == "@foo"
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
|
+
describe "#from_user" do
|
23
|
+
before(:each) do
|
24
|
+
@bot = Chatterbot::Bot.new
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should accept strings" do
|
28
|
+
@bot.from_user("x").should == "x"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should accept :from_user" do
|
32
|
+
@bot.from_user(:from_user => "x").should == "x"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should accept :screen_name" do
|
36
|
+
@bot.from_user(:user => {:screen_name => "x"}).should == "x"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
22
40
|
describe "#botname" do
|
23
41
|
before(:each) do
|
42
|
+
class TestBot < Chatterbot::Bot; end
|
24
43
|
@bot = Chatterbot::Bot.new
|
25
44
|
@bot.client = mock(Object)
|
26
45
|
end
|
27
46
|
|
47
|
+
it "can set botname" do
|
48
|
+
@bot = TestBot.new
|
49
|
+
@bot.botname = "foo"
|
50
|
+
@bot.botname.should == "foo"
|
51
|
+
end
|
52
|
+
|
28
53
|
it "calls botname smartly for inherited classes" do
|
29
|
-
class TestBot < Chatterbot::Bot; end
|
30
54
|
@bot2 = TestBot.new
|
31
55
|
@bot2.botname.should == "testbot"
|
32
56
|
end
|
@@ -35,6 +59,30 @@ describe "Chatterbot::Helpers" do
|
|
35
59
|
File.should_receive(:basename).and_return("bot")
|
36
60
|
@bot.botname.should == "bot"
|
37
61
|
end
|
62
|
+
|
63
|
+
it "uses specified name" do
|
64
|
+
@bot = Chatterbot::Bot.new(:name => 'xyzzy')
|
65
|
+
@bot.botname.should == "xyzzy"
|
66
|
+
end
|
38
67
|
end
|
39
|
-
|
68
|
+
|
69
|
+
describe "#replace_variables" do
|
70
|
+
before(:each) do
|
71
|
+
@bot = Chatterbot::Bot.new(:name => 'xyzzy')
|
72
|
+
@tweet = {}
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should replace username by calling tweet_user" do
|
76
|
+
@bot.should_receive(:tweet_user).and_return("@foobar")
|
77
|
+
@bot.replace_variables("#USER#", @tweet).should == "@foobar"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should be fine with not replacing anything" do
|
81
|
+
@bot.replace_variables("foobar", @tweet).should == "foobar"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should be fine without a tweet" do
|
85
|
+
@bot.replace_variables("foobar").should == "foobar"
|
86
|
+
end
|
87
|
+
end
|
40
88
|
end
|
data/spec/reply_spec.rb
CHANGED
@@ -72,6 +72,16 @@ describe "Chatterbot::Reply" do
|
|
72
72
|
|
73
73
|
bot.replies
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
|
+
|
77
|
+
it "outputs an error if we get one from API" do
|
78
|
+
bot = test_bot
|
79
|
+
bot.stub!(:require_login).and_return(true)
|
80
|
+
bot.stub!(:client).and_return(mock(Object, :replies => {"error" => "You messed up"}))
|
81
|
+
|
82
|
+
bot.should_receive(:critical).with("You messed up")
|
83
|
+
|
84
|
+
bot.replies
|
85
|
+
end
|
76
86
|
|
77
87
|
end
|
data/spec/search_spec.rb
CHANGED
@@ -1,12 +1,30 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
3
|
describe "Chatterbot::Search" do
|
4
|
+
describe "exclude_retweets" do
|
5
|
+
before(:each) do
|
6
|
+
@bot = Chatterbot::Bot.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should tack onto query" do
|
10
|
+
@bot.exclude_retweets("foo").should == ("foo -include:retweets")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "shouldn't tack onto query" do
|
14
|
+
@bot.exclude_retweets("foo -include:retweets").should == ("foo -include:retweets")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "shouldn't tack onto query" do
|
18
|
+
@bot.exclude_retweets("foo include:retweets").should == ("foo include:retweets")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
4
22
|
it "calls search" do
|
5
23
|
bot = Chatterbot::Bot.new
|
6
24
|
bot.should_receive(:search)
|
7
25
|
bot.search("foo")
|
8
26
|
end
|
9
|
-
|
27
|
+
|
10
28
|
it "calls init_client" do
|
11
29
|
bot = test_bot
|
12
30
|
bot.should_receive(:init_client).and_return(false)
|
@@ -27,8 +45,8 @@ describe "Chatterbot::Search" do
|
|
27
45
|
#bot = Chatterbot::Bot.new
|
28
46
|
|
29
47
|
bot.stub!(:client).and_return(fake_search(100))
|
30
|
-
bot.client.should_receive(:search).with("foo", {})
|
31
|
-
bot.client.should_receive(:search).with("bar", {})
|
48
|
+
bot.client.should_receive(:search).with("foo -include:retweets", {})
|
49
|
+
bot.client.should_receive(:search).with("bar -include:retweets", {})
|
32
50
|
|
33
51
|
bot.search(["foo", "bar"])
|
34
52
|
end
|
@@ -37,7 +55,7 @@ describe "Chatterbot::Search" do
|
|
37
55
|
bot = test_bot
|
38
56
|
|
39
57
|
bot.stub!(:client).and_return(fake_search(100))
|
40
|
-
bot.client.should_receive(:search).with("foo", {:lang => "en"})
|
58
|
+
bot.client.should_receive(:search).with("foo -include:retweets", {:lang => "en"})
|
41
59
|
|
42
60
|
bot.search("foo", :lang => "en")
|
43
61
|
end
|
@@ -46,7 +64,7 @@ describe "Chatterbot::Search" do
|
|
46
64
|
bot = test_bot
|
47
65
|
|
48
66
|
bot.stub!(:client).and_return(fake_search(100))
|
49
|
-
bot.client.should_receive(:search).with("foo", {})
|
67
|
+
bot.client.should_receive(:search).with("foo -include:retweets", {})
|
50
68
|
|
51
69
|
bot.search("foo")
|
52
70
|
end
|
@@ -56,7 +74,7 @@ describe "Chatterbot::Search" do
|
|
56
74
|
bot.stub!(:since_id).and_return(123)
|
57
75
|
|
58
76
|
bot.stub!(:client).and_return(fake_search(100))
|
59
|
-
bot.client.should_receive(:search).with("foo", {:since_id => 123})
|
77
|
+
bot.client.should_receive(:search).with("foo -include:retweets", {:since_id => 123, :result_type => "recent"})
|
60
78
|
|
61
79
|
bot.search("foo")
|
62
80
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
#$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
#$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
5
|
|
4
6
|
require 'bundler/setup'
|
5
7
|
Bundler.require
|
6
8
|
|
7
|
-
require 'rspec'
|
8
|
-
require 'chatterbot'
|
9
9
|
|
10
|
-
require
|
10
|
+
#require 'rspec'
|
11
|
+
#require 'chatterbot'
|
11
12
|
|
13
|
+
require "twitter_oauth"
|
12
14
|
|
13
15
|
require 'tempfile'
|
14
16
|
require 'sqlite3'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chatterbot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-10-15 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: twitter_oauth
|
16
|
-
requirement: &
|
16
|
+
requirement: &9989900 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *9989900
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: shoulda
|
27
|
-
requirement: &
|
27
|
+
requirement: &9989400 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *9989400
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &9988920 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *9988920
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rdoc
|
49
|
-
requirement: &
|
49
|
+
requirement: &9988440 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *9988440
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: bundler
|
60
|
-
requirement: &
|
60
|
+
requirement: &9987960 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.0.0
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *9987960
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
71
|
-
requirement: &
|
70
|
+
name: simplecov
|
71
|
+
requirement: &9987480 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *9987480
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: watchr
|
82
|
-
requirement: &
|
82
|
+
requirement: &9987000 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,12 +87,14 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *9987000
|
91
91
|
description: A framework for writing bots that run on Twitter. Comes with a simple
|
92
92
|
DSL for easy coding.
|
93
93
|
email: colin@muffinlabs.com
|
94
94
|
executables:
|
95
95
|
- chatterbot-blacklist
|
96
|
+
- chatterbot-register
|
97
|
+
- chatterbot-status
|
96
98
|
extensions: []
|
97
99
|
extra_rdoc_files: []
|
98
100
|
files:
|
@@ -100,9 +102,11 @@ files:
|
|
100
102
|
- .gitignore
|
101
103
|
- Gemfile
|
102
104
|
- LICENSE.txt
|
103
|
-
- README.
|
105
|
+
- README.markdown
|
104
106
|
- Rakefile
|
105
107
|
- bin/chatterbot-blacklist
|
108
|
+
- bin/chatterbot-register
|
109
|
+
- bin/chatterbot-status
|
106
110
|
- chatterbot.gemspec
|
107
111
|
- examples/class_bot.rb
|
108
112
|
- examples/config.yml.example
|
@@ -155,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
159
|
version: '0'
|
156
160
|
requirements: []
|
157
161
|
rubyforge_project: chatterbot
|
158
|
-
rubygems_version: 1.8.
|
162
|
+
rubygems_version: 1.8.6
|
159
163
|
signing_key:
|
160
164
|
specification_version: 3
|
161
165
|
summary: A framework for writing Twitter bots
|