mirror of
https://github.com/thewesker/ebooks_example.git
synced 2025-12-20 12:21:16 -05:00
Ebooks example repo
This commit is contained in:
4
Gemfile
Normal file
4
Gemfile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
source 'http://rubygems.org'
|
||||||
|
ruby '1.9.3'
|
||||||
|
|
||||||
|
gem 'twitter_ebooks'
|
||||||
19
README.md
Normal file
19
README.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# ebooks_example
|
||||||
|
|
||||||
|
As requested, this is the [twitter_ebooks](https://github.com/mispy/twitter_ebooks) app which I use to run most of my own bots. It tweets one guaranteed tweet every 24h, always responds to interactions, and has some small unprompted interaction probability based on keyword matching.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/mispy/ebooks_example.git
|
||||||
|
cd ebooks_example
|
||||||
|
bundle install
|
||||||
|
ebooks archive username corpus/username.json
|
||||||
|
ebooks consume corpus/username.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Populate bots.rb with your auth details, the bot username and model name, then:
|
||||||
|
|
||||||
|
`./run.rb`
|
||||||
|
|
||||||
|
Also runs as a Heroku app! See the [twitter_ebooks](https://github.com/mispy/twitter_ebooks) README for more information.
|
||||||
129
bots.rb
Normal file
129
bots.rb
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'twitter_ebooks'
|
||||||
|
include Ebooks
|
||||||
|
|
||||||
|
CONSUMER_KEY = ""
|
||||||
|
CONSUMER_SECRET = ""
|
||||||
|
DELAY = 2..30 # Simulated human reply delay range in seconds
|
||||||
|
BLACKLIST = ['insomnius', 'upulie'] # Grumpy users to avoid interaction with
|
||||||
|
|
||||||
|
# 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?('ebooks') && rand > 0.05
|
||||||
|
|
||||||
|
tokens = NLP.tokenize(tweet[:text])
|
||||||
|
|
||||||
|
very_interesting = tokens.find_all { |t| @top50.include?(t.downcase) }.length > 2
|
||||||
|
special = tokens.find { |t| ['ebooks', 'bot', 'bots', 'clone', 'singularity', 'world domination'].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| ['ebooks', 'bot', 'bots', 'clone', 'singularity', 'world domination'].include?(t) }
|
||||||
|
|
||||||
|
if special
|
||||||
|
favorite(tweet)
|
||||||
|
|
||||||
|
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
|
||||||
|
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 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("username_ebooks") do |bot| # Ebooks account username
|
||||||
|
bot.oauth_token = "" # oauth token for ebooks account
|
||||||
|
bot.oauth_token_secret = "" # oauth secret for ebooks account
|
||||||
|
|
||||||
|
make_bot(bot, "username") # This should be the name of the text model
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user