ichverstehe-isaac 0.2.2 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.rdoc +7 -14
  2. data/isaac.gemspec +3 -2
  3. data/lib/isaac.rb +103 -66
  4. metadata +2 -2
data/README.rdoc CHANGED
@@ -45,6 +45,13 @@ If you want to match private messages use the +on :private+ event:
45
45
  msg nick, "Login successful!"
46
46
  end
47
47
 
48
+ You can also pass the RegExp captures as block arguments:
49
+
50
+ on :channel, /catch this: (.*) and this: (.*)/ do |first, last|
51
+ # `first` will contain the first regexp capture,
52
+ # `last` the second.
53
+ end
54
+
48
55
  === Defining helpers
49
56
  Helpers should not be defined in the top level, but instead using the +helpers+-constructor:
50
57
 
@@ -67,20 +74,6 @@ Errors, as specified by RFC 1459, can be reacted upon as well. If you e.g. try t
67
74
 
68
75
  Available variables: +nick+ and +channel+.
69
76
 
70
- === Send commands from outside an event (not implemented in Shaft atm)
71
- You might want to send messages, join channels etc. without it strictly being the result of an on()-event, e.g. send a message every time a RSS feed is updated or whatever. You can use +Isaac.execute+ for that, and all your normal commands, +msg+, +join+, +topic+ etc. will be available:
72
-
73
- class K
74
- def smoke(brand)
75
- Isaac.execute { msg "harryjr", "you should smoke #{brand} cigarettes" }
76
- end
77
- end
78
-
79
- on :connect do
80
- k = K.new
81
- k.smoke("Lucky Strike")
82
- end
83
-
84
77
  == Contribute
85
78
  The source is hosted at GitHub: http://github.com/ichverstehe/isaac
86
79
 
data/isaac.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "isaac"
3
- s.version = "0.2.2"
4
- s.date = "2009-02-23"
3
+ s.version = "0.2.4"
4
+ s.date = "2009-04-01"
5
5
  s.summary = "The smallish DSL for writing IRC bots"
6
6
  s.email = "harry@vangberg.name"
7
7
  s.homepage = "http://github.com/ichverstehe/isaac"
@@ -16,3 +16,4 @@ Gem::Specification.new do |s|
16
16
  s.rdoc_options = ["--main", "README.rdoc"]
17
17
  s.extra_rdoc_files = ["LICENSE", "README.rdoc"]
18
18
  end
19
+
data/lib/isaac.rb CHANGED
@@ -20,53 +20,29 @@ module Isaac
20
20
  instance_eval(&b) if block_given?
21
21
  end
22
22
 
23
- def start
24
- puts "========================================="
25
- puts "Connecting to #{@config.server}:#{@config.port}"
26
- @irc = IRC.new(self, @config)
27
- @irc.connect
28
- puts "========================================="
23
+ def configure(&b)
24
+ b.call(@config)
29
25
  end
30
26
 
31
- def on(event, match=//, &b)
27
+ def on(event, match=//, &block)
32
28
  match = match.to_s if match.is_a? Integer
33
- (@events[event] ||= []) << [Regexp.new(match), b]
29
+ (@events[event] ||= []) << [Regexp.new(match), block]
34
30
  end
35
31
 
36
32
  def helpers(&b)
37
- instance_eval &b
38
- end
39
-
40
- def configure(&b)
41
- b.call(@config)
42
- end
43
-
44
- def dispatch(event, env={})
45
- self.nick, self.userhost, self.channel, self.error =
46
- env[:nick], env[:userhost], env[:channel], env[:error]
47
- self.message = env[:message] || ""
48
-
49
- event = @events[event] && @events[event].detect do |regexp,_|
50
- message.match(regexp)
51
- end
52
-
53
- if event
54
- regexp, block = *event
55
- self.match = message.match(regexp).captures
56
- catch(:halt) { instance_eval(&block) }
57
- end
33
+ instance_eval(&b)
58
34
  end
59
35
 
60
36
  def halt
61
37
  throw :halt
62
38
  end
63
39
 
64
- def raw(m)
65
- @irc.message(m)
40
+ def raw(command)
41
+ @irc.message(command)
66
42
  end
67
43
 
68
- def msg(recipient, m)
69
- raw("PRIVMSG #{recipient} :#{m}")
44
+ def msg(recipient, text)
45
+ raw("PRIVMSG #{recipient} :#{text}")
70
46
  end
71
47
 
72
48
  def join(*channels)
@@ -80,6 +56,44 @@ module Isaac
80
56
  def topic(channel, text)
81
57
  raw("TOPIC #{channel} :#{text}")
82
58
  end
59
+
60
+ def start
61
+ puts "Connecting to #{@config.server}:#{@config.port}" unless @config.environment == :test
62
+ @irc = IRC.new(self, @config)
63
+ @irc.connect
64
+ end
65
+
66
+ def dispatch(event, env={})
67
+ self.nick, self.userhost, self.channel, self.error =
68
+ env[:nick], env[:userhost], env[:channel], env[:error]
69
+ self.message = env[:message] || ""
70
+
71
+ if handler = find(event, message)
72
+ regexp, block = *handler
73
+ self.match = message.match(regexp).captures
74
+ invoke block
75
+ end
76
+ end
77
+
78
+ private
79
+ def find(type, message)
80
+ if events = @events[type]
81
+ events.detect {|regexp,_| message.match(regexp)}
82
+ end
83
+ end
84
+
85
+ def invoke(block)
86
+ mc = class << self; self; end
87
+ mc.send :define_method, :__isaac_event_handler, &block
88
+
89
+ bargs = case block.arity <=> 0
90
+ when -1; match
91
+ when 0; []
92
+ when 1; match[0..block.arity-1]
93
+ end
94
+
95
+ catch(:halt) { __isaac_event_handler(*bargs) }
96
+ end
83
97
  end
84
98
 
85
99
  class IRC
@@ -87,45 +101,34 @@ module Isaac
87
101
  @bot, @config = bot, config
88
102
  @transfered = 0
89
103
  @registration = []
90
- @lock = false
91
- @queue = []
92
104
  end
93
105
 
94
106
  def connect
95
107
  @socket = TCPSocket.open(@config.server, @config.port)
96
- message "PASSWORD #{@config.password}" if @config.password
108
+ @queue = Queue.new(@socket, @bot.config.server)
109
+ message "PASS #{@config.password}" if @config.password
97
110
  message "NICK #{@config.nick}"
98
111
  message "USER #{@config.nick} 0 * :#{@config.realname}"
99
- @lock = true
112
+ @queue.lock
100
113
 
101
- # This should probably be somewhere else..
102
- if @config.environment == :test
103
- Thread.start {
104
- while line = @socket.gets
105
- parse line
106
- end
107
- }
108
- else
109
- while line = @socket.gets
110
- parse line
111
- end
114
+ while line = @socket.gets
115
+ parse line
112
116
  end
113
117
  end
114
118
 
115
119
  def parse(input)
116
120
  puts "<< #{input}" if @bot.config.verbose
117
- case input
121
+ case input.chomp
118
122
  when /^:\S+ 00([1-4])/
119
123
  @registration << $1.to_i
120
124
  if registered?
121
- @lock = false
125
+ @queue.unlock
122
126
  @bot.dispatch(:connect)
123
- continue_queue
124
127
  end
125
128
  when /^:(\S+)!\S+ PRIVMSG \S+ :?\001VERSION\001/
126
129
  message "NOTICE #{$1} :\001VERSION #{@bot.config.version}\001"
127
130
  when /^PING (\S+)/
128
- @transfered, @lock = 0, false
131
+ @queue.unlock
129
132
  message "PONG #{$1}"
130
133
  when /^:(\S+)!(\S+) PRIVMSG (\S+) :?(.*)/
131
134
  env = { :nick => $1, :userhost => $2, :channel => $3, :message => $4 }
@@ -135,8 +138,7 @@ module Isaac
135
138
  env = {:error => $1.to_i, :message => $1, :nick => $2, :channel => $2}
136
139
  @bot.dispatch(:error, env)
137
140
  when /^:\S+ PONG/
138
- @transfered, @lock = 0, false
139
- continue_queue
141
+ @queue.unlock
140
142
  end
141
143
  end
142
144
 
@@ -146,21 +148,56 @@ module Isaac
146
148
 
147
149
  def message(msg)
148
150
  @queue << msg
149
- continue_queue
151
+ end
152
+ end
153
+
154
+ class Queue
155
+ def initialize(socket, server)
156
+ # We need server for pinging us out of an excess flood
157
+ @socket, @server = socket, server
158
+ @queue, @lock, @transfered = [], false, 0
159
+ end
160
+
161
+ def lock
162
+ @lock = true
163
+ end
164
+
165
+ def unlock
166
+ @lock, @transfered = false, 0
167
+ invoke
168
+ end
169
+
170
+ def <<(message)
171
+ @queue << message
172
+ invoke
173
+ end
174
+
175
+ private
176
+ def message_to_send?
177
+ !@lock && !@queue.empty?
178
+ end
179
+
180
+ def transfered_after_next_send
181
+ @transfered + @queue.first.size + 1 # the 1 is for \n
182
+ end
183
+
184
+ def exceed_limit?
185
+ transfered_after_next_send > 1472
186
+ end
187
+
188
+ def lock_and_ping
189
+ lock
190
+ @socket.puts "PING :#{@server}"
150
191
  end
151
192
 
152
- def continue_queue
153
- # <= 1472 allows for \n
154
- while !@lock && msg = @queue.shift
155
- if (@transfered + msg.size) < 1472
156
- @socket.puts msg
157
- puts ">> #{msg}" if @bot.config.verbose
158
- @transfered += msg.size + 1
193
+ def invoke
194
+ while message_to_send?
195
+ if exceed_limit?
196
+ lock_and_ping; break
159
197
  else
160
- @queue.unshift(msg)
161
- @lock = true
162
- @socket.puts "PING :#{@bot.config.server}"
163
- break
198
+ @transfered = transfered_after_next_send
199
+ @socket.puts @queue.shift
200
+ # puts ">> #{msg}" if @bot.config.verbose
164
201
  end
165
202
  end
166
203
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ichverstehe-isaac
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harry Vangberg
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-23 00:00:00 -08:00
12
+ date: 2009-04-01 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15