public
Rubygem
Description: irccat is like `cat`, but here, the STDOUT is an IRC channel.
Homepage: http://irccat.rubyforge.org/
Clone URL: git://github.com/webs/irccat.git
Search Repo:
Click here to lend your support to: irccat and make a donation at www.pledgie.com !
commit  d92e4ed56832bc138d56854109947340fe90dcfc
tree    c0925b2e5a52a0c2084120003bf59c3599d2e6dc
parent  84d4b0d3b127fb8a9bdb091256b0828e68093bb2
irccat / lib / irc_cat / bot.rb
100644 143 lines (115 sloc) 2.932 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# This is the bot.
# Original code by Madx (yapok.org)
class H < HashWithIndifferentAccess; end;
 
module IrcCat
# The IRC bot
class Bot
 
  attr_accessor :socket, :host, :port, :nick, :channel, :nick_pass, :channel_pass
  
  # Initialize the bot with default values
  def initialize(constructor = H.new)
    @realname = "irc_cat #{IrcCat::VERSION::STRING} - http://irccat.rubyforge.org/"
    @refresh_rate = 10
    
    constructor.each do |key, val|
      if val.is_a?(String)
        instance_eval("@#{key} = '#{val}'")
      elsif val.is_a?(Array)
        instance_eval("@#{key} = []")
        val.each do |v| instance_eval("@#{key}.push('#{v}')") end
      end
    end
    puts "Connecting to IRC #{@host}:#{@port} #{@channel}"
  end
  
  def run
    @socket = TCPSocket.open(@host, @port)
    login
    
    trap(:INT) {
      puts "Bye bye."
      self.sexit('God^WConsole killed me')
      sleep 1
      @socket.close
      exit
    }
 
    
    threads=[]
    
    threads << Thread.new {
      begin
        while line = @socket.gets do
          # Remove all formatting
          line.gsub!(/[\x02\x1f\x16\x0f]/,'')
          # Remove CTCP ASCII
          line.gsub!(/\001/,'')
          # Send to event handler
          handle line
          # Handle Pings from Server
          sendln "PONG #{$1}" if /^PING\s(.*)/ =~ line
        end
      rescue EOFError
        err 'Server Reset Connection'
      rescue Exception => e
        err e
      end
    }
    threads << Thread.new {
    }
    threads.each { |th| th.join }
    
    
  end
  
  # Announces states
  def announce(msg)
    @channels.each do |channel|
      say(channel, msg)
    end
  end
  
  # Say something funkeh
  def say(chan,msg)
    sendln "PRIVMSG #{chan} :#{msg}"
  end
  
  # Send EXIT
  def sexit(message='quit')
    sendln("QUIT :#{message}")
  end
  
  private
  
  # Sends a message to the server
  
  def sendln(cmd)
    if cmd.size <= 510
      @socket.write("#{cmd}\r\n")
      STDOUT.flush
    else
    end
  end
  
  # Handle a received message
  
  def handle(line)
    if line =~ /^:.+\s376/
      join_channels
    elsif line =~ /^:.+KICK #([^\s]+)/
      auto_rejoin($1)
    end
  end
  
  # Automatic events
  
  def join_channels
    sendln "JOIN #{@channel} #{@channel_pass}"
  end
  
  
  def auto_rejoin(channel)
    sendln "JOIN ##{channel} #{@channel_pass}"
  end
  
  def login
    begin
      #user = @mail.split("@")
      sendln "NICK #{@nick}"
      sendln "USER irc_cat . . :#{@realname}"
      if @nick_pass
        puts "logging in to NickServ"
        sendln "PRIVMSG NICKSERV :identify #{@nick_pass}"
      end
    rescue Exception => e
      err e
    end
  end
  
  # Loggin methods
  
  def log(str)
    $stdout.puts "DEBUG: #{str}"
  end
  
  def err(exception)
    $stderr.puts "ERROR: #{exception}"
    $stderr.puts "TRACE: #{exception.backtrace}"
  end
  
end
end