Skip to content

Instantly share code, notes, and snippets.

@FluffyPira
Last active March 3, 2016 02:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FluffyPira/fc4a2d5008cb083ba5cc to your computer and use it in GitHub Desktop.
Save FluffyPira/fc4a2d5008cb083ba5cc to your computer and use it in GitHub Desktop.
require 'twitter_ebooks'
require 'set'
require 'twilio-ruby'
require 'configru'
# This is an example bot definition with event handlers commented out
# You can define and instantiate as many bots as you like
# Load us up some configuration file
auth = Configru::Config.new('auth.yml') do
option_group :twitter do
option_required :consumer_key, String
option_required :consumer_secret, String
option_required :access_token, String
option_required :access_token_secret, String
end
option_group :twilio do
option_required :account, String
option_required :token, String
option_required :number, Fixnum
end
end
ROBOT_ID = "books" # Avoid infinite reply chains
SPECIAL_WORDS = ['bot', 'mew', 'ebooks', 'pira', 'fluffy', 'muffins', 'kittens', 'trans']
TRIGGER_WORDS = ['cunt', 'bitch', 'tranny', 'shemale', 'faggot', 'fag'] # Block users who say these
CONSUMER_KEY = auth.twitter.consumer_key
CONSUMER_SECRET = auth.twitter.consumer_secret
ACCESS_TOKEN = auth.twitter.access_token
ACCESS_TOKEN_SECRET = auth.twitter.access_token_secret
TWILIO_ACCOUNT = auth.twilio.account
TWILIO_AUTH_TOKEN = auth.twilio.token
TWILIO_PHONE_NUMBER = auth.twilio.number
$have_talked = {}
# Information about a particular Twitter user we know
class UserInfo
attr_reader :username
# @return [Integer] how many times we can pester this user unprompted
attr_accessor :pesters_left
# @param username [String]
def initialize(username)
@username = username
@pesters_left = 1
end
end
class MyBot < Ebooks::Bot
attr_accessor :original, :model, :model_path
# Configuration here applies to all MyBots
def configure
# Consumer details come from registering an app at https://dev.twitter.com/
# Once you have consumer details, use "ebooks auth" for new access tokens
self.consumer_key = CONSUMER_KEY
self.consumer_secret = CONSUMER_SECRET
self.blacklist = ['insomnius', 'upulie', 'horse_inky', 'gray_noise', 'lookingglasssab', 'AmaznPhilEbooks', 'AKBAE_BOT']
self.delay_range = 1..5
@userinfo = {}
load_model!
end
def on_startup
# Schedule a tweet for every 30 minutes
@pics = (Dir.entries("pictures/") - %w[.. . .DS_Store]).sort()
log @pics.take(5) # poll for consistency and tracking purposes.
@status_count = twitter.user.statuses_count
@client = Twilio::REST::Client.new TWILIO_ACCOUNT, TWILIO_AUTH_TOKEN
@client.messages.create(
from: "+#{TWILIO_PHONE_NUMBER}",
to: "+19057307275",
body: model.make_statement
)
@posttime = rand(2000..3600)
puts "Time between posts is #{@posttime} seconds."
scheduler.every "#{@posttime}" do
post_tweet
end
post_tweet
# twitter.search("#lewd", result_type: "recent").take(1).each do |tweet|
# reply(tweet, model.make_response(meta(tweet).mentionless, meta(tweet).limit))
# end
prune_following()
# Clears the have_talked variable daily at midnight.
scheduler.cron '0 0 * * *' do
prune_following()
$have_talked = {}
end
end
def on_message(dm)
# Reply to a DM
# bot.reply(dm, "secret secrets")
shit = Random.new.bytes(5)
if dm.text.start_with?('SMS')
message = dm.text.split(" ")
pic = @pics[next_index]
@client.messages.create(
from: "+#{TWILIO_PHONE_NUMBER}",
to: "+#{message[1]}",
# media_url: "pictures/#{pic}"
body: model.make_statement
)
reply(dm, "Text sent to +#{message[1]} - #{shit}")
else
reply(dm, model.make_response(dm.text))
end
end
def on_follow(user)
delay do
follow(user.screen_name)
end
end
def on_mention(tweet)
# Become more inclined to pester a user when they talk to us
userinfo(tweet.user.screen_name).pesters_left += 1
tokens = Ebooks::NLP.tokenize(tweet.text)
very_interesting = tokens.find_all { |t| top20.include?(t.downcase) }.length > 2
special = tokens.find { |t| SPECIAL_WORDS.include?(t.downcase) }
trigger = tokens.find { |t| TRIGGER_WORDS.include?(t.downcase) }
if trigger
block(tweet)
end
if very_interesting || special
favorite(tweet)
end
if tokens.select{|x| x[0] == '@' }.length < 3 # less than 3 @-mentions.
reply(tweet, model.make_response(meta(tweet).mentionless, meta(tweet).limit))
end
end
def on_timeline(tweet)
# Reply to a tweet in the bot's timeline
# bot.reply(tweet, meta(tweet)[:reply_prefix] + "nice tweet")
return if tweet.retweeted_status?
return unless can_pester?(tweet.user.screen_name)
tokens = Ebooks::NLP.tokenize(tweet.text)
interesting = tokens.find { |t| top100.include?(t.downcase) }
very_interesting = tokens.find_all { |t| top20.include?(t.downcase) }.length > 2
special = tokens.find { |t| SPECIAL_WORDS.include?(t.downcase) }
delay do
if special
favorite(tweet) if rand < 0.75
if rand < 0.20
reply(tweet, model.make_response(meta(tweet).mentionless, meta(tweet).limit))
userinfo(tweet.user.screen_name).pesters_left -= 1
end
elsif very_interesting
favorite(tweet) if rand < 0.1
if rand < 0.05
reply(tweet, model.make_response(meta(tweet).mentionless, meta(tweet).limit))
userinfo(tweet.user.screen_name).pesters_left -= 1
end
elsif interesting
favorite(tweet) if rand < 0.05
if rand < 0.01
reply(tweet, model.make_response(meta(tweet).mentionless, meta(tweet).limit))
userinfo(tweet.user.screen_name).pesters_left -= 1
end
end
end
end
def can_follow?(username)
@original.nil? || username == @original || twitter.friendship?(username, @original)
end
# Find information we've collected about a user
# @param username [String]
# @return [Ebooks::UserInfo]
def userinfo(username)
@userinfo[username] ||= UserInfo.new(username)
end
# Check if we're allowed to send unprompted tweets to a user
# @param username [String]
# @return [Boolean]
def can_pester?(username)
userinfo(username).pesters_left > 0
end
def favorite(tweet)
delay do
super(tweet)
end
end
def block(tweet)
log "Blocking and reporting @#{tweet[:user][:screen_name]}"
twitter.block(tweet[:user][:screen_name])
twitter.report_spam(tweet[:user][:screen_name])
end
def next_index()
seq = (0..(@pics.size - 1)).to_a
seed = @status_count / @pics.size
r = Random.new(seed)
seq.shuffle!(random: r)
res = seq[@status_count % @pics.size]
@status_count = @status_count + 1
return res
end
def prune_following
following = Set.new(twitter.friend_ids.to_a)
followers = Set.new(twitter.follower_ids.to_a)
to_unfollow = (following - followers).to_a
# to_follow = (followers - following).to_a
log("Unfollowing user ids: #{to_unfollow}")
twitter.unfollow(to_unfollow)
# log("Following user ids: #{to_follow}")
# follow(to_follow)
end
def post_tweet
txt = model.make_statement
pic = @pics[next_index]
# this has a 20% chance of tweeting a picture from a specified folder, otherwise it will tweet normally.
if rand < 0.20
pictweet(txt,"pictures/#{pic}")
else
tweet(txt)
end
end
def top100; @top100 ||= model.keywords.take(100); end
def top20; @top20 ||= model.keywords.take(20); end
private
def load_model!
return if @model
@model_path ||= "model/FluffyPira.model"
log "Loading model #{model_path}"
@model = Ebooks::Model.load(model_path)
end
end
# Make a MyBot and attach it to an account
MyBot.new('pira_ebooks') do |bot|
bot.access_token = ACCESS_TOKEN # Token connecting the app to this account
bot.access_token_secret = ACCESS_TOKEN_SECRET # Secret connecting the app to this account
bot.original = 'FluffyPira'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment