Class: Marvin::AbstractClient
- Inherits:
-
Object
- Object
- Marvin::AbstractClient
- Includes:
- Dispatchable
- Defined in:
- lib/marvin/abstract_client.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#channels ⇒ Object
Returns the value of attribute channels.
-
#disconnect_expected ⇒ Object
Returns the value of attribute disconnect_expected.
-
#nickname ⇒ Object
Returns the value of attribute nickname.
-
#nicks ⇒ Object
Returns the value of attribute nicks.
-
#original_opts ⇒ Object
Returns the value of attribute original_opts.
-
#pass ⇒ Object
Returns the value of attribute pass.
-
#port ⇒ Object
Returns the value of attribute port.
-
#server ⇒ Object
Returns the value of attribute server.
Class Method Summary collapse
-
.configuration=(config) ⇒ Object
Sets the current class-wide settings of this IRC Client to either an OpenStruct or the results of #to_hash on any other value that is passed in.
-
.setup ⇒ Object
Initializes class-wide settings and those that are required such as the logger.
Instance Method Summary collapse
- #action(target, message) ⇒ Object
-
#command(name, *args) ⇒ Object
Sends a specified command to the server.
- #default_channels ⇒ Object
- #default_channels=(channels) ⇒ Object
-
#handle_client_connected(opts = {}) ⇒ Object
The default handler for all things initialization-related on the client.
-
#handle_incoming_numeric(opts = {}) ⇒ Object
TODO: Get the correct mapping for a given Code.
-
#handle_incoming_ping(opts = {}) ⇒ Object
The default response for PING’s - it simply replies with a PONG.
-
#handle_nick_taken ⇒ Object
The default handler for when a users nickname is taken on on the server.
- #handle_welcome ⇒ Object
-
#initialize(opts = {}) ⇒ AbstractClient
constructor
A new instance of AbstractClient.
- #join(channel) ⇒ Object
- #msg(target, message) ⇒ Object
- #nick(new_nick) ⇒ Object
- #part(channel, reason = nil) ⇒ Object
- #pong(data) ⇒ Object
-
#process_connect ⇒ Object
Initializes the instance variables used for the current connection, dispatching a :client_connected event once it has finished.
- #process_disconnect ⇒ Object
- #quit(reason = nil) ⇒ Object
-
#receive_line(line) ⇒ Object
Handling all of the the actual client stuff.
Methods included from Dispatchable
Constructor Details
#initialize(opts = {}) ⇒ AbstractClient
Returns a new instance of AbstractClient.
10 11 12 13 14 15 16 17 |
# File 'lib/marvin/abstract_client.rb', line 10 def initialize(opts = {}) self.original_opts = opts.dup # Copy the options so we can use them to reconnect. self.server = opts[:server] self.port = opts[:port] self.default_channels = opts[:channels] self.nicks = opts[:nicks] || [] self.pass = opts[:pass] end |
Instance Attribute Details
#channels ⇒ Object
Returns the value of attribute channels.
20 21 22 |
# File 'lib/marvin/abstract_client.rb', line 20 def channels @channels end |
#disconnect_expected ⇒ Object
Returns the value of attribute disconnect_expected.
20 21 22 |
# File 'lib/marvin/abstract_client.rb', line 20 def disconnect_expected @disconnect_expected end |
#nickname ⇒ Object
Returns the value of attribute nickname.
20 21 22 |
# File 'lib/marvin/abstract_client.rb', line 20 def nickname @nickname end |
#nicks ⇒ Object
Returns the value of attribute nicks.
20 21 22 |
# File 'lib/marvin/abstract_client.rb', line 20 def nicks @nicks end |
#original_opts ⇒ Object
Returns the value of attribute original_opts.
20 21 22 |
# File 'lib/marvin/abstract_client.rb', line 20 def original_opts @original_opts end |
#pass ⇒ Object
Returns the value of attribute pass.
20 21 22 |
# File 'lib/marvin/abstract_client.rb', line 20 def pass @pass end |
#port ⇒ Object
Returns the value of attribute port.
20 21 22 |
# File 'lib/marvin/abstract_client.rb', line 20 def port @port end |
#server ⇒ Object
Returns the value of attribute server.
20 21 22 |
# File 'lib/marvin/abstract_client.rb', line 20 def server @server end |
Class Method Details
.configuration=(config) ⇒ Object
Sets the current class-wide settings of this IRC Client to either an OpenStruct or the results of #to_hash on any other value that is passed in.
58 59 60 |
# File 'lib/marvin/abstract_client.rb', line 58 def self.configuration=(config) @@configuration = config.is_a?(OpenStruct) ? config : OpenStruct.new(config.to_hash) end |
.setup ⇒ Object
Initializes class-wide settings and those that are required such as the logger. by default, it will convert the channel option of the configuration to be channels - hence normalising it into a format that is more widely used throughout the client.
67 68 69 70 71 72 73 74 75 |
# File 'lib/marvin/abstract_client.rb', line 67 def self.setup return if self.is_setup if configuration.logger.blank? require 'logger' configuration.logger = Marvin::Logger.logger end self.logger = self.configuration.logger self.is_setup = true end |
Instance Method Details
#action(target, message) ⇒ Object
233 234 235 236 237 238 |
# File 'lib/marvin/abstract_client.rb', line 233 def action(target, ) action_text = Marvin::Util.last_param "\01ACTION #{message.strip}\01" command :privmsg, target, action_text dispatch :outgoing_action, :target => target, :message => logger.info "Action sent to #{target} - #{message}" end |
#command(name, *args) ⇒ Object
Sends a specified command to the server. Takes name (e.g. :privmsg) and all of the args. Very simply formats them as a string correctly and calls send_data with the results.
183 184 185 186 187 188 189 |
# File 'lib/marvin/abstract_client.rb', line 183 def command(name, *args) # First, get the appropriate command name = name.to_s.upcase args = args.flatten.compact irc_command = "#{name} #{args.join(" ").strip}\r\n" send_line irc_command end |
#default_channels ⇒ Object
109 110 111 |
# File 'lib/marvin/abstract_client.rb', line 109 def default_channels @default_channels ||= [] end |
#default_channels=(channels) ⇒ Object
113 114 115 |
# File 'lib/marvin/abstract_client.rb', line 113 def default_channels=(channels) @default_channels = channels.to_a.map { |c| c.to_s } end |
#handle_client_connected(opts = {}) ⇒ Object
The default handler for all things initialization-related on the client. Usually, this will send the user command, set out nick, join all of the channels / rooms we wish to be in and if a password is specified in the configuration, it will also attempt to identify us.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/marvin/abstract_client.rb', line 92 def handle_client_connected(opts = {}) logger.info "About to handle client connected" # If the pass is set unless self.pass.blank? logger.info "Sending pass for connection" command :pass, self.pass end # IRC Connection is establish so we send all the required commands to the server. logger.info "Setting default nickname" default_nickname = self.nicks.shift nick default_nickname logger.info "sending user command" command :user, self.configuration.user, "0", "*", Marvin::Util.last_param(self.configuration.name) rescue Exception => e Marvin::ExceptionTracker.log(e) end |
#handle_incoming_numeric(opts = {}) ⇒ Object
TODO: Get the correct mapping for a given Code.
137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/marvin/abstract_client.rb', line 137 def handle_incoming_numeric(opts = {}) case opts[:code] when Marvin::IRC::Replies[:RPL_WELCOME] handle_welcome when Marvin::IRC::Replies[:ERR_NICKNAMEINUSE] handle_nick_taken end code = opts[:code].to_i args = Marvin::Util.arguments(opts[:data]) dispatch :incoming_numeric_processed, :code => code, :data => args end |
#handle_incoming_ping(opts = {}) ⇒ Object
The default response for PING’s - it simply replies with a PONG.
130 131 132 133 |
# File 'lib/marvin/abstract_client.rb', line 130 def handle_incoming_ping(opts = {}) logger.info "Received Incoming Ping - Handling with a PONG" pong(opts[:data]) end |
#handle_nick_taken ⇒ Object
The default handler for when a users nickname is taken on on the server. It will attempt to get the nicknickname from the nicknames part of the configuration (if available) and will then call #nick to change the nickname.
163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/marvin/abstract_client.rb', line 163 def handle_nick_taken logger.info "Nickname '#{self.nickname}' on #{self.server} taken, trying next." logger.info "Available Nicknames: #{self.nicks.empty? ? "None" : self.nicks.join(", ")}" if !self.nicks.empty? logger.info "Getting next nickname to switch" next_nick = self.nicks.shift # Get the next nickname logger.info "Attemping to set nickname to '#{next_nick}'" nick next_nick else logger.fatal "No Nicknames available - QUITTING" quit end end |
#handle_welcome ⇒ Object
149 150 151 152 153 154 155 156 157 |
# File 'lib/marvin/abstract_client.rb', line 149 def handle_welcome logger.info "Say hello to my little friend - Got welcome" # If a password is specified, we will attempt to message # NickServ to identify ourselves. say ":IDENTIFY #{self.configuration.password}", "NickServ" unless self.configuration.password.blank? # Join the default channels IF they're already set # Note that Marvin::IRC::Client.connect will set them AFTER this stuff is run. self.default_channels.each { |c| self.join(c) } end |
#join(channel) ⇒ Object
191 192 193 194 195 196 197 198 199 |
# File 'lib/marvin/abstract_client.rb', line 191 def join(channel) channel = Marvin::Util.channel_name(channel) # Record the fact we're entering the room. # TODO: Refactor to only add the channel when we receive confirmation we've joined. self.channels << channel command :JOIN, channel logger.info "Joined channel #{channel}" dispatch :outgoing_join, :target => channel end |
#msg(target, message) ⇒ Object
227 228 229 230 231 |
# File 'lib/marvin/abstract_client.rb', line 227 def msg(target, ) command :privmsg, target, Marvin::Util.last_param() logger.info "Message sent to #{target} - #{message}" dispatch :outgoing_message, :target => target, :message => end |
#nick(new_nick) ⇒ Object
246 247 248 249 250 251 252 |
# File 'lib/marvin/abstract_client.rb', line 246 def nick(new_nick) logger.info "Changing nickname to #{new_nick}" command :nick, new_nick self.nickname = new_nick dispatch :outgoing_nick, :new_nick => new_nick logger.info "Nickname changed to #{new_nick}" end |
#part(channel, reason = nil) ⇒ Object
201 202 203 204 205 206 207 208 209 210 |
# File 'lib/marvin/abstract_client.rb', line 201 def part(channel, reason = nil) channel = Marvin::Util.channel_name(channel) if self.channels.include?(channel) command :part, channel, Marvin::Util.last_param(reason) dispatch :outgoing_part, :target => channel, :reason => reason logger.info "Parted from room #{channel}#{reason ? " - #{reason}" : ""}" else logger.warn "Tried to disconnect from #{channel} - which you aren't a part of" end end |
#pong(data) ⇒ Object
240 241 242 243 244 |
# File 'lib/marvin/abstract_client.rb', line 240 def pong(data) command :pong, data dispatch :outgoing_pong logger.info "PONG sent to #{data}" end |
#process_connect ⇒ Object
Initializes the instance variables used for the current connection, dispatching a :client_connected event once it has finished. During this process, it will call #client= on each handler if they respond to it.
32 33 34 35 36 37 38 39 40 41 |
# File 'lib/marvin/abstract_client.rb', line 32 def process_connect self.class.setup logger.info "Initializing the current instance" self.channels = [] self.connections << self logger.info "Setting the client for each handler" self.handlers.each { |h| h.client = self if h.respond_to?(:client=) } logger.info "Dispatching the default :client_connected event" dispatch :client_connected end |
#process_disconnect ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/marvin/abstract_client.rb', line 43 def process_disconnect logger.info "Handling disconnect for #{self.server}:#{self.port}" self.connections.delete(self) if self.connections.include?(self) dispatch :client_disconnected unless self.disconnect_expected logger.warn "Lost connection to server - adding reconnect" self.class.add_reconnect self.original_opts else Marvin::Loader.stop! if self.connections.blank? end end |
#quit(reason = nil) ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/marvin/abstract_client.rb', line 212 def quit(reason = nil) self.disconnect_expected = true logger.info "Preparing to part from #{self.channels.size} channels" self.channels.to_a.each do |chan| logger.info "Parting from #{chan}" self.part chan, reason end logger.info "Parted from all channels, quitting" command :quit dispatch :quit # Remove the connections from the pool self.connections.delete(self) logger.info "Quit from server" end |
#receive_line(line) ⇒ Object
Handling all of the the actual client stuff.
79 80 81 82 83 |
# File 'lib/marvin/abstract_client.rb', line 79 def receive_line(line) dispatch :incoming_line, :line => line event = Marvin::Settings.default_parser.parse(line) dispatch(event.to_incoming_event_name, event.to_hash) unless event.nil? end |