Last active
August 29, 2015 14:10
-
-
Save FluffyPira/61a3d5db87cdeb3a3fbf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'twitter_ebooks' | |
include Ebooks | |
CONSUMER_KEY = "" | |
CONSUMER_SECRET = "" | |
OATH_TOKEN = "" # oauth token for ebooks account | |
OAUTH_TOKEN_SECRET = "" # oauth secret for ebooks account | |
ROBOT_ID = "book" # Avoid infinite reply chains | |
TWITTER_USERNAME = "stawbewwi_books" # Ebooks account username | |
TEXT_MODEL_NAME = "stawbewwi" # 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'] | |
TRIGGER_WORDS = ['cunt', 'bitch', 'tranny', 'shemale', 'faggot', 'fag'] # Block users who say these words | |
# 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") | |
@top50 = @model.keywords.top(50).map(&:to_s).map(&:downcase) | |
@top20 = @model.keywords.top(20).map(&:to_s).map(&:downcase) | |
prune_following() | |
bot.tweet @model.make_statement | |
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.10 | |
next if tweet[:user][:screen_name].include?('bot') && rand > 0.20 | |
next if tweet[:user][:screen_name].include?('generateacat') && rand > 0.05 | |
tokens = NLP.tokenize(tweet[:text]) | |
very_interesting = tokens.find_all { |t| @top20.include?(t.downcase) }.length > 2 | |
special = tokens.find { |t| SPECIAL_WORDS.include?(t) } | |
trigger = tokens.find { |t| TRIGGER_WORDS.include?(t.downcase) } | |
if trigger | |
block(tweet) if rand < 0.25 | |
end | |
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| @top50.include?(t.downcase) } | |
very_interesting = tokens.find_all { |t| @top20.include?(t.downcase) }.length > 2 | |
special = tokens.find { |t| SPECIAL_WORDS.include?(t) } | |
if special | |
favorite(tweet) if rand < 0.5 | |
favd = true # Mark this tweet as favorited | |
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 tweet for every couple hours | |
bot.scheduler.every '1800' do | |
bot.tweet @model.make_statement | |
end | |
# Clear the have talked list every day at midnight | |
bot.scheduler.cron '0 0 * * *' do | |
$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 | |
def block(tweet) | |
@bot.log "Blocking and reporting @#{tweet[:user][:screen_name]}" | |
@bot.twitter.block(tweet[:user][:screen_name]) | |
@bot.twitter.report_spam(tweet[:user][:screen_name]) | |
end | |
def prune_following | |
following = Set.new(@bot.twitter.friend_ids.to_a) | |
followers = Set.new(@bot.twitter.follower_ids.to_a) | |
to_unfollow = (following - followers).to_a | |
@bot.log("Unfollowing user ids: #{to_unfollow}") | |
@bot.twitter.unfollow(to_unfollow) | |
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment