Class: Tkellem::Backlog
Overview
This is implemented as a plugin – in theory, it could be switched out for a different backlog implementation. Right now, it’s always loaded though.
Defined Under Namespace
Classes: Device
Class Method Summary
collapse
Instance Method Summary
collapse
-
#all_existing_ctxs ⇒ Object
-
#client_connected(conn) ⇒ Object
-
#client_msg(msg) ⇒ Object
-
#get_device(conn) ⇒ Object
-
#get_stream(ctx, for_reading = false) ⇒ Object
-
#initialize(bouncer) ⇒ Backlog
constructor
A new instance of Backlog.
-
#log_name ⇒ Object
-
#parse_line(line, ctx_name) ⇒ Object
-
#send_backlog(conn, ctx_name, stream) ⇒ Object
-
#send_backlog_since(conn, start_time, contexts) ⇒ Object
-
#send_connect_backlogs(conn, device, contexts) ⇒ Object
-
#server_msg(msg) ⇒ Object
-
#stream_path(ctx) ⇒ Object
-
#stream_size(ctx) ⇒ Object
-
#update_pos(ctx_name, pos) ⇒ Object
-
#write_msg(ctx, processed_msg) ⇒ Object
Methods included from EasyLogger
#failsafe, logger, logger=, trace, #trace, trace=
Constructor Details
#initialize(bouncer) ⇒ Backlog
Returns a new instance of Backlog.
81
82
83
84
85
86
87
|
# File 'lib/tkellem/plugins/backlog.rb', line 81
def initialize(bouncer)
@bouncer = bouncer
@network_user = bouncer.network_user
@devices = {}
@dir = Pathname.new(File.expand_path("~/.tkellem/logs/#{bouncer.user.username}/#{bouncer.network.name}"))
@dir.mkpath()
end
|
Class Method Details
.client_msg(bouncer, client, msg) ⇒ Object
35
36
37
38
39
|
# File 'lib/tkellem/plugins/backlog.rb', line 35
def self.client_msg(bouncer, client, msg)
instance = get_instance(bouncer)
instance.client_msg(msg)
true
end
|
.get_instance(bouncer) ⇒ Object
26
27
28
|
# File 'lib/tkellem/plugins/backlog.rb', line 26
def self.get_instance(bouncer)
bouncer.data(self)[:instance] ||= self.new(bouncer)
end
|
.new_client_connected(bouncer, client) ⇒ Object
30
31
32
33
|
# File 'lib/tkellem/plugins/backlog.rb', line 30
def self.new_client_connected(bouncer, client)
instance = get_instance(bouncer)
instance.client_connected(client)
end
|
.server_msg(bouncer, msg) ⇒ Object
41
42
43
44
45
|
# File 'lib/tkellem/plugins/backlog.rb', line 41
def self.server_msg(bouncer, msg)
instance = get_instance(bouncer)
instance.server_msg(msg)
true
end
|
Instance Method Details
#all_existing_ctxs ⇒ Object
93
94
95
|
# File 'lib/tkellem/plugins/backlog.rb', line 93
def all_existing_ctxs
@dir.entries.select { |e| e.extname == ".log" }.map { |e| e.basename(".log").to_s }
end
|
#client_connected(conn) ⇒ Object
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# File 'lib/tkellem/plugins/backlog.rb', line 118
def client_connected(conn)
device = get_device(conn)
behind = all_existing_ctxs.select do |ctx_name|
eof = stream_size(ctx_name)
device.pos(ctx_name, eof) < eof
end
if !behind.empty?
send_connect_backlogs(conn, device, behind)
end
end
|
#client_msg(msg) ⇒ Object
161
162
163
164
165
166
167
168
|
# File 'lib/tkellem/plugins/backlog.rb', line 161
def client_msg(msg)
case msg.command
when 'PRIVMSG'
return if msg.ctcp? && !msg.action?
ctx = msg.args.first
write_msg(ctx, Time.now.strftime("%d-%m-%Y %H:%M:%S") + " > #{'* ' if msg.action?}#{msg.args.last}")
end
end
|
#get_device(conn) ⇒ Object
114
115
116
|
# File 'lib/tkellem/plugins/backlog.rb', line 114
def get_device(conn)
@devices[conn.device_name] ||= Device.new(@network_user, conn.device_name)
end
|
#get_stream(ctx, for_reading = false) ⇒ Object
97
98
99
100
101
102
103
104
105
106
107
108
|
# File 'lib/tkellem/plugins/backlog.rb', line 97
def get_stream(ctx, for_reading = false)
mode = for_reading ? 'rb:utf-8' : 'ab:utf-8'
ctx = ctx.gsub(%r{[\./\\]}, '')
path = stream_path(ctx)
return nil if !path.file? && for_reading
path.open(mode) do |stream|
if !for_reading
stream.seek(0, IO::SEEK_END)
end
yield stream
end
end
|
#log_name ⇒ Object
141
142
143
|
# File 'lib/tkellem/plugins/backlog.rb', line 141
def log_name
"backlog:#{@bouncer.log_name}"
end
|
#parse_line(line, ctx_name) ⇒ Object
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
# File 'lib/tkellem/plugins/backlog.rb', line 235
def parse_line(line, ctx_name)
timestamp = Time.parse(line[0, 19])
case line[20..-1]
when %r{^> (\* )?(.+)$}
msg = IrcMessage.new(nil, 'PRIVMSG', [ctx_name, $2])
if $1 == '* '
msg.ctcp = 'ACTION'
end
return timestamp, msg
when %r{^< (\* )?([^:]+): (.+)$}
msg = IrcMessage.new($2, 'PRIVMSG', [ctx_name, $3])
if $1 == '* '
msg.ctcp = 'ACTION'
end
return timestamp, msg
else
nil
end
end
|
#send_backlog(conn, ctx_name, stream) ⇒ Object
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
# File 'lib/tkellem/plugins/backlog.rb', line 205
def send_backlog(conn, ctx_name, stream)
while line = stream.gets
timestamp, msg = parse_line(line, ctx_name)
next unless msg
privmsg = msg.args.first[0] != '#'[0]
if msg.prefix
if privmsg
msg.args[0] = @bouncer.nick
else
end
else
if privmsg
msg.prefix = msg.args.first
msg.args[0] = @bouncer.nick
msg.args[-1] = "-> #{msg.args.last}"
else
msg.prefix = @bouncer.nick
end
end
conn.send_msg(msg.with_timestamp(timestamp))
end
end
|
#send_backlog_since(conn, start_time, contexts) ⇒ Object
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
# File 'lib/tkellem/plugins/backlog.rb', line 188
def send_backlog_since(conn, start_time, contexts)
debug "scanning for backlog from #{start_time.inspect}"
contexts.each do |ctx_name|
get_stream(ctx_name, true) do |stream|
last_line_len = 0
BackwardsFileReader.scan(stream) do |line|
last_line_len = line.length
timestamp = Time.parse(line[0,19]) rescue nil
!timestamp || timestamp >= start_time
end
stream.seek(last_line_len, IO::SEEK_CUR)
send_backlog(conn, ctx_name, stream)
end
end
end
|
#send_connect_backlogs(conn, device, contexts) ⇒ Object
177
178
179
180
181
182
183
184
185
186
|
# File 'lib/tkellem/plugins/backlog.rb', line 177
def send_connect_backlogs(conn, device, contexts)
contexts.each do |ctx_name|
start_pos = device.pos(ctx_name)
get_stream(ctx_name, true) do |stream|
stream.seek(start_pos)
send_backlog(conn, ctx_name, stream)
device.update_pos(ctx_name, stream.pos)
end
end
end
|
#server_msg(msg) ⇒ Object
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
# File 'lib/tkellem/plugins/backlog.rb', line 145
def server_msg(msg)
case msg.command
when /3\d\d/, 'JOIN', 'PART'
return
when 'PRIVMSG'
return if msg.ctcp? && !msg.action?
ctx = msg.args.first
if ctx == @bouncer.nick
ctx = msg.prefix.split(/[!~@]/, 2).first
end
write_msg(ctx, Time.now.strftime("%d-%m-%Y %H:%M:%S") + " < #{'* ' if msg.action?}#{msg.prefix}: #{msg.args.last}")
end
end
|
#stream_path(ctx) ⇒ Object
89
90
91
|
# File 'lib/tkellem/plugins/backlog.rb', line 89
def stream_path(ctx)
@dir + "#{ctx}.log"
end
|
#stream_size(ctx) ⇒ Object
110
111
112
|
# File 'lib/tkellem/plugins/backlog.rb', line 110
def stream_size(ctx)
stream_path(ctx).size
end
|
#update_pos(ctx_name, pos) ⇒ Object
132
133
134
135
136
137
138
139
|
# File 'lib/tkellem/plugins/backlog.rb', line 132
def update_pos(ctx_name, pos)
@bouncer.active_conns.each do |conn|
device = get_device(conn)
device.update_pos(ctx_name, pos)
end
end
|
#write_msg(ctx, processed_msg) ⇒ Object
170
171
172
173
174
175
|
# File 'lib/tkellem/plugins/backlog.rb', line 170
def write_msg(ctx, processed_msg)
get_stream(ctx) do |stream|
stream.puts(processed_msg)
update_pos(ctx, stream.pos)
end
end
|