Slightly different pesters model
This commit is contained in:
parent
24e8ce5ae3
commit
1a40ef85f9
2 changed files with 45 additions and 68 deletions
48
bin/ebooks
48
bin/ebooks
|
@ -163,49 +163,9 @@ STR
|
||||||
bot.tweet(statement)
|
bot.tweet(statement)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.jsonify(paths)
|
def self.c
|
||||||
usage = <<STR
|
load 'bots.rb'
|
||||||
Usage: ebooks jsonify <old_corpus_path> [old_corpus_path2] [...]
|
require 'pry'; pry
|
||||||
|
|
||||||
Takes an old-style corpus of plain tweet text and converts it to json.
|
|
||||||
STR
|
|
||||||
|
|
||||||
if paths.empty?
|
|
||||||
log usage
|
|
||||||
exit
|
|
||||||
end
|
|
||||||
|
|
||||||
paths.each do |path|
|
|
||||||
name = File.basename(path).split('.')[0]
|
|
||||||
new_path = name + ".json"
|
|
||||||
|
|
||||||
tweets = []
|
|
||||||
id = nil
|
|
||||||
if path.split('.')[-1] == "csv" #from twitter archive
|
|
||||||
csv_archive = CSV.read(path, :headers=>:first_row)
|
|
||||||
tweets = csv_archive.map do |tweet|
|
|
||||||
{ text: tweet['text'], id: tweet['tweet_id'] }
|
|
||||||
end
|
|
||||||
else
|
|
||||||
File.read(path).split("\n").each do |l|
|
|
||||||
if l.start_with?('# ')
|
|
||||||
id = l.split('# ')[-1]
|
|
||||||
else
|
|
||||||
tweet = { text: l }
|
|
||||||
if id
|
|
||||||
tweet[:id] = id
|
|
||||||
id = nil
|
|
||||||
end
|
|
||||||
tweets << tweet
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
File.open(new_path, 'w') do |f|
|
|
||||||
log "Writing #{tweets.length} tweets to #{new_path}"
|
|
||||||
f.write(JSON.pretty_generate(tweets))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.command(args)
|
def self.command(args)
|
||||||
|
@ -218,7 +178,6 @@ Usage:
|
||||||
ebooks score <model_path> <input>
|
ebooks score <model_path> <input>
|
||||||
ebooks archive <@user> <outpath>
|
ebooks archive <@user> <outpath>
|
||||||
ebooks tweet <model_path> <botname>
|
ebooks tweet <model_path> <botname>
|
||||||
ebooks jsonify <old_corpus_path> [old_corpus_path2] [...]
|
|
||||||
STR
|
STR
|
||||||
|
|
||||||
if args.length == 0
|
if args.length == 0
|
||||||
|
@ -235,6 +194,7 @@ STR
|
||||||
when "archive" then archive(args[1], args[2])
|
when "archive" then archive(args[1], args[2])
|
||||||
when "tweet" then tweet(args[1], args[2])
|
when "tweet" then tweet(args[1], args[2])
|
||||||
when "jsonify" then jsonify(args[1..-1])
|
when "jsonify" then jsonify(args[1..-1])
|
||||||
|
when "c" then c
|
||||||
else
|
else
|
||||||
log usage
|
log usage
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
@ -10,15 +10,15 @@ module Ebooks
|
||||||
# each user and start dropping them from mentions after two in a row
|
# each user and start dropping them from mentions after two in a row
|
||||||
class UserInfo
|
class UserInfo
|
||||||
attr_reader :username
|
attr_reader :username
|
||||||
attr_accessor :pester_count
|
attr_accessor :pesters_left
|
||||||
|
|
||||||
def initialize(username)
|
def initialize(username)
|
||||||
@username = username
|
@username = username
|
||||||
@pester_count = 0
|
@pesters_left = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_pester?
|
def can_pester?
|
||||||
@pester_count < 2
|
@pesters_left > 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ module Ebooks
|
||||||
def receive(tweet)
|
def receive(tweet)
|
||||||
@received << tweet
|
@received << tweet
|
||||||
@last_update = Time.now
|
@last_update = Time.now
|
||||||
@userinfo.pester_count = 0
|
@userinfo.pesters_left += 2
|
||||||
end
|
end
|
||||||
|
|
||||||
# Make an informed guess as to whether this user is a bot
|
# Make an informed guess as to whether this user is a bot
|
||||||
|
@ -88,6 +88,9 @@ module Ebooks
|
||||||
@users ||= {}
|
@users ||= {}
|
||||||
@interactions ||= {}
|
@interactions ||= {}
|
||||||
configure(*args, &b)
|
configure(*args, &b)
|
||||||
|
|
||||||
|
# Tweet ids we've already observed, to avoid duplication
|
||||||
|
@seen_tweets ||= {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def userinfo(username)
|
def userinfo(username)
|
||||||
|
@ -103,15 +106,17 @@ module Ebooks
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def make_client
|
def twitter
|
||||||
@twitter = Twitter::REST::Client.new do |config|
|
@twitter ||= Twitter::REST::Client.new do |config|
|
||||||
config.consumer_key = @consumer_key
|
config.consumer_key = @consumer_key
|
||||||
config.consumer_secret = @consumer_secret
|
config.consumer_secret = @consumer_secret
|
||||||
config.access_token = @access_token
|
config.access_token = @access_token
|
||||||
config.access_token_secret = @access_token_secret
|
config.access_token_secret = @access_token_secret
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@stream = Twitter::Streaming::Client.new do |config|
|
def stream
|
||||||
|
@stream ||= Twitter::Streaming::Client.new do |config|
|
||||||
config.consumer_key = @consumer_key
|
config.consumer_key = @consumer_key
|
||||||
config.consumer_secret = @consumer_secret
|
config.consumer_secret = @consumer_secret
|
||||||
config.access_token = @access_token
|
config.access_token = @access_token
|
||||||
|
@ -183,6 +188,13 @@ module Ebooks
|
||||||
@twitter.block(ev.user.screen_name)
|
@twitter.block(ev.user.screen_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Avoid responding to duplicate tweets
|
||||||
|
if @seen_tweets[ev.id]
|
||||||
|
return
|
||||||
|
else
|
||||||
|
@seen_tweets[ev.id] = true
|
||||||
|
end
|
||||||
|
|
||||||
if meta[:mentions_bot]
|
if meta[:mentions_bot]
|
||||||
log "Mention from @#{ev.user.screen_name}: #{ev.text}"
|
log "Mention from @#{ev.user.screen_name}: #{ev.text}"
|
||||||
interaction(ev.user.screen_name).receive(ev)
|
interaction(ev.user.screen_name).receive(ev)
|
||||||
|
@ -201,7 +213,8 @@ module Ebooks
|
||||||
|
|
||||||
def start_stream
|
def start_stream
|
||||||
log "starting tweet stream"
|
log "starting tweet stream"
|
||||||
@stream.user do |ev|
|
|
||||||
|
stream.user do |ev|
|
||||||
receive_event ev
|
receive_event ev
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -212,7 +225,7 @@ module Ebooks
|
||||||
raise ConfigurationError, "bot.username cannot be nil"
|
raise ConfigurationError, "bot.username cannot be nil"
|
||||||
end
|
end
|
||||||
|
|
||||||
make_client
|
twitter
|
||||||
fire(:startup)
|
fire(:startup)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -249,7 +262,7 @@ module Ebooks
|
||||||
if ev.is_a? Twitter::DirectMessage
|
if ev.is_a? Twitter::DirectMessage
|
||||||
return if blacklisted?(ev.sender.screen_name)
|
return if blacklisted?(ev.sender.screen_name)
|
||||||
log "Sending DM to @#{ev.sender.screen_name}: #{text}"
|
log "Sending DM to @#{ev.sender.screen_name}: #{text}"
|
||||||
@twitter.create_direct_message(ev.sender.screen_name, text, opts)
|
twitter.create_direct_message(ev.sender.screen_name, text, opts)
|
||||||
elsif ev.is_a? Twitter::Tweet
|
elsif ev.is_a? Twitter::Tweet
|
||||||
meta = calc_meta(ev)
|
meta = calc_meta(ev)
|
||||||
|
|
||||||
|
@ -258,17 +271,17 @@ module Ebooks
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if !meta[:mentions_bot] && !userinfo(ev.user.screen_name).can_pester?
|
if !meta[:mentions_bot]
|
||||||
log "Already pestered @#{ev.user.screen_name} enough for now"
|
if !userinfo(ev.user.screen_name).can_pester?
|
||||||
|
log "Not replying: leaving @#{ev.user.screen_name} alone"
|
||||||
return
|
return
|
||||||
|
else
|
||||||
|
userinfo(ev.user.screen_name).pesters_left -= 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
log "Replying to @#{ev.user.screen_name} with: #{meta[:reply_prefix] + text}"
|
log "Replying to @#{ev.user.screen_name} with: #{meta[:reply_prefix] + text}"
|
||||||
@twitter.update(meta[:reply_prefix] + text, in_reply_to_status_id: ev.id)
|
twitter.update(meta[:reply_prefix] + text, in_reply_to_status_id: ev.id)
|
||||||
|
|
||||||
meta[:reply_mentions].each do |username|
|
|
||||||
userinfo(username).pester_count += 1
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
raise Exception("Don't know how to reply to a #{ev.class}")
|
raise Exception("Don't know how to reply to a #{ev.class}")
|
||||||
end
|
end
|
||||||
|
@ -278,8 +291,13 @@ module Ebooks
|
||||||
return if blacklisted?(tweet.user.screen_name)
|
return if blacklisted?(tweet.user.screen_name)
|
||||||
log "Favoriting @#{tweet.user.screen_name}: #{tweet.text}"
|
log "Favoriting @#{tweet.user.screen_name}: #{tweet.text}"
|
||||||
|
|
||||||
|
meta = calc_meta(tweet)
|
||||||
|
if !meta[:mentions_bot] && !userinfo(ev.user.screen_name).can_pester?
|
||||||
|
log "Not favoriting: leaving @#{ev.user.screen_name} alone"
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@twitter.favorite(tweet.id)
|
twitter.favorite(tweet.id)
|
||||||
rescue Twitter::Error::Forbidden
|
rescue Twitter::Error::Forbidden
|
||||||
log "Already favorited: #{tweet.user.screen_name}: #{tweet.text}"
|
log "Already favorited: #{tweet.user.screen_name}: #{tweet.text}"
|
||||||
end
|
end
|
||||||
|
@ -290,7 +308,7 @@ module Ebooks
|
||||||
log "Retweeting @#{tweet.user.screen_name}: #{tweet.text}"
|
log "Retweeting @#{tweet.user.screen_name}: #{tweet.text}"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@twitter.retweet(tweet.id)
|
twitter.retweet(tweet.id)
|
||||||
rescue Twitter::Error::Forbidden
|
rescue Twitter::Error::Forbidden
|
||||||
log "Already retweeted: #{tweet.user.screen_name}: #{tweet.text}"
|
log "Already retweeted: #{tweet.user.screen_name}: #{tweet.text}"
|
||||||
end
|
end
|
||||||
|
@ -298,13 +316,12 @@ module Ebooks
|
||||||
|
|
||||||
def follow(*args)
|
def follow(*args)
|
||||||
log "Following #{args}"
|
log "Following #{args}"
|
||||||
|
twitter.follow(*args)
|
||||||
@twitter.follow(*args)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def tweet(*args)
|
def tweet(*args)
|
||||||
log "Tweeting #{args.inspect}"
|
log "Tweeting #{args.inspect}"
|
||||||
@twitter.update(*args)
|
twitter.update(*args)
|
||||||
end
|
end
|
||||||
|
|
||||||
def scheduler
|
def scheduler
|
||||||
|
@ -314,7 +331,7 @@ module Ebooks
|
||||||
# could easily just be *args however the separation keeps it clean.
|
# could easily just be *args however the separation keeps it clean.
|
||||||
def pictweet(txt, pic, *args)
|
def pictweet(txt, pic, *args)
|
||||||
log "Tweeting #{txt.inspect} - #{pic} #{args}"
|
log "Tweeting #{txt.inspect} - #{pic} #{args}"
|
||||||
@twitter.update_with_media(txt, File.new(pic), *args)
|
twitter.update_with_media(txt, File.new(pic), *args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue