Created
July 14, 2010 07:23
-
-
Save meh/475141 to your computer and use it in GitHub Desktop.
lol a bot
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
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/env ruby | |
require 'failirc/client' | |
require 'getoptlong' | |
require 'uri' | |
require 'net/http' | |
require 'timeout' | |
require 'sqlite3' | |
VERSION = '0.2' | |
args = GetoptLong.new( | |
['--version', '-v', GetoptLong::NO_ARGUMENT], | |
['--verbose', '-V', GetoptLong::NO_ARGUMENT], | |
['--config', '-f', GetoptLong::REQUIRED_ARGUMENT], | |
['--database', '-d', GetoptLong::REQUIRED_ARGUMENT], | |
) | |
options = { | |
:verbose => false, | |
:config => '/etc/failbot.conf', | |
} | |
args.each {|option, value| | |
case option | |
when '--version' | |
puts "Fail IRC #{IRC::VERSION}" | |
exit 0 | |
when '--verbose' | |
options[:verbose] = true | |
when '--config' | |
options[:config] = value | |
when '--database' | |
options[:database] = value | |
end | |
} | |
class Database | |
def initialize (path) | |
if !path | |
raise 'No database.' | |
end | |
@db = SQLite3::Database.new(path) | |
@db.results_as_hash = true | |
self.url :init | |
self.quotes :init | |
self.karma :init | |
end | |
def close | |
@db.close | |
end | |
def url (what, *args) | |
self.send "url_#{what}", *args | |
end | |
def url_init | |
@db.execute(%{ | |
CREATE TABLE IF NOT EXISTS urls ( | |
url TEXT UNIQUE, | |
date INTEGER, | |
user TEXT, | |
channel TEXT, | |
server TEXT | |
); | |
}) | |
end | |
def url_insert (url, date, user, channel, server) | |
@db.execute('INSERT OR IGNORE INTO urls VALUES(?, ?, ?, ?, ?)', [url, date, user, channel, server]) | |
end | |
def url_get (channel, query, *objects) | |
if objects.last.is_a?(Range) | |
range = objects.pop | |
end | |
if query.is_a?(Range) | |
@db.execute("SELECT * FROM urls WHERE server = ? AND channel = ? LIMIT #{query.end - query.begin} OFFSET #{query.begin}", [channel.server.to_s, channel.to_s]) | |
elsif query.is_a?(Fixnum) | |
@db.execute('SELECT WHERE server = ? AND channel = ?', [channel.server.to_s, channel.to_s]) | |
else | |
@db.execute("SELECT * FROM urls WHERE #{query} AND server = ? AND channel = ?", objects.concat([channel.server.to_s, channel.to_s])) | |
end | |
end | |
def url_all | |
@db.execute('SELECT * FROM urls') | |
end | |
def url_length | |
@db.execute('SELECT COUNT(*) AS length FROM urls').shift['length'] | |
end | |
def quotes (what, *args) | |
self.send "quotes_#{what}", *args | |
end | |
def quotes_init | |
@db.execute(%{ | |
CREATE TABLE IF NOT EXISTS quotes ( | |
id INTEGER PRIMARY KEY AUTOINCREMENT, | |
quote TEXT, | |
date INTEGER, | |
user TEXT, | |
channel TEXT, | |
server TEXT | |
); | |
}) | |
end | |
def quotes_insert (quote, date, user, channel, server) | |
@db.execute('INSERT INTO quotes VALUES(NULL, ?, ?, ?, ?, ?)', [quote, date, user, channel, server]) | |
end | |
def quotes_get (what, *stuff) | |
if what.is_a?(Symbol) | |
case what | |
when :random | |
@db.execute('SELECT * FROM quotes ORDER BY RANDOM() LIMIT 1').shift | |
end | |
else | |
query = '' | |
objects = [] | |
stuff.each {|string| | |
query << "quote LIKE ?" | |
objects << "%#{string}%" | |
} | |
@db.execute("SELECT * FROM quotes WHERE #{query}", objects) | |
end | |
end | |
def karma (what, *args) | |
self.send "karma_#{what}", *args | |
end | |
def karma_init | |
@db.execute(%{ | |
CREATE TABLE IF NOT EXISTS karma ( | |
name TEXT PRIMARY KEY UNIQUE, | |
value INTEGER DEFAULT 0 | |
); | |
}) | |
end | |
def karma_set (name, what) | |
name.strip! | |
@db.execute('INSERT OR IGNORE INTO karma VALUES(?, 0)', name) | |
if what.is_a?(String) | |
if what == '++' | |
@db.execute('UPDATE karma SET value = value + 1 WHERE name LIKE ?', name) | |
elsif what == '--' | |
@db.execute('UPDATE karma SET value = value - 1 WHERE name LIKE ?', name) | |
end | |
else | |
@db.execute('UPDATE karma SET value = ? WHERE name LIKE ?', [what, name]) | |
end | |
end | |
def karma_get (name) | |
@db.execute('SELECT * FROM karma WHERE name LIKE ?', name).shift | |
end | |
end | |
$client = IRC::Client.new(File.new(options[:config]), options[:verbose]) | |
if tmp = $client.config.elements['config/informations/database'] | |
options[:database] = tmp.text | |
end | |
$db = Database.new(options[:database]) | |
$authorized = Hash.new | |
def stop (client) | |
client.stop | |
$db.close | |
Process.exit!(0) | |
end | |
trap('INT') { stop $client } | |
trap('KILL') { stop $client } | |
module Commands | |
def self.version (server, from, to, string) | |
version = "lulzBot-\x02#{VERSION}\x02 [failirc-#{IRC::VERSION}]" | |
if to.is_a?(IRC::Client::Channel) | |
$client.fire :message, server, :output, $client, to, version | |
else | |
$client.fire :message, server, :output, $client, from, version | |
end | |
end | |
def self.auth (server, from, to, string) | |
if string == $client.config.elements['config/informations/password'].text | |
$authorized[from] = true | |
end | |
end | |
def self.quit (server, from, to, string) | |
if !$authorized[from] | |
return | |
end | |
$client.servers.each_value {|server| | |
$client.fire :quit, server, string | |
} | |
self.debug 'Quitting...' | |
while true | |
if $client.servers.empty? | |
Process.exit!(0) | |
end | |
sleep 0.1 | |
end | |
end | |
def self.raw (server, from, to, string) | |
if !$authorized[from] | |
return | |
end | |
server.send :raw, string | |
end | |
def self.urls (server, from, to, string) | |
if !to.is_a?(IRC::Client::Channel) | |
to = from | |
end | |
if string.empty? | |
if string.empty? | |
$client.fire :message, server, :output, $client, to, "I've got \x02#{$db.url :length}\x02 URLs." | |
else | |
end | |
else | |
end | |
# $urls.each_value {|url| | |
# $client.fire :message, server, :output, $client, to, "[#{url[:at]}] #{url[:uri]} { #{url[:from]} }" | |
# } | |
end | |
def self.quotes (server, from, to, string) | |
matches = string.match(/^([^ ]+)(\s+(.+))?$/) | |
if !matches | |
quote = $db.quotes :get, :random | |
$client.fire :message, server, :output, $client, to, "\002#{quote['id']}\002. #{quote['quote']}" | |
return | |
end | |
command = matches[1].to_sym | |
value = matches[3] | |
case command | |
when :add | |
$db.quotes :insert, value, Time.new.to_i, from.mask.to_s, to.to_s, server.to_s | |
end | |
end | |
def self.karma (server, from, to, string) | |
matches = string.match(/^([^ ]+)(\s+(.+))?$/) | |
if !matches | |
return | |
end | |
command = matches[1].to_sym | |
value = matches[3] | |
case command | |
when :get | |
karma = $db.karma :get, value | |
$client.fire :message, server, :output, $client, to, "\x02#{karma['name']}\x02 == \x1F#{karma['value']}\x1F" | |
end | |
end | |
def self.regexp (server, from, to, string) | |
matches = string.match(%r{"(([^"\\]|\\.)*?)"\s+(((m)?/(([^/\\]|\\.)*?)/(.*?))|((s)/(([^/\\]|\\.)*?)/(([^/\\]|\\.)*?)/(.*)))$}) | |
if !matches | |
$client.fire :message, server, :output, $client, to, "#{from.nick}, wat" | |
return | |
end | |
string = matches[1] | |
type = matches[5] || matches[10] || 'm' | |
regexp = matches[6] || matches[11] | |
mode = matches[8] || matches[15] | |
into = matches[13] || '' | |
regexp = Regexp.new(regexp, mode) | |
if mode.include?('g') | |
if type == 'm' | |
result = string.scan(regexp) | |
else | |
result = string.gsub(regexp, into) | |
end | |
else | |
if type == 'm' | |
result = string.match(regexp) | |
else | |
result = string.sub(regexp, into) | |
end | |
end | |
if type == 's' | |
$client.fire :message, server, :output, $client, to, result | |
else | |
do_shit = lambda {|result| | |
if !result.is_a?(Array) | |
result = result.to_a | |
end | |
text = "\x1F#{result.shift}\x1F: " | |
result.each {|match| | |
text << "\x1F#{match}\x1F, " | |
} | |
$client.fire :message, server, :output, $client, to, text[0, text.length - 2] | |
} | |
if mode.include?('g') | |
result.each {|result| | |
do_shit.call result | |
} | |
else | |
do_shit.call result | |
end | |
end | |
end | |
end | |
def add_urls (message, from, to, server) | |
URI.extract(message).each {|uri| | |
if !uri.match(%r{\w+://}) | |
next | |
end | |
if match = uri.match('http://tinyurl.com/(.+)$') | |
uri = timeout 5 do | |
Net::HTTP.get(URI.parse("http://preview.tinyurl.com/#{match[1]}")) | |
end rescue next | |
if match = uri.match(/redirecturl" href="(.+?)"/) | |
uri = URI.decode(match[1]) | |
else | |
next | |
end | |
end | |
if to.is_a?(IRC::Client::Channel) | |
$db.url :insert, uri, Time.new.to_i, from.to_s, to.to_s, server.to_s | |
end | |
} | |
end | |
# check for connection | |
$client.observe :connected, lambda {|server| | |
$client.config.elements.each('config/misc/channels/channel') {|channel| | |
$client.fire :join, server, channel.text | |
} | |
} | |
# fetch URLs | |
$client.observe :message, lambda {|server, chain, from, to, message| | |
if chain != :input | |
return | |
end | |
add_urls(message, from, to, server) | |
} | |
$client.observe :topic_change, lambda {|server, old, topic| | |
add_urls(topic.text, topic.setBy, topic.channel, server) | |
} | |
# get karma | |
$client.observe :message, lambda {|server, chain, from, to, message| | |
if chain != :input | |
return | |
end | |
if !to.is_a?(IRC::Client::Channel) | |
return | |
end | |
if matches = message.match(/^([^\+\-]+)(\+\+|\-\-)$/) | |
if matches[1] == from.nick && matches[2] == '++' | |
$client.fire :message, server, :output, $client, to, "#{from.nick}, do you think I don't see what you did there?" | |
else | |
$db.karma :set, matches[1], matches[2] | |
end | |
end | |
} | |
# fix shit | |
$client.observe :message, lambda {|server, chain, from, to, message| | |
if chain != :input | |
return | |
end | |
if $__last && matches = message.match(%r{^(s|tr)/(([^/\\]|\\.)*?)/(([^/\\]|\\.)*?)/(.*)$}) | |
type = matches[1] | |
regexp = matches[2] | |
into = matches[4] | |
mode = matches[6] | |
if type == 's' | |
regexp = Regexp.new(regexp, mode) | |
if mode.include?('g') | |
result = $__last[1].gsub(regexp, into) | |
else | |
result = $__last[1].sub(regexp, into) | |
end | |
else | |
result = $__last[1].tr(regexp, into) | |
end | |
$client.fire :message, server, :output, $client, to, "<#{$__last[0].nick}> #{result} <-- fix'd" | |
else | |
$__last = [from, message] | |
end | |
} | |
# dispatch commands | |
$client.observe :message, lambda {|server, chain, from, to, message| | |
if chain != :input | |
return | |
end | |
if match = message.match(/^~([^ ]+)(\s+(.*))?$/) | |
begin | |
if command = Commands.method(match[1].to_sym) | |
command.call(server, from, to, match[3] || '') | |
end | |
rescue Exception => e | |
self.debug e | |
end | |
end | |
} | |
$client.observe :parted, lambda {|server, user, channel| | |
$authorized.delete(user) | |
} | |
$client.start |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment