Class: Isaac::Application

Inherits:
Object
  • Object
show all
Defined in:
lib/isaac.rb

Overview

These are top level methods you use to construct your bot.

Instance Method Summary collapse

Constructor Details

#initializeApplication

:nodoc:



33
34
35
36
# File 'lib/isaac.rb', line 33

def initialize #:nodoc:
  @events = Hash.new {|k,v| k[v] = []}
  @registration = []
end

Instance Method Details

#config(&block) ⇒ Object

Configure the bot:

defaults to the 'default' or first network

config do |c|
  c.server      = "irc.freenode.net"
  c.nick        = "AwesomeBot"
  c.port        = 6667
  c.realname    = "James Dean"
  c.username    = "jdean"
  c.version     = "James Dean Bot v2.34"
  c.verbose     = true
  c.server_pass = "secrets_for_server_connections"
  c.nick_pass   = "secrets_for_nickserv"
end

config("mynet") do |c|
  c.server      = "irc.example.com"
  c.port        = 6667
  c.nick        = "larry"
end

Can also be used as an accessor to configuration:

config.nick          => "AwesomeBot"
config("mynet").nick => "larry"


75
76
77
78
79
# File 'lib/isaac.rb', line 75

def config(&block)
  Config::Data.load unless Config.loaded?
  block.call(Config) if block_given?
  Config
end

#connectObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/isaac.rb', line 132

def connect
  begin
    unless have_required_config?
      msg = "Required configuration data is missing: #{required_config.delete_if {|c| !config[c].nil? }.join(', ')}\n"
      msg += "you need to either add them to your config.yml or in a config block, eg:\n"
      msg +=<<-CODE
        config do |c|
          c.nick      = 'foo'
          c.server    = 'irc.example.com'
          c.port      = 6667
          c.username  = 'foo'
          c.realname  = 'foo'
        end
      CODE
      puts msg
      logger.error msg
      exit
    end
    logger.info "Connecting to #{config.server} at port #{config.port}"
    @irc = TCPSocket.open(config.server, config.port)
    logger.info "Connection established."

    @irc.puts "PASS #{config.server_pass}" if config.server_pass
    @irc.puts "NICK #{config.nick}"
    @irc.puts "USER #{config.username} foobar foobar :#{config.realname}"

    @queue = Queue.new(@irc)
    @queue << @events[:connect].first.invoke if @events[:connect].first

    while line = @irc.gets
      handle line
    end
  rescue Interrupt => e
    logger.info "Disconnected! An error occurred: #{e.inspect}"
  #rescue Timeout::Error => e
  #  puts "Timeout: #{e}. Reconnecting."
  #  connect
  end
end

#event(type, matcher) ⇒ Object



116
117
118
119
120
# File 'lib/isaac.rb', line 116

def event(type, matcher)
  @events[type].detect do |e| 
    type == :error ? matcher == e.match : matcher =~ e.match
  end
end

#execute(params = {}, &block) ⇒ Object

:nodoc:



111
112
113
114
# File 'lib/isaac.rb', line 111

def execute(params={}, &block) #:nodoc:
  event = Event.new(:dsl, block)
  @queue << event.invoke(params)
end

#handle(line) ⇒ Object

This is one hell of a nasty method. Something should be done, I suppose.



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/isaac.rb', line 178

def handle(line)
  logger.info "> #{line}" if config.verbose

  case line
  when /^:(\S+)!\S+ PRIVMSG \S+ :?\001VERSION\001/
    @queue << "NOTICE #{$1} :\001VERSION #{config.version}\001"
  when /^:(\S+)!(\S+) PRIVMSG (\S+) :?(.*)/
    nick, userhost, channel, message = $1, $2, $3, $4
    type = channel.match(/^#/) ? :channel : :private
    if event = event(type, message)
      @queue << event.invoke(:nick => nick, :userhost => userhost, :channel => channel, :message => message)
    end
  when /^:\S+ 00([1-4])/
    @registration << $1.to_i
    @queue.lock = false if registered?
  when /^:\S+ ([4-5]\d\d) \S+ (\S+)/
    error = $1
    nick = channel = $2
    if event = event(:error, error.to_i)
      @queue << event.invoke(:nick => nick, :channel => channel)
    end
  when /^PING (\S+)/
    #TODO not sure this is correct. Damned RFC.
    @queue << "PONG #{$1}" 
  when /^:\S+ PONG \S+ :excess/
    @queue.lock = false
  end
end

#have_required_config?Boolean

Returns:

  • (Boolean)


126
127
128
129
130
# File 'lib/isaac.rb', line 126

def have_required_config?
  required_config.all? do |r|
    !config[r].nil?
  end
end

#helpers(&block) ⇒ Object

Methods defined inside the helpers-block will be available to on()-events at execution time.



82
83
84
# File 'lib/isaac.rb', line 82

def helpers(&block)
  EventContext.class_eval(&block)
end

#loggerObject



38
39
40
# File 'lib/isaac.rb', line 38

def logger
  Isaac.logger
end

#on(type, match = nil, &block) ⇒ Object

on()-events responds to certain actions. Depending on type certain local variables are available: nick, channel, message and in particular match, which contains a MatchData object returned by the given regular expression.

  • Do something after connection has been established, e.g. join channels.

    on :connect do
      join "#awesome_channel", "#lee_marvin_fans"
    end
    
  • Respond to private messages matching a given regular expression.

    on :private, /^echo (.*)/ do
      msg nick, "You said '#{match[1]}!"
    end
    
  • Respond to messages matching a given regular expression send to a channel.

    on :channel, /quote/ do
      msg channel, "#{nick} requested a quote: 'Smoking, a subtle form a suicide.' - Vonnegut"
    end
    
  • Respond to error codes, according to the RFC.

    on :error, 401 do
      # Execute this if you try to send a message to a non-existing nick/channel.
    end
    


106
107
108
109
# File 'lib/isaac.rb', line 106

def on(type, match=nil, &block)
  @events[type] << e = Event.new(match, block)
  return e
end

#registered?Boolean

Returns:

  • (Boolean)


172
173
174
175
# File 'lib/isaac.rb', line 172

def registered?
  arr = [1,2,3,4] - @registration 
  arr.empty?
end

#required_configObject



122
123
124
# File 'lib/isaac.rb', line 122

def required_config
  %w(nick server port username realname)
end

#startObject

This is plain stupid. Might be useful for logging or something later on.



43
44
45
46
47
48
# File 'lib/isaac.rb', line 43

def start #:nodoc:
   
  logger.info " ==== Starting Isaac v#{Isaac::VERSION} ==== "
  connect
  logger.info " ====  Ending Isaac  ==== "
end