irc-socket 0.9

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