Class: Irc::Bot::MessageTemplate

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

Overview

MessageTemplate is the class that holds the actual message template map()‘d by a BotModule and handled by a MessageMapper

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(botmodule, template, hash = {}) ⇒ MessageTemplate

call-seq: initialize(botmodule, template, opts={})

Create a new MessageTemplate associated to BotModule botmodule, with template template and options opts

Raises:

  • (ArgumentError)


360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
# File 'lib/rbot/messagemapper.rb', line 360

def initialize(botmodule, template, hash={})
  raise ArgumentError, "Third argument must be a hash!" unless hash.kind_of?(Hash)
  @defaults = hash[:defaults].kind_of?(Hash) ? hash.delete(:defaults) : {}
  @requirements = hash[:requirements].kind_of?(Hash) ? hash.delete(:requirements) : {}
  @template = template
  case botmodule
  when String
    @botmodule = botmodule
  when Plugins::BotModule
    @botmodule = botmodule.name
  else
    raise ArgumentError, "#{botmodule.inspect} is not a botmodule nor a botmodule name"
  end

  self.items = template
  # @dyn_items is an array of MessageParameters, except for the first entry
  # which is the template
  @dyn_items = @items.collect { |it|
    if it.kind_of?(Symbol)
      i = it.to_s
      opt = MessageParameter.new(i)
      if i.sub!(/^\*/,"")
        opt.name = i
        opt.multi = true
      end
      opt.default = @defaults[opt.name]
      opt.collector = @requirements[opt.name]
      opt
    else
      nil
    end
  }
  @dyn_items.unshift(template).compact!
  debug "Items: #{@items.inspect}; dyn items: #{@dyn_items.inspect}"

  self.regexp = template
  debug "Command #{template.inspect} in #{@botmodule} will match using #{@regexp}"

  set_auth_path(hash)

  unless hash.has_key?(:action)
    hash[:action] = items[0]
  end

  @options = hash

  # debug "Create template #{self.inspect}"
end

Instance Attribute Details

#botmoduleObject (readonly)

the BotModule that map()‘d this MessageTemplate



353
354
355
# File 'lib/rbot/messagemapper.rb', line 353

def botmodule
  @botmodule
end

#defaultsObject (readonly)

the defaults hash



348
349
350
# File 'lib/rbot/messagemapper.rb', line 348

def defaults
  @defaults
end

#itemsObject

the collection of dynamic and static items in the template



351
352
353
# File 'lib/rbot/messagemapper.rb', line 351

def items
  @items
end

#optionsObject (readonly)

the options hash



349
350
351
# File 'lib/rbot/messagemapper.rb', line 349

def options
  @options
end

#regexpObject

the Regexp corresponding to the template



352
353
354
# File 'lib/rbot/messagemapper.rb', line 352

def regexp
  @regexp
end

#templateObject (readonly)

the actual template string



350
351
352
# File 'lib/rbot/messagemapper.rb', line 350

def template
  @template
end

Instance Method Details

#inspectObject



593
594
595
596
597
# File 'lib/rbot/messagemapper.rb', line 593

def inspect
  when_str = @requirements.empty? ? "" : " when #{@requirements.inspect}"
  default_str = @defaults.empty? ? "" : " || #{@defaults.inspect}"
  "<#{self.class.to_s} #{@items.map { |c| c.inspect }.join(' ').inspect}#{default_str}#{when_str}>"
end

#recognize(m) ⇒ Object

Recognize the provided string components, returning a hash of recognized values, or [nil, reason] if the string isn’t recognized.



528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
# File 'lib/rbot/messagemapper.rb', line 528

def recognize(m)

  debug "Testing #{m.message.inspect} against #{self.inspect}"

  # Early out
  return nil, "template #{@template} is not configured for private messages" if @options.has_key?(:private) && !@options[:private] && m.private?
  return nil, "template #{@template} is not configured for public messages" if @options.has_key?(:public) && !@options[:public] && !m.private?

  options = {}

  matching = @regexp.match(m.message)
  return nil, "#{m.message.inspect} doesn't match #{@template} (#{@regexp})" unless matching
  return nil, "#{m.message.inspect} only matches #{@template} (#{@regexp}) partially: #{matching[0].inspect}" unless matching[0] == m.message

  debug_match = matching[1..-1].collect{ |d| d.inspect}.join(', ')
  debug "#{m.message.inspect} matched #{@regexp} with #{debug_match}"
  debug "Associating #{debug_match} with dyn items #{@dyn_items.join(', ')}"

  @dyn_items.each_with_index { |it, i|
    next if i == 0
    item = it.name
    debug "dyn item #{item} (multi-word: #{it.multi?.inspect})"
    if it.multi?
      if matching[i].nil?
        default = it.default
        case default
        when Array
          value = default.clone
        when String
          value = default.strip.split
        when nil, false, []
          value = []
        else
          warning "Unmanageable default #{default} detected for :*#{item.to_s}, using []"
          value = []
        end
        case default
        when String
          value.instance_variable_set(:@string_value, default)
        else
          value.instance_variable_set(:@string_value, value.join(' '))
        end
      else
        value = matching[i].split
        value.instance_variable_set(:@string_value, matching[i])
      end
      def value.to_s
        @string_value
      end
    else
      if matching[i].nil?
        warning "No default value for option #{item.inspect} specified" unless @defaults.has_key?(item)
        value = it.default
      else
        value = it.collect(matching[i])
      end
    end
    options[item] = value
    debug "set #{item} to #{options[item].inspect}"
  }

  options.delete_if {|k, v| v.nil?} # Remove nil values.
  return options, nil
end

#requirements_for(name) ⇒ Object



599
600
601
602
603
604
605
606
607
608
609
610
611
# File 'lib/rbot/messagemapper.rb', line 599

def requirements_for(name)
  name = name.to_s.sub(/^\*/,"").intern if (/^\*/ =~ name.inspect)
  presence = (@defaults.key?(name) && @defaults[name].nil?)
  requirement = case @requirements[name]
    when nil then nil
    when Regexp then "match #{@requirements[name].inspect}"
    else "be equal to #{@requirements[name].inspect}"
  end
  if presence && requirement then "#{name} must be present and #{requirement}"
  elsif presence || requirement then "#{name} must #{requirement || 'be present'}"
  else "#{name} has no requirements"
  end
end

#set_auth_path(hash) ⇒ Object



409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
# File 'lib/rbot/messagemapper.rb', line 409

def set_auth_path(hash)
  if hash.has_key?(:auth)
    warning "Command #{@template.inspect} in #{@botmodule} uses old :auth syntax, please upgrade"
  end
  if hash.has_key?(:full_auth_path)
    warning "Command #{@template.inspect} in #{@botmodule} sets :full_auth_path, please don't do this"
  else
    pre = @botmodule
    words = items.reject{ |x|
      x == pre || x.kind_of?(Symbol) || x =~ /\[|\]/
    }
    if words.empty?
      post = nil
    else
      post = words.first
    end
    if hash.has_key?(:auth_path)
      extra = hash[:auth_path]
      if extra.sub!(/^:/, "")
        pre += "::" + post
        post = nil
      end
      if extra.sub!(/:$/, "")
        if words.length > 1
          post = [post,words[1]].compact.join("::")
        end
      end
      pre = nil if extra.sub!(/^!/, "")
      post = nil if extra.sub!(/!$/, "")
      extra = nil if extra.empty?
    else
      extra = nil
    end
    hash[:full_auth_path] = [pre,extra,post].compact.join("::")
    debug "Command #{@template} in #{botmodule} will use authPath #{hash[:full_auth_path]}"
    # TODO check if the full_auth_path is sane
  end
end