ircguerilla-irc 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. data/lib/irc/client/command_handler.rb +2 -2
  2. data/lib/irc/client/connected_state.rb +53 -8
  3. data/lib/irc/client/connection.rb +41 -6
  4. data/lib/irc/client/connection_listener.rb +26 -11
  5. data/lib/irc/client/connection_state.rb +15 -2
  6. data/lib/irc/client/context.rb +49 -11
  7. data/lib/irc/client/disconnected_state.rb +28 -16
  8. data/lib/irc/client/message_handler.rb +40 -16
  9. data/lib/irc/client/registered_state.rb +18 -0
  10. data/lib/irc/client/unregistered_state.rb +51 -16
  11. data/lib/irc/commands/nick_command.rb +14 -0
  12. data/lib/irc/messages/error_join_message.rb +1 -1
  13. data/lib/irc/messages/error_message.rb +53 -24
  14. data/lib/irc/messages/error_nick_name_in_use_message.rb +70 -0
  15. data/lib/irc/messages/factory.rb +16 -0
  16. data/lib/irc/messages/isupport_message.rb +86 -0
  17. data/lib/irc/messages/kick_message.rb +114 -0
  18. data/lib/irc/messages/message.rb +21 -1
  19. data/lib/irc/messages/nick_message.rb +17 -2
  20. data/lib/irc/messages/pong_message.rb +1 -1
  21. data/lib/irc/messages/welcome_message.rb +72 -0
  22. data/lib/irc/util/color.rb +77 -0
  23. data/lib/irc/util/nick_generator.rb +58 -0
  24. data/test/functional/irc/client/connection_test.rb +34 -1
  25. data/test/functional/irc/client/context_test.rb +5 -2
  26. data/test/mocks/test/irc/client/connection.rb +128 -0
  27. data/test/mocks/test/irc/client/disconnected_state.rb +44 -0
  28. data/test/test_helper.rb +1 -1
  29. data/test/unit/irc/client/command_handler_test.rb +12 -12
  30. data/test/unit/irc/client/message_handler_test.rb +136 -0
  31. data/test/unit/irc/commands/command_test.rb +87 -84
  32. data/test/unit/irc/commands/join_command_test.rb +3 -1
  33. data/test/unit/irc/commands/nick_command_test.rb +7 -1
  34. data/test/unit/irc/commands/ping_command_test.rb +12 -16
  35. data/test/unit/irc/commands/pong_command_test.rb +2 -1
  36. data/test/unit/irc/messages/error_join_message_test.rb +23 -2
  37. data/test/unit/irc/messages/error_message_test.rb +56 -0
  38. data/test/unit/irc/messages/error_nick_name_in_use_message_test.rb +56 -0
  39. data/test/unit/irc/messages/factory_test.rb +25 -0
  40. data/test/unit/irc/messages/isupport_message_test.rb +138 -0
  41. data/test/unit/irc/messages/join_message_test.rb +22 -1
  42. data/test/unit/irc/messages/kick_message_test.rb +76 -0
  43. data/test/unit/irc/messages/message_test.rb +33 -0
  44. data/test/unit/irc/messages/nick_message_test.rb +22 -1
  45. data/test/unit/irc/messages/notice_message_test.rb +22 -1
  46. data/test/unit/irc/messages/part_message_test.rb +22 -1
  47. data/test/unit/irc/messages/ping_message_test.rb +21 -1
  48. data/test/unit/irc/messages/pong_message_test.rb +21 -1
  49. data/test/unit/irc/messages/private_message_test.rb +22 -1
  50. data/test/unit/irc/messages/welcome_message_test.rb +59 -0
  51. data/test/unit/irc/util/color_test.rb +97 -0
  52. data/test/unit/irc/util/nick_generator_test.rb +52 -0
  53. metadata +69 -52
@@ -25,13 +25,17 @@
25
25
  #
26
26
  require 'irc/messages/message'
27
27
  require 'irc/messages/error_message'
28
+ require 'irc/messages/error_nick_name_in_use_message'
29
+ require 'irc/messages/isupport_message'
28
30
  require 'irc/messages/join_message'
31
+ require 'irc/messages/kick_message'
29
32
  require 'irc/messages/nick_message'
30
33
  require 'irc/messages/notice_message'
31
34
  require 'irc/messages/part_message'
32
35
  require 'irc/messages/ping_message'
33
36
  require 'irc/messages/pong_message'
34
37
  require 'irc/messages/private_message'
38
+ require 'irc/messages/welcome_message'
35
39
 
36
40
  module IRC
37
41
 
@@ -50,6 +54,9 @@ module IRC
50
54
  # Create a new specialized message object, depending on the message code.
51
55
  case message.code
52
56
 
57
+ when ErrorMessage::CODE
58
+ return ErrorMessage.new(raw_message)
59
+
53
60
  when ErrorAlreadyRegisteredMessage::CODE
54
61
  return ErrorAlreadyRegisteredMessage.new(raw_message)
55
62
 
@@ -97,10 +104,16 @@ module IRC
97
104
 
98
105
  when ErrorTooManyChannelsMessage::CODE
99
106
  return ErrorTooManyChannelsMessage.new(raw_message)
107
+
108
+ when ISupportMessage::CODE
109
+ return ISupportMessage.new(raw_message)
100
110
 
101
111
  when JoinMessage::CODE
102
112
  return JoinMessage.new(raw_message)
103
113
 
114
+ when KickMessage::CODE
115
+ return KickMessage.new(raw_message)
116
+
104
117
  when NickMessage::CODE
105
118
  return NickMessage.new(raw_message)
106
119
 
@@ -119,6 +132,9 @@ module IRC
119
132
  when PrivateMessage::CODE
120
133
  return PrivateMessage.new(raw_message)
121
134
 
135
+ when WelcomeMessage::CODE
136
+ return WelcomeMessage.new(raw_message)
137
+
122
138
  end
123
139
 
124
140
  return message
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2006 Roman Scherer | IRC Guerilla | Rapid Packet Movement
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #
24
+ # $Id$
25
+ #
26
+ require 'irc/messages/message'
27
+ require 'irc/messages/invalid_message'
28
+
29
+ module IRC
30
+
31
+ module Messages
32
+
33
+ class ISupportMessage < Message
34
+
35
+ CODE = RPL_ISUPPORT
36
+
37
+ attr_reader :options
38
+
39
+ # Saves the supported options to the context.
40
+ def handle(context)
41
+
42
+ # Notify all connection listeners by calling their on_server_response method.
43
+ super(context)
44
+
45
+ options.each do |key, value|
46
+ context.options[key] = value
47
+ end
48
+
49
+ end
50
+
51
+ protected
52
+
53
+ def parse(raw_message)
54
+
55
+ # Initialize the base message fields.
56
+ super(raw_message)
57
+
58
+ # Extract the message specific fields.
59
+ match_data = Regexp.new('(\S+)\s+([^:]+)*\s+:?.*').match(message)
60
+ raise InvalidMessage.new("Can't parse isupport message. Invalid message format.") if match_data == nil || code != CODE
61
+
62
+ # Extract the nick name.
63
+ @nick = match_data[1]
64
+
65
+ # Extract the supported options.
66
+ @options = Hash.new
67
+ match_data[2].split(" ").each do |supported_option|
68
+
69
+ key, value = supported_option.split("=")
70
+
71
+ if value == nil
72
+ @options[key] = true
73
+ else
74
+ # TODO: value.to_i.to_s ?? Why does /\d+/ not work?
75
+ @options[key] = (value.to_i.to_s == value ? value.to_i : value)
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2006 Roman Scherer | IRC Guerilla | Rapid Packet Movement
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #
24
+ # $Id$
25
+ #
26
+ require 'irc/messages/message'
27
+ require 'irc/messages/invalid_message'
28
+
29
+ module IRC
30
+
31
+ module Messages
32
+
33
+
34
+ # 4.2.8 Kick command
35
+ #
36
+ # Command: KICK
37
+ # Parameters: <channel> <user> [<comment>]
38
+ #
39
+ # The KICK command can be used to forcibly remove a user from a channel. It 'kicks them out'
40
+ # of the channel (forced PART).
41
+ #
42
+ # Only a channel operator may kick another user out of a channel. Each server that receives
43
+ # a KICK message checks that it is valid (ie the sender is actually a channel operator)
44
+ # before removing the victim from the channel.
45
+ #
46
+ # Numeric Replies:
47
+ # * ERR_NEEDMOREPARAMS
48
+ # * ERR_NOSUCHCHANNEL
49
+ # * ERR_BADCHANMASK
50
+ # * ERR_CHANOPRIVSNEEDED
51
+ # * ERR_NOTONCHANNEL
52
+ #
53
+ # Examples:
54
+ #
55
+ # KICK &Melbourne Matthew ; Kick Matthew from &Melbourne
56
+ #
57
+ # KICK #Finnish John :Speaking English
58
+ # ; Kick John from #Finnish using
59
+ # "Speaking English" as the reason
60
+ # (comment).
61
+ #
62
+ # :WiZ KICK #Finnish John ; KICK message from WiZ to remove John
63
+ # from channel #Finnish
64
+ #
65
+ # NOTE:
66
+ #
67
+ # It is possible to extend the KICK command parameters to the following:
68
+ #
69
+ # <channel>{,<channel>} <user>{,<user>} [<comment>]
70
+ #
71
+ class KickMessage < Message
72
+
73
+ CODE = "KICK"
74
+
75
+ attr_reader :channel
76
+ attr_reader :kicker
77
+ attr_reader :kicked
78
+ attr_reader :reason
79
+
80
+ # Notify all connection listeners, that a user has joined a channel.
81
+ def handle(context)
82
+
83
+ # Notify all connection listeners by calling their on_server_response method.
84
+ super(context)
85
+
86
+ # Notify all connection listeners by calling their on_join method.
87
+ notify(context) do |connection_listener|
88
+ connection_listener.on_kick(context, context.lookup_channel(channel), context.lookup_user(kicker), context.lookup_user(kicked), reason)
89
+ end
90
+
91
+ end
92
+
93
+ protected
94
+
95
+ def parse(raw_message)
96
+
97
+ # Initialize the base message fields.
98
+ super(raw_message)
99
+
100
+ # Extract the message specific fields.
101
+ match_data = Regexp.new('(\S+)\s+(\S+)(\s+:?(.+))?').match(message)
102
+ raise InvalidMessage.new("Can't parse kick message. Invalid message format.") if match_data == nil || code != CODE
103
+
104
+ # Extract the channel, kicker and the kciked user.
105
+ @channel, @kicker, @kicked, @reason = match_data[1], nick, match_data[2], match_data[4]
106
+ @server = nil
107
+
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -35,7 +35,7 @@ module IRC
35
35
 
36
36
  include Codes
37
37
 
38
- MESSAGE_FORMAT = Regexp.new('(:([^!\s]+)(!([^@\s]+))?(@(\S+))?\s+)?(\w+|\d\d\d)\s+(.*)')
38
+ MESSAGE_FORMAT = Regexp.new('(:([^!\s]+)(!([^@\s]+))?(@(\S+))?\s+)?(\w+|\d\d\d)\s*(.*)')
39
39
 
40
40
  attr_reader :code
41
41
  attr_reader :host
@@ -49,6 +49,22 @@ module IRC
49
49
  parse(raw_message)
50
50
  end
51
51
 
52
+ def ==(other)
53
+ return eql?(other)
54
+ end
55
+
56
+ # Returns true if the other Message object is equal to the current.
57
+ def eql?(other)
58
+ return false if !other.kind_of?(Message)
59
+ return false if code != other.code
60
+ return false if host != other.host
61
+ return false if message != other.message
62
+ return false if raw_message != other.raw_message
63
+ return false if server != other.server
64
+ return false if login != other.login
65
+ return true
66
+ end
67
+
52
68
  # Notify all connection listeners that a message was received from the IRC server,
53
69
  # by calling their on_server_response method.
54
70
  def handle(context)
@@ -65,6 +81,10 @@ module IRC
65
81
  return Regexp.new(MESSAGE_FORMAT).match(raw_message) != nil
66
82
  end
67
83
 
84
+ def to_s
85
+ return raw_message
86
+ end
87
+
68
88
  protected
69
89
 
70
90
  # Notify all connection listeners, by calling the surrounding block with a channel listener as parameter.
@@ -71,18 +71,33 @@ module IRC
71
71
  attr_reader :after
72
72
  attr_reader :before
73
73
 
74
+ # Notify all connection listeners, that a user changed it's nick name.
75
+ def handle(context)
76
+
77
+ # Notify all connection listeners by calling their on_server_response method.
78
+ super(context)
79
+
80
+ # Notify all connection listeners by calling their on_nick method.
81
+ notify(context) do |connection_listener|
82
+ connection_listener.on_nick(context, context.lookup_user(before), context.lookup_user(after))
83
+ end
84
+
85
+ end
86
+
87
+ protected
88
+
74
89
  def parse(raw_message)
75
90
 
76
91
  # Initialize the base message fields.
77
92
  super(raw_message)
78
93
 
79
94
  # Match the message against the message format.
80
- match_data = Regexp.new('\s*:?(\S+)\s+NICK\s+(\S+)\s*').match(raw_message)
95
+ match_data = Regexp.new('\s*:?(\S+)\s+NICK\s+:?(\S+)\s*').match(raw_message)
81
96
  raise InvalidMessage.new("Can't parse nick message. Invalid message format.") unless match_data
82
97
 
83
98
  # Initialize the variables holding the nick names before & after the nick change.
84
99
  @after = match_data[2]
85
- @before = match_data[1]
100
+ @before = nick #match_data[1]
86
101
 
87
102
  end
88
103
 
@@ -61,7 +61,7 @@ module IRC
61
61
 
62
62
  # Notify all connection listeners by calling their on_pong method.
63
63
  notify(context) do |connection_listener|
64
- message_listener.on_pong(context, daemons)
64
+ connection_listener.on_pong(context, daemons)
65
65
  end
66
66
 
67
67
  end
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2006 Roman Scherer | IRC Guerilla | Rapid Packet Movement
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #
24
+ # $Id$
25
+ #
26
+ require 'irc/messages/message'
27
+ require 'irc/messages/invalid_message'
28
+
29
+ module IRC
30
+
31
+ module Messages
32
+
33
+ class WelcomeMessage < Message
34
+
35
+ CODE = RPL_WELCOME
36
+
37
+ attr_reader :text
38
+
39
+ # Notify all connection listeners, that a private message was received.
40
+ def handle(context)
41
+
42
+ # Notify all connection listeners by calling their on_server_response method.
43
+ super(context)
44
+
45
+ # Notify all connection listeners by calling their on_private_message method.
46
+ notify(context) do |connection_listener|
47
+ connection_listener.on_welcome(context, context.lookup_user(nick), text)
48
+ end
49
+
50
+ end
51
+
52
+ protected
53
+
54
+ def parse(raw_message)
55
+
56
+ # Initialize the base message fields.
57
+ super(raw_message)
58
+
59
+ # Extract the message specific fields.
60
+ match_data = Regexp.new('(\S+)\s+:?(.+)').match(message)
61
+ raise InvalidMessage.new("Can't parse private message. Invalid message format.") if match_data == nil || code != CODE
62
+
63
+ # Extract the sender, target and the text.
64
+ @nick, @text = match_data[1], match_data[2]
65
+
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2006 Roman Scherer | IRC Guerilla | Rapid Packet Movement
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #
24
+ # $Id$
25
+ #
26
+ module IRC
27
+
28
+ module Util
29
+
30
+ class Color
31
+
32
+ NORMAL = "\x0f"
33
+ BOLD = "\x02"
34
+ UNDERLINE = "\x1f"
35
+ REVERSE = "\x16"
36
+
37
+ WHITE = "\x030"
38
+ BLACK = "\x031"
39
+ DARK_BLUE = "\x032"
40
+ DARK_GREEN = "\x033"
41
+ RED = "\x034"
42
+ BROWN = "\x035"
43
+ PURPLE = "\x036"
44
+ OLIVE = "\x037"
45
+ YELLOW = "\x038"
46
+ GREEN = "\x039"
47
+ TEAL = "\x0310"
48
+ CYAN = "\x0311"
49
+ BLUE = "\x0312"
50
+ MAGENTA = "\x0313"
51
+ DARK_GRAY = "\x0314"
52
+ LIGHT_GRAY = "\x0315"
53
+
54
+ REGEXP_COLORS = Regexp.new("\x03(\\d\\d?(,\\d\\d?)?)?")
55
+
56
+ REGEXP_FORMATTING = Regexp.new("#{NORMAL}|#{BOLD}|#{UNDERLINE}|#{REVERSE}")
57
+
58
+ # Removes all IRC color characters from the given string.
59
+ def self.remove_color(str)
60
+ return str.gsub(REGEXP_COLORS, '')
61
+ end
62
+
63
+ # Removes all IRC color and formatting characters from the given string.
64
+ def self.remove_color_and_formatting(str)
65
+ return remove_color(remove_formatting(str))
66
+ end
67
+
68
+ # Removes all IRC formatting characters from the given string.
69
+ def self.remove_formatting(str)
70
+ return str.gsub(REGEXP_FORMATTING, '')
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ end