ircmachine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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