ratchet 0.3.0

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.
Files changed (49) hide show
  1. data/gem_bin/ratchet +23 -0
  2. data/lib/ratchet.rb +613 -0
  3. data/lib/ratchet/aliases.rb +106 -0
  4. data/lib/ratchet/bufferparser.rb +409 -0
  5. data/lib/ratchet/commandbuffer.rb +66 -0
  6. data/lib/ratchet/commandparser.rb +668 -0
  7. data/lib/ratchet/configuration.rb +278 -0
  8. data/lib/ratchet/connections.rb +403 -0
  9. data/lib/ratchet/constants.rb +111 -0
  10. data/lib/ratchet/contrib/instance_exec.rb +21 -0
  11. data/lib/ratchet/eventparser.rb +486 -0
  12. data/lib/ratchet/gtk/bufferlistview.rb +514 -0
  13. data/lib/ratchet/gtk/bufferview.rb +167 -0
  14. data/lib/ratchet/gtk/configwindow.rb +229 -0
  15. data/lib/ratchet/gtk/connectionwindow.rb +218 -0
  16. data/lib/ratchet/gtk/keybinding.rb +356 -0
  17. data/lib/ratchet/gtk/linkwindow.rb +137 -0
  18. data/lib/ratchet/gtk/mainwindow.rb +504 -0
  19. data/lib/ratchet/gtk/networkpresenceconf.rb +567 -0
  20. data/lib/ratchet/gtk/pluginconfig.rb +94 -0
  21. data/lib/ratchet/gtk/pluginwindow.rb +146 -0
  22. data/lib/ratchet/gtk/userlistview.rb +161 -0
  23. data/lib/ratchet/help.rb +64 -0
  24. data/lib/ratchet/items.rb +271 -0
  25. data/lib/ratchet/lines.rb +63 -0
  26. data/lib/ratchet/networks.rb +652 -0
  27. data/lib/ratchet/plugins.rb +616 -0
  28. data/lib/ratchet/queue.rb +47 -0
  29. data/lib/ratchet/ratchet-version.rb +21 -0
  30. data/lib/ratchet/replies.rb +134 -0
  31. data/lib/ratchet/replyparser.rb +441 -0
  32. data/lib/ratchet/tabcomplete.rb +98 -0
  33. data/lib/ratchet/users.rb +237 -0
  34. data/lib/ratchet/utils.rb +178 -0
  35. data/share/defaults.yaml +169 -0
  36. data/share/glade/config.glade +2634 -0
  37. data/share/glade/connect.glade +950 -0
  38. data/share/glade/keybindings.glade +109 -0
  39. data/share/glade/linkwindow.glade +188 -0
  40. data/share/glade/mainwindow.glade +335 -0
  41. data/share/glade/network-presences.glade +1373 -0
  42. data/share/glade/pluginconf.glade +97 -0
  43. data/share/glade/plugins.glade +360 -0
  44. data/share/plugins/colorewrite.rb +193 -0
  45. data/share/plugins/highlighter.rb +115 -0
  46. data/share/plugins/mpdplay.rb +123 -0
  47. data/share/plugins/numberswitcher.rb +30 -0
  48. data/share/plugins/sysinfo.rb +82 -0
  49. metadata +96 -0
@@ -0,0 +1,47 @@
1
+ =begin
2
+ This file is part of the Ratchet project, a client for Icecap.
3
+ Copyright (C) 2005-6 Andrew Thompson
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ =end
19
+
20
+ #### queue.rb ####
21
+ # Provides a threadsafe queue and a watcher for it
22
+ ####
23
+
24
+ require 'thread'
25
+ require 'observer'
26
+ module Ratchet
27
+ class MessageQueue < Queue
28
+ include Observable
29
+
30
+ def enq(*args)
31
+ super
32
+ changed
33
+ notify_observers
34
+ end
35
+ end
36
+
37
+ class Watcher
38
+ def initialize(obj, &block)
39
+ obj.add_observer(self)
40
+ @queue = obj
41
+ @block = block
42
+ end
43
+ def update
44
+ @block.call(@queue.deq)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ =begin
2
+ This file is part of the Ratchet project, a client for Icecap.
3
+ Copyright (C) 2005-6 Andrew Thompson
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ =end
19
+
20
+ # the version of rachet
21
+ $version = '0.3.0'
@@ -0,0 +1,134 @@
1
+ =begin
2
+ This file is part of the Ratchet project, a client for Icecap.
3
+ Copyright (C) 2005-6 Andrew Thompson
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ =end
19
+
20
+ #### replies.rb ####
21
+ # A class that holds the replies from icecap in one object
22
+ # it also tracks the orginal command that was sent which
23
+ # returns this reply
24
+ ####
25
+
26
+ module Ratchet
27
+ class Reply
28
+ attr_reader :complete, :lines, :name, :command, :origcommand, :error, :network, :channel, :start, :retries
29
+ attr_writer :retries
30
+ attr_accessor :lineref, :network, :presence, :channel
31
+
32
+ def initialize(main, name, command)
33
+ @main = main
34
+ @start = Time.new
35
+ @name = name
36
+ @lines = []
37
+ @complete = false
38
+ @command = {}
39
+ @error = false
40
+ @origcommand = command
41
+ parsecommand(command)
42
+ @network = nil
43
+ @channel = nil
44
+ @presence = nil
45
+ @retries = 0
46
+ end
47
+
48
+ #get the info of the original command
49
+ def parsecommand(command)
50
+ attribs = command.split(';')
51
+
52
+ @command['command'] = attribs[0]
53
+
54
+ attribs.each do |x|
55
+ vals = x.split('=', 2)
56
+ if vals[1] and vals[1] != ''
57
+ #unescape the original command values
58
+ vals[1].gsub!('\\\\.', ';')
59
+ vals[1].gsub!('\\.', ';')
60
+ vals[1].gsub!('\\\\\\\\', '\\')
61
+ @command[vals[0].to_sym] = vals[1]
62
+ elsif x.count('=') == 0
63
+ @command[x.to_sym] = true
64
+ end
65
+ end
66
+ end
67
+
68
+ #parse a line and add it to the reply object
69
+ def addline(line)
70
+ #time = Time.new
71
+ temp = Line.new
72
+ vars = line.split(";", 3)
73
+ temp['tagname'] = vars[0]
74
+ temp[:reply_status] = vars[1]
75
+ temp['original'] = line
76
+
77
+ if !vars[2]
78
+ lines.push(temp)
79
+ break
80
+ end
81
+
82
+ items = vars[2].split(';')
83
+
84
+ items.each do |x|
85
+ vals = x.split('=', 2)
86
+ if vals[1] and vals[1] != ''
87
+ #unescape the reply values
88
+ vals[1].gsub!("\\.", "\\\\.")
89
+ vals[1].gsub!(%r{\\{1}\\\.}, '!.')
90
+ vals[1].gsub!('\\.', ';')
91
+ vals[1].gsub!('!.', '\\.')
92
+ vals[1].gsub!('\\\\', '\\')
93
+ temp[vals[0].to_sym] = vals[1]
94
+ elsif x.count('=') == 0
95
+ temp[x.to_sym] = true
96
+ end
97
+ end
98
+
99
+ if @command['command'] != 'event get'
100
+ @main.calculate_clock_drift(temp['time'])
101
+ end
102
+
103
+ if @main.config['canonicaltime'] == 'client'
104
+ begin
105
+ temp['time'] = Time.at(temp['time'].to_i + @main.drift)
106
+ rescue RangeError
107
+ puts "#{temp['time']} is too large"
108
+ puts line
109
+ end
110
+ end
111
+
112
+ if temp[:reply_status] == '+'
113
+ @complete = true
114
+ end
115
+
116
+ if temp[:reply_status] == '-'
117
+ error = line.gsub(temp['tagname']+';-;', '')
118
+ temp[:error] = error
119
+ @complete = true
120
+ @error = true
121
+ end
122
+
123
+ @lines.push(temp)
124
+ #finish if @complete
125
+ end
126
+
127
+ def finish
128
+ #@lines.sort!{|x, y| x[ID] <=> y[ID]}
129
+ #@lines.sort!{|x, y| x[TIME].to_i <=> y[TIME].to_i}
130
+ @lines = @lines.sort_by {|l| [l[ID], l[TIME].to_i]}
131
+ #@complete = true
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,441 @@
1
+ =begin
2
+ This file is part of the Ratchet project, a client for Icecap.
3
+ Copyright (C) 2005-6 Andrew Thompson
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ =end
19
+
20
+ #### replyparser.rb ####
21
+ # dispatches replies similarly to the commandparser
22
+ ####
23
+
24
+ #TODO: this, like the eventparser needs extensive cleanup
25
+ #TODO: ideally this could be unified with the eventparser for the event_get commands
26
+
27
+ module Ratchet
28
+ module ReplyParser
29
+ #handle replies from irssi2 (responses to commands sent from a client)
30
+ def reply_parse(reply)
31
+
32
+ #~ puts 'dispatch'
33
+ #target = dispatch(reply.command[NETWORK], reply.command[MYPRESENCE], reply.command[CHANNEL], reply.command[PRESENCE])
34
+ #~ puts "target is #{target.class}"
35
+ #~ return
36
+
37
+ if reply.error
38
+ reply.lines.each do |line|
39
+ if line[REPLY_STATUS] == '-'
40
+ handle_error(line, reply)
41
+ end
42
+ end
43
+ end
44
+
45
+ if reply.command['command'] == 'presence status'
46
+ reply_presence_status(reply)
47
+ return
48
+ elsif reply.command['command'] == 'config get'
49
+ puts 'config get'
50
+ @config.parse_config(reply)
51
+ return
52
+ end
53
+
54
+ reply.lines.each do |line|
55
+
56
+ if reply.name == 'raw'
57
+ @console.send_user_event({'msg' =>line['original']}, EVENT_NOTICE)
58
+ next
59
+ end
60
+
61
+ #~ if line[NETWORK] and line[MYPRESENCE]
62
+ #~ if !@serverlist[line[NETWORK], line[MYPRESENCE]]
63
+ #~ else
64
+ #~ network = @serverlist[line[NETWORK], line[MYPRESENCE]]
65
+ #~ end
66
+
67
+ #~ if line[CHANNEL] and @serverlist[line[NETWORK], line[MYPRESENCE]]
68
+ #~ if !@serverlist[line[NETWORK], line[MYPRESENCE]][line[CHANNEL]]
69
+ #~ else
70
+ #~ channel = @serverlist[line[NETWORK], line[MYPRESENCE]][line[CHANNEL]]
71
+ #~ end
72
+ #~ end
73
+ #~ #elsif reply.command[NETWORK] and reply.command[MYPRESENCE]
74
+ #~ end
75
+
76
+ target = find_buffer(line[NETWORK], line[MYPRESENCE], line[CHANNEL], line[PRESENCE])
77
+ #puts line.inspect unless target
78
+ #puts "#{[line[NETWORK], line[MYPRESENCE], line[CHANNEL], line[PRESENCE]].inspect} => #{target.class}"
79
+
80
+ begin
81
+ cmd = 'reply_'+reply.command['command'].gsub(' ', '_')
82
+ if self.respond_to?(cmd)
83
+ res = callback(cmd, line, target, reply)
84
+ return if res === true
85
+ self.send(cmd, *res)
86
+ end
87
+ #rescue any exceptions...
88
+ rescue =>exception
89
+ puts 'Error parsing reply : '+$!
90
+ puts exception.backtrace
91
+ end
92
+ end
93
+ end
94
+
95
+ def reply_msg(line, target, reply)
96
+ if line['msg_reply'] and reply.lineref
97
+ # puts reply.name, reply.command[NETWORK], reply.command[CHANNEL], reply.command[MYPRESENCE]
98
+ if reply.command[NETWORK] and reply.command[CHANNEL] and reply.command[MYPRESENCE]
99
+ channel = @serverlist[reply.command[NETWORK], reply.command[MYPRESENCE]][reply.command[CHANNEL]]
100
+ # puts reply.command[:type]
101
+ #hack to handle actions
102
+ #TODO: try to do this a better way
103
+ if reply.command[:type] == 'action'
104
+ iter = channel.view.get_line(reply.lineref)
105
+ # puts iter[2], channel.server.username
106
+ start, rest = iter[2].split(channel.server.username)
107
+ line['msg_reply'] = start+channel.server.username+' '+line['msg_reply']
108
+ end
109
+ channel.view.update_line(reply.lineref, line['msg_reply'])
110
+ end
111
+ #@window.view.
112
+ end
113
+ end
114
+
115
+ #sending a file
116
+ def reply_file_send(line, target, reply)
117
+ if line['handle']
118
+ if line['closed'] and @filehandles[line['handle'].to_i]
119
+ # puts 'file sent'
120
+ @filehandles[line['handle'].to_i].close
121
+ @filehandles.delete_at(line['handle'].to_i)
122
+ return
123
+ end
124
+ if reply.command['presence']
125
+ @filehandles[line['handle'].to_i] = @filedescriptors[reply.command['presence']]
126
+ end
127
+
128
+ file = @filehandles[line['handle'].to_i]
129
+
130
+ puts line['handle']
131
+ length = line['end'].to_i - line['start'].to_i
132
+ send_command('1', 'file send;handle='+line['handle'], length)
133
+ file.seek(line['start'].to_i)
134
+ data = file.read(length)
135
+ @connection.send(data)
136
+ return
137
+ end
138
+ end
139
+
140
+ def reply_quit(line, target, reply)
141
+ puts 'got quit confirmation'
142
+ do_quit
143
+ # if @quitting
144
+ # @quit = true
145
+ # do_quit
146
+ # end
147
+ end
148
+
149
+ #list the connected presences
150
+ def reply_presence_list(line, target, reply)
151
+ if line[NETWORK] and line[MYPRESENCE]
152
+ network = add_buffer(line[NETWORK], line[MYPRESENCE])
153
+ #~ unless network = @serverlist[line[NETWORK], line[MYPRESENCE]]
154
+ #~ network = @serverlist.add(line[NETWORK], line[MYPRESENCE])
155
+ if nw = @networks[line[NETWORK]]
156
+ presence = nw.add_presence(line[MYPRESENCE])
157
+ presence.autoconnect = true if line[AUTOCONNECT] and presence
158
+ end
159
+ #~ end
160
+ network.username = line[PRESENCE] if line[PRESENCE]
161
+ # puts
162
+ if line[CONNECTED]
163
+ network.connect
164
+ puts 'connected network'
165
+ #~ network.loggedin = true
166
+ #~ @window.redraw_channellist
167
+ #~ #switchchannel(network)
168
+ #~ @tabmodel.set_active(network)
169
+ end
170
+ end
171
+ if line[REPLY_STATUS] == '+'
172
+ send_command('channels', "channel list")
173
+ end
174
+ end
175
+
176
+ def reply_network_list(line, target, reply)
177
+ if line[NETWORK] and !@networks[line[NETWORK]]
178
+ @networks.add(line[NETWORK], line[PROTOCOL])
179
+ elsif line[REPLY_STATUS] == '+'
180
+ send_command('gateways', 'gateway list')
181
+ end
182
+ end
183
+
184
+ def reply_gateway_list(line, target, reply)
185
+ if line[NETWORK] and line[HOST]
186
+ if @networks[line[NETWORK]]
187
+ if line[PORT]
188
+ network = @networks[line[NETWORK]].add_gateway(line[HOST], line[PORT])
189
+ else
190
+ network = @networks[line[NETWORK]].add_gateway(line[HOST])
191
+ end
192
+ else
193
+ puts 'unknown network '+line[NETWORK]
194
+ end
195
+ elsif line[REPLY_STATUS] == '+'
196
+ send_command('presences', 'presence list')
197
+ end
198
+ end
199
+
200
+ def reply_protocol_list(line, target, reply)
201
+ if line[PROTOCOL] and !@protocols[line[PROTOCOL]]
202
+ @protocols.add(line[PROTOCOL], line[:in_charsets], line[:out_charset])
203
+ elsif line[REPLY_STATUS] == '+'
204
+ send_command('networks', 'network list')
205
+ end
206
+ end
207
+
208
+ def reply_window_add(line, target, reply)
209
+ puts "#{reply.network}, #{reply.presence}, #{reply.channel}"
210
+ puts line['original']
211
+ if target = find_buffer(reply.network, reply.presence, reply.channel)
212
+ target.window_id = line['window'] if line['window']
213
+ target.last_seen = line['last_seen_event_id'] if line['last_seen_event_id']
214
+ end
215
+ end
216
+
217
+ #list the connected channels
218
+ def reply_channel_list(line, target, reply)
219
+ # puts 'channel list', line.inspect
220
+ if line[NETWORK] and line[MYPRESENCE] and line[CHANNEL]
221
+ # puts 'adding channel'
222
+ if channel = add_buffer(line[NETWORK], line[MYPRESENCE], line[CHANNEL])
223
+ # reply = send_command("window#{rand(100)}", "window add;filter=&(network=#{line[NETWORK]})(mypresence=#{line[MYPRESENCE]})(channel=#{line[CHANNEL]})")
224
+ # reply.network = line[NETWORK]
225
+ # reply.presence = line[MYPRESENCE]
226
+ # reply.channel = line[CHANNEL]
227
+ # puts "new channel #{channel}"
228
+ if line[JOINED] and channel
229
+ if line[TOPIC]
230
+ channel.topic = line[TOPIC]
231
+ end
232
+ channel.join
233
+ end
234
+ else
235
+ puts 'uh-oh'
236
+ end
237
+ #~ if !@serverlist[line[NETWORK], line[MYPRESENCE]]
238
+ #~ puts 'network does not exist '+line[NETWORK]+', '+line[MYPRESENCE]
239
+ #~ else
240
+ #~ unless channel = @serverlist[line[NETWORK], line[MYPRESENCE]][line[CHANNEL]]
241
+ #~ channel = @serverlist[line[NETWORK], line[MYPRESENCE]].add(line[CHANNEL])
242
+ #~ end
243
+
244
+ #~ if line[JOINED] and channel
245
+ #~ if line[TOPIC]
246
+ #~ channel.topic = line[TOPIC]
247
+ #~ end
248
+ #~ channel.connect
249
+ #~ #switchchannel(channel)
250
+ #~ @tabmodel.set_active(channel)
251
+ #~ end
252
+ #~ end
253
+
254
+ elsif line[REPLY_STATUS] == '+'
255
+ #check for connected networks
256
+ i = 0
257
+ @buffers.values.select{|x| x.class == NetworkBuffer}.each do |network|
258
+ i+=1 if network.connected?
259
+ end
260
+
261
+ #if no networks are connected, raise the network window
262
+ if i == 0
263
+ @windows[0].open_networks
264
+ end
265
+ syncchannels
266
+ end
267
+
268
+ end
269
+
270
+ #list of users on the channel
271
+ def reply_channel_names(line, target, reply)
272
+ #puts reply.class
273
+ #network = assign_window.buffers.find_network(reply.command[NETWORK], reply.command[MYPRESENCE])
274
+ #if network
275
+ # channel = network[reply.command[CHANNEL]]
276
+ #end
277
+ #puts network, channel
278
+ #if line[NETWORK] and line[MYPRESENCE] and line[CHANNEL] and line[PRESENCE]
279
+ #puts "userlist #{target.class}"
280
+ target = find_buffer(reply.command[NETWORK], reply.command[MYPRESENCE], reply.command[CHANNEL], line[PRESENCE])
281
+ if reply.command[NETWORK] and reply.command[MYPRESENCE] and reply.command[CHANNEL] and line[PRESENCE] and target and !target.users.include?(line[PRESENCE])
282
+ target.network.users.create(line[PRESENCE])
283
+ chuser = target.users.add(target.network.users[line[PRESENCE]], false)
284
+ if line[MODE] and chuser
285
+ chuser.mode= line[MODE]
286
+ end
287
+ elsif line[REPLY_STATUS] == '+'
288
+ #@serverlist[reply.command[NETWORK], reply.command[MYPRESENCE]][reply.command[CHANNEL]].drawusers
289
+ #@window.updateusercount
290
+ #@serverlist[reply.command[NETWORK], reply.command[MYPRESENCE]][reply.command[CHANNEL]].usersync = true
291
+ target = find_buffer(reply.command[NETWORK], reply.command[MYPRESENCE], reply.command[CHANNEL])
292
+ target.usersync = true
293
+ target.users.sort
294
+ target.users.fill_view
295
+ end
296
+ end
297
+
298
+ #handle past events here
299
+ def reply_event_get(line, target, reply)
300
+ #reply.network ||= target.network if target
301
+ reply.channel ||= target if target and target.respond_to? :join
302
+ #puts "#{[line[NETWORK], line[MYPRESENCE], line[CHANNEL], line[PRESENCE]].inspect} => #{target.class}"
303
+ if line[EVENT] == 'msg'
304
+ puts line.inspect unless target
305
+ return unless target
306
+ if line[ADDRESS] and target.network.users[line[PRESENCE]] and target.network.users[line[PRESENCE]].hostname == 'hostname'
307
+ target.network.users[line[PRESENCE]].hostname = line[ADDRESS]
308
+ end
309
+
310
+ #TODO - fix this
311
+ #~ if line[PRESENCE] and !line[NO_AUTOREPLY] and !line[CHANNEL]
312
+ #~ unless target = network.has_chat?(line[PRESENCE])
313
+ #~ target = network.addchat(line[PRESENCE])
314
+ #~ puts 'chat for '+line[PRESENCE]
315
+ #~ puts line['original']
316
+ #~ end
317
+ #~ target.connect unless target.connected
318
+ #~ end
319
+
320
+ if line[OWN]
321
+ #I don't know why I did this, but I'm fixing something else ATM so 'll come back to it
322
+ #line[PRESENCE] = line[PRESENCE]
323
+ target.send_event(line, EVENT_USERMESSAGE, BUFFER_START)
324
+ else
325
+ target.send_event(line, EVENT_MESSAGE, BUFFER_START)
326
+ end
327
+
328
+ elsif line[EVENT] == 'notice'
329
+ return unless target
330
+ target.send_event(event, EVENT_NOTICE, BUFFER_START)
331
+
332
+ elsif line[EVENT] == 'channel_changed'
333
+ if line[TOPIC] and line['init']
334
+ #send the topic stuff as 2 lines
335
+ #channel.topic = line[TOPIC]
336
+ line['line'] = 2
337
+ target.send_event(line, EVENT_TOPIC, BUFFER_START)
338
+ line['line'] = 1
339
+ target.send_event(line, EVENT_TOPIC, BUFFER_START)
340
+ #@window.updatetopic
341
+ elsif line[TOPIC]
342
+ #channel.topic = line[TOPIC]
343
+ target.send_event(line, EVENT_TOPIC, BUFFER_START)
344
+ #@window.updatetopic
345
+ end
346
+
347
+ elsif line[EVENT] == 'presence_changed'
348
+ #this doesn't seem to be reached, ever
349
+ if line[NAME]
350
+ if line[NAME] == network.username
351
+ type = EVENT_USERNICKCHANGE
352
+ else
353
+ type = EVENT_NICKCHANGE
354
+ end
355
+
356
+ if type
357
+ network.channels.each do |c|
358
+ if c.users[line[NAME]]
359
+ #this isn't really a great thing to be doing ATM
360
+ #c.drawusers
361
+ #c.send_event(line, type, BUFFER_START)
362
+ end
363
+ end
364
+ end
365
+ end
366
+
367
+ elsif line[EVENT] == 'channel_presence_removed'
368
+ return if line[DEINIT]
369
+ line[:type] = 'part'
370
+ if line[PRESENCE] == target.username
371
+ target.send_event(line, EVENT_USERPART, BUFFER_START)
372
+ else
373
+ target.send_event(line, EVENT_PART, BUFFER_START)
374
+ end
375
+
376
+ elsif line[EVENT] == 'channel_part'
377
+ line[:type] = 'part'
378
+ target.send_event(line, EVENT_USERPART, BUFFER_START)
379
+
380
+ elsif line[EVENT] == 'channel_join'
381
+ target.send_event(line, EVENT_USERJOIN, BUFFER_START)
382
+
383
+ elsif line[EVENT] == 'channel_presence_added'
384
+ return if line[INIT]
385
+
386
+ if line[PRESENCE] == target.username
387
+ target.send_event(line, EVENT_USERJOIN, BUFFER_START)
388
+ else
389
+ target.send_event(line, EVENT_JOIN, BUFFER_START)
390
+ end
391
+
392
+ elsif line[REPLY_STATUS] == '+'
393
+ reply.channel.eventsync = true if reply.channel
394
+ end
395
+ end
396
+
397
+ #output the result of a whois
398
+ def reply_presence_status(reply)
399
+ target ||= find_buffer(reply.command[NETWORK], reply.command[MYPRESENCE])
400
+
401
+ reply.lines.each do |line|
402
+
403
+ if line[ADDRESS] and line['real_name']
404
+ msg = '('+line[ADDRESS]+') : '+line['real_name']
405
+ elsif line[ADDRESS]
406
+ address = line[ADDRESS]
407
+ next
408
+ elsif line['real_name'] and address
409
+ msg = address+' : '+line['real_name']
410
+ elsif line['server_address'] and line['server_name']
411
+ msg = line['server_address']+' : '+line['server_name']
412
+ elsif line['idle'] and line['login_time']
413
+ idletime = duration(line['idle'].to_i)
414
+ logintime = duration(Time.at(line[TIME].to_i) - Time.at(line['login_time'].to_i))
415
+ msg = 'Idle: '+idletime+' -- Logged on: '+Time.at(line['login_time'].to_i).strftime('%c')+' ('+logintime+')'
416
+ elsif line['channels']
417
+ msg = line['channels']
418
+ elsif line['extra']
419
+ msg = line['extra']
420
+ elsif line[REPLY_STATUS] == '+'
421
+ msg = 'End of /whois'
422
+ line[PRESENCE] = reply.command['presence']
423
+ else
424
+ next
425
+ end
426
+
427
+ pattern = @config['whois'].dup
428
+ pattern['%m'] = msg if msg
429
+ if line[PRESENCE]
430
+ pattern['%n'] = line[PRESENCE]
431
+ else
432
+ pattern['%n'] = reply.command[PRESENCE]
433
+ end
434
+ line[MSG] = pattern
435
+ target.send_event(line, EVENT_NOTICE)
436
+ time = line[TIME]
437
+ end
438
+ end
439
+
440
+ end
441
+ end