chatterbot 1.0.2 → 2.0.0.pre
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.
- 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
|
#
|