Class: Ponder::Thaum

Inherits:
Object
  • Object
show all
Includes:
AsyncIRC::Delegate, IRC
Defined in:
lib/ponder/thaum.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from AsyncIRC::Delegate

#channel_info, #get_topic, #whois

Methods included from IRC

#action, #away, #back, #ban, #invite, #join, #kick, #message, #mode, #notice, #part, #quit, #raw, #register, #rename, #topic

Constructor Details

#initialize(&block) ⇒ Thaum

Returns a new instance of Thaum.



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
# File 'lib/ponder/thaum.rb', line 21

def initialize(&block)
  # default settings
  @config = OpenStruct.new(
    :server             => 'localhost',
    :port               => 6667,
    :nick               => 'Ponder',
    :username           => 'Ponder',
    :real_name          => 'Ponder',
    :verbose            => true,
    :logging            => false,
    :reconnect          => true,
    :reconnect_interval => 30
  )

  # custom settings
  block.call(@config) if block_given?

  # setting up loggers
  @console_logger = if @config.verbose
    Logger::Twoflogger.new($stdout)
  else
    Logger::BlindIo.new
  end

  @logger = if @config.logging
    if @config.logger
      @config.logger
    else
      log_path = File.join(ROOT, 'logs', 'log.log')
      log_dir = File.dirname(log_path)
      FileUtils.mkdir_p(log_dir) unless File.exist?(log_dir)
      Logger::Twoflogger.new(log_path, File::WRONLY | File::APPEND)
    end
  else
    Logger::BlindIo.new
  end

  # when using methods like #get_topic or #whois, a Deferrable object will wait
  # for the response and call a callback. these Deferrables are stored in this Set
  @deferrables = Set.new

  @connected = false

  # user callbacks
  @callbacks = Hash.new { |hash, key| hash[key] = [] }

  # standard callbacks for PING, VERSION, TIME and Nickname is already in use
  on :query, /^\001PING \d+\001$/ do |event_data|
    time = event_data[:message].scan(/\d+/)[0]
    notice event_data[:nick], "\001PING #{time}\001"
  end

  on :query, /^\001VERSION\001$/ do |event_data|
    notice event_data[:nick], "\001VERSION Ponder #{Ponder::VERSION} (https://github.com/tbuehlmann/ponder)\001"
  end

  on :query, /^\001TIME\001$/ do |event_data|
    notice event_data[:nick], "\001TIME #{Time.now.strftime('%a %b %d %H:%M:%S %Y')}\001"
  end

  # before and after filter
  @before_filters = Hash.new { |hash, key| hash[key] = [] }
  @after_filters = Hash.new { |hash, key| hash[key] = [] }
end

Instance Attribute Details

#callbacksObject (readonly)

Returns the value of attribute callbacks.



18
19
20
# File 'lib/ponder/thaum.rb', line 18

def callbacks
  @callbacks
end

#configObject (readonly)

Returns the value of attribute config.



18
19
20
# File 'lib/ponder/thaum.rb', line 18

def config
  @config
end

#connectedObject

Returns the value of attribute connected.



19
20
21
# File 'lib/ponder/thaum.rb', line 19

def connected
  @connected
end

#console_loggerObject

Returns the value of attribute console_logger.



19
20
21
# File 'lib/ponder/thaum.rb', line 19

def console_logger
  @console_logger
end

#deferrablesObject

Returns the value of attribute deferrables.



19
20
21
# File 'lib/ponder/thaum.rb', line 19

def deferrables
  @deferrables
end

#loggerObject

Returns the value of attribute logger.



19
20
21
# File 'lib/ponder/thaum.rb', line 19

def logger
  @logger
end

Instance Method Details

#after_filter(event_types = :all, match = //, &block) ⇒ Object



199
200
201
# File 'lib/ponder/thaum.rb', line 199

def after_filter(event_types = :all, match = //, &block)
  filter(@after_filters, event_types, match, block)
end

#before_filter(event_types = :all, match = //, &block) ⇒ Object



195
196
197
# File 'lib/ponder/thaum.rb', line 195

def before_filter(event_types = :all, match = //, &block)
  filter(@before_filters, event_types, match, block)
end

#connectObject



101
102
103
104
105
106
107
108
# File 'lib/ponder/thaum.rb', line 101

def connect
  @logger.info '-- Starting Ponder'
  @console_logger.info '-- Starting Ponder'

  EventMachine::run do
    @connection = EventMachine::connect(@config.server, @config.port, Connection, self)
  end
end

#on(event_types = [:channel], match = //, *options, &block) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ponder/thaum.rb', line 86

def on(event_types = [:channel], match = //, *options, &block)
  options = options.extract_options!

  if event_types.is_a?(Array)
    callbacks = event_types.map { |event_type| Callback.new(event_type, match, options, block) }
  else
    callbacks = [Callback.new(event_types, match, options, block)]
    event_types = [event_types]
  end

  callbacks.each_with_index do |callback, index|
    @callbacks[event_types[index]] << callback
  end
end

#parse(message) ⇒ Object

parsing incoming traffic



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
144
145
146
147
148
149
150
151
# File 'lib/ponder/thaum.rb', line 111

def parse(message)
  message.chomp!
  @logger.info "<< #{message}"
  @console_logger.info "<< #{message}"

  case message
  when /^PING \S+$/
    raw message.sub(/PING/, 'PONG')

  when /^(?:\:\S+ )?(\d\d\d) /
    number = $1.to_i
    parse_event(number, :type => number, :params => $')

  when /^:(\S+)!(\S+)@(\S+) PRIVMSG #(\S+) :/
    parse_event(:channel, :type => :channel, :nick => $1, :user => $2, :host => $3, :channel => "##{$4}", :message => $')

  when /^:(\S+)!(\S+)@(\S+) PRIVMSG \S+ :/
    parse_event(:query, :type => :query, :nick => $1, :user => $2, :host => $3, :message => $')

  when /^:(\S+)!(\S+)@(\S+) JOIN :*(\S+)$/
    parse_event(:join, :type => :join, :nick => $1, :user => $2, :host => $3, :channel => $4)

  when /^:(\S+)!(\S+)@(\S+) PART (\S+)/
    parse_event(:part, :type => :part, :nick => $1, :user => $2, :host => $3, :channel => $4, :message => $'.sub(/ :/, ''))

  when /^:(\S+)!(\S+)@(\S+) QUIT/
    parse_event(:quit, :type => :quit, :nick => $1, :user => $2, :host => $3, :message => $'.sub(/ :/, ''))

  when /^:(\S+)!(\S+)@(\S+) NICK :/
    parse_event(:nickchange, :type => :nickchange, :nick => $1, :user => $2, :host => $3, :new_nick => $')

  when /^:(\S+)!(\S+)@(\S+) KICK (\S+) (\S+) :/
    parse_event(:kick, :type => :kick, :nick => $1, :user => $2, :host => $3, :channel => $4, :victim => $5, :reason => $')

  when /^:(\S+)!(\S+)@(\S+) TOPIC (\S+) :/
    parse_event(:topic, :type => :topic, :nick => $1, :user => $2, :host => $3, :channel => $4, :topic => $')
  end

  # if there are pending deferrabels, check if the message suits their matching pattern
  @deferrables.each { |d| d.try(message) }
end

#process_callbacks(event_type, event_data) ⇒ Object

process callbacks with its begin; rescue; end



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/ponder/thaum.rb', line 154

def process_callbacks(event_type, event_data)
  @callbacks[event_type].each do |callback|
    # process chain of before_filters, callback handling and after_filters
    process = proc do
      begin
        stop_running = false

        # before filters (specific filters first, then :all)
        (@before_filters[event_type] + @before_filters[:all]).each do |filter|
          if filter.call(event_type, event_data) == false
            stop_running = true
            break
          end
        end

        unless stop_running
          # handling
          callback.call(event_type, event_data)

          # after filters (specific filters first, then :all)
          (@after_filters[event_type] + @after_filters[:all]).each do |filter|
            filter.call(event_type, event_data)
          end
        end
      rescue => e
        [@logger, @console_logger].each do |logger|
          logger.error("-- #{e.class}: #{e.message}")
          e.backtrace.each { |line| logger.error("-- #{line}") }
        end
      end
    end

    # defer the whole process
    if callback.options[:defer]
      EM.defer(process)
    else
      process.call
    end
  end
end