Class: Autumn::Daemon

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

Overview

Describes an IRC server daemon program. Different IRC servers run off of different IRC daemons, each of which has a slightly different implementation of the IRC protocol. To encapsulate this, the Daemon class stores the names of some of the more common IRC server types, as well as the unique information about those daemons, such as supported usermodes, response codes, and supported channel types.

An instance of Daemon is an IRC server type. The Daemon class keeps a catalog of all instances, assigning each a descriptive name (for example, “Unreal” for the UnrealIRCd program, a popular IRC server daemon).

A Daemon instance can be queried for information about the IRC server type, as necessary to parse messages from that IRC server.

A “default” daemon will also be created representing a common denominator of IRC features, which is used in situations where a server’s exact type is unknown. This daemon will consist of all non-conflicting entries among the defined daemons.

In addition to the methods and attributes below, you can also call predicate methods such as usermode? and channel_prefix? to test if a character is in a set of known modes/privileges/prefixes, or if a number is in the set of known events.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, info) ⇒ Daemon

Creates a new Daemon instance associated with a given name. You must also pass in the hashes for it to store.



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
# File 'lib/autumn/daemon.rb', line 35

def initialize(name, info)
  if name.nil? and info.nil? then # it's the default hash
    raise "Already created a default Daemon" if self.class.class_variable_defined? :@@default
    @usermode = Hash.parroting
    @privilege = Hash.parroting
    @user_prefix = Hash.parroting
    @channel_prefix = Hash.parroting
    @channel_mode = Hash.parroting
    @server_mode = Hash.parroting
    @event = Hash.parroting
    @default = true
  else
    @usermode = Hash.parroting(info['usermode'])
    @privilege = Hash.parroting(info['privilege'])
    @user_prefix = Hash.parroting(info['user_prefix'])
    @channel_prefix = Hash.parroting(info['channel_prefix'])
    @channel_mode = Hash.parroting(info['channel_mode'])
    @server_mode = Hash.parroting(info['server_mode'])
    @event = Hash.parroting(info['event'])
    @@instances[name] = self

    # Build up our default so it contains all keys with no conflicting
    # values across different server specs. Delete keys from the default
    # hash for which we found duplicates.
    info.each do |hname, hsh|
      next unless @@default.respond_to? hname.to_sym
      default_hash = @@default.send(hname.to_sym)
      
      uniques = hsh.reject { |k, v| default_hash.include? k }
      default_hash.update uniques
      default_hash.reject! { |k, v| hsh.include?(k) and hsh[k] != v }
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ Object

:nodoc:



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/autumn/daemon.rb', line 182

def method_missing(meth, *args) # :nodoc:
  if meth.to_s =~ /^([a-z_]+)\?$/ then
    base = $1
    if (instance_variables.include?("@#{base}") or instance_variables.include?("@#{base}".to_sym)) and args.size == 1 then
      if base.end_with?('_prefix') and args.only.kind_of?(Numeric) then
        arg = args.only.chr
      else
        arg = args.only
      end
      eval "#{base}.include? #{arg.inspect}"
    end
  else
    super
  end
end

Class Method Details

.[](name) ⇒ Object

Returns a Daemon instance by associated name.



72
73
74
# File 'lib/autumn/daemon.rb', line 72

def self.[](name)
  @@instances[name]
end

.defaultObject

Returns the fallback server type.



78
79
80
# File 'lib/autumn/daemon.rb', line 78

def self.default
  @@default
end

.each_nameObject

Yields the name of each Daemon registered with the class.



84
85
86
# File 'lib/autumn/daemon.rb', line 84

def self.each_name
  @@instances.keys.sort.each { |name| yield name }
end

Instance Method Details

#channel_modeObject

Hash of channel mode characters (e.g., m) to their symbol representations (e.g., :moderated).



119
120
121
# File 'lib/autumn/daemon.rb', line 119

def channel_mode
  @default ? @channel_mode : @@default.channel_mode.merge(@channel_mode)
end

#channel_prefixObject

Hash of channel prefixes (e.g., &) to their symbol representations (e.g., :local).



112
113
114
# File 'lib/autumn/daemon.rb', line 112

def channel_prefix
  @default ? @channel_prefix : @@default.channel_prefix.merge(@channel_prefix)
end

#eventObject

Hash of numerical event codes (e.g., 372) to their symbol representations (e.g., :motd).



133
134
135
# File 'lib/autumn/daemon.rb', line 133

def event
  @default ? @event : @@default.event.merge(@event)
end

#inspectObject

:nodoc:



198
199
200
# File 'lib/autumn/daemon.rb', line 198

def inspect # :nodoc:
  "#<#{self.class.to_s} #{@@instances.index self}>"
end

#just_nick(name) ⇒ Object

Given a nick, returns that nick stripped of any privilege characters on the left side.



155
156
157
158
159
160
161
# File 'lib/autumn/daemon.rb', line 155

def just_nick(name)
  nick = name.dup
  while nick_prefixed?(nick)
    nick.slice! 0, 1
  end
  return nick
end

#nick_prefixed?(nick) ⇒ Boolean

Returns true if the first character(s) of a nick are valid privilege prefixes.

Returns:

  • (Boolean)


148
149
150
# File 'lib/autumn/daemon.rb', line 148

def nick_prefixed?(nick)
  user_prefix? nick[0,1]
end

#nick_privilege(name) ⇒ Object

Given a nick, returns the privileges granted to this nick, as indicated by the prefix characters. Returns :unvoiced if no prefix characters are present. Returns an array of privileges if multiple prefix characters are present.



168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/autumn/daemon.rb', line 168

def nick_privilege(name)
  privs = Set.new
  nick = name.dup
  while user_prefix? nick[0,1]
    privs << user_prefix[nick[0,1]]
    nick.slice! 0, 1
  end
  case privs.size
    when 0 then :unvoiced
    when 1 then privs.only
    else privs
  end
end

#privilegeObject

Hash of user privilege characters (e.g., v) to their symbol representations (e.g., :voiced).



98
99
100
# File 'lib/autumn/daemon.rb', line 98

def privilege
  @default ? @privilege : @@default.privilege.merge(@privilege)
end

#privilege_mode?(mode) ⇒ Boolean

Returns true if the mode string (e.g., “+v”) appears to be changing a user privilege as opposed to a channel mode.

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


140
141
142
143
# File 'lib/autumn/daemon.rb', line 140

def privilege_mode?(mode)
  raise ArgumentError, "Invalid mode string '#{mode}'" unless mode =~ /^[\+\-]\S+$/
  mode.except_first.chars.all? { |c| privilege? c }
end

#server_modeObject

Hash of server mode characters (e.g., H) to their symbol representations (e.g., :hidden).



126
127
128
# File 'lib/autumn/daemon.rb', line 126

def server_mode
  @default ? @server_mode : @@default.server_mode.merge(@server_mode)
end

#user_prefixObject

Hash of user privilege prefixes (e.g., @) to their symbol representations (e.g., :operator).



105
106
107
# File 'lib/autumn/daemon.rb', line 105

def user_prefix
  @default ? @user_prefix : @@default.user_prefix.merge(@user_prefix)
end

#usermodeObject

Hash of usermode characters (e.g., i) to their symbol representations (e.g., :invisible).



91
92
93
# File 'lib/autumn/daemon.rb', line 91

def usermode
  @default ? @usermode : @@default.usermode.merge(@usermode)
end