Last active
March 3, 2016 02:39
-
-
Save FluffyPira/fc4a2d5008cb083ba5cc 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
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