Class: CamperVan::IRCD

Inherits:
Object
  • Object
show all
Includes:
CommandDefinition, CommandParser, Logger, ServerReply, Utils
Defined in:
lib/camper_van/ircd.rb

Overview

the IRCD is the server that IRC clients connect to. It handles:

  • irc client registration and validation against campfire

  • mapping irc commands to internal Commands

  • proxying irc commands to campfire channels

Constant Summary collapse

MOTD =
<<-motd
  Welcome to CamperVan.
  To see what campfire rooms are available to the
  configured subdomain and api key, use the LIST command.
motd

Constants included from ServerReply

ServerReply::NUMERIC_REPLIES

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logger

#logger

Methods included from Utils

#irc_name, #stringify_keys

Methods included from ServerReply

#campfire_reply, #command_reply, #error_reply, #numeric_reply, #user_reply

Methods included from CommandParser

#parse

Methods included from CommandDefinition

included

Constructor Details

#initialize(client, options = {}) ⇒ IRCD

Public: initialize an IRC server connection

client - the EM connection representing the IRC client options - a Hash of additional options, defaults to {}

:part_on_away - leave connected campfire rooms when irc client
                goes away, rejoin when coming back


51
52
53
54
55
56
57
58
# File 'lib/camper_van/ircd.rb', line 51

def initialize(client, options = {})
  @client = client
  @active = true
  @channels = {}
  @away = false
  @saved_channels = []
  @options = options
end

Instance Attribute Details

#activeObject (readonly)

Whether or not this server is actively sending/receiving data. Set to false when shutting down so extra commands are ignored.



27
28
29
# File 'lib/camper_van/ircd.rb', line 27

def active
  @active
end

#api_keyObject (readonly)

Registration information for campfire authentication, comes from the PASS command from the irc client



17
18
19
# File 'lib/camper_van/ircd.rb', line 17

def api_key
  @api_key
end

#awayObject (readonly)

Information for the connected user



20
21
22
# File 'lib/camper_van/ircd.rb', line 20

def away
  @away
end

#channelsObject (readonly)

A Hash of connected CampfireChannels



23
24
25
# File 'lib/camper_van/ircd.rb', line 23

def channels
  @channels
end

#clientObject (readonly)

The IRC client



13
14
15
# File 'lib/camper_van/ircd.rb', line 13

def client
  @client
end

#hostObject (readonly)

Information for the connected user



20
21
22
# File 'lib/camper_van/ircd.rb', line 20

def host
  @host
end

#nickObject (readonly)

Information for the connected user



20
21
22
# File 'lib/camper_van/ircd.rb', line 20

def nick
  @nick
end

#optionsObject (readonly)

Additional options



30
31
32
# File 'lib/camper_van/ircd.rb', line 30

def options
  @options
end

#subdomainObject (readonly)

Registration information for campfire authentication, comes from the PASS command from the irc client



17
18
19
# File 'lib/camper_van/ircd.rb', line 17

def subdomain
  @subdomain
end

#userObject (readonly)

Information for the connected user



20
21
22
# File 'lib/camper_van/ircd.rb', line 20

def user
  @user
end

Instance Method Details

#campfireObject

The campfire client

Returns the existing or initializes a new instance of a campfire client using the configured subdomain and API key.



64
65
66
67
68
69
70
71
# File 'lib/camper_van/ircd.rb', line 64

def campfire
  @campfire ||= Firering::Connection.new(
    "https://#{subdomain}.campfirenow.com"
  ) do |c|
    c.token = api_key
    c.logger = CamperVan.logger
  end
end

#check_campfire_authentication(&callback) ⇒ Object

Checks that the campfire authentication is successful.

callback - a block to call if successful.

Yields to the callback on success (async)

If it fails, it replies with an error to the client and disconnects.



308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/camper_van/ircd.rb', line 308

def check_campfire_authentication(&callback)
  # invalid user only returns a nil result!
  campfire.user("me") do |user|
    if user.name
      yield
    else
      command_reply :notice, "AUTH", "could not connect to campfire: invalid API key"
      shutdown
    end
  end
rescue Firering::Connection::HTTPError => e
  command_reply :notice, "AUTH", "could not connect to campfire: #{e.message}"
  shutdown
end

#check_nick_matches_authenticated_userObject

Check to see that the nick as provided during the registration process matches the authenticated campfire user. If the nicks don’t match, send a nick change to the connected client.



326
327
328
329
330
331
332
333
334
# File 'lib/camper_van/ircd.rb', line 326

def check_nick_matches_authenticated_user
  campfire.user("me") do |user|
    name = irc_name user.name
    if name != nick
      user_reply :nick, name
      @nick = name
    end
  end
end

#join_channel(name) ⇒ Object



367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/camper_van/ircd.rb', line 367

def join_channel(name)
  campfire.rooms do |rooms|
    if room = rooms.detect { |r| "#" + irc_name(r.name) == name }
      channel = channels[name] || Channel.new(name, self, room)
      if channel.join
        channels[name] = channel
      end
    else
      numeric_reply :err_nosuchchannel, name, "No such campfire room!"
    end
  end
end

#receive_line(line) ⇒ Object

Handler for when a client sends an IRC command



74
75
76
77
78
79
80
81
# File 'lib/camper_van/ircd.rb', line 74

def receive_line(line)
  if @active
    cmd = parse(line)
    handle cmd
  end
rescue HandlerMissing
  logger.info "ignoring irc command #{cmd.inspect}: no handler"
end

#send_line(line) ⇒ Object

Send a line back to the irc client



84
85
86
# File 'lib/camper_van/ircd.rb', line 84

def send_line(line)
  client.send_line line if @active
end

#send_luser_infoObject



352
353
354
355
356
357
# File 'lib/camper_van/ircd.rb', line 352

def send_luser_info
  numeric_reply :rpl_luserclient, "There is 1 user on 1 channel"
  numeric_reply :rpl_luserop, 0, "IRC Operators online"
  numeric_reply :rpl_luserchannels, 0, "channels formed"
  numeric_reply :rpl_myinfo, "I have 1 client and 0 servers"
end

#send_motdObject



359
360
361
362
363
364
365
# File 'lib/camper_van/ircd.rb', line 359

def send_motd
  numeric_reply :rpl_motdstart, ":- MOTD for camper_van -"
  MOTD.split("\n").each do |line|
    numeric_reply :rpl_motd, ":- #{line.strip}"
  end
  numeric_reply :rpl_endofmotd, "END of MOTD"
end

#send_welcomeObject



336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
# File 'lib/camper_van/ircd.rb', line 336

def send_welcome
  hostname = Socket.gethostname
  numeric_reply :rpl_welcome, "Welcome to CamperVan, #{nick}!#{user}@#{host}"
  numeric_reply :rpl_yourhost, "Your host is #{hostname}, " +
    "running CamperVan version #{CamperVan::VERSION}"
  # using Time.now instead of a global start time since, well, this
  # particular instance really did just start right now. Give or
  # take a few seconds.
  numeric_reply :rpl_created, "This server was created #{Time.now}"
  numeric_reply :rpl_myinfo, hostname, CamperVan::VERSION,
    # channel modes: invite-only, secret
    "is",
    # user modes: away
    "a"
end

#shutdownObject

Shuts down this connection to the server



89
90
91
92
# File 'lib/camper_van/ircd.rb', line 89

def shutdown
  @active = false
  client.close_connection
end

#successful_registrationObject

Completes a successful registration with the appropriate responses



291
292
293
294
295
296
297
298
# File 'lib/camper_van/ircd.rb', line 291

def successful_registration
  check_campfire_authentication do
    check_nick_matches_authenticated_user
    send_welcome
    send_luser_info
    send_motd
  end
end