Skip to content

Instantly share code, notes, and snippets.

@oogali
Created December 29, 2010 00:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oogali/757951 to your computer and use it in GitHub Desktop.
Save oogali/757951 to your computer and use it in GitHub Desktop.
be.gs irc bot
#!/usr/bin/env ruby
require 'rubygems'
require 'isaac'
require 'em-http-request'
require 'uri'
configure do |c|
c.nick = 'begs'
c.server = 'irc'
c.realname = 'be.gs URL shortener (http://be.gs)'
c.port = 6667
c.verbose = true
end
# list of channels we should join upon connecting
CHANNELS = [
{ :channel => '#channel' },
{ :channel => '#anotherchannel', :key => 'sup3rs3kr1t' }
]
# options...
# * SHORTENER url shortener we should use
# * LENGTH_THRESHOLD minimum # of characters we should trigger shortening for
# * HTTP_OPTIONS options for EM::HttpRequest
#
SHORTENER = URI.parse('http://be.gs/shorten')
LENGTH_THRESHOLD = 22 # characters
HTTP_OPTIONS = {
:connect_timeout => 3,
:inactivity_timeout => 5
}
helpers do
# shorten a url for a requester...
def shorten(target, url)
# we don't want to clutter the channel with unnecessarily shortened links
return nil if url.length < LENGTH_THRESHOLD
# make sure this is a valid url, and not a loop back to us
uri = URI.parse url rescue nil
return nil if !uri or uri.host == SHORTENER.host
# create our response hash
response = {
:url => nil,
:title => nil
}
# spin up parallel requests for shortening and title fetching
multi = EventMachine::MultiRequest.new
multi.add(:shorten, EventMachine::HttpRequest.new(SHORTENER, HTTP_OPTIONS).post(:body => { :url => URI.encode(url) }))
multi.add(:source, EventMachine::HttpRequest.new(uri.to_s, HTTP_OPTIONS).get(:redirects => 5, :head => { 'Accept-Encoding' => 'gzip, deflate', 'Range' => 'bytes=0-4095' }))
# sort through our responses
multi.callback do
# if shortener returned 200, take text of response
if multi.responses[:callback][:shorten].response_header.status == 200
response[:url] = multi.responses[:callback][:shorten].response
end
# if source returned 200 (aka not-redirect-hell), and contains a <title> tag in the first 512 bytes
if multi.responses[:callback][:source] and multi.responses[:callback][:source].response_header.status == 200
if multi.responses[:callback][:source].response[0..4095] =~ /<title>(.*)<\/title>/
# we only want the first 64 characters of the title...
response[:title] = $~[1].strip[0..63]
response[:title] += '...' if $~[1].length > 64
end
end
# send shortened url and title to requester
display target, response
end
end
# display shortened url and/or title
def display(target, u)
if u and (u[:url] or u[:title])
msg target, "#{u[:url] ? u[:url].ljust(18) : nil} #{u[:title] ? ('## ' + u[:title]) : nil }"
end
end
end
# after connecting to the irc server, join our channels (w/keys if specified)
on :connect do
CHANNELS.each do |channel|
join channel[:channel] + " #{channel[:key]}"
end
end
# look for urls in public channels, grab only the first one per line
on :channel, /(http[s]*:\/\/\S+)/ do
url = match[0]
shorten channel, url
end
# get urls from private messages, grab only the first one per line
on :private, /(http[s]*:\/\/\S+)/ do
url = match[0]
shorten nick, url
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment