blur 1.5.3 → 1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/library/blur.rb +27 -5
- data/library/blur/client.rb +56 -38
- data/library/blur/encryption.rb +17 -0
- data/library/blur/encryption/base64.rb +71 -0
- data/library/blur/encryption/fish.rb +80 -0
- data/library/blur/enhancements.rb +22 -0
- data/library/blur/handling.rb +108 -14
- data/library/blur/network.rb +78 -24
- data/library/blur/network/channel.rb +39 -1
- data/library/blur/network/command.rb +34 -1
- data/library/blur/network/connection.rb +53 -57
- data/library/blur/network/user.rb +44 -10
- data/library/blur/script.rb +35 -1
- data/library/blur/script/cache.rb +26 -1
- data/library/blur/script/messageparsing.rb +32 -1
- metadata +64 -14
data/library/blur.rb
CHANGED
@@ -5,15 +5,37 @@ require 'majic'
|
|
5
5
|
require 'socket'
|
6
6
|
require 'ostruct'
|
7
7
|
require 'openssl'
|
8
|
+
require 'eventmachine'
|
8
9
|
|
9
|
-
|
10
|
+
# Require all library files.
|
11
|
+
require 'blur/client'
|
12
|
+
require 'blur/script'
|
13
|
+
require 'blur/network'
|
14
|
+
require 'blur/encryption'
|
15
|
+
require 'blur/enhancements'
|
16
|
+
require 'blur/script/cache'
|
17
|
+
require 'blur/network/user'
|
18
|
+
require 'blur/network/channel'
|
19
|
+
require 'blur/network/command'
|
20
|
+
require 'blur/network/connection'
|
21
|
+
require 'blur/script/messageparsing'
|
10
22
|
|
23
|
+
# Blur is a very modular IRC-framework for ruby.
|
24
|
+
#
|
25
|
+
# It allows the developer to extend it in multiple ways.
|
26
|
+
# It can be by handlers, scripts, communications, and what have you.
|
11
27
|
module Blur
|
12
|
-
|
13
|
-
|
14
|
-
end
|
28
|
+
# The major and minor version-values of Blur.
|
29
|
+
Version = "1.6"
|
15
30
|
|
16
|
-
|
31
|
+
# Instantiates a client with given options and then makes the client instance
|
32
|
+
# evaluate the given block to form a DSL.
|
33
|
+
#
|
34
|
+
# @note The idea is that this should never stop or return anything.
|
35
|
+
# @param [Hash] options the options for the client.
|
36
|
+
# @option options [Array] networks list of hashes that contain network
|
37
|
+
# options.
|
38
|
+
def self.connect options = {}, &block
|
17
39
|
Client.new(options).tap do |client|
|
18
40
|
client.instance_eval &block
|
19
41
|
end.connect
|
data/library/blur/client.rb
CHANGED
@@ -3,35 +3,59 @@
|
|
3
3
|
require 'blur/handling'
|
4
4
|
|
5
5
|
module Blur
|
6
|
+
# The +Client+ class is the controller of the low-level access.
|
7
|
+
#
|
8
|
+
# It stores networks, scripts and callbacks, and is also encharge of
|
9
|
+
# distributing the incoming commands to the right networks and scripts.
|
6
10
|
class Client
|
7
11
|
include Handling
|
8
12
|
|
9
|
-
|
13
|
+
# @return [Array] the options that is passed upon initialization.
|
14
|
+
attr_accessor :options
|
15
|
+
# @return [Array] a list of scripts that is loaded during runtime.
|
16
|
+
attr_accessor :scripts
|
17
|
+
# @return [Array] a list of instantiated networks.
|
18
|
+
attr_accessor :networks
|
10
19
|
|
20
|
+
# Instantiates the client, stores the options, instantiates the networks
|
21
|
+
# and then loads available scripts.
|
22
|
+
#
|
23
|
+
# @param [Hash] options the options for the client.
|
24
|
+
# @option options [Array] networks list of hashes that contain network
|
25
|
+
# options.
|
11
26
|
def initialize options
|
12
27
|
@options = options
|
13
28
|
@scripts = []
|
14
29
|
@networks = []
|
15
30
|
@callbacks = {}
|
16
|
-
@connected = true
|
17
31
|
|
18
|
-
@networks = @options[:networks].map {
|
32
|
+
@networks = @options[:networks].map {|options| Network.new options }
|
19
33
|
|
20
34
|
load_scripts
|
21
35
|
trap 2, &method(:quit)
|
22
36
|
end
|
23
37
|
|
38
|
+
# Connect to each network available that is not already connected, then
|
39
|
+
# proceed to start the run-loop.
|
24
40
|
def connect
|
25
|
-
networks = @networks.select {
|
41
|
+
networks = @networks.select {|network| not network.connected? }
|
26
42
|
|
27
|
-
|
28
|
-
|
29
|
-
|
43
|
+
EventMachine.run do
|
44
|
+
networks.each do |network|
|
45
|
+
network.delegate = self
|
46
|
+
network.connect
|
47
|
+
end
|
48
|
+
|
49
|
+
EventMachine.error_handler{|e| p e }
|
30
50
|
end
|
31
|
-
|
32
|
-
run_loop
|
33
51
|
end
|
34
52
|
|
53
|
+
# Is called when a command have been received and parsed, this distributes
|
54
|
+
# the command to the loader, which then further distributes it to events
|
55
|
+
# and scripts.
|
56
|
+
#
|
57
|
+
# @param [Network] network the network that received the command.
|
58
|
+
# @param [Network::Command] command the received command.
|
35
59
|
def got_command network, command
|
36
60
|
puts "<- #{network.inspect ^ :bold} | #{command}"
|
37
61
|
name = :"got_#{command.name.downcase}"
|
@@ -41,6 +65,7 @@ module Blur
|
|
41
65
|
end
|
42
66
|
end
|
43
67
|
|
68
|
+
# Searches for scripts in working_directory/scripts and then loads them.
|
44
69
|
def load_scripts
|
45
70
|
script_path = File.dirname $0
|
46
71
|
|
@@ -52,50 +77,38 @@ module Blur
|
|
52
77
|
end
|
53
78
|
end
|
54
79
|
|
80
|
+
# Unload all scripts gracefully that have been loaded into the client.
|
81
|
+
#
|
82
|
+
# @see Script#unload!
|
55
83
|
def unload_scripts
|
56
84
|
@scripts.each do |script|
|
57
85
|
script.unload!
|
58
86
|
end.clear
|
59
87
|
end
|
60
88
|
|
61
|
-
|
89
|
+
# Try to gracefully disconnect from each network, unload all scripts and
|
90
|
+
# exit properly.
|
91
|
+
#
|
92
|
+
# @param [optional, Symbol] signal The signal received by the system, if any.
|
93
|
+
def quit signal = :SIGINT
|
62
94
|
@networks.each do |network|
|
63
95
|
network.transmit :QUIT, "Got SIGINT?"
|
64
|
-
network.transcieve
|
65
96
|
network.disconnect
|
66
97
|
end
|
67
98
|
|
68
|
-
@connected = false
|
69
99
|
unload_scripts
|
70
100
|
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
def run_loop
|
77
|
-
puts "Starting run loop ..."
|
78
|
-
|
79
|
-
while @connected
|
80
|
-
@networks.select(&:connected?).each do |network|
|
81
|
-
begin
|
82
|
-
network.transcieve
|
83
|
-
sleep 0.05
|
84
|
-
rescue StandardError => exception
|
85
|
-
if network.connected?
|
86
|
-
network.disconnect
|
87
|
-
end
|
88
|
-
|
89
|
-
emit :connection_terminated, network
|
90
|
-
|
91
|
-
puts "#{"Network error" ^ :red} (#{exception.class.name}): #{exception.message}"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
puts "Ended run loop ..."
|
101
|
+
EventMachine.stop
|
97
102
|
end
|
98
103
|
|
104
|
+
private
|
105
|
+
# Finds all callbacks with name `name` and then calls them.
|
106
|
+
# It also sends `name` to {Script} if the script responds to `name`, to all
|
107
|
+
# available scripts.
|
108
|
+
#
|
109
|
+
# @param [Symbol] name the corresponding event-handlers name.
|
110
|
+
# @param [...] args Arguments that is passed to the event-handler.
|
111
|
+
# @private
|
99
112
|
def emit name, *args
|
100
113
|
@callbacks[name].each do |callback|
|
101
114
|
callback.call *args
|
@@ -110,6 +123,11 @@ module Blur
|
|
110
123
|
end
|
111
124
|
end
|
112
125
|
|
126
|
+
# Stores the block as an event-handler with name `name`.
|
127
|
+
#
|
128
|
+
# @param [Symbol] name the corresponding event-handlers name.
|
129
|
+
# @param [Block] block the event-handlers block that serves as a trigger.
|
130
|
+
# @private
|
113
131
|
def catch name, &block
|
114
132
|
(@callbacks[name] ||= []) << block
|
115
133
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Blur
|
4
|
+
# The +Encryption+ module extends the communication-functionality of
|
5
|
+
# the client. It is intended to enable helpers but also core functionality
|
6
|
+
# that encrypts the incoming and outgoing data of Blur.
|
7
|
+
#
|
8
|
+
# Encryption modules are not loaded into the VM until it's required.
|
9
|
+
module Encryption
|
10
|
+
# Indicates that user-input (a channel user message, e.g.) is in invalid
|
11
|
+
# format to a certain encryption algorithm.
|
12
|
+
class BadInputError < StandardError; end
|
13
|
+
|
14
|
+
autoload :FiSH, "blur/encryption/fish"
|
15
|
+
autoload :Base64, "blur/encryption/base64"
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Blur
|
4
|
+
module Encryption
|
5
|
+
# The +Encryption::Base64+ module differs from the original Base64
|
6
|
+
# implementation. I'm not sure how exactly, perhaps the charset?
|
7
|
+
#
|
8
|
+
# I originally found the Ruby implementation of FiSH on a website where
|
9
|
+
# it was graciously submitted by an anonymous user, since then I've
|
10
|
+
# implemented it in a weechat script, and now I've refactored it for use in
|
11
|
+
# Blur.
|
12
|
+
#
|
13
|
+
# @see http://maero.dk/pub/sources/weechat/ruby/autoload/fish.rb
|
14
|
+
module Base64
|
15
|
+
# The difference I suspect between the original Base64 implementation
|
16
|
+
# and the one used in FiSH.
|
17
|
+
Charset = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
18
|
+
|
19
|
+
# Decode a base64-encoded string.
|
20
|
+
#
|
21
|
+
# @return [String] Base64-decoded string.
|
22
|
+
def self.decode string
|
23
|
+
unless string.length % 12 == 0
|
24
|
+
raise BadInputError, "input has to be a multiple of 12 characters."
|
25
|
+
end
|
26
|
+
|
27
|
+
String.new.tap do |buffer|
|
28
|
+
j = -1
|
29
|
+
|
30
|
+
while j < string.length - 1
|
31
|
+
right, left = 0, 0
|
32
|
+
|
33
|
+
6.times{|i| right |= Charset.index(string[j += 1]) << (i * 6) }
|
34
|
+
6.times{|i| left |= Charset.index(string[j += 1]) << (i * 6) }
|
35
|
+
|
36
|
+
4.times do |i|
|
37
|
+
buffer << ((left & (0xFF << ((3 - i) * 8))) >> ((3 - i) * 8)).chr
|
38
|
+
end
|
39
|
+
|
40
|
+
4.times do |i|
|
41
|
+
buffer << ((right & (0xFF << ((3 - i) * 8))) >> ((3 - i) * 8)).chr
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Encode a string-cipher.
|
48
|
+
#
|
49
|
+
# @return [String] Base64-encoded string.
|
50
|
+
def self.encode string
|
51
|
+
unless string.length % 8 == 0
|
52
|
+
raise BadInputError, "input has to be a multiple of 8 characters."
|
53
|
+
end
|
54
|
+
|
55
|
+
left = 0
|
56
|
+
right = 0
|
57
|
+
decimals = [24, 16, 8, 0]
|
58
|
+
|
59
|
+
String.new.tap do |buffer|
|
60
|
+
string.each_block do |block|
|
61
|
+
4.times{|i| left += (block[i].ord << decimals[i]) }
|
62
|
+
4.times{|i| right += (block[i+4].ord << decimals[i]) }
|
63
|
+
|
64
|
+
6.times{|i| buffer << Charset[right & 0x3F].chr; right = right >> 6 }
|
65
|
+
6.times{|i| buffer << Charset[left & 0x3F].chr; left = left >> 6 }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'crypt/blowfish'
|
4
|
+
|
5
|
+
module Blur
|
6
|
+
module Encryption
|
7
|
+
# The +FiSH+ algorithm is a combination of Base64 encoding
|
8
|
+
# and the blowfish encryption.
|
9
|
+
#
|
10
|
+
# Shared text messages are prepended by "++OK+", an older implementation
|
11
|
+
# prepends it with "+mcps+" - Blur drops support for that implementation.
|
12
|
+
#
|
13
|
+
# There's multiple client-implementations available on the official FiSH
|
14
|
+
# homepage.
|
15
|
+
#
|
16
|
+
# == DH1080 Key exchange
|
17
|
+
# The newer FiSH implementation introduces a 1080bit Diffie-Hellman
|
18
|
+
# key-exchange mechanism.
|
19
|
+
#
|
20
|
+
# Blur does currently not support key exchanges.
|
21
|
+
class FiSH
|
22
|
+
# The standard FiSH block-size.
|
23
|
+
BlockSize = 8
|
24
|
+
|
25
|
+
# @return [String] the blowfish salt-key.
|
26
|
+
attr_accessor :keyphrase
|
27
|
+
|
28
|
+
# Change the keyphrase and instantiate a new blowfish object.
|
29
|
+
def keyphrase= keyphrase
|
30
|
+
@keyphrase = keyphrase
|
31
|
+
@blowfish = Crypt::Blowfish.new @keyphrase
|
32
|
+
end
|
33
|
+
|
34
|
+
# Instantiate a new fish-encryption object.
|
35
|
+
def initialize keyphrase
|
36
|
+
@keyphrase = keyphrase
|
37
|
+
@blowfish = Crypt::Blowfish.new keyphrase
|
38
|
+
end
|
39
|
+
|
40
|
+
# Encrypt an input string using the keyphrase stored in the +@blowfish+
|
41
|
+
# object.
|
42
|
+
#
|
43
|
+
# @return [String] the encrypted string.
|
44
|
+
def encrypt string
|
45
|
+
String.new.tap do |buffer|
|
46
|
+
nullpad(string).each_block do |block|
|
47
|
+
chunk = @blowfish.encrypt_block block
|
48
|
+
buffer.concat Base64.encode chunk
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Decrypt an input string using the keyphrase stored in the +@blowfish+
|
54
|
+
# object.
|
55
|
+
#
|
56
|
+
# @return [String] the decrypted string.
|
57
|
+
def decrypt string
|
58
|
+
unless string.length % 12 == 0
|
59
|
+
raise BadInputError, "input has to be a multiple of 12 characters."
|
60
|
+
end
|
61
|
+
|
62
|
+
String.new.tap do |buffer|
|
63
|
+
string.each_block 12 do |block|
|
64
|
+
chunk = @blowfish.decrypt_block Base64.decode block
|
65
|
+
buffer.concat chunk
|
66
|
+
end
|
67
|
+
end.rstrip
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
# Fill up the last block with null-bytes until it's a multiple of 8.
|
72
|
+
#
|
73
|
+
# @return [String] the nullpadded string.
|
74
|
+
def nullpad string
|
75
|
+
length = string.length + BlockSize - string.length % BlockSize
|
76
|
+
string.ljust length, ?\0
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -1,17 +1,39 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
# Reopens the scope of the standard Exception-class to extend it with helpful
|
4
|
+
# methods.
|
3
5
|
class Exception
|
6
|
+
# The pattern to match against the backtrace log.
|
4
7
|
Pattern = /^.*?:(\d+):/
|
5
8
|
|
9
|
+
# Retrieve the line on which the exception was raised from when raised inside
|
10
|
+
# a script.
|
11
|
+
#
|
12
|
+
# @return Fixnum the line of the script the exception was raised on.
|
6
13
|
def line
|
7
14
|
backtrace[0].match(Pattern)[1].to_i + 1
|
8
15
|
end
|
9
16
|
end
|
10
17
|
|
18
|
+
# Reopens the scope of the standard String-class to extend it with helpful
|
19
|
+
# methods.
|
11
20
|
class String
|
21
|
+
# Checks if the string contains nothing but a numeric value.
|
22
|
+
#
|
23
|
+
# @return true if it is a numeric value.
|
12
24
|
def numeric?
|
13
25
|
self =~ /^\d+$/
|
14
26
|
end
|
15
27
|
|
28
|
+
# Split a string up in n chunks and then iterate through them, exactly like
|
29
|
+
# Enumerable#each_slice.
|
30
|
+
#
|
31
|
+
# @return [Enumerator] list of slices.
|
32
|
+
# @yieldreturn [Array] list of elements in each slice consecutively.
|
33
|
+
def each_slice size = 8
|
34
|
+
self.chars.each_slice(size).each{|slice| yield slice.join }
|
35
|
+
end
|
36
|
+
|
16
37
|
alias_method :starts_with?, :start_with?
|
38
|
+
alias_method :each_block, :each_slice
|
17
39
|
end
|
data/library/blur/handling.rb
CHANGED
@@ -2,11 +2,41 @@
|
|
2
2
|
|
3
3
|
module Blur
|
4
4
|
class Client
|
5
|
+
# The +Handling+ module is the very core of the IRC-part in Blur.
|
6
|
+
#
|
7
|
+
# When the client receives a parsed command instance, it immediately starts
|
8
|
+
# looking for a got_(the command name) method inside the client, which
|
9
|
+
# is implemented in this module.
|
10
|
+
#
|
11
|
+
# == Implementing a handler
|
12
|
+
# Implementing a handler is very, very easy.
|
13
|
+
#
|
14
|
+
# All you need to do is define a method named got_(command you want to
|
15
|
+
# implement) that accepts 2 parameters, +network+ and +command+.
|
16
|
+
#
|
17
|
+
# You can then do whatever you need to do with the command instance,
|
18
|
+
# you can access the parameters of it through {Network::Command#[]}.
|
19
|
+
#
|
20
|
+
# Don't forget that this module is inside the clients scope, so you can
|
21
|
+
# access all instance-variables and methods.
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# # RPL_WHOISUSER
|
25
|
+
# # <nick> <user> <host> * :<real name>
|
26
|
+
# def got_whois_user network, command
|
27
|
+
# puts "nick: #{command[0]} user: #{command[1]} host: #{command[2]} …"
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# @see http://www.irchelp.org/irchelp/rfc/chapter6.html
|
5
31
|
module Handling
|
6
|
-
|
7
32
|
protected
|
8
33
|
|
9
|
-
#
|
34
|
+
# Called when the MOTD was received, which also means it is ready.
|
35
|
+
#
|
36
|
+
# == Callbacks:
|
37
|
+
# Emits +:connection_ready+ with the parameter +network+.
|
38
|
+
#
|
39
|
+
# Automatically joins the channels specified in +:channels+.
|
10
40
|
def got_end_of_motd network, command
|
11
41
|
emit :connection_ready, network
|
12
42
|
|
@@ -15,8 +45,8 @@ module Blur
|
|
15
45
|
end
|
16
46
|
end
|
17
47
|
|
18
|
-
#
|
19
|
-
def
|
48
|
+
# Called when the namelist of a channel was received.
|
49
|
+
def got_name_reply network, command
|
20
50
|
name = command[2]
|
21
51
|
users = command[3].split.map &Network::User.method(:new)
|
22
52
|
|
@@ -28,30 +58,46 @@ module Blur
|
|
28
58
|
channel.users << user
|
29
59
|
end
|
30
60
|
else
|
31
|
-
|
61
|
+
channel = Network::Channel.new name, network, users
|
62
|
+
|
63
|
+
if network.fish? and network.options[:fish].key? name
|
64
|
+
keyphrase = network.options[:fish][name]
|
65
|
+
channel.encryption = Encryption::FiSH.new keyphrase
|
66
|
+
end
|
67
|
+
|
68
|
+
network.channels << channel
|
32
69
|
end
|
33
70
|
end
|
34
71
|
|
35
|
-
#
|
36
|
-
|
72
|
+
# Called when a channel topic was changed.
|
73
|
+
#
|
74
|
+
# == Callbacks:
|
75
|
+
# Emits :topic_change with the parameters +channel+ and +topic+.
|
76
|
+
def got_channel_topic network, command
|
37
77
|
me, name, topic = command.params
|
38
78
|
|
39
79
|
if channel = network.channel_by_name(name)
|
80
|
+
emit :topic_change, channel, topic
|
40
81
|
channel.topic = topic
|
41
82
|
else
|
42
83
|
channel = Network::Channel.new name, network, []
|
84
|
+
emit :topic_change, channel, topic
|
43
85
|
channel.topic = topic
|
44
86
|
|
45
87
|
network.channels << channel
|
46
88
|
end
|
47
89
|
end
|
48
90
|
|
49
|
-
#
|
91
|
+
# Called when the server needs to verify that we're alive.
|
50
92
|
def got_ping network, command
|
51
93
|
network.transmit :PONG, command[0]
|
52
94
|
end
|
53
95
|
|
54
|
-
#
|
96
|
+
# Called when a user changed nickname.
|
97
|
+
#
|
98
|
+
# == Callbacks:
|
99
|
+
# Emits :user_rename with the parameters +channel+, +user+ and +nickname+
|
100
|
+
# where +nickname+ is the new name.
|
55
101
|
def got_nick network, command
|
56
102
|
nick = command.sender.nickname
|
57
103
|
|
@@ -65,7 +111,15 @@ module Blur
|
|
65
111
|
end
|
66
112
|
end
|
67
113
|
|
68
|
-
#
|
114
|
+
# Called when a message was received (both channel and private messages).
|
115
|
+
#
|
116
|
+
# == Callbacks:
|
117
|
+
# === When it's a channel message:
|
118
|
+
# Emits +:message+ with the parameters +user+, +channel+ and +message+.
|
119
|
+
# === When it's a private message:
|
120
|
+
# Emits +:private_message+ with the parameters +user+ and +message+.
|
121
|
+
#
|
122
|
+
# @note Messages are contained as strings.
|
69
123
|
def got_privmsg network, command
|
70
124
|
return if command.sender.is_a? String # Ignore all server privmsgs
|
71
125
|
name, message = command.params
|
@@ -74,6 +128,18 @@ module Blur
|
|
74
128
|
if user = channel.user_by_nick(command.sender.nickname)
|
75
129
|
user.name = command.sender.username
|
76
130
|
user.host = command.sender.hostname
|
131
|
+
|
132
|
+
begin
|
133
|
+
if message[0..3] == "+OK " and channel.encrypted?
|
134
|
+
message = channel.encryption.decrypt message[4..-1]
|
135
|
+
end
|
136
|
+
rescue Encryption::BadInputError
|
137
|
+
# …
|
138
|
+
rescue => exception
|
139
|
+
puts "-!- There was a problem with the FiSH encryption, disabling"
|
140
|
+
|
141
|
+
channel.encryption = nil
|
142
|
+
end
|
77
143
|
|
78
144
|
emit :message, user, channel, message
|
79
145
|
else
|
@@ -89,7 +155,10 @@ module Blur
|
|
89
155
|
end
|
90
156
|
end
|
91
157
|
|
92
|
-
#
|
158
|
+
# Called when a user joined a channel.
|
159
|
+
#
|
160
|
+
# == Callbacks:
|
161
|
+
# Emits +:user_entered+ with the parameters +channel+ and +user+.
|
93
162
|
def got_join network, command
|
94
163
|
name = command[0]
|
95
164
|
user = Network::User.new command.sender.nickname
|
@@ -106,7 +175,10 @@ module Blur
|
|
106
175
|
end
|
107
176
|
end
|
108
177
|
|
109
|
-
#
|
178
|
+
# Called when a user left a channel.
|
179
|
+
#
|
180
|
+
# == Callbacks:
|
181
|
+
# Emits +:user_left+ with the parameters +channel+ and +user+.
|
110
182
|
def got_part network, command
|
111
183
|
name = command[0]
|
112
184
|
|
@@ -119,7 +191,10 @@ module Blur
|
|
119
191
|
end
|
120
192
|
end
|
121
193
|
|
122
|
-
#
|
194
|
+
# Called when a user disconnected from a network.
|
195
|
+
#
|
196
|
+
# == Callbacks:
|
197
|
+
# Emits +:user_quit+ with the parameters +channel+ and +user+.
|
123
198
|
def got_quit network, command
|
124
199
|
nick = command.sender.nickname
|
125
200
|
|
@@ -134,7 +209,13 @@ module Blur
|
|
134
209
|
end
|
135
210
|
end
|
136
211
|
|
137
|
-
#
|
212
|
+
# Called when a user was kicked from a channel.
|
213
|
+
#
|
214
|
+
# == Callbacks:
|
215
|
+
# Emits +:user_kicked+ with the parameters +kicker+, +channel+, +kickee+
|
216
|
+
# and +reason+.
|
217
|
+
#
|
218
|
+
# +kicker+ is the user that kicked +kickee+.
|
138
219
|
def got_kick network, command
|
139
220
|
name, target, reason = command.params
|
140
221
|
|
@@ -149,6 +230,10 @@ module Blur
|
|
149
230
|
end
|
150
231
|
end
|
151
232
|
|
233
|
+
# Called when a topic was changed for a channel.
|
234
|
+
#
|
235
|
+
# == Callbacks:
|
236
|
+
# Emits :topic with the parameters +user+, +channel+ and +topic+.
|
152
237
|
def got_topic network, command
|
153
238
|
name, topic = command.params
|
154
239
|
|
@@ -161,6 +246,13 @@ module Blur
|
|
161
246
|
end
|
162
247
|
end
|
163
248
|
|
249
|
+
# Called when a channel or a users flags was altered.
|
250
|
+
#
|
251
|
+
# == Callbacks:
|
252
|
+
# === When it's channel modes:
|
253
|
+
# Emits +:channel_mode+ with the parameters +channel+ and +modes+.
|
254
|
+
# === When it's user modes:
|
255
|
+
# Emits +:user_mode+ with the parameters +user+ and +modes+.
|
164
256
|
def got_mode network, command
|
165
257
|
name, modes, limit, nick, mask = command.params
|
166
258
|
|
@@ -181,8 +273,10 @@ module Blur
|
|
181
273
|
end
|
182
274
|
end
|
183
275
|
|
276
|
+
alias_method :got_353, :got_name_reply
|
184
277
|
alias_method :got_422, :got_end_of_motd
|
185
278
|
alias_method :got_376, :got_end_of_motd
|
279
|
+
alias_method :got_332, :got_channel_topic
|
186
280
|
end
|
187
281
|
end
|
188
282
|
end
|