chatterbot 0.2.8 → 0.2.9
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/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
|