-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbots.rb
139 lines (110 loc) · 4.05 KB
/
bots.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
#!/usr/bin/env ruby
require 'twitter_ebooks'
include Ebooks
# Note: try not to upload private keys to public git repository (thank you #based @ckolderup)
CONSUMER_KEY = ENV['CONSUMER_KEY']
CONSUMER_SECRET = ENV['CONSUMER_SECRET']
OATH_TOKEN = ENV['OATH_TOKEN'] # oauth token for ebooks account
OAUTH_TOKEN_SECRET = ENV['OAUTH_TOKEN_SECRET'] # oauth secret for ebooks account
ROBOT_ID = "ebooks" # Avoid infinite reply chains
TWITTER_USERNAME = "tull_ebooks" # Ebooks account username
TEXT_MODEL_NAME = "tull_ebooks" # This should be the name of the text model
DELAY = 2..30 # Simulated human reply delay range in seconds
BLACKLIST = ['insomnius', 'upulie'] # Grumpy users to avoid interaction with
SPECIAL_WORDS = ['ebooks', 'bot', 'bots', 'clone', 'singularity', 'world domination']
# Track who we've randomly interacted with globally
$have_talked = {}
class GenBot
def initialize(bot, modelname)
@bot = bot
@model = nil
bot.consumer_key = CONSUMER_KEY
bot.consumer_secret = CONSUMER_SECRET
bot.on_startup do
@model = Model.load("model/#{modelname}.model")
@top100 = @model.keywords.top(100).map(&:to_s).map(&:downcase)
@top50 = @model.keywords.top(20).map(&:to_s).map(&:downcase)
end
bot.on_message do |dm|
bot.delay DELAY do
bot.reply dm, @model.make_response(dm[:text])
end
end
bot.on_follow do |user|
bot.delay DELAY do
bot.follow user[:screen_name]
end
end
bot.on_mention do |tweet, meta|
# Avoid infinite reply chains (very small chance of crosstalk)
next if tweet[:user][:screen_name].include?(ROBOT_ID) && rand > 0.05
tokens = NLP.tokenize(tweet[:text])
very_interesting = tokens.find_all { |t| @top50.include?(t.downcase) }.length > 2
special = tokens.find { |t| SPECIAL_WORDS.include?(t) }
if very_interesting || special
favorite(tweet)
end
reply(tweet, meta)
end
bot.on_timeline do |tweet, meta|
next if tweet[:retweeted_status] || tweet[:text].start_with?('RT')
next if BLACKLIST.include?(tweet[:user][:screen_name])
tokens = NLP.tokenize(tweet[:text])
# We calculate unprompted interaction probability by how well a
# tweet matches our keywords
interesting = tokens.find { |t| @top100.include?(t.downcase) }
very_interesting = tokens.find_all { |t| @top50.include?(t.downcase) }.length > 2
special = tokens.find { |t| SPECIAL_WORDS.include?(t) }
if special
favorite(tweet)
favd = true # Mark this tweet as favorited
bot.delay DELAY do
bot.follow tweet[:user][:screen_name]
end
end
# Any given user will receive at most one random interaction per day
# (barring special cases)
next if $have_talked[tweet[:user][:screen_name]]
$have_talked[tweet[:user][:screen_name]] = true
if very_interesting || special
favorite(tweet) if (rand < 0.5 && !favd) # Don't fav the tweet if we did earlier
retweet(tweet) if rand < 0.1
reply(tweet, meta) if rand < 0.1
elsif interesting
favorite(tweet) if rand < 0.1
reply(tweet, meta) if rand < 0.05
end
end
# Schedule a main tweet for every day at midnight
bot.scheduler.cron '0 * * * *' do
bot.tweet @model.make_statement
$have_talked = {}
end
end
def reply(tweet, meta)
resp = @model.make_response(meta[:mentionless], meta[:limit])
@bot.delay DELAY do
@bot.reply tweet, meta[:reply_prefix] + resp
end
end
def favorite(tweet)
@bot.log "Favoriting @#{tweet[:user][:screen_name]}: #{tweet[:text]}"
@bot.delay DELAY do
@bot.twitter.favorite(tweet[:id])
end
end
def retweet(tweet)
@bot.log "Retweeting @#{tweet[:user][:screen_name]}: #{tweet[:text]}"
@bot.delay DELAY do
@bot.twitter.retweet(tweet[:id])
end
end
end
def make_bot(bot, modelname)
GenBot.new(bot, modelname)
end
Ebooks::Bot.new(TWITTER_USERNAME) do |bot|
bot.oauth_token = OATH_TOKEN
bot.oauth_token_secret = OAUTH_TOKEN_SECRET
make_bot(bot, TEXT_MODEL_NAME)
end