irc-socket 0.9

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.
data/README.rdoc ADDED
@@ -0,0 +1,39 @@
1
+ == Description
2
+
3
+ IRCSocket is an IRC wrapper around a TCPSocket. It implements all of the major
4
+ commands laid out in {RFC 2812}[http://irchelp.org/irchelp/rfc/rfc2812.txt].
5
+ All these commands are available as instance methods of an IRCSocket Object.
6
+
7
+ API documentation is available {here}[http://rdoc.injekt.net/irc-socket]
8
+
9
+ == Example
10
+ irc = IRCSocket.new('irc.freenode.org')
11
+ irc.connect
12
+
13
+ if irc.connected?
14
+ irc.nick "HulkHogan"
15
+ irc.user "Hulk", 0, "*", "I am Hulk Hogan"
16
+
17
+ while line = irc.read
18
+
19
+ # Join a channel after MOTD
20
+ if line.split[1] == '376'
21
+ irc.join "#mychannel"
22
+ end
23
+
24
+ puts "Received: #{line}"
25
+ end
26
+ end
27
+
28
+ == Installation
29
+ gem install irc-socket
30
+
31
+ Or alternatively you can clone the Github repository
32
+ git clone https://github.com/injekt/irc-socket
33
+
34
+
35
+ == Author
36
+ * Lee Jarvis - ljjarvis@gmail.com
37
+
38
+ == Notes
39
+ I may have missed something in the RFC. Patches welcome.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require "rake"
2
+ require "rake/clean"
3
+ require "rake/gempackagetask"
4
+ require "spec/rake/spectask"
5
+ require "rake/rdoctask"
6
+
7
+ NAME = 'irc-socket'
8
+ VERSION = '0.9'
9
+ CLEAN.include ["*.gem", "rdoc"]
10
+
11
+ RDOC_OPTS = [
12
+ "-U", "--main", "README.rdoc",
13
+ "--op", "rdoc",
14
+ ]
15
+
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = "rdoc"
18
+ rdoc.options += RDOC_OPTS
19
+ rdoc.rdoc_files.add %w(README.rdoc lib/irc-socket.rb)
20
+ end
21
+
22
+ desc "Run specs"
23
+ Spec::Rake::SpecTask.new('spec') do |t|
24
+ t.spec_files = Dir['spec/*.rb']
25
+ end
26
+
27
+ desc "Package"
28
+ task :package => [:clean] do |p|
29
+ sh "gem build #{NAME}.gemspec"
30
+ end
31
+
32
+ desc "Install gem"
33
+ task :install => [:package] do
34
+ sh "sudo gem install ./#{NAME}-#{VERSION} --local"
35
+ end
36
+
37
+ desc "Uninstall gem"
38
+ task :uninstall => [:clean] do
39
+ sh "sudo gem uninstall #{NAME}"
40
+ end
41
+
42
+ desc "Upload gem to gemcutter"
43
+ task :release => [:package] do
44
+ sh "gem push ./#{NAME}-#{VERSION}.gem"
45
+ end
46
+
47
+ desc "Print #{NAME} version"
48
+ task :version do
49
+ puts VERSION
50
+ end
51
+
52
+ desc "Upload rdoc to injekt.net"
53
+ task :upload => [:clean, :rdoc] do
54
+ sh("scp -r rdoc/* injekt@injekt.net:/var/www/injekt.net/rdoc/irc-socket")
55
+ end
56
+
57
+ task :default => [:spec]
58
+
data/lib/irc-socket.rb ADDED
@@ -0,0 +1,290 @@
1
+ require 'socket'
2
+
3
+ # == Author
4
+ # * Lee Jarvis - ljjarvis@gmail.com
5
+ #
6
+ #
7
+ # == Description
8
+ #
9
+ # IRCSocket is an IRC wrapper around a TCPSocket. It implements all of the major
10
+ # commands laid out in {RFC 2812}[http://irchelp.org/irchelp/rfc/rfc2812.txt].
11
+ # All these commands are available as instance methods of an IRCSocket Object.
12
+ #
13
+ # == Example
14
+ # irc = IRCSocket.new('irc.freenode.org')
15
+ # irc.connect
16
+ #
17
+ # if irc.connected?
18
+ # irc.nick "HulkHogan"
19
+ # irc.user "Hulk", 0, "*", "I am Hulk Hogan"
20
+ #
21
+ # while line = irc.read
22
+ #
23
+ # # Join a channel after MOTD
24
+ # if line.split[1] == '376'
25
+ # irc.join "#mychannel"
26
+ # end
27
+ #
28
+ # puts "Received: #{line}"
29
+ # end
30
+ # end
31
+ #
32
+ # === Block Form
33
+ # IRCSocket.new('irc.freenode.org') do |irc|
34
+ # irc.nick "SpongeBob"
35
+ # irc.user "Spongey", 0, "*", "Square Pants"
36
+ #
37
+ # puts irc.read
38
+ # end
39
+ class IRCSocket
40
+
41
+ # The server our socket is connected to
42
+ attr_reader :server
43
+
44
+ # The port our socket is connected on
45
+ attr_reader :port
46
+
47
+ # The TCPSocket instance
48
+ attr_reader :socket
49
+
50
+ # Creates a new IRCSocket and automatically connects
51
+ #
52
+ # === Example
53
+ # irc = IRCSocket.open('irc.freenode.org')
54
+ #
55
+ # while data = irc.read
56
+ # puts data
57
+ # end
58
+ def self.open(server, port=6667)
59
+ irc = new(server, port)
60
+ irc.connect
61
+ irc
62
+ end
63
+
64
+ # Create a new IRCSocket to connect to +server+ on +port+. Defaults to port 6667.
65
+ # If an optional code block is given, it will be passed an instance of the IRCSocket.
66
+ # NOTE: Using the block form does not mean the socket will send the applicable QUIT
67
+ # command to leave the IRC server. You must send this yourself.
68
+ def initialize(server, port=6667)
69
+ @server = server
70
+ @port = port
71
+
72
+ @socket = nil
73
+ @connected = false
74
+
75
+ if block_given?
76
+ connect
77
+ yield self
78
+ end
79
+ end
80
+
81
+ # Check if our socket is alive and connected to an IRC server
82
+ def connected?
83
+ @connected
84
+ end
85
+ alias connected connected?
86
+
87
+ # Connect to an IRC server, returns true on a successful connection, or
88
+ # raises otherwise
89
+ def connect
90
+ @socket = TCPSocket.new(server, port)
91
+ rescue Interrupt
92
+ raise
93
+ rescue Exception
94
+ raise
95
+ else
96
+ @connected = true
97
+ end
98
+
99
+ # Read the next line in from the server. If no arguments are passed
100
+ # the line will have the CRLF chomp'ed. Returns nil if no data could be read
101
+ def read(chompstr="\r\n")
102
+ if data = @socket.gets("\r\n")
103
+ data.chomp(chompstr) if chompstr
104
+ data
105
+ else
106
+ nil
107
+ end
108
+ rescue IOError
109
+ nil
110
+ end
111
+
112
+ # Write to our Socket and append CRLF
113
+ def write(data)
114
+ @socket.write(data + "\r\n")
115
+ rescue IOError
116
+ raise
117
+ end
118
+
119
+ # Sugar for #write
120
+ def raw(*args) # :nodoc:
121
+ args.last.insert(0, ':') unless args.last.nil?
122
+ args.join(' ').strip
123
+ end
124
+
125
+ # More sugar
126
+ def write_optional(command, *optional) # :nodoc:
127
+ command = "#{command} #{optional.join(' ')}" if optional
128
+ write(command.strip)
129
+ end
130
+ private :raw, :write_optional
131
+
132
+ # Send PASS command
133
+ def pass(password)
134
+ write("PASS #{password}")
135
+ end
136
+
137
+ # Send NICK command
138
+ def nick(nickname)
139
+ write("NICK #{nickname}")
140
+ end
141
+
142
+ # Send USER command -
143
+ def user(user, mode, unused, realname)
144
+ write("USER #{user} #{mode} #{unused} :#{realname}")
145
+ end
146
+
147
+ # Send OPER command
148
+ def oper(name, password)
149
+ write("OPER #{name} #{password}")
150
+ end
151
+
152
+ # Send the MODE command.
153
+ # Should probably implement a better way of doing this
154
+ def mode(channel, *modes)
155
+ write("MODE #{channel} #{modes.join(' ')}")
156
+ end
157
+
158
+ # Send QUIT command
159
+ def quit(message=nil)
160
+ raw("QUIT", message)
161
+ end
162
+
163
+ # Send JOIN command - Join a channel with given password
164
+ def join(channel, password=nil)
165
+ write("JOIN #{channel}")
166
+ end
167
+
168
+ # Send PART command -
169
+ def part(channel, message=nil)
170
+ raw("PART", channel, message)
171
+ end
172
+
173
+ # Send TOPIC command
174
+ def topic(channel, topic=nil)
175
+ raw("TOPIC", channel, topic)
176
+ end
177
+
178
+ # Send NAMES command
179
+ def names(*channels)
180
+ write("NAMES #{channels.join(',') unless channels.empty?}")
181
+ end
182
+
183
+ # Send LIST command
184
+ def list(*channels)
185
+ write("LIST #{channels.join(',') unless channels.empty?}")
186
+ end
187
+
188
+ # Send INVITE
189
+ def invite(nickname, channel)
190
+ write("INVITE #{nickname} #{channel}")
191
+ end
192
+
193
+ # Send KICK
194
+ def kick(channel, user, comment=nil)
195
+ raw("KICK", channel, user, comment)
196
+ end
197
+
198
+ # Send PRIVMSG
199
+ def privmsg(target, message)
200
+ write("PRIVMSG #{target} :#{message}")
201
+ end
202
+
203
+ # Send NOTICE
204
+ def notice(target, message)
205
+ write("NOTICE #{target} :#{message}")
206
+ end
207
+
208
+ # Send MOTD
209
+ def motd(target=nil)
210
+ write_optional("MOTD", target)
211
+ end
212
+
213
+ # Send VERSION
214
+ def version(target=nil)
215
+ write_optional("VERSION", target)
216
+ end
217
+
218
+ # Send STATS
219
+ def stats(*params)
220
+ write_optional("STATS", params)
221
+ end
222
+
223
+ # Send TIME
224
+ def time(target=nil)
225
+ write_optional("TIME", target)
226
+ end
227
+
228
+ # Send INFO
229
+ def info(target=nil)
230
+ write_optional("INFO", target)
231
+ end
232
+
233
+ # Send SQUERY
234
+ def squery(target, message)
235
+ write("SQUERY #{target} :#{message}")
236
+ end
237
+
238
+ # Send WHO
239
+ def who(*params)
240
+ write_optional("WHO", params)
241
+ end
242
+
243
+ # Send WHOIS
244
+ def whois(*params)
245
+ write_optional("WHOIS", params)
246
+ end
247
+
248
+ # Send WHOWAS
249
+ def whowas(*params)
250
+ write_optional("WHOWAS", params)
251
+ end
252
+
253
+ # Send KILL
254
+ def kill(user, message)
255
+ write("KILL #{user} :#{message}")
256
+ end
257
+
258
+ # Send PING
259
+ def ping(server)
260
+ write("PING #{server}")
261
+ end
262
+
263
+ # Send PONG
264
+ def pong(server)
265
+ write("PONG #{server}")
266
+ end
267
+
268
+ # Send AWAY
269
+ def away(message=nil)
270
+ raw("AWAY", message)
271
+ end
272
+
273
+ # Send USERS
274
+ def users(target=nil)
275
+ write_optional("USERS", target)
276
+ end
277
+
278
+ # Send USERHOST
279
+ def userhost(*users)
280
+ write("USERHOST #{users.join(' ')}")
281
+ end
282
+
283
+ # Close our socket instance
284
+ def close
285
+ @socket.close if connected?
286
+ end
287
+
288
+ end
289
+
290
+
@@ -0,0 +1,81 @@
1
+ require File.expand_path('../../lib/irc-socket', __FILE__)
2
+
3
+ class IRCSocket
4
+ def write(data)
5
+ return data
6
+ end
7
+ end
8
+
9
+ commands = [
10
+ [:pass, %w(foobar), "PASS foobar"],
11
+ [:nick, %(ipsum), "NICK ipsum"],
12
+ [:user, ["guest", 0, '*', "real name"], "USER guest 0 * :real name"],
13
+ [:oper, %w(foo bar), "OPER foo bar"],
14
+ [:mode, %w(#foo +v bar), "MODE #foo +v bar"],
15
+ [:quit, %w(goodbye), "QUIT :goodbye"],
16
+ [:join, %w(#mychan), "JOIN #mychan"],
17
+ [:part, %w(#mychan), "PART #mychan"],
18
+ [:part, %w(#mychan cya!), "PART #mychan :cya!", "with part message"],
19
+ [:topic, %w(#mychan newtopic), "TOPIC #mychan :newtopic"],
20
+ [:names, %w(#foo #bar), "NAMES #foo,#bar"],
21
+ [:list, %w(#foo #bar), "LIST #foo,#bar"],
22
+ [:invite, %w(foo #mychan), "INVITE foo #mychan"],
23
+ [:kick, %w(#chan villian), "KICK #chan villian"],
24
+ [:kick, %w(#chan villian gtfo!), "KICK #chan villian :gtfo!", "with kick reason"],
25
+ [:privmsg, ['#chan', 'foo bar baz'], "PRIVMSG #chan :foo bar baz"],
26
+ [:notice, ['#chan', 'foo bar baz'], "NOTICE #chan :foo bar baz"],
27
+ [:motd, %w(someserver), "MOTD someserver"],
28
+ [:version, %w(anotherserver), "VERSION anotherserver"],
29
+ [:stats, %w(m server), "STATS m server"],
30
+ [:time, %w(irc.someserver.net), "TIME irc.someserver.net"],
31
+ [:info, %w(foobar), "INFO foobar"],
32
+ [:squery, %w(irchelp HELPME), "SQUERY irchelp :HELPME"],
33
+ [:who, %w(*.com o), "WHO *.com o"],
34
+ [:whois, %w(foo.org user), "WHOIS foo.org user"],
35
+ [:whowas, %w(foo.org user), "WHOWAS foo.org user"],
36
+ [:kill, ['badperson', 'get out!'], "KILL badperson :get out!"],
37
+ [:ping, %w(010123444), "PING 010123444"],
38
+ [:pong, %w(irc.foobar.org), "PONG irc.foobar.org"],
39
+ [:away, [], "AWAY"],
40
+ [:away, ['gone for lunch'], "AWAY :gone for lunch"],
41
+ [:users, %w(irc.foobar.org), "USERS irc.foobar.org"],
42
+ [:userhost, %w(foo bar baz), "USERHOST foo bar baz"],
43
+ ]
44
+
45
+ describe "IRCSocket" do
46
+ before do
47
+ @irc = IRCSocket.new('irc.myserver.net')
48
+ end
49
+
50
+ describe "::new" do
51
+ it "should return an IRCSocket" do
52
+ @irc.class.should == IRCSocket
53
+ end
54
+
55
+ it "should default to port 6667" do
56
+ @irc.port.should == 6667
57
+ end
58
+
59
+ it "should not automatically connect" do
60
+ @irc.connected.should == false
61
+ end
62
+
63
+ it "should set socket instance as nil" do
64
+ @irc.socket.should == nil
65
+ end
66
+
67
+ end
68
+
69
+ describe "IRC commands as per rfc2812" do
70
+ commands.each do |requirements|
71
+ meth, params, pass, extra = *requirements
72
+ describe "##{meth}" do
73
+ it "should send a #{meth.to_s.upcase} command #{extra if extra}" do
74
+ @irc.send(meth, *params).should == pass
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: irc-socket
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 9
8
+ version: "0.9"
9
+ platform: ruby
10
+ authors:
11
+ - Lee 'injekt' Jarvis
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-04-22 00:00:00 +01:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: bacon
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 1
28
+ - 1
29
+ - 0
30
+ version: 1.1.0
31
+ type: :development
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 1
42
+ - 3
43
+ - 0
44
+ version: 1.3.0
45
+ type: :development
46
+ version_requirements: *id002
47
+ description: An IRC wrapper around TCPSocket
48
+ email: ljjarvis@gmail.com
49
+ executables: []
50
+
51
+ extensions: []
52
+
53
+ extra_rdoc_files:
54
+ - README.rdoc
55
+ files:
56
+ - README.rdoc
57
+ - Rakefile
58
+ - spec/irc-socket_spec.rb
59
+ - lib/irc-socket.rb
60
+ has_rdoc: true
61
+ homepage: http://wiki.github.com/injekt/irc-socket
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options:
66
+ - --quiet
67
+ - --main
68
+ - README.rdoc
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 1
77
+ - 8
78
+ - 4
79
+ version: 1.8.4
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.6
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: An IRC wrapper around TCPSocket
94
+ test_files: []
95
+