ircmachine 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: eb3c6abf09f3ce657496ebac2b2bb384a5fa9962
4
+ data.tar.gz: fff381302cd8132fe6412be5837f398d500a0d0f
5
+ SHA512:
6
+ metadata.gz: ed5df1caa8891bfa3da2e627d1eccfb21d85d06d08ed4dcce37d8d5eea72aa8b3f6b6551238801be388b836f57f6c0185eea881aefa0964177e10cff4cd52dfb
7
+ data.tar.gz: 1b677c17b260d8c4234967a689e0fa70891c11ccacb65c0c0ad1701995d33fe2e8be0c98b1854fef39a5f767a2d0b51d47e65912dc28e16e81e9892bdb0a74ce
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ ref
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ircmachine.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Chris Davies
2
+
3
+ MIT License
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.
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # IRCMachine
2
+
3
+ A very basic gem for parsing and dealing with the IRC protocol.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'ircmachine'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install ircmachine
18
+
19
+ ## Contributing
20
+
21
+ 1. Fork it ( http://github.com/north636/ircmachine/fork )
22
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
23
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
24
+ 4. Push to the branch (`git push origin my-new-feature`)
25
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'ircmachine'
6
+ t.test_files = FileList['spec/**/*.rb']
7
+ t.verbose = true
8
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ircmachine/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'ircmachine'
8
+ spec.version = IRCMachine::VERSION
9
+ spec.authors = ['Chris Davies']
10
+ spec.email = ['chris.davies.uk@member.mensa.org']
11
+ spec.summary = %q{A simple IRC protocol parser.}
12
+ spec.description = spec.summary
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.5'
22
+ spec.add_development_dependency 'rake'
23
+ end
@@ -0,0 +1,155 @@
1
+ require 'ircmachine/message'
2
+
3
+ module IRCMachine
4
+ module Command
5
+
6
+ class << self
7
+ def cmds
8
+ @cmds ||= {}
9
+ end
10
+ private :cmds
11
+
12
+ def from_msg(msg)
13
+ if (klass = cmds[msg.command]).nil?
14
+ fail ArgumentError, "Unknown command: #{msg.command}"
15
+ else
16
+ klass.new(msg.prefix, *msg.params)
17
+ end
18
+ end
19
+
20
+ def parse(str)
21
+ if (msg = IRCMachine::Message.parse(str)).nil?
22
+ fail ArgumentError, 'Invalid format for IRC message.'
23
+ else
24
+ from_msg(msg)
25
+ end
26
+ end
27
+
28
+ def defcmd(cmd, *arg_names)
29
+ cmd = cmd.strip.upcase
30
+
31
+ klass = Class.new do
32
+ define_method(:initialize) do |prefix = nil, *args|
33
+ instance_variable_set('@prefix', prefix)
34
+
35
+ arg_names.zip(args).each do |e|
36
+ name, value = e[0], e[1]
37
+ instance_variable_set("@#{name}", value)
38
+ end
39
+ end
40
+
41
+ # Create readers for the parameters.
42
+ arg_names.each do |name|
43
+ define_method(name) { instance_variable_get("@#{name}") }
44
+ end
45
+
46
+ define_method(:prefix) { instance_variable_get('@prefix') }
47
+
48
+ define_method(:to_msg) do
49
+ param_values = arg_names.map { |k| instance_variable_get("@#{k}") }.join(' ')
50
+
51
+ IRCMachine::Message.new(
52
+ instance_variable_get('@prefix'),
53
+ cmd,
54
+ param_values
55
+ )
56
+ end
57
+
58
+ define_method(:to_s) { self.to_msg.to_s }
59
+ end
60
+
61
+ const_set("#{cmd.capitalize}Command", klass)
62
+ cmds[cmd] = klass
63
+ end
64
+ private :defcmd
65
+
66
+ # Same as defcmd, but arguments are passed in reverse order. This is to
67
+ # support commands like WHOIS, which has an optional parameter in the
68
+ # middle, rather than at the end...
69
+ def defrcmd(cmd, *arg_names)
70
+ cmd = cmd.strip.upcase
71
+
72
+ klass = Class.new do
73
+ define_method(:initialize) do |prefix = nil, *args|
74
+ instance_variable_set('@prefix', prefix)
75
+
76
+ arg_names.reverse.zip(args.reverse).each do |e|
77
+ name, value = e[0], e[1]
78
+ instance_variable_set("@#{name}", value)
79
+ end
80
+ end
81
+
82
+ # Create readers for the parameters.
83
+ arg_names.each do |name|
84
+ define_method(name) { instance_variable_get("@#{name}") }
85
+ end
86
+
87
+ define_method(:prefix) { instance_variable_get('@prefix') }
88
+
89
+ define_method(:to_msg) do
90
+ param_values = arg_names.reverse.map { |k| instance_variable_get("@#{k}") }.join(' ')
91
+
92
+ IRCMachine::Message.new(
93
+ instance_variable_get('@prefix'),
94
+ cmd,
95
+ param_values
96
+ )
97
+ end
98
+
99
+ define_method(:to_s) { self.to_msg.to_s }
100
+ end
101
+
102
+ const_set("#{cmd.capitalize}Command", klass)
103
+ cmds[cmd] = klass
104
+ end
105
+ private :defrcmd
106
+ end
107
+
108
+ defcmd 'PASS', :password
109
+ defcmd 'NICK', :nickname
110
+ defcmd 'USER', :user, :mode, :unused, :realname, :name, :password
111
+ defcmd 'MODE', :target, :modestring
112
+ defcmd 'SERVICE', :nickname, :reserved, :distribution, :type, :reserved2, :info
113
+ defcmd 'QUIT', :message
114
+ defcmd 'SQUIT', :server, :comment
115
+ defcmd 'JOIN', :channels, :keys
116
+ defcmd 'PART', :channels
117
+ defcmd 'TOPIC', :channel, :topic
118
+ defcmd 'NAMES', :channels, :target
119
+ defcmd 'LIST', :channels, :target
120
+ defcmd 'INVITE', :nickname, :channel
121
+ defcmd 'KICK', :channels, :users, :comment
122
+ defcmd 'PRIVMSG', :target, :message
123
+ defcmd 'NOTICE', :target, :message
124
+ defcmd 'MOTD', :target
125
+ defcmd 'LUSERS', :mask, :target
126
+ defcmd 'VERSION', :target
127
+ defcmd 'STATS', :query, :target
128
+ defcmd 'LINKS', :remote_server, :server_mask
129
+ defcmd 'TIME', :target
130
+ defcmd 'CONNECT', :server, :port, :remote_server
131
+ defcmd 'TRACE', :target
132
+ defcmd 'ADMIN', :target
133
+ defcmd 'INFO', :target
134
+ defcmd 'SERVLIST', :mask, :type
135
+ defcmd 'SQUERY', :service, :text
136
+ defcmd 'WHO', :mask, :o
137
+ defrcmd 'WHOIS', :target, :who
138
+ defcmd 'WHOWAS', :nicknames, :count, :target
139
+ defcmd 'KILL', :nickname, :comment
140
+ defcmd 'PING', :who, :server
141
+ defcmd 'PONG', :who, :server
142
+ defcmd 'ERROR', :message
143
+ defcmd 'AWAY', :text
144
+ defcmd 'REHASH'
145
+ defcmd 'DIE'
146
+ defcmd 'RESTART'
147
+ defcmd 'SUMMON', :user, :target, :channel
148
+ defcmd 'USERS', :target
149
+ defcmd 'WALLOPS', :text
150
+
151
+ # TODO: support multiple nicknames properly?
152
+ defcmd 'USERHOST', :nickname, :nickname2, :nickname3, :nickname4, :nickname5
153
+ defcmd 'ISON', :nickname, :nickname2, :nickname3, :nickname4, :nickname5
154
+ end
155
+ end
@@ -0,0 +1,71 @@
1
+ module IRCMachine
2
+ class IRCSocketAdapter
3
+ attr_reader :socket
4
+
5
+ # As per RFC 2812:
6
+ IRC_MAX_DATA = 512
7
+
8
+ def initialize(socket)
9
+ @socket = socket
10
+ @messages = []
11
+ @messages_mtx = Mutex.new
12
+ @buffer = ''
13
+ @buffer_mtx = Mutex.new
14
+ end
15
+
16
+ def recv(blocking = true)
17
+ # If we have data to return already, return it.
18
+ @messages_mtx.synchronize { return @messages.shift unless @messages.empty? }
19
+
20
+ got_msg = false
21
+ msg = nil
22
+ until got_msg
23
+ data =
24
+ if blocking
25
+ @socket.recv(IRC_MAX_DATA)
26
+ else
27
+ @socket.recv_nonblock(IRC_MAX_DATA)
28
+ end
29
+
30
+ unless data.nil?
31
+ @buffer_mtx.synchronize do
32
+ data.each_char do |c|
33
+ @buffer << c
34
+
35
+ if c == "\n"
36
+ @messages_mtx.synchronize do
37
+ begin
38
+ msg = IRCMachine::Message.parse(@buffer)
39
+ @messages << msg
40
+ rescue ArgumentError
41
+ # => Not recognised; ignore it.
42
+ end
43
+ end
44
+ @buffer = ''
45
+ elsif @buffer.size > IRC_MAX_DATA
46
+ # Too long. Drop it.
47
+ @buffer = ''
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ msg = @messages_mtx.synchronize { @messages.shift unless @messages.empty? }
54
+ got_msg = !blocking || !msg.nil?
55
+ end
56
+
57
+ msg
58
+ end
59
+
60
+ def recv_nonblock
61
+ recv(false)
62
+ end
63
+
64
+ def send(data)
65
+ msg = IRCMachine::Message.parse(data)
66
+ fail ArgumentError, "Invalid IRC data." if msg.nil?
67
+
68
+ @socket.send(msg.to_s)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,53 @@
1
+ module IRCMachine
2
+ class Message
3
+ # Based on RFC 2812, section 2.3.1
4
+ SHORTNAME = /[a-z0-9][a-z0-9-]*[a-z0-9]*/in
5
+ HOSTNAME = /#{SHORTNAME}(?:\.#{SHORTNAME})*/n
6
+ SERVERNAME = /#{HOSTNAME}/n
7
+ SPECIAL = /[\x5b-\x60\x7b-\x7d]/n
8
+ NICKNAME = /[a-z\x5b-\x60\x7b-\x7d][a-z0-9\x5b-\x60\x7b-\x7d-]{,8}/in
9
+ USER = /[\x01-\x09\x0b-\x0c\x0e-\x1f\x21-\x3f\x41-\xff]+/n
10
+ IP4ADDR = /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/n
11
+ IP6ADDR = /(?:[0-9a-f]+(?::[0-9a-f]+){7})|(?:0:0:0:0:0:(?:0|ffff):#{IP4ADDR})/in
12
+ HOSTADDR = /#{IP4ADDR}|#{IP6ADDR}/n
13
+ HOST = /#{HOSTNAME}|#{HOSTADDR}/n
14
+ PREFIX = /#{SERVERNAME}|(?:#{NICKNAME}((?:!#{USER})?@#{HOST})?)/n
15
+ COMMAND = /[a-z]+|[0-9]{3}/in
16
+ NOSPCRLFCL = /[\x01-\x09\x0b-\x0c\x0e-\x1f\x21-\x39\x3b-\xff]/n
17
+ TRAILING = /(?:[: ]|#{NOSPCRLFCL})*/n
18
+ MIDDLE = /#{NOSPCRLFCL}(?::|#{NOSPCRLFCL})*/n
19
+ PARAMS = /(?:(?: #{MIDDLE}){,14}(?: :#{TRAILING})?)|(?:(?: #{MIDDLE}){,14}(?: :?#{TRAILING})?)/n
20
+ MESSAGE = /^(?<prefix>:#{PREFIX} )?(?<command>#{COMMAND})(?<params>#{PARAMS})?\r\n$/n
21
+
22
+ attr_reader :prefix, :command, :params
23
+
24
+ def initialize(prefix, command, params)
25
+ @prefix = prefix && prefix.strip
26
+ @command = command
27
+
28
+ params = (params || '').strip
29
+ @params =
30
+ if params[0] == ':'
31
+ [ params ]
32
+ elsif (trail_index = params.index(' :')).nil?
33
+ params.split(/ +/)
34
+ else
35
+ params[0...trail_index].split(/ +/).push(params[trail_index..-1].strip)
36
+ end
37
+ end
38
+
39
+ def to_s
40
+ str = ''
41
+ str << "#{prefix} " unless prefix.nil?
42
+ str << command
43
+ str << " #{params.join(' ')}" unless params.empty?
44
+ str << "\r\n"
45
+ end
46
+
47
+ def self.parse(str)
48
+ unless (m = MESSAGE.match(str)).nil?
49
+ Message.new(m[:prefix], m[:command], m[:params])
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ module IRCMachine
2
+ VERSION = "0.0.1"
3
+ end
data/lib/ircmachine.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'ircmachine/command'
2
+ require 'ircmachine/message'
3
+ require 'ircmachine/version'
@@ -0,0 +1,47 @@
1
+ require 'minitest/autorun'
2
+
3
+ require 'ircmachine/command'
4
+
5
+ describe IRCMachine::Command do
6
+ describe 'defcmd' do
7
+ it 'should populate arguments correctly' do
8
+ c = IRCMachine::Command.parse("JOIN #channel key\r\n")
9
+ c.channels.must_equal '#channel'
10
+ c.keys.must_equal 'key'
11
+ end
12
+
13
+ it 'should leave fields as nil if not given' do
14
+ c = IRCMachine::Command.parse("JOIN #channel\r\n")
15
+ c.channels.must_equal '#channel'
16
+ c.keys.must_be_nil
17
+ end
18
+
19
+ it 'should produce commands that themselves produce correct Message objects' do
20
+ c = IRCMachine::Command.parse(":foo JOIN #channel key\r\n")
21
+ m = c.to_msg
22
+ m.wont_be_nil
23
+ m.prefix.must_equal ':foo'
24
+ m.command.must_equal 'JOIN'
25
+ m.params.must_equal ['#channel', 'key']
26
+ end
27
+
28
+ it 'should produce commands that themselves produce valid IRC commands with to_s' do
29
+ c = IRCMachine::Command.parse(":foo QUIT :my quit message\r\n")
30
+ c.to_s.must_equal ":foo QUIT :my quit message\r\n"
31
+ end
32
+ end
33
+
34
+ describe 'defrcmd' do
35
+ it 'should populate the last argument first' do
36
+ c = IRCMachine::Command.parse("WHOIS foo\r\n")
37
+ c.target.must_be_nil
38
+ c.who.must_equal 'foo'
39
+ end
40
+
41
+ it 'should populate the arguments in reverse order' do
42
+ c = IRCMachine::Command.parse("WHOIS example.com foo\r\n")
43
+ c.target.must_equal 'example.com'
44
+ c.who.must_equal 'foo'
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,90 @@
1
+ require 'minitest/autorun'
2
+
3
+ require 'ircmachine/ircsocketadapter'
4
+
5
+ describe IRCMachine::IRCSocketAdapter do
6
+ it 'sends valid IRC data' do
7
+ sock = MiniTest::Mock.new
8
+ sock.expect(:send, true, [ "JOIN #channel\r\n" ])
9
+
10
+ sa = IRCMachine::IRCSocketAdapter.new(sock)
11
+ sa.send("JOIN #channel\r\n")
12
+
13
+ sock.verify
14
+ end
15
+
16
+ it 'raises an ArgumentError when trying to send invalid IRC data' do
17
+ sock = MiniTest::Mock.new
18
+ sa = IRCMachine::IRCSocketAdapter.new(sock)
19
+
20
+ proc {
21
+ sa.send("this isn't IRC data!")
22
+ }.must_raise ArgumentError
23
+ end
24
+
25
+ it 'returns Message objects when receiving a single message' do
26
+ sock = MiniTest::Mock.new
27
+ sock.expect(:recv, ":foo@example.com QUIT :some message\r\n", [ Fixnum ])
28
+
29
+ sa = IRCMachine::IRCSocketAdapter.new(sock)
30
+ msg = sa.recv
31
+
32
+ msg.wont_be_nil
33
+ msg.must_be_instance_of IRCMachine::Message
34
+
35
+ sock.verify
36
+ end
37
+
38
+ it 'queues Message objects and returns them in order when receiving multiple messages' do
39
+ sock = MiniTest::Mock.new
40
+ sock.expect(:recv, ":foo@example.com QUIT :some message\r\n:bar@example.com PRIVMSG #chan :blah blah\r\n", [ Fixnum ])
41
+
42
+ sa = IRCMachine::IRCSocketAdapter.new(sock)
43
+ msg = sa.recv
44
+
45
+ msg.wont_be_nil
46
+ msg.must_be_instance_of IRCMachine::Message
47
+ msg.command.must_equal 'QUIT'
48
+
49
+ msg = sa.recv
50
+
51
+ msg.wont_be_nil
52
+ msg.must_be_instance_of IRCMachine::Message
53
+ msg.command.must_equal 'PRIVMSG'
54
+
55
+ sock.verify
56
+ end
57
+
58
+ it 'buffers messages if only partial data is received and does multiple recv if blocking' do
59
+ sock = MiniTest::Mock.new
60
+ sock.expect(:recv, ":foo@example.com QUIT :", [ Fixnum ])
61
+ sock.expect(:recv, "some message\r\n", [ Fixnum ])
62
+
63
+ sa = IRCMachine::IRCSocketAdapter.new(sock)
64
+ msg = sa.recv
65
+
66
+ msg.wont_be_nil
67
+ msg.must_be_instance_of IRCMachine::Message
68
+ msg.command.must_equal 'QUIT'
69
+
70
+ sock.verify
71
+ end
72
+
73
+ it 'buffers messages if only partial data is received, but only does on recv if non-blocking' do
74
+
75
+ sock = MiniTest::Mock.new
76
+ sock.expect(:recv_nonblock, ":foo@example.com QU", [ Fixnum ])
77
+ sock.expect(:recv_nonblock, "IT :blah\r\n", [ Fixnum ])
78
+
79
+ sa = IRCMachine::IRCSocketAdapter.new(sock)
80
+ msg = sa.recv_nonblock
81
+ msg.must_be_nil
82
+
83
+ msg = sa.recv_nonblock
84
+ msg.wont_be_nil
85
+ msg.must_be_instance_of IRCMachine::Message
86
+ msg.command.must_equal 'QUIT'
87
+
88
+ sock.verify
89
+ end
90
+ end
@@ -0,0 +1,59 @@
1
+ require 'minitest/autorun'
2
+
3
+ require 'ircmachine/message'
4
+
5
+ describe IRCMachine::Message do
6
+ it 'should parse basic commands with no prefix and no parameters' do
7
+ m = IRCMachine::Message.parse("QUIT\r\n")
8
+ m.wont_be_nil
9
+ m.command.must_equal 'QUIT'
10
+ m.prefix.must_be_nil
11
+ m.params.must_be_empty
12
+ end
13
+
14
+ it 'should parse commands that have one parameter' do
15
+ m = IRCMachine::Message.parse("JOIN #hello\r\n")
16
+ m.wont_be_nil
17
+ m.command.must_equal 'JOIN'
18
+ m.prefix.must_be_nil
19
+ m.params.size.must_equal 1
20
+ m.params[0].must_equal '#hello'
21
+ end
22
+
23
+ it 'should parse commands that have multiple parameters' do
24
+ m = IRCMachine::Message.parse("PRIVMSG #chan :this is my message\r\n")
25
+ m.wont_be_nil
26
+ m.command.must_equal 'PRIVMSG'
27
+ m.prefix.must_be_nil
28
+ m.params.size.must_equal 2
29
+ m.params[0].must_equal '#chan'
30
+ m.params[1].must_equal ':this is my message'
31
+ end
32
+
33
+ it 'should parse commands with a prefix containing just a nickname' do
34
+ m = IRCMachine::Message.parse(":nick QUIT :blah\r\n")
35
+ m.wont_be_nil
36
+ m.command.must_equal 'QUIT'
37
+ m.prefix.must_equal ':nick'
38
+ m.params.size.must_equal 1
39
+ m.params[0].must_equal ':blah'
40
+ end
41
+
42
+ it 'should parse commands with a prefix containing a nickname and a host' do
43
+ m = IRCMachine::Message.parse(":nick@host QUIT :blah\r\n")
44
+ m.wont_be_nil
45
+ m.command.must_equal 'QUIT'
46
+ m.prefix.must_equal ':nick@host'
47
+ m.params.size.must_equal 1
48
+ m.params[0].must_equal ':blah'
49
+ end
50
+
51
+ it 'should parse commands with a prefix containing a nickname, username and a host' do
52
+ m = IRCMachine::Message.parse(":nick!user@host QUIT :blah\r\n")
53
+ m.wont_be_nil
54
+ m.command.must_equal 'QUIT'
55
+ m.prefix.must_equal ':nick!user@host'
56
+ m.params.size.must_equal 1
57
+ m.params[0].must_equal ':blah'
58
+ end
59
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ircmachine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chris Davies
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: A simple IRC protocol parser.
42
+ email:
43
+ - chris.davies.uk@member.mensa.org
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - ircmachine.gemspec
54
+ - lib/ircmachine.rb
55
+ - lib/ircmachine/command.rb
56
+ - lib/ircmachine/ircsocketadapter.rb
57
+ - lib/ircmachine/message.rb
58
+ - lib/ircmachine/version.rb
59
+ - spec/command_spec.rb
60
+ - spec/ircsocketadapter_spec.rb
61
+ - spec/message_spec.rb
62
+ homepage: ''
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.0.3
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: A simple IRC protocol parser.
86
+ test_files:
87
+ - spec/command_spec.rb
88
+ - spec/ircsocketadapter_spec.rb
89
+ - spec/message_spec.rb