chatterbot 1.0.2 → 2.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/LICENSE.txt +18 -9
- data/README.markdown +83 -65
- data/bin/chatterbot-register +0 -1
- data/chatterbot.gemspec +3 -10
- data/examples/class_bot.rb +0 -1
- data/examples/echoes_bot.rb +2 -2
- data/examples/search_bot.rb +1 -1
- data/examples/streaming_bot.rb +21 -15
- data/lib/chatterbot.rb +7 -12
- data/lib/chatterbot/blocklist.rb +61 -0
- data/lib/chatterbot/bot.rb +118 -13
- data/lib/chatterbot/client.rb +52 -20
- data/lib/chatterbot/config.rb +92 -215
- data/lib/chatterbot/config_manager.rb +49 -0
- data/lib/chatterbot/direct_messages.rb +46 -0
- data/lib/chatterbot/dsl.rb +157 -78
- data/lib/chatterbot/followers.rb +4 -0
- data/lib/chatterbot/handler.rb +29 -0
- data/lib/chatterbot/helpers.rb +14 -3
- data/lib/chatterbot/home_timeline.rb +5 -8
- data/lib/chatterbot/logging.rb +0 -17
- data/lib/chatterbot/profile.rb +0 -1
- data/lib/chatterbot/reply.rb +6 -11
- data/lib/chatterbot/retweet.rb +2 -6
- data/lib/chatterbot/safelist.rb +33 -0
- data/lib/chatterbot/search.rb +26 -16
- data/lib/chatterbot/skeleton.rb +7 -38
- data/lib/chatterbot/streaming.rb +26 -33
- data/lib/chatterbot/tweet.rb +0 -1
- data/lib/chatterbot/ui.rb +9 -2
- data/lib/chatterbot/utils.rb +13 -0
- data/lib/chatterbot/version.rb +1 -1
- data/spec/blocklist_spec.rb +170 -0
- data/spec/bot_spec.rb +83 -8
- data/spec/client_spec.rb +61 -7
- data/spec/config_manager_spec.rb +59 -0
- data/spec/config_spec.rb +33 -158
- data/spec/direct_messages_spec.rb +115 -0
- data/spec/dsl_spec.rb +95 -53
- data/spec/handler_spec.rb +27 -0
- data/spec/helpers_spec.rb +7 -11
- data/spec/home_timeline_spec.rb +42 -31
- data/spec/logging_spec.rb +0 -34
- data/spec/reply_spec.rb +10 -34
- data/spec/search_spec.rb +65 -6
- data/spec/spec_helper.rb +25 -1
- data/spec/streaming_spec.rb +56 -58
- data/spec/whitelist_spec.rb +10 -10
- data/specs.watchr +2 -4
- data/templates/skeleton.txt +148 -12
- metadata +20 -22
- data/bin/chatterbot-blacklist +0 -65
- data/bin/chatterbot-status +0 -55
- data/examples/loop_bot.rb +0 -44
- data/lib/chatterbot/blacklist.rb +0 -61
- data/lib/chatterbot/db.rb +0 -79
- data/lib/chatterbot/streaming_handler.rb +0 -96
- data/lib/chatterbot/whitelist.rb +0 -32
- data/spec/blacklist_spec.rb +0 -116
- data/spec/db_spec.rb +0 -53
- data/spec/streaming_handler_spec.rb +0 -78
@@ -0,0 +1,49 @@
|
|
1
|
+
module Chatterbot
|
2
|
+
require 'yaml/store'
|
3
|
+
|
4
|
+
#
|
5
|
+
# wrap YAML::Store to maintain config but have a few read-only
|
6
|
+
# variables which we will never set/override
|
7
|
+
#
|
8
|
+
class ConfigManager
|
9
|
+
|
10
|
+
# list of vars that shouldn't ever be written
|
11
|
+
READ_ONLY_VARIABLES = [:consumer_key, :consumer_secret, :access_token, :access_token_secret, :log_dest]
|
12
|
+
|
13
|
+
# if true, we will never actually update the config file
|
14
|
+
attr_accessor :no_update
|
15
|
+
|
16
|
+
def initialize(dest, read_only={}, no_update=false)
|
17
|
+
@read_only = read_only
|
18
|
+
@store = YAML::Store.new(dest, true)
|
19
|
+
@no_update = no_update
|
20
|
+
end
|
21
|
+
|
22
|
+
# delete a key from the config
|
23
|
+
def delete(key)
|
24
|
+
return if @no_update == true
|
25
|
+
@store.transaction do
|
26
|
+
@store.delete(key)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# set/update a key
|
31
|
+
def []=(key, value)
|
32
|
+
return if @no_update == true
|
33
|
+
@store.transaction do
|
34
|
+
@store[key] = value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# retrieve a key
|
39
|
+
def [](key)
|
40
|
+
if READ_ONLY_VARIABLES.include?(key)
|
41
|
+
return @read_only[key]
|
42
|
+
end
|
43
|
+
@store.transaction do
|
44
|
+
@store[key]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Chatterbot
|
2
|
+
#
|
3
|
+
# handle Twitter DMs
|
4
|
+
module DirectMessages
|
5
|
+
#
|
6
|
+
# send a direct message
|
7
|
+
#
|
8
|
+
def direct_message(txt, user=nil)
|
9
|
+
return unless require_login
|
10
|
+
|
11
|
+
if user.nil?
|
12
|
+
user = current_user
|
13
|
+
end
|
14
|
+
client.create_direct_message(user, txt)
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# check direct messages for the bot
|
19
|
+
#
|
20
|
+
def direct_messages(opts = {}, &block)
|
21
|
+
return unless require_login
|
22
|
+
debug "check for DMs since #{since_id_dm}"
|
23
|
+
|
24
|
+
#
|
25
|
+
# search twitter
|
26
|
+
#
|
27
|
+
|
28
|
+
@current_tweet = nil
|
29
|
+
client.direct_messages_received(since_id:since_id_dm, count:200).each { |s|
|
30
|
+
update_since_id_dm(s)
|
31
|
+
debug s.text
|
32
|
+
if has_safelist? && !on_safelist?(s.sender)
|
33
|
+
debug "skipping because user not on safelist"
|
34
|
+
elsif block_given? && !on_blocklist?(s.sender) && !skip_me?(s)
|
35
|
+
@current_tweet = s
|
36
|
+
yield s
|
37
|
+
end
|
38
|
+
}
|
39
|
+
@current_tweet = nil
|
40
|
+
rescue Twitter::Error::Forbidden => e
|
41
|
+
puts "sorry, looks like we're not allowed to check DMs for this account"
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
data/lib/chatterbot/dsl.rb
CHANGED
@@ -14,20 +14,17 @@ module Chatterbot
|
|
14
14
|
#
|
15
15
|
# search twitter for the specified terms, then pass any matches to
|
16
16
|
# the block.
|
17
|
-
# @param
|
17
|
+
# @param args [Hash] options. these will be passed directly to
|
18
18
|
# Twitter via the twitter gem. You can see the possible arguments
|
19
19
|
# at http://www.rubydoc.info/gems/twitter/Twitter/REST/Search#search-instance_method
|
20
|
-
#
|
21
|
-
# @option options [Integer] :limit limit the number of tweets to
|
22
|
-
# return per search
|
23
|
-
|
20
|
+
#
|
24
21
|
# @example
|
25
22
|
# search("chatterbot is cool!") do |tweet|
|
26
23
|
# puts tweet.text # this is the actual tweeted text
|
27
24
|
# reply "I agree!", tweet
|
28
25
|
# end
|
29
|
-
def search(
|
30
|
-
bot.search
|
26
|
+
def search(*args, &block)
|
27
|
+
bot.register_handler(:search, args, &block)
|
31
28
|
end
|
32
29
|
|
33
30
|
#
|
@@ -39,8 +36,8 @@ module Chatterbot
|
|
39
36
|
# puts tweet.text # this is the actual tweeted text
|
40
37
|
# favorite tweet # i like to fave tweets
|
41
38
|
# end
|
42
|
-
def home_timeline(
|
43
|
-
bot.home_timeline
|
39
|
+
def home_timeline(&block)
|
40
|
+
bot.register_handler(:home_timeline, block)
|
44
41
|
end
|
45
42
|
|
46
43
|
#
|
@@ -53,23 +50,64 @@ module Chatterbot
|
|
53
50
|
# reply "Thanks for the mention!", tweet
|
54
51
|
# end
|
55
52
|
def replies(&block)
|
56
|
-
bot.replies
|
53
|
+
bot.register_handler(:replies, block)
|
57
54
|
end
|
58
55
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
56
|
+
#
|
57
|
+
# handle direct messages sent to the bot. Each time this is called, chatterbot
|
58
|
+
# will pass any DMs since the last call to the specified block
|
59
|
+
#
|
60
|
+
# @example
|
61
|
+
# direct_messages do |dm|
|
62
|
+
# puts dm.text # this is the actual tweeted text
|
63
|
+
# direct_message "Thanks for the mention!", dm.sender
|
64
|
+
# end
|
65
|
+
def direct_messages(&block)
|
66
|
+
bot.register_handler(:direct_messages, block)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
#
|
71
|
+
# handle notifications of bot tweets favorited by other users.
|
72
|
+
# Using this block will require usage of the Streaming API.
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
# favorited do |tweet|
|
76
|
+
# puts tweet.text # this is the actual tweeted text
|
77
|
+
# reply "@#{user.screen_name} thanks for the fave!", tweet
|
78
|
+
# end
|
79
|
+
def favorited(&block)
|
80
|
+
bot.register_handler(:favorited, block)
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# handle notifications that the bot has a new follower.
|
85
|
+
# Using this block will require usage of the Streaming API.
|
86
|
+
#
|
87
|
+
# @example
|
88
|
+
# followed do |user|
|
89
|
+
# follow user
|
90
|
+
# end
|
91
|
+
def followed(&block)
|
92
|
+
bot.register_handler(:followed, block)
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# handle notifications of tweets on the bot's timeline that were deleted.
|
97
|
+
# Using this block will require usage of the Streaming API.
|
98
|
+
def deleted(&block)
|
99
|
+
bot.register_handler(:deleted, block)
|
100
|
+
end
|
63
101
|
|
64
|
-
h = StreamingHandler.new(bot, params)
|
65
|
-
h.apply block
|
66
102
|
|
67
|
-
|
103
|
+
#
|
104
|
+
# enable or disable usage of the Streaming API
|
105
|
+
#
|
106
|
+
def use_streaming(s=nil)
|
107
|
+
s = true if s.nil?
|
108
|
+
bot.streaming = s
|
68
109
|
end
|
69
110
|
|
70
|
-
def streaming_tweets(opts={}, &block)
|
71
|
-
bot.streaming_tweets(opts, &block)
|
72
|
-
end
|
73
111
|
|
74
112
|
#
|
75
113
|
# send a tweet
|
@@ -107,6 +145,16 @@ module Chatterbot
|
|
107
145
|
bot.reply(txt, source)
|
108
146
|
end
|
109
147
|
|
148
|
+
#
|
149
|
+
# send a direct message to the specified user
|
150
|
+
#
|
151
|
+
# @param [String] txt the text you want to tweet
|
152
|
+
# @param [User] user to send the DM to
|
153
|
+
def direct_message(txt, user=nil)
|
154
|
+
bot.direct_message(txt, user)
|
155
|
+
end
|
156
|
+
|
157
|
+
|
110
158
|
#
|
111
159
|
# handle getting/setting the profile text.
|
112
160
|
# @param [p] p The new value for the profile. If this isn't passed in, the method will simply return the current value
|
@@ -121,7 +169,7 @@ module Chatterbot
|
|
121
169
|
|
122
170
|
#
|
123
171
|
# handle getting/setting the profile website
|
124
|
-
# @param [
|
172
|
+
# @param [w] w The new value for the website. If this isn't passed in, the method will simply return the current value
|
125
173
|
# @return profile website
|
126
174
|
def profile_website(w=nil)
|
127
175
|
if w.nil?
|
@@ -138,6 +186,7 @@ module Chatterbot
|
|
138
186
|
def bot
|
139
187
|
return @bot unless @bot.nil?
|
140
188
|
|
189
|
+
@bot_command = nil
|
141
190
|
|
142
191
|
#
|
143
192
|
# parse any command-line options and use them to initialize the bot
|
@@ -153,26 +202,24 @@ module Chatterbot
|
|
153
202
|
opts.separator "Specific options:"
|
154
203
|
|
155
204
|
|
156
|
-
opts.on('-d', '--db [ARG]', "Specify a DB connection URI") { |d| ENV["chatterbot_db"] = d }
|
157
205
|
opts.on('-c', '--config [ARG]', "Specify a config file to use") { |c| ENV["chatterbot_config"] = c }
|
158
206
|
opts.on('-t', '--test', "Run the bot without actually sending any tweets") { params[:debug_mode] = true }
|
159
207
|
opts.on('-v', '--verbose', "verbose output to stdout") { params[:verbose] = true }
|
160
208
|
opts.on('--dry-run', "Run the bot in test mode, and also don't update the database") { params[:debug_mode] = true ; params[:no_update] = true }
|
161
|
-
|
162
|
-
opts.on('-m', '--since_id_reply [ARG]', "Check for mentions since tweet id #[ARG]") { |s| params[:since_id_reply] = s.to_i }
|
209
|
+
|
163
210
|
opts.on('-r', '--reset', "Reset your bot to ignore old tweets") {
|
164
|
-
|
165
|
-
params[:reset_since_id] = true
|
211
|
+
@bot_command = :reset_since_id_counters
|
166
212
|
}
|
213
|
+
|
167
214
|
opts.on('--profile [ARG]', "get/set your bot's profile text") { |p|
|
168
|
-
@
|
169
|
-
@
|
215
|
+
@bot_command = :profile_text
|
216
|
+
@bot_command_args = [ p ]
|
170
217
|
}
|
218
|
+
|
171
219
|
opts.on('--website [ARG]', "get/set your bot's profile URL") { |u|
|
172
|
-
@
|
173
|
-
@
|
220
|
+
@bot_command = :profile_website
|
221
|
+
@bot_command_args = [ u ]
|
174
222
|
}
|
175
|
-
|
176
223
|
|
177
224
|
opts.on_tail("-h", "--help", "Show this message") do
|
178
225
|
puts opts
|
@@ -183,25 +230,10 @@ module Chatterbot
|
|
183
230
|
#:nocov:
|
184
231
|
|
185
232
|
@bot = Chatterbot::Bot.new(params)
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
else
|
191
|
-
puts @bot.profile_text
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
if @handle_profile_website == true
|
196
|
-
if !@profile_website.nil?
|
197
|
-
@bot.profile_website @profile_website
|
198
|
-
else
|
199
|
-
puts @bot.profile_website
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
if @handle_profile_website == true || @handle_profile_text == true
|
204
|
-
exit
|
233
|
+
if @bot_command != nil
|
234
|
+
@bot.skip_run = true
|
235
|
+
result = @bot.send(@bot_command, *@bot_command_args)
|
236
|
+
puts result
|
205
237
|
end
|
206
238
|
|
207
239
|
@bot
|
@@ -235,45 +267,52 @@ module Chatterbot
|
|
235
267
|
end
|
236
268
|
|
237
269
|
#
|
238
|
-
# specify a bot-specific
|
270
|
+
# specify a bot-specific blocklist of users. accepts an array, or a
|
239
271
|
# comma-delimited string. when called, any subsequent calls to
|
240
272
|
# search or replies will filter out these users.
|
241
273
|
#
|
242
274
|
# @param [Array, String] args list of usernames
|
243
275
|
# @example
|
244
|
-
#
|
276
|
+
# blocklist "mean_user, private_user"
|
245
277
|
#
|
246
|
-
def
|
278
|
+
def blocklist(*args)
|
247
279
|
list = flatten_list_of_strings(args)
|
248
280
|
|
249
281
|
if list.nil? || list.empty?
|
250
|
-
bot.
|
282
|
+
bot.blocklist = []
|
251
283
|
else
|
252
|
-
bot.
|
284
|
+
bot.blocklist += list
|
253
285
|
end
|
254
286
|
end
|
287
|
+
alias :blacklist :blocklist
|
255
288
|
|
289
|
+
|
256
290
|
#
|
257
|
-
# specify a bot-specific
|
291
|
+
# specify a bot-specific safelist of users. accepts an array, or a
|
258
292
|
# comma-delimited string. when called, any subsequent calls to
|
259
293
|
# search or replies will only act upon these users.
|
260
294
|
#
|
261
295
|
# @param [Array, String] args list of usernames or Twitter::User objects
|
262
296
|
# @example
|
263
|
-
#
|
297
|
+
# safelist "mean_user, private_user"
|
264
298
|
#
|
265
|
-
def
|
299
|
+
def safelist(*args)
|
266
300
|
list = flatten_list_of_strings(args)
|
267
301
|
|
268
302
|
if list.nil? || list.empty?
|
269
|
-
bot.
|
303
|
+
bot.safelist = []
|
270
304
|
else
|
271
|
-
bot.
|
305
|
+
bot.safelist += list
|
272
306
|
end
|
273
307
|
end
|
274
|
-
|
308
|
+
alias :whitelist :safelist
|
309
|
+
|
310
|
+
#
|
311
|
+
# specify that the bot should only reply to tweets from users that
|
312
|
+
# are followers, basically making interactions opt-in
|
313
|
+
#
|
275
314
|
def only_interact_with_followers
|
276
|
-
|
315
|
+
bot.config[:only_interact_with_followers] = true
|
277
316
|
end
|
278
317
|
|
279
318
|
#
|
@@ -299,10 +338,55 @@ module Chatterbot
|
|
299
338
|
# lifted from https://github.com/dariusk/wordfilter/blob/master/lib/badwords.json
|
300
339
|
#
|
301
340
|
def bad_words
|
302
|
-
[
|
303
|
-
|
304
|
-
|
305
|
-
|
341
|
+
[
|
342
|
+
"biatch",
|
343
|
+
"bitch",
|
344
|
+
"chinaman",
|
345
|
+
"chinamen",
|
346
|
+
"chink",
|
347
|
+
"crip",
|
348
|
+
"cunt",
|
349
|
+
"dago",
|
350
|
+
"daygo",
|
351
|
+
"dego",
|
352
|
+
"dick",
|
353
|
+
"douchebag",
|
354
|
+
"dyke",
|
355
|
+
"fag",
|
356
|
+
"fatass",
|
357
|
+
"fatso",
|
358
|
+
"gash",
|
359
|
+
"gimp",
|
360
|
+
"golliwog",
|
361
|
+
"gook",
|
362
|
+
"gyp",
|
363
|
+
"homo",
|
364
|
+
"hooker",
|
365
|
+
"jap",
|
366
|
+
"kike",
|
367
|
+
"kraut",
|
368
|
+
"lardass",
|
369
|
+
"lesbo",
|
370
|
+
"negro",
|
371
|
+
"nigger",
|
372
|
+
"paki",
|
373
|
+
"pussy",
|
374
|
+
"raghead",
|
375
|
+
"retard",
|
376
|
+
"shemale",
|
377
|
+
"skank",
|
378
|
+
"slut",
|
379
|
+
"spic",
|
380
|
+
"tard",
|
381
|
+
"tits",
|
382
|
+
"titt",
|
383
|
+
"trannies",
|
384
|
+
"tranny",
|
385
|
+
"twat",
|
386
|
+
"wetback",
|
387
|
+
"whore",
|
388
|
+
"wop"
|
389
|
+
]
|
306
390
|
end
|
307
391
|
|
308
392
|
#
|
@@ -338,13 +422,15 @@ module Chatterbot
|
|
338
422
|
# set the consumer secret
|
339
423
|
# @param s [String] the consumer secret
|
340
424
|
def consumer_secret(s)
|
425
|
+
bot.deprecated "Setting consumer_secret outside of your config file is deprecated!", Kernel.caller.first
|
341
426
|
bot.config[:consumer_secret] = s
|
342
427
|
end
|
343
|
-
|
428
|
+
|
344
429
|
#
|
345
430
|
# set the consumer key
|
346
431
|
# @param k [String] the consumer key
|
347
432
|
def consumer_key(k)
|
433
|
+
bot.deprecated "Setting consumer_key outside of your config file is deprecated!", Kernel.caller.first
|
348
434
|
bot.config[:consumer_key] = k
|
349
435
|
end
|
350
436
|
|
@@ -352,14 +438,16 @@ module Chatterbot
|
|
352
438
|
# set the secret
|
353
439
|
# @param s [String] the secret
|
354
440
|
def secret(s)
|
355
|
-
bot.config
|
441
|
+
bot.deprecated "Setting access_token_secret outside of your config file is deprecated!", Kernel.caller.first
|
442
|
+
bot.config[:access_token_secret] = s
|
356
443
|
end
|
357
444
|
|
358
445
|
#
|
359
446
|
# set the token
|
360
447
|
# @param s [String] the token
|
361
448
|
def token(s)
|
362
|
-
bot.config
|
449
|
+
bot.deprecated "Setting access_token outside of your config file is deprecated!", Kernel.caller.first
|
450
|
+
bot.config[:access_token] = s
|
363
451
|
end
|
364
452
|
|
365
453
|
#
|
@@ -377,15 +465,6 @@ module Chatterbot
|
|
377
465
|
bot.update_config
|
378
466
|
end
|
379
467
|
|
380
|
-
#
|
381
|
-
# return the bot's current database connection, if available.
|
382
|
-
# handy if you need to manage data with your bot
|
383
|
-
#
|
384
|
-
def db
|
385
|
-
bot.db
|
386
|
-
end
|
387
|
-
|
388
|
-
|
389
468
|
protected
|
390
469
|
|
391
470
|
#
|