Created
April 25, 2011 23:51
-
-
Save muffinista/941495 to your computer and use it in GitHub Desktop.
This file contains 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
#!/bin/ruby | |
require 'skeleton' | |
class BuyThatBot < Skeleton | |
def search | |
debug "check for tweets since #{@config[:since_id]}" | |
# | |
# search twitter | |
# | |
search = @client.search('robocop', {:lang => "en"}.merge(default_opts)) | |
if search != nil | |
if @config[:since_id].nil? or search["max_id"].to_i > @config[:since_id] | |
@config[:since_id] = search["max_id"].to_i | |
end | |
exclude = ['soulja', 'crank', 'kraus', 'kanye', 'west', '808', "want no", "become", "movin", "mix", "@robocop"] | |
#blocklist = ['CollectiveDrone', 'Exclusionzone', 'Hyperborea47', 'IanDavidB'] | |
search["results"].each { |s| | |
begin | |
skip_me = exclude.detect { |e| s["text"].downcase.include?(e) } != nil | |
if ! skip_me and ! on_blacklist?(s) | |
debug s["text"] | |
txt = "@#{s['from_user']} I'd buy that for a dollar!" | |
tweet txt, {:in_reply_to_status_id => s["id"]}, s | |
end | |
rescue Exception => e | |
puts e.inspect | |
debug e.message | |
end | |
} | |
end | |
end | |
end | |
@sk = BuyThatBot.new | |
@sk.run |
This file contains 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/ruby | |
require 'rubygems' | |
require 'sequel' | |
require 'twitter_oauth' | |
require 'yaml' | |
# | |
# extend Hash class to turn keys into symbols | |
# | |
class Hash | |
def symbolize_keys! | |
replace(inject({}) do |hash,(key,value)| | |
hash[key.to_sym] = value.is_a?(Hash) ? value.symbolize_keys! : value | |
hash | |
end) | |
end | |
end | |
# | |
# base class to handle being a twitter bot | |
# | |
class Skeleton | |
attr_accessor :config | |
attr_accessor :client | |
attr_accessor :exclude | |
attr_accessor :blacklist | |
attr_accessor :debug_mode | |
attr_accessor :write_config | |
def skip_me?(s) | |
@exclude.detect { |e| s["text"].downcase.include?(e) } != nil | |
end | |
def on_blacklist?(s) | |
@blacklist ||= [] | |
@global_blacklist ||= [] | |
(@blacklist + @global_blacklist).detect { |b| s['from_user'].downcase.include?(b.downcase) } != nil | |
end | |
def debug_mode=(d) | |
@debug_mode = d | |
end | |
def debug_mode | |
return true if ENV['DEBUG'] == "true" | |
@debug_mode.nil? ? false : @debug_mode | |
end | |
def debug(s) | |
puts "***** #{s}" | |
end | |
def botname | |
self.class.to_s.downcase | |
end | |
def log(txt, source=nil) | |
# create a dataset from the items table | |
return unless @config.has_key?(:log_uri) | |
if @db.nil? | |
# connect to an in-memory database | |
@db = Sequel.connect(@config[:log_uri]) | |
# # create an items table | |
if ! @db.tables.include?(:tweets) | |
@db.create_table :tweets do | |
primary_key :id | |
String :txt | |
String :bot | |
String :user | |
String :source_id | |
String :source_tweet | |
DateTime :created_at | |
end | |
end | |
end | |
tweets = @db[:tweets] | |
data = {:txt => txt, :bot => botname, :created_at => 'NOW()'.lit} | |
if source != nil | |
data = data.merge(:user => source['from_user'], | |
:source_id => source['id'], | |
:source_tweet => source['text']) | |
end | |
# populate the table | |
tweets.insert(data) | |
end | |
def load_global_blacklist | |
return unless @config.has_key?(:log_uri) | |
if @db.nil? | |
# connect to an in-memory database | |
@db = Sequel.connect(@config[:log_uri]) | |
# # create an items table | |
if ! @db.tables.include?(:blacklist) | |
@db.create_table :blacklist do | |
String :user, :primary_key => true | |
DateTime :created_at | |
end | |
end | |
end | |
blacklist = @db[:blacklist] | |
@global_blacklist = blacklist.collect{|x| x[:user]} | |
end | |
def run | |
load_config | |
load_global_blacklist | |
login | |
begin | |
replies | |
search | |
other | |
rescue Exception => e | |
debug e.inspect | |
puts e.inspect | |
end | |
update_config | |
end | |
def other | |
end | |
def default_opts | |
{ | |
:since_id => @config.has_key?(:since_id) ? @config[:since_id] : 0 | |
} | |
end | |
# implement search in the extended class | |
def search | |
end | |
# implement replies in the extended class | |
def replies | |
end | |
# simple wrapper for sending a message | |
def tweet(txt, params = {}, original = nil) | |
debug txt | |
log txt, original | |
if debug_mode == false | |
@client.update txt, params | |
end | |
end | |
# track the most recent msg we've handled | |
def update_since_id(s) | |
if s.class != Bignum && s.class != Fixnum && s.class != String | |
if s.respond_to?("[]") | |
s = s["id"] | |
end | |
end | |
s = s.to_i | |
@tmp_since_id ||= @config[:since_id] | |
if @tmp_since_id.nil? or s > @tmp_since_id | |
@tmp_since_id = s | |
end | |
end | |
protected | |
# | |
# handle oauth for this request. if the client isn't authorized, print | |
# out the auth URL and get a pin code back from the user | |
# | |
def login | |
@client = TwitterOAuth::Client.new( | |
:consumer_key => @config[:consumer_key], | |
:consumer_secret => @config[:consumer_secret], | |
:token => @config[:token].nil? ? nil : @config[:token], | |
:secret => @config[:secret].nil? ? nil : @config[:secret] | |
) | |
if @config[:token].nil? | |
request_token = @client.request_token | |
puts "#{request_token.authorize_url}\n" | |
puts "Paste your PIN and hit enter when you have completed authorization." | |
pin = STDIN.readline.chomp | |
access_token = @client.authorize( | |
request_token.token, | |
request_token.secret, | |
:oauth_verifier => pin | |
) | |
if @client.authorized? | |
@config[:token] = access_token.token | |
@config[:secret] = access_token.secret | |
update_config | |
else | |
debug "OOPS" | |
exit | |
end | |
end | |
end | |
# | |
# figure out what config file to load | |
# | |
def config_file | |
filename = "#{File.basename($0,".rb")}.yml" | |
debug "load config: #{filename}" | |
File.expand_path(filename) | |
end | |
def load_config | |
tmp = {} | |
begin | |
File.open( config_file ) { |yf| | |
tmp = YAML::load( yf ) | |
} | |
tmp.symbolize_keys! if tmp | |
rescue Exception => err | |
debug err.message | |
tmp = { | |
:since_id => 0 | |
} | |
end | |
# defaults for now, obviously a big hack. this is for botly, at: | |
# http://dev.twitter.com/apps/207151 | |
if ! tmp.has_key?(:consumer_key) | |
tmp[:consumer_key] = "hjaOOEeeMpJSqZR7dvhxjg" | |
tmp[:consumer_secret] = "wA5iqjfCf9aeGMMItqd6ylEEZAbcm7m6R7vVpaQV0s" | |
end | |
@config = tmp | |
end | |
# write out our config file | |
def update_config(tmp=@config) | |
# update datastore | |
if ! @tmp_since_id.nil? | |
tmp[:since_id] = @tmp_since_id | |
end | |
File.open(config_file, 'w') { |f| YAML.dump(tmp, f) } unless @write_config == false | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment