This repository has been archived by the owner on Mar 6, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 104
/
dsl.rb
463 lines (406 loc) · 12.5 KB
/
dsl.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
require File.join(File.dirname(__FILE__), '..', 'chatterbot')
require 'optparse'
module Chatterbot
#
# very basic DSL to handle the common stuff you would want to do with a bot.
module DSL
#
# @return initialized Twitter::REST::Client
def client
bot.client
end
#
# search twitter for the specified terms, then pass any matches to
# the block.
# NOTE: by default, search terms are wrapped in quotes so the
# Twitter API will return tweets that include your exact query.
# You can disable this by passing exact:false as an option
#
# @param args [Hash] options. these will be passed directly to
# Twitter via the twitter gem. You can see the possible arguments
# at http://www.rubydoc.info/gems/twitter/Twitter/REST/Search#search-instance_method
#
# @example
# search("chatterbot is cool!") do |tweet|
# puts tweet.text # this is the actual tweeted text
# reply "I agree!", tweet
# end
def search(*args, &block)
bot.register_handler(:search, args, &block)
end
#
# handle tweets that are on the bot's home timeline. this includes
# tweets from accounts the bot is following, as well as its own tweets
#
# @example
# home_timeline do |tweet|
# puts tweet.text # this is the actual tweeted text
# favorite tweet # i like to fave tweets
# end
def home_timeline(&block)
bot.register_handler(:home_timeline, block)
end
#
# handle replies to the bot. Each time this is called, chatterbot
# will pass any replies since the last call to the specified block
#
# @example
# replies do |tweet|
# puts tweet.text # this is the actual tweeted text
# reply "Thanks for the mention!", tweet
# end
def replies(&block)
bot.register_handler(:replies, block)
end
#
# handle direct messages sent to the bot. Each time this is called, chatterbot
# will pass any DMs since the last call to the specified block
#
# @example
# direct_messages do |dm|
# puts dm.text # this is the actual tweeted text
# direct_message "Thanks for the mention!", dm.sender
# end
def direct_messages(&block)
bot.register_handler(:direct_messages, block)
end
#
# send a tweet
#
# @param [String] txt the text you want to tweet
# @param [Hash] params options for the tweet. You can get an idea
# of possible values you can send here from the underlying Twitter
# gem docs: http://rdoc.info/gems/twitter/Twitter/API#update-instance_method
# @option params [String,File] :media Optional file object to send
# with the tweet. Must be an image or video that will be accepted by
# Twitter. You can pass a File object, or the path to a file
# @see http://rdoc.info/gems/twitter/Twitter/API#update-instance_method
# @param [Tweet] original if this is a reply, the original tweet. this will
# be used for variable substitution, and for logging
def tweet(txt, params = {}, original = nil)
bot.tweet(txt, params, original)
end
#
# retweet a tweet
# @param [id] id A tweet or the ID of a tweet
def retweet(id)
bot.retweet(id)
end
#
# favorite a tweet
# @param [id] id A tweet or the ID of a tweet
def favorite(id)
bot.favorite(id)
end
#
# reply to a tweet
#
# @param [String] txt the text you want to tweet
# @param [Tweet] source the original tweet you are replying to
# @param [Hash] params options for the tweet. You can get an idea
# of possible values you can send here from the underlying Twitter
# gem docs: http://rdoc.info/gems/twitter/Twitter/API#update-instance_method
# @option params [String,File] :media Optional file object to send with the
# tweet. Must be an image or video that will be accepted by
# Twitter. You can pass a File object, or the path to a file
# @see http://rdoc.info/gems/twitter/Twitter/API#update-instance_method
def reply(txt, source, params={})
bot.reply(txt, source, params)
end
#
# send a direct message to the specified user
#
# @param [String] txt the text you want to tweet
# @param [User] user to send the DM to
def direct_message(txt, user=nil)
bot.direct_message(txt, user)
end
#
# handle getting/setting the profile text.
# @param [p] p The new value for the profile. If this isn't passed in, the method will simply return the current value
# @return profile text
def profile_text(p=nil)
if p.nil?
bot.profile_text
else
bot.profile_text(p)
end
end
#
# handle getting/setting the profile website
# @param [w] w The new value for the website. If this isn't passed in, the method will simply return the current value
# @return profile website
def profile_website(w=nil)
if w.nil?
bot.profile_website
else
bot.profile_website(w)
end
end
#
# generate a Bot object. if the DSL is being called from a Bot object, just return it
# otherwise create a bot and return that
def bot
return @bot unless @bot.nil?
@bot_command = nil
#
# parse any command-line options and use them to initialize the bot
#
params = {}
#:nocov:
opts = OptionParser.new
opts.banner = "Usage: #{File.basename($0)} [options]"
opts.separator ""
opts.separator "Specific options:"
opts.on('-c', '--config [ARG]', "Specify a config file to use") { |c| ENV["chatterbot_config"] = c }
opts.on('-t', '--test', "Run the bot without actually sending any tweets") { params[:debug_mode] = true }
opts.on('-v', '--verbose', "verbose output to stdout") { params[:verbose] = true }
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 }
opts.on('-r', '--reset', "Reset your bot to ignore old tweets") {
@bot_command = :reset_since_id_counters
}
opts.on('--profile [ARG]', "get/set your bot's profile text") { |p|
@bot_command = :profile_text
@bot_command_args = [ p ]
}
opts.on('--website [ARG]', "get/set your bot's profile URL") { |u|
@bot_command = :profile_website
@bot_command_args = [ u ]
}
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
opts.parse!(ARGV)
#:nocov:
@bot = Chatterbot::Bot.new(params)
if @bot_command != nil
@bot.skip_run = true
result = @bot.send(@bot_command, *@bot_command_args)
puts result
end
@bot
end
#
# should we send tweets?
# @param [Boolean] d true/false if we should send tweets
#
def debug_mode(d=nil)
d = true if d.nil?
bot.debug_mode = d
end
#
# should we update the db with a new since_id?
# @param [Boolean] d true/false if we should update the database
#
def no_update(d=nil)
d = true if d.nil?
bot.no_update = d
end
#
# turn on/off verbose output
# @param [Boolean] d true/false use verbose output
#
def verbose(d=nil)
d = true if d.nil?
bot.verbose = d
end
#
# specify a bot-specific blocklist of users. accepts an array, or a
# comma-delimited string. when called, any subsequent calls to
# search or replies will filter out these users.
#
# @param [Array, String] args list of usernames
# @example
# blocklist "mean_user, private_user"
#
def blocklist(*args)
list = flatten_list_of_strings(args)
if list.nil? || list.empty?
bot.blocklist = []
else
bot.blocklist += list
end
end
alias :blacklist :blocklist
#
# specify a bot-specific safelist of users. accepts an array, or a
# comma-delimited string. when called, any subsequent calls to
# search or replies will only act upon these users.
#
# @param [Array, String] args list of usernames or Twitter::User objects
# @example
# safelist "mean_user, private_user"
#
def safelist(*args)
list = flatten_list_of_strings(args)
if list.nil? || list.empty?
bot.safelist = []
else
bot.safelist += list
end
end
alias :whitelist :safelist
#
# specify that the bot should only reply to tweets from users that
# are followers, basically making interactions opt-in
#
def only_interact_with_followers
bot.config[:only_interact_with_followers] = true
end
#
# return a list of users following the bot. This passes directly
# to the underlying Twitter API call
# @see http://rdoc.info/gems/twitter/Twitter/API/FriendsAndFollowers#followers-instance_method
#
def followers(opts={})
bot.followers(opts)
end
#
# follow a user
#
# @param u a Twitter::User or user id
def follow(u)
bot.follow(u)
end
#
# a common list of bad words, which you might want to filter out.
# lifted from https://github.com/dariusk/wordfilter/blob/master/lib/badwords.json
#
def bad_words
[
"biatch",
"bitch",
"chinaman",
"chinamen",
"chink",
"crip",
"cunt",
"dago",
"daygo",
"dego",
"dick",
"douchebag",
"dyke",
"fag",
"fatass",
"fatso",
"gash",
"gimp",
"golliwog",
"gook",
"gyp",
"homo",
"hooker",
"jap",
"kike",
"kraut",
"lardass",
"lesbo",
"negro",
"nigger",
"paki",
"pussy",
"raghead",
"retard",
"shemale",
"skank",
"slut",
"spic",
"tard",
"tits",
"titt",
"trannies",
"tranny",
"twat",
"wetback",
"whore",
"wop"
]
end
#
# specify list of strings we will check when deciding to respond
# to a tweet or not. accepts an array or a comma-delimited string.
# when called, any subsequent calls to search or replies will
# filter out tweets with these strings
#
# @param [Array, String] args list of usernames
# @example
# exclude "spam, junk, something"
def exclude(*args)
e = flatten_list_of_strings(args)
if e.nil? || e.empty?
bot.exclude = []
else
bot.exclude += e
end
end
#
# The ID of the most recent tweet processed by the bot
#
def since_id(s=nil)
if s
bot.config[:since_id] = s
end
bot.config[:since_id]
end
#
# set the consumer secret
# @param s [String] the consumer secret
def consumer_secret(s)
bot.deprecated "Setting consumer_secret outside of your config file is deprecated!", Kernel.caller.first
bot.config[:consumer_secret] = s
end
#
# set the consumer key
# @param k [String] the consumer key
def consumer_key(k)
bot.deprecated "Setting consumer_key outside of your config file is deprecated!", Kernel.caller.first
bot.config[:consumer_key] = k
end
#
# set the secret
# @param s [String] the secret
def secret(s)
bot.deprecated "Setting access_token_secret outside of your config file is deprecated!", Kernel.caller.first
bot.config[:access_token_secret] = s
end
#
# set the token
# @param s [String] the token
def token(s)
bot.deprecated "Setting access_token outside of your config file is deprecated!", Kernel.caller.first
bot.config[:access_token] = s
end
#
# get the id of the last tweet the bot replied to
# @return tweet id
def since_id_reply
bot.config[:since_id_reply]
end
#
# explicitly save the configuration/state of the bot.
#
def update_config
bot.update_config
end
protected
#
# take a variable list of strings and possibly arrays and turn
# them into a single flat array of strings
#
def flatten_list_of_strings(args)
args.collect do |b|
if b.is_a?(String)
# string, split on commas and turn into array
b.split(",").collect { |s| s.strip }
else
# presumably an array
b
end
end.flatten
end
end
end
include Chatterbot::DSL
include Chatterbot::Helpers