Created
June 8, 2009 12:15
-
-
Save presidentbeef/125781 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
#A little Twitter thing to post random quotes from Edsger Dijkstra | |
require 'yaml' | |
require 'open-uri' | |
require 'twitter' #twitter4r gem | |
require 'hpricot' | |
class DijkstraQuote | |
class << self | |
#Match the website's naming scheme | |
def random_ewd | |
(rand(1289) + 30).to_s.rjust(4, "0") | |
end | |
#Get a random quote | |
def get_quote | |
quote = nil | |
while quote.nil? do | |
quote = fetch random_ewd | |
end | |
quote | |
end | |
#Get a random quote from the specified set of notes | |
def fetch ewd | |
#Check if we've already retrieved this set of notes | |
if File.exists? "ewd#{ewd}" | |
quotes = YAML.load_file "ewd#{ewd}" | |
quotes[rand quotes.length] | |
else | |
$stderr.puts "Fetching EWD#{ewd}..." if $DEBUG | |
#Fetch a transcript of Dijkstra's notes | |
begin | |
file = open("http://www.cs.utexas.edu/~EWD/transcriptions/EWD#{ewd[0,2]}xx/EWD#{ewd}.html") { |f| Hpricot(f) } | |
rescue OpenURI::HTTPError | |
$stderr.puts "Not found" if $DEBUG | |
return nil | |
end | |
text = file.to_plain_text | |
#Pick some sentences that seem good | |
lines = text.split(/\.(?:\s+|\n+)/).map do |l| | |
l.gsub(/\t|\n|\r/, " ").squeeze(" ").strip | |
end.select do |l| | |
l.length > 40 and l.length < 140 and l[0,1] == l[0,1].upcase and l[-3, 3] != "viz" | |
end | |
#Cache them for later | |
File.open "ewd#{ewd}", "w" do |f| | |
YAML.dump lines, f | |
end | |
#Return a random sentence | |
lines[rand lines.length] | |
end | |
end | |
#(Very crudely) tries to find a quote that is related to the message. | |
#Note that this only searches the cache. | |
def find_related message | |
#Get the longer words | |
words = message.gsub(/[^a-zA-Z ]/, "").split.select { |w| w.length > 4 } | |
quote = nil | |
if words.length > 0 | |
word = /#{Regexp.union(words)}/i | |
#Check local files for the search word | |
Dir.glob("ewd[0-9][0-9][0-9][0-9]").find do |f| | |
text = File.read f | |
if text =~ word | |
#Get the list of quotes and grab one | |
quotes = YAML.load_file f | |
matches = quotes.grep word | |
quote = matches[rand(matches.length)] | |
else | |
false | |
end | |
end | |
else | |
quote = get_quote | |
end | |
quote | |
end | |
end | |
end | |
#Post to Twitter | |
class DijkstraTwitter | |
def initialize | |
@twitter = Twitter::Client.new :login => "?", :password => "?" | |
end | |
#Post a random quote. If _ask_ is true, asks for approval first | |
def post_random ask = false | |
quote = DijkstraQuote.get_quote | |
if ask and ask_permission("Would you like to post this: \"#{quote}\"") or not ask | |
@twitter.status :post, quote | |
end | |
end | |
#Check unanswered @ewd messages and come up with responses | |
def post_replies ask = false | |
require 'set' | |
#Keep track of what has been replied to already | |
if File.exist? "ewdreplies" | |
replied = YAML.load_file "ewdreplies" | |
else | |
replied = Set.new | |
end | |
replies = @twitter.status(:replies) | |
replies.each do |status| | |
status_id = status.id.to_s | |
next if replied.include? status_id | |
message = status.text | |
user = status.user.screen_name | |
if reply_to message, user, ask | |
replied << status_id | |
end | |
end | |
File.open "ewdreplies", "w" do |f| | |
YAML.dump replied, f | |
end | |
end | |
#Send a reply if we can find one | |
def reply_to message, sender, ask = false | |
puts "Responding to \"#{message}\"" | |
quote = DijkstraQuote.find_related message | |
if not quote | |
puts "Nothing related. Skipping." | |
return false | |
elsif ask and ask_permission("Would you like to post this: \"#{quote}\"") or not ask | |
response = "@#{sender} #{quote}" | |
if response.length > 140 | |
response = response[0,140] | |
end | |
@twitter.status(:post, "@#{sender} #{quote}") | |
true | |
else | |
ask and ask_permission "Ignore this reply?" | |
end | |
end | |
#Ask the user a question | |
def ask_permission message | |
puts message | |
response = nil | |
until response =~ /^(y|n)/i | |
print "(Y/N): " | |
response = gets | |
end | |
$1.downcase == "y" | |
end | |
end | |
#Try it out | |
puts DijkstraQuote.get_quote | |
#dt = DijkstraTwitter.new | |
##dt.post_random true | |
##dt.post_replies true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment