#!/usr/bin/env ruby require 'socket' require 'open3' # configurable environment variables nick = ENV['OUR_NICK'] || 'our' channels = ENV['OUR_CHANNELS'] || '#tildetown,#bots' prefix = ENV['OUR_PREFIX'] || "#{nick}/" cmds_dir = ENV['OUR_CMDS_DIR'] || '/town/our' module IRC class User attr_accessor :s def initialize addr, port, nick @hooks = [] @s = TCPSocket.open addr, port.to_s s.puts "USER #{nick} fakehost whatevenisaservername :beep boop" s.puts "NICK #{nick}" hook do |m| next unless m.cmd == 'PING' raw "PING #{nick}" end end def raw msg @s.puts msg end def join chan raw "JOIN #{chan}" end def privmsg target, msg raw "PRIVMSG #{target} :#{msg}" end def hook &h @hooks << h end def loop while line = s.gets msg = Message.new line @hooks.each{|h| h.call(msg)} end end end class Message attr_accessor :prefix, :cmd, :args, :raw # TODO custom constructor def initialize msg msg = msg.delete_suffix "\r\n" @raw = msg @prefix = nil @prefix, msg = msg[1..].split(' ', 2) if msg[0] == ':' @cmd, msg = msg.split(' ', 2) @args = [] while msg and not msg.empty? if msg[0] == ':' @args << msg[1..] break end s, msg = msg.split(' ', 2) @args << s end end end end puts "starting" i = IRC::User.new 'localhost', 6667, nick channels.split(',').each { |channel| i.join channel } i.hook do |msg| next unless msg.cmd == 'PRIVMSG' target, content = msg.args next unless content.delete_prefix! prefix cmd, args = content.split(' ', 2) cmd = "#{cmds_dir}/#{cmd}" args ||= '' next unless File.exists? cmd if not File.executable? cmd i.privmsg target, "#{cmd} isn't executable. try chmod +x" next end begin # child = IO.popen [cmd, args, msg.prefix, target] # out = child.gets # child.close Open3.popen2e(cmd, args, msg.prefix, target) {|_, stdout, _| out = stdout.gets i.privmsg target, out if out } rescue Exception => e i.privmsg target, "[our.rb] #{e.to_s}" end next true end i.loop