Ruby-IRC 1.0.11 → 1.0.12

Sign up to get free protection for your applications and to get access to all the features.
data/lib/IRC.rb CHANGED
@@ -13,7 +13,7 @@ require 'IRCUtil'
13
13
  class IRC
14
14
  @channels = nil
15
15
  # Create a new IRC Object instance
16
- def initialize( nick, server, port, realname='RBot')
16
+ def initialize( nick, server, port, realname='RBot', options = {})
17
17
  @nick = nick
18
18
  @server = server
19
19
  @port = port
@@ -21,9 +21,8 @@ class IRC
21
21
  @channels = Array.new(0)
22
22
  # Some good default Event handlers. These can and will be overridden by users.
23
23
  # Thses make changes on the IRCbot object. So they need to be here.
24
-
25
- # Topic events can come on two tags, so we create on proc to handle them.
26
24
 
25
+ # Topic events can come on two tags, so we create one proc to handle them.
27
26
  topic_proc = Proc.new { |event|
28
27
  self.channels.each { |chan|
29
28
  if chan == event.channel
@@ -34,7 +33,7 @@ class IRC
34
33
 
35
34
  IRCEvent.add_handler('332', topic_proc)
36
35
  IRCEvent.add_handler('topic', topic_proc)
37
-
36
+ @@options = options;
38
37
 
39
38
  end
40
39
 
@@ -64,7 +63,7 @@ class IRC
64
63
  trap("INT", quithandler)
65
64
  trap("TERM", quithandler)
66
65
 
67
- IRCConnection.handle_connection(@server, @port, @nick, @realname) do
66
+ IRCConnection.handle_connection(@server, @port, @nick, @realname, @@options) do
68
67
  # Log in information moved to IRCConnection
69
68
  @threads = []
70
69
  IRCConnection.main do |event|
@@ -75,6 +74,8 @@ class IRC
75
74
  else
76
75
  thread_event(event)
77
76
  end
77
+ # Memory leak patch thanks to Patrick Sinclair
78
+ @threads.delete_if {|thr| thr.stop? }
78
79
  end
79
80
  @threads.each {|thr| thr.join }
80
81
  end
@@ -13,7 +13,7 @@ require 'IRCUtil'
13
13
  class IRC
14
14
  @channels = nil
15
15
  # Create a new IRC Object instance
16
- def initialize( nick, server, port, realname='RBot')
16
+ def initialize( nick, server, port, realname='RBot', options = {})
17
17
  @nick = nick
18
18
  @server = server
19
19
  @port = port
@@ -21,9 +21,8 @@ class IRC
21
21
  @channels = Array.new(0)
22
22
  # Some good default Event handlers. These can and will be overridden by users.
23
23
  # Thses make changes on the IRCbot object. So they need to be here.
24
-
25
- # Topic events can come on two tags, so we create on proc to handle them.
26
24
 
25
+ # Topic events can come on two tags, so we create one proc to handle them.
27
26
  topic_proc = Proc.new { |event|
28
27
  self.channels.each { |chan|
29
28
  if chan == event.channel
@@ -34,7 +33,7 @@ class IRC
34
33
 
35
34
  IRCEvent.add_handler('332', topic_proc)
36
35
  IRCEvent.add_handler('topic', topic_proc)
37
-
36
+ @@options = options;
38
37
 
39
38
  end
40
39
 
@@ -64,15 +63,19 @@ class IRC
64
63
  trap("INT", quithandler)
65
64
  trap("TERM", quithandler)
66
65
 
67
- IRCConnection.handle_connection(@server, @port, @nick, @realname) do
66
+ IRCConnection.handle_connection(@server, @port, @nick, @realname, @@options) do
68
67
  # Log in information moved to IRCConnection
69
- threads = []
68
+ @threads = []
70
69
  IRCConnection.main do |event|
71
- threads << Thread.new(event) {|localevent|
72
- localevent.process
73
- }
70
+ if event.kind_of?(Array)
71
+ event.each {|event|
72
+ thread_event(event)
73
+ }
74
+ else
75
+ thread_event(event)
76
+ end
74
77
  end
75
- threads.each {|thr| thr.join }
78
+ @threads.each {|thr| thr.join }
76
79
  end
77
80
  end
78
81
 
@@ -150,4 +153,10 @@ class IRC
150
153
  def get_user_info(user)
151
154
  IRCConnection.send_to_server("WHO #{user}")
152
155
  end
156
+ private
157
+ def thread_event (event)
158
+ @threads << Thread.new(event) {|localevent|
159
+ localevent.process
160
+ }
161
+ end
153
162
  end
@@ -8,11 +8,15 @@ class IRCConnection
8
8
  @@last_send = Time.now.to_f
9
9
  @@message_delay = 0.2 # Default delay to 1 fifth of a second.
10
10
  # Creates a socket connection and then yields.
11
- def IRCConnection.handle_connection(server, port, nick='ChangeMe', realname='MeToo' )
11
+ def IRCConnection.handle_connection(server, port, nick='ChangeMe', realname='MeToo', options = nil)
12
12
  @server = server;
13
13
  @port = port
14
14
  @nick = nick
15
15
  @realname = realname
16
+ @@options = options
17
+ if options.nil?
18
+ @@options = Array.new(0)
19
+ end
16
20
  socket = create_tcp_socket(server, port)
17
21
  add_IO_socket(socket) {|sock|
18
22
  begin
@@ -22,7 +26,7 @@ class IRCConnection
22
26
  # after sleeping for 10 second.
23
27
  remove_IO_socket(sock)
24
28
  sleep 10
25
- handle_connection(@server, @port, @nick, @realname)
29
+ handle_connection(@server, @port, @nick, @realname, @@options)
26
30
  end
27
31
  }
28
32
  send_to_server "NICK #{nick}"
@@ -34,7 +38,18 @@ class IRCConnection
34
38
  end
35
39
 
36
40
  def IRCConnection.create_tcp_socket(server, port)
37
- @@socket = TCPsocket.open(server, port)
41
+ # Now with SSL Support. Thanks to dominiek@digigen.nl for the idea on this.
42
+ tcpsocket = TCPsocket.open(server, port)
43
+ if @@options[:use_ssl]
44
+ ssl_context = OpenSSL::SSL::SSLContext.new()
45
+ ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
46
+ @@socket = OpenSSL::SSL::SSLSocket.new(tcpsocket, ssl_context)
47
+ @@socket.sync = true
48
+ @@socket.connect
49
+ else
50
+ @@socket = tcpsocket
51
+ end
52
+
38
53
  if block_given?
39
54
  yield
40
55
  @@socket.close
@@ -72,12 +87,11 @@ class IRCConnection
72
87
  if !read_sockets.nil?
73
88
  read_sockets[0].each {|sock|
74
89
  if sock.eof? && sock == @@socket
75
- p "Detected Socket Close"
76
90
  remove_IO_socket(sock)
77
91
  sleep 10
78
92
  handle_connection(@server, @port, @nick, @realname)
79
93
  else
80
- yield @@events[sock.to_i].call(sock)
94
+ yield @@events[sock.object_id.to_i].call(sock)
81
95
  end
82
96
  }
83
97
  end
@@ -108,7 +122,7 @@ class IRCConnection
108
122
  # Adds a new socket to the list of sockets to monitor for new data.
109
123
  def IRCConnection.add_IO_socket(socket, &event_generator)
110
124
  @@readsockets.push(socket)
111
- @@events[socket.to_i] = event_generator
125
+ @@events[socket.object_id.to_i] = event_generator
112
126
  end
113
127
 
114
128
  def IRCConnection.remove_IO_socket(sock)
@@ -1,15 +1,22 @@
1
1
 
2
2
  # Handles connection to IRC Server
3
3
  class IRCConnection
4
- @@quit = 0
5
- @@readsockets = Array.new(0)
6
- @@events = Hash.new()
4
+ @@quit = 0
5
+ @@readsockets = Array.new(0)
6
+ @@output_buffer = Array.new(0)
7
+ @@events = Hash.new()
8
+ @@last_send = Time.now.to_f
9
+ @@message_delay = 0.2 # Default delay to 1 fifth of a second.
7
10
  # Creates a socket connection and then yields.
8
- def IRCConnection.handle_connection(server, port, nick='ChangeMe', realname='MeToo' )
11
+ def IRCConnection.handle_connection(server, port, nick='ChangeMe', realname='MeToo', options = nil)
9
12
  @server = server;
10
13
  @port = port
11
14
  @nick = nick
12
15
  @realname = realname
16
+ @@options = options
17
+ if options.nil?
18
+ @@options = Array.new(0)
19
+ end
13
20
  socket = create_tcp_socket(server, port)
14
21
  add_IO_socket(socket) {|sock|
15
22
  begin
@@ -19,7 +26,7 @@ class IRCConnection
19
26
  # after sleeping for 10 second.
20
27
  remove_IO_socket(sock)
21
28
  sleep 10
22
- handle_connection(@server, @port, @nick, @realname)
29
+ handle_connection(@server, @port, @nick, @realname, @@options)
23
30
  end
24
31
  }
25
32
  send_to_server "NICK #{nick}"
@@ -31,7 +38,18 @@ class IRCConnection
31
38
  end
32
39
 
33
40
  def IRCConnection.create_tcp_socket(server, port)
34
- @@socket = TCPsocket.open(server, port)
41
+ # Now with SSL Support. Thanks to dominiek@digigen.nl for the idea on this.
42
+ tcpsocket = TCPsocket.open(server, port)
43
+ if @@options[:use_ssl]
44
+ ssl_context = OpenSSL::SSL::SSLContext.new()
45
+ ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
46
+ @@socket = OpenSSL::SSL::SSLSocket.new(tcpsocket, ssl_context)
47
+ @@socket.sync = true
48
+ @@socket.connect
49
+ else
50
+ @@socket = tcpsocket
51
+ end
52
+
35
53
  if block_given?
36
54
  yield
37
55
  @@socket.close
@@ -42,9 +60,16 @@ class IRCConnection
42
60
 
43
61
  # Sends a line of text to the server
44
62
  def IRCConnection.send_to_server(line)
63
+ puts "sending line #{line}"
45
64
  @@socket.write(line + "\n")
46
65
  end
47
66
 
67
+ # Adds data an output buffer. This let's us keep a handle on how
68
+ # fast we send things. Yay.
69
+ def IRCConnection.output_push(line)
70
+ @@output_buffer.push(line)
71
+ end
72
+
48
73
  # This loop monitors all IO_Sockets IRCConnection controls
49
74
  # (including the IRC socket) and yields events to the IO_Sockets
50
75
  # event handler.
@@ -59,24 +84,39 @@ class IRCConnection
59
84
  # Makes one single loop pass, checking all sockets for data to read,
60
85
  # and yields the data to the sockets event handler.
61
86
  def IRCConnection.do_one_loop
62
- read_sockets = select(@@readsockets, nil, nil, nil);
63
- read_sockets[0].each {|sock|
64
- if sock.eof? && sock == @@socket
65
- p "Detected Socket Close"
66
- remove_IO_socket(sock)
67
- sleep 10
68
- handle_connection(@server, @port, @nick, @realname)
69
- else
70
- yield @@events[sock.to_i].call(sock)
87
+ read_sockets = select(@@readsockets, nil, nil, 0.1);
88
+ if !read_sockets.nil?
89
+ puts "STUFF TO READ!"
90
+ read_sockets[0].each {|sock|
91
+ if sock.eof? && sock == @@socket
92
+ p "Detected Socket Close"
93
+ remove_IO_socket(sock)
94
+ sleep 10
95
+ handle_connection(@server, @port, @nick, @realname)
96
+ else
97
+ yield @@events[sock.object_id.to_i].call(sock)
98
+ end
99
+ }
100
+ end
101
+ if @@output_buffer.length > 0
102
+ timer = Time.now.to_f
103
+ if (timer > @@last_send + @@message_delay)
104
+ message = @@output_buffer.shift();
105
+ if !message.nil?
106
+ IRCConnection.send_to_server(message);
107
+ @@last_send = timer
108
+ end
71
109
  end
72
- }
110
+ end
73
111
  end
74
112
 
75
113
  # Ends connection to the irc server
76
114
  def IRCConnection.quit
77
115
  @@quit = 1
78
116
  end
79
-
117
+ def IRCConnection.delay=(delay)
118
+ @@message_delay = delay.to_f
119
+ end
80
120
  # Retrieves user info from the server
81
121
  def IRCConnection.get_user_info(user)
82
122
  IRCConnection.send_to_server("WHOIS #{user}")
@@ -85,10 +125,10 @@ class IRCConnection
85
125
  # Adds a new socket to the list of sockets to monitor for new data.
86
126
  def IRCConnection.add_IO_socket(socket, &event_generator)
87
127
  @@readsockets.push(socket)
88
- @@events[socket.to_i] = event_generator
128
+ @@events[socket.object_id.to_i] = event_generator
89
129
  end
90
130
 
91
- def IRCConnection.remove_IO_socket(socket)
131
+ def IRCConnection.remove_IO_socket(sock)
92
132
  sock.close
93
133
  @@readsockets.delete_if {|item| item == sock }
94
134
  end
@@ -26,7 +26,6 @@ class IRCEvent
26
26
  # mess_parts[1] is the message that was sent
27
27
  @message = mess_parts[1]
28
28
  @stats = mess_parts[0].scan(/[-`\^\{\}\[\]\w.\#\@\+]+/)
29
-
30
29
  if @stats[0].match(/^PING/)
31
30
  @event_type = 'ping'
32
31
  elsif @stats[1] && @stats[1].match(/^\d+/)
@@ -45,9 +44,12 @@ class IRCEvent
45
44
  @channel = @stats[3] if @stats[3] && !@channel
46
45
  @target = @stats[5] if @stats[5]
47
46
  @mode = @stats[4] if @stats[4]
47
+ if @mode.nil? && @event_type == 'mode'
48
+ # Server modes (like +i) are sent in the 'message' part, and not
49
+ # the 'stat' part of the message.
50
+ @mode = @message
51
+ end
48
52
 
49
-
50
-
51
53
  # Unfortunatly, not all messages are created equal. This is our
52
54
  # special exceptions section
53
55
  if @event_type == 'join'
@@ -83,7 +85,6 @@ class IRCEvent
83
85
  handled = 1
84
86
  end
85
87
  if !handled
86
- # puts "No handler for event type #@event_type in #{self.class}"
87
88
  end
88
89
  end
89
90
  end
@@ -25,8 +25,7 @@ class IRCEvent
25
25
  # mess_parts[0] is server info
26
26
  # mess_parts[1] is the message that was sent
27
27
  @message = mess_parts[1]
28
- @stats = mess_parts[0].scan(/[-\w.\#\@\+]+/)
29
-
28
+ @stats = mess_parts[0].scan(/[-`\^\{\}\[\]\w.\#\@\+]+/)
30
29
  if @stats[0].match(/^PING/)
31
30
  @event_type = 'ping'
32
31
  elsif @stats[1] && @stats[1].match(/^\d+/)
@@ -45,9 +44,14 @@ class IRCEvent
45
44
  @channel = @stats[3] if @stats[3] && !@channel
46
45
  @target = @stats[5] if @stats[5]
47
46
  @mode = @stats[4] if @stats[4]
47
+ if @mode.nil? && @event_type == 'mode'
48
+ # Server modes (like +i) are sent in the 'message' part, and not
49
+ # the 'stat' part of the message.
50
+ @mode = @message
51
+ end
48
52
 
49
-
50
-
53
+ puts "Line: #{line}"
54
+ puts "Breakdown #{@stats.join(",")}"
51
55
  # Unfortunatly, not all messages are created equal. This is our
52
56
  # special exceptions section
53
57
  if @event_type == 'join'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
2
+ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: Ruby-IRC
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.0.11
7
- date: 2007-11-08 00:00:00 -08:00
6
+ version: 1.0.12
7
+ date: 2008-06-10 00:00:00 -07:00
8
8
  summary: An IRC Client library
9
9
  require_paths:
10
- - lib
10
+ - lib
11
11
  email: cboyer@musiciansfriend.com
12
12
  homepage: http://www.pulpreligion.org
13
13
  rubyforge_project:
@@ -18,39 +18,34 @@ bindir: bin
18
18
  has_rdoc: "true"
19
19
  required_ruby_version: !ruby/object:Gem::Version::Requirement
20
20
  requirements:
21
- - - ">"
22
- - !ruby/object:Gem::Version
23
- version: 0.0.0
21
+ -
22
+ - ">"
23
+ - !ruby/object:Gem::Version
24
+ version: 0.0.0
24
25
  version:
25
26
  platform: ruby
26
27
  signing_key:
27
28
  cert_chain:
28
29
  post_install_message:
29
30
  authors:
30
- - Chris Boyer
31
+ - Chris Boyer
31
32
  files:
32
- - lib/IRCEvent.rb
33
- - lib/IRC.rb
34
- - lib/IRC.rb.~1.8.~
35
- - lib/IRCChannel.rb
36
- - lib/IRCConnection.rb
37
- - lib/IRCUser.rb
38
- - lib/IRCUtil.rb
39
- - lib/eventmap.yml
40
- - lib/IRCConnection.rb.~1.4.~
41
- - lib/IRCEvent.rb.~1.8.~
42
- - README
33
+ - lib/eventmap.yml
34
+ - lib/IRC.rb
35
+ - lib/IRC.rb.~1.10.~
36
+ - lib/IRCChannel.rb
37
+ - lib/IRCConnection.rb
38
+ - lib/IRCConnection.rb.~1.6.~
39
+ - lib/IRCEvent.rb
40
+ - lib/IRCEvent.rb.~1.10.~
41
+ - lib/IRCUser.rb
42
+ - lib/IRCUtil.rb
43
+ - README
43
44
  test_files: []
44
-
45
45
  rdoc_options: []
46
-
47
46
  extra_rdoc_files:
48
- - README
47
+ - README
49
48
  executables: []
50
-
51
49
  extensions: []
52
-
53
50
  requirements: []
54
-
55
- dependencies: []
56
-
51
+ dependencies: []