butler 1.8.3 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +293 -37
- data/README.txt +10 -0
- data/Rakefile +24 -13
- data/bin/botcontrol +6 -5
- data/data/butler/dialogs/create.rb +21 -6
- data/data/butler/dialogs/create_config.rb +5 -2
- data/data/butler/dialogs/en/create.yaml +6 -3
- data/data/butler/dialogs/en/create_config.yaml +1 -0
- data/data/butler/dialogs/en/quickcreate.yaml +1 -1
- data/data/butler/dialogs/en/sync.yaml +7 -0
- data/data/butler/dialogs/en/username.yaml +2 -0
- data/data/butler/dialogs/quickcreate.rb +6 -2
- data/data/butler/dialogs/sync.rb +83 -0
- data/data/butler/dialogs/username.rb +1 -0
- data/data/butler/plugins/core/ping.rb +22 -0
- data/data/butler/plugins/core/remote.rb +38 -0
- data/data/butler/plugins/dev/eval.rb +6 -4
- data/data/butler/plugins/dev/onhandlers.rb +93 -0
- data/data/butler/plugins/dev/rawlog.rb +109 -45
- data/data/butler/plugins/games/countdown.rb +23 -14
- data/data/butler/plugins/games/eightball.rb +21 -13
- data/data/butler/plugins/games/roll.rb +12 -12
- data/data/butler/plugins/irc/join.rb +2 -2
- data/data/butler/plugins/irc/notice.rb +10 -10
- data/data/butler/plugins/irc/part.rb +12 -12
- data/data/butler/plugins/irc/privmsg.rb +10 -10
- data/data/butler/plugins/irc/quit.rb +12 -12
- data/data/butler/plugins/operator/devoice.rb +1 -1
- data/data/butler/plugins/public/help.rb +10 -4
- data/data/butler/plugins/{util → service}/calculator.rb +0 -0
- data/data/butler/plugins/service/define.rb +16 -13
- data/data/butler/plugins/service/log.rb +85 -0
- data/data/butler/plugins/service/seen.rb +64 -0
- data/data/butler/plugins/service/svn.rb +6 -5
- data/data/butler/plugins/util/load.rb +3 -1
- data/data/butler/services/org.rubyforge.butler/calculator/1/service.rb +96 -0
- data/data/butler/services/org.rubyforge.butler/log/1/service.rb +148 -68
- data/lib/access/admin.rb +5 -0
- data/lib/blank.rb +32 -0
- data/lib/butler.rb +4 -4
- data/lib/butler/bot.rb +118 -33
- data/lib/butler/control.rb +5 -4
- data/lib/butler/debuglog.rb +12 -4
- data/lib/butler/dialog.rb +1 -1
- data/lib/butler/initialvalues.rb +1 -1
- data/lib/butler/irc/client.rb +31 -12
- data/lib/butler/irc/message.rb +32 -13
- data/lib/butler/irc/parser.rb +67 -30
- data/lib/butler/irc/parser/{commands.rb → command.rb} +0 -38
- data/lib/butler/irc/parser/generic.rb +9 -12
- data/lib/butler/irc/parser/rfc2812.rb +40 -2
- data/lib/butler/irc/socket.rb +66 -41
- data/lib/butler/irc/string.rb +1 -5
- data/lib/butler/plugin.rb +56 -23
- data/lib/butler/plugin/configproxy.rb +1 -0
- data/lib/butler/plugin/more.rb +2 -2
- data/lib/butler/plugins.rb +7 -1
- data/lib/butler/remote/connection.rb +113 -0
- data/lib/butler/remote/message.rb +157 -0
- data/lib/butler/remote/server.rb +85 -0
- data/lib/butler/remote/user.rb +46 -0
- data/lib/butler/service.rb +2 -1
- data/lib/butler/services.rb +2 -2
- data/lib/butler/version.rb +2 -2
- data/lib/configuration.rb +13 -16
- data/lib/ostructfixed.rb +0 -6
- data/lib/ruby/array/random.rb +2 -1
- data/lib/scriptfile.rb +63 -14
- data/lib/timingoutresource.rb +54 -0
- data/test/test_scriptfile.rb +51 -0
- metadata +63 -61
- data/data/butler/dialogs/en/sync_plugins.yaml +0 -3
- data/data/butler/dialogs/sync_plugins.rb +0 -30
- data/data/butler/services/org.rubyforge.butler/calculator/1/calculator.rb +0 -68
- data/lib/log/splitter.rb +0 -30
- data/test/test_access/privilege/banners.statistics.yaml +0 -3
- data/test/test_access/privilege/banners.yaml +0 -3
- data/test/test_access/privilege/news.create.yaml +0 -3
- data/test/test_access/privilege/news.delete.yaml +0 -3
- data/test/test_access/privilege/news.edit.yaml +0 -3
- data/test/test_access/privilege/news.read.yaml +0 -3
- data/test/test_access/privilege/news.yaml +0 -3
- data/test/test_access/privilege/paid_content.yaml +0 -3
- data/test/test_access/privilege/statistics.ftp.yaml +0 -3
- data/test/test_access/privilege/statistics.web.yaml +0 -3
- data/test/test_access/privilege/statistics.yaml +0 -3
- data/test/test_access/role/chiefeditor.yaml +0 -7
- data/test/test_access/role/editor.yaml +0 -9
- data/test/test_access/user/test.yaml +0 -12
@@ -0,0 +1,85 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
def on_start_logging(params)
|
10
|
+
params.channels.each { |channel|
|
11
|
+
service("log").start_logging(channel)
|
12
|
+
}
|
13
|
+
answer(:started_logging, :channels => params.channels)
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_stop_logging(params)
|
17
|
+
params.channels.each { |channel|
|
18
|
+
service("log").stop_logging(channel)
|
19
|
+
}
|
20
|
+
answer(:stopped_logging, :channels => params.channels)
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_list_logged_channels(params)
|
24
|
+
answer(:logging_channels, :channels => service("log").logged_channels)
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_search_log(params)
|
28
|
+
args = {}
|
29
|
+
args[:nick] = params.nick
|
30
|
+
args[:text] = params.text.split(/\s+/) if params.text
|
31
|
+
args[:channel] = params.channel
|
32
|
+
|
33
|
+
found = service("log").find_last(5, args)
|
34
|
+
|
35
|
+
if found.length.zero? then
|
36
|
+
answer(:no_match)
|
37
|
+
else
|
38
|
+
upper = [5,found.length].min
|
39
|
+
answer("Found (1-#{upper} of #{found.length}):")
|
40
|
+
found.each_with_index { |row, index|
|
41
|
+
answer(
|
42
|
+
"#{index+1}: " \
|
43
|
+
"[#{row.time.strftime('%Y-%m-%d %H:%M')}, " \
|
44
|
+
"#{row.nick} in #{row.channel}] " \
|
45
|
+
"#{row.text}"
|
46
|
+
)
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
__END__
|
52
|
+
---
|
53
|
+
:about:
|
54
|
+
:mail: "apeiros@gmx.net"
|
55
|
+
:version: "1.0.0"
|
56
|
+
:author: "Stefan Rusterholz"
|
57
|
+
:help:
|
58
|
+
en:
|
59
|
+
"": Log channel messages.
|
60
|
+
:map:
|
61
|
+
:on_start_logging:
|
62
|
+
en: start logging in *channels@Channelname
|
63
|
+
:on_stop_logging:
|
64
|
+
en: stop logging in *channels@Channelname
|
65
|
+
:on_list_logged_channels:
|
66
|
+
en: list logged channels
|
67
|
+
:on_search_log:
|
68
|
+
en: search log [for +text] [from :nick@Nick] [in :channel@Channelname]
|
69
|
+
:strings:
|
70
|
+
:no_match:
|
71
|
+
en: "No match found."
|
72
|
+
:logging_channels:
|
73
|
+
en: |
|
74
|
+
Logging is active for: <%= channels.join(', ') %>.
|
75
|
+
:started_logging:
|
76
|
+
en: |
|
77
|
+
Logging activated in: <%= channels.join(', ') %>.
|
78
|
+
:stopped_logging:
|
79
|
+
en: |
|
80
|
+
Logging deactivated in: <%= channels.join(', ') %>.
|
81
|
+
:summary:
|
82
|
+
en: Log channel messages
|
83
|
+
:revision:
|
84
|
+
:plugin: 2
|
85
|
+
:configuration: 2
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
def on_seen(params)
|
10
|
+
found = service("log").find_last(
|
11
|
+
:nick => params.nick,
|
12
|
+
:type => [:JOIN, :PART, :QUIT, :KICK, :KILL]
|
13
|
+
)
|
14
|
+
if found then
|
15
|
+
case found.type
|
16
|
+
when :JOIN
|
17
|
+
answer(:still_online, :nick => params.nick)
|
18
|
+
when :PART
|
19
|
+
answer(:last_seen_part, :time => found.time, :nick => params.nick, :text => found.text || "", :channel => found.channel)
|
20
|
+
when :QUIT
|
21
|
+
answer(:last_seen_quit, :time => found.time, :nick => params.nick, :text => found.text || "")
|
22
|
+
when :KICK
|
23
|
+
answer(:last_seen_kick, :time => found.time, :nick => params.nick, :text => found.text || "", :channel => found.channel)
|
24
|
+
when :KILL
|
25
|
+
answer(:last_seen_kill, :time => found.time, :nick => params.nick, :text => found.text || "")
|
26
|
+
end
|
27
|
+
else
|
28
|
+
service("strings").answer(@message, "ignorance")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
__END__
|
33
|
+
---
|
34
|
+
:about:
|
35
|
+
:mail: "apeiros@gmx.net"
|
36
|
+
:version: "1.0.0"
|
37
|
+
:author: "Stefan Rusterholz"
|
38
|
+
:help:
|
39
|
+
en:
|
40
|
+
"": "Check when a user was last online."
|
41
|
+
:map:
|
42
|
+
:on_seen:
|
43
|
+
en: "seen :nick@Nick[?]"
|
44
|
+
de: "hast du :nick@Nick gesehen[?]"
|
45
|
+
:revision:
|
46
|
+
:plugin: 1
|
47
|
+
:services:
|
48
|
+
-log
|
49
|
+
-strings
|
50
|
+
:strings:
|
51
|
+
:still_online:
|
52
|
+
en: "<%= nick %> is still online."
|
53
|
+
:last_seen_part:
|
54
|
+
en: "<%= nick %> was last seen <%= time.strftime('%Y-%m-%d at %H:%M') %>, parting from <%= channel %><% if text.strip.empty? then %> not saying why<% else %> saying <%= text %><% end %>."
|
55
|
+
:last_seen_quit:
|
56
|
+
en: "<%= nick %> was last seen <%= time.strftime('%Y-%m-%d at %H:%M') %>, when he quit<% if text.strip.empty? then %> without a reason<% else %> with reason <%= text %><% end %>."
|
57
|
+
:last_seen_kick:
|
58
|
+
en: "<%= nick %> was last seen <%= time.strftime('%Y-%m-%d at %H:%M') %>, when he was kicked from <%= channel %><% if text.strip.empty? then %> for no reason<% else %> for <%= text %><% end %>."
|
59
|
+
:last_seen_kill:
|
60
|
+
en: "<%= nick %> was last seen <%= time.strftime('%Y-%m-%d at %H:%M') %>, when he was killed<% if text.strip.empty? then %> for no reason<% else %> for <%= text %><% end %>."
|
61
|
+
:summary:
|
62
|
+
en: "Check when a user was last online."
|
63
|
+
:usage:
|
64
|
+
en: "![b]seen![o] nick?"
|
@@ -11,7 +11,7 @@ require 'hpricot'
|
|
11
11
|
require 'cgi'
|
12
12
|
|
13
13
|
configuration(
|
14
|
-
"frequency" => 900,
|
14
|
+
"frequency" => 900, # In seconds, default is 900 == 15 minutes
|
15
15
|
"repositories" => {}
|
16
16
|
)
|
17
17
|
|
@@ -32,6 +32,7 @@ end
|
|
32
32
|
every(@config["frequency"]) do
|
33
33
|
repositories = @config["repositories"]
|
34
34
|
repositories.each { |repo, data|
|
35
|
+
debug "Checking SVN repository #{repo}"
|
35
36
|
cr, lr = current_revision(repo), data[:revision]
|
36
37
|
if cr > lr then
|
37
38
|
data[:revision] = cr
|
@@ -77,15 +78,15 @@ __END__
|
|
77
78
|
en: "Poll repositories for changes and publicate them."
|
78
79
|
:about:
|
79
80
|
:mail: "apeiros@gmx.net"
|
80
|
-
:version: "1.
|
81
|
+
:version: "1.2.0"
|
81
82
|
:author: "Stefan Rusterholz"
|
82
83
|
:usage:
|
83
|
-
en: "![b]svn![o] 'add' repository channel ..."
|
84
|
+
en: "![b]svn![o] 'add' repository #channel [#channel2...]"
|
84
85
|
:help:
|
85
86
|
en:
|
86
87
|
"": "Poll repositories for changes and publicate them."
|
87
88
|
:strings:
|
88
89
|
:added:
|
89
|
-
en: Added repository <%= repository
|
90
|
+
en: Added repository <%= repository %>
|
90
91
|
:removed:
|
91
|
-
en:
|
92
|
+
en: Removed repository <%= repository %>
|
@@ -11,6 +11,8 @@ def on_trigger
|
|
11
11
|
vsz, rss, cpu, pmem = ps_out.scan(/\d+(?:[.,]\d+)?/).map { |e| e.gsub(/,/,'.').to_f } # ps on 10.5.1 outputs ',' instead of '.' for MEM%
|
12
12
|
virtual, real = (vsz-rss).div(1024), rss.div(1024)
|
13
13
|
answer(:memusage, :real => real, :virtual => virtual, :cpu => cpu, :pmem => pmem)
|
14
|
+
rescue Interrupt
|
15
|
+
raise
|
14
16
|
rescue Exception => e
|
15
17
|
answer(:failure, :exception => e)
|
16
18
|
end
|
@@ -32,7 +34,7 @@ __END__
|
|
32
34
|
:strings:
|
33
35
|
:memusage:
|
34
36
|
en: |
|
35
|
-
Memory: <%= real %>MB real, <%= virtual %>MB virtual
|
37
|
+
Memory: <%= pmem %>% (<%= real %>MB real, <%= virtual %>MB virtual), CPU: <%= cpu %>%.
|
36
38
|
:failure:
|
37
39
|
en: |
|
38
40
|
Failed with exception <%= exception %>.
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'blank'
|
2
|
+
|
3
|
+
class Functions
|
4
|
+
def initialize
|
5
|
+
@functions = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def [](name)
|
9
|
+
@functions[name.to_s]
|
10
|
+
end
|
11
|
+
|
12
|
+
def []=(name, definition)
|
13
|
+
@functions[name.to_s] = definition
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(m, *args)
|
17
|
+
@functions[m.to_s].call(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def respond_to?(m, *a)
|
21
|
+
super || @functions.has_key?(m.to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(m, *args)
|
25
|
+
super unless @functions.has_key?(m.to_s)
|
26
|
+
@functions[m.to_s].call(*args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Calculator < Blank('inspect', 'binding', 'method_missing')
|
31
|
+
include Math
|
32
|
+
|
33
|
+
attr_reader :term
|
34
|
+
|
35
|
+
def initialize(term, delegate=nil)
|
36
|
+
@term = term.scan(/\s+|,|[a-z]*\(|\)|-?\d(?:\.\d+)?|[a-z]+|[*\/%+-]/).join.gsub(/%[^\d\s]/, '')
|
37
|
+
@variables = {}
|
38
|
+
@delegate = delegate
|
39
|
+
@results = []
|
40
|
+
end
|
41
|
+
|
42
|
+
def result(variables={})
|
43
|
+
@variables = variables
|
44
|
+
error = nil
|
45
|
+
@results.unshift Thread.new {
|
46
|
+
begin
|
47
|
+
Kernel.eval(@term, binding)
|
48
|
+
rescue Exception => e
|
49
|
+
error = e
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
}.value
|
53
|
+
if error then
|
54
|
+
@results.shift
|
55
|
+
Kernel.raise error
|
56
|
+
end
|
57
|
+
@results.pop if @results.length > 10
|
58
|
+
@results.first
|
59
|
+
end
|
60
|
+
alias call result
|
61
|
+
|
62
|
+
def load(result)
|
63
|
+
@results[result]
|
64
|
+
end
|
65
|
+
|
66
|
+
def method_missing(m, *a)
|
67
|
+
if a.empty? && @variables.has_key?(m.to_s) then
|
68
|
+
@variables[m.to_s]
|
69
|
+
elsif @delegate.respond_to?(m) then
|
70
|
+
@delegate.call(m, *a)
|
71
|
+
else
|
72
|
+
super
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class CalcService
|
78
|
+
def initialize
|
79
|
+
@functions = Functions.new
|
80
|
+
end
|
81
|
+
|
82
|
+
def register_function(name, variables, term)
|
83
|
+
calculator = Calculator.new(term, @functions)
|
84
|
+
@functions[name] = proc { |*args|
|
85
|
+
hash = {}
|
86
|
+
variables.zip(args) { |key, value| hash[key.to_s] = value }
|
87
|
+
calculator.result(hash)
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
def calculate(term)
|
92
|
+
Calculator.new(term, @functions).result
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
register(CalcService.new)
|
@@ -6,37 +6,44 @@
|
|
6
6
|
|
7
7
|
|
8
8
|
|
9
|
+
# FIXME, remove as soon as the sqlite people figured out how to init globals
|
10
|
+
$swig_runtime_data_type_pointer2 = nil unless defined? $swig_runtime_data_type_pointer2
|
11
|
+
require 'log/comfort'
|
9
12
|
require 'sqlite3'
|
10
13
|
require 'thread'
|
11
14
|
require 'ruby/file/write'
|
12
15
|
|
13
16
|
|
14
17
|
|
15
|
-
MessageTypes = [:PRIVMSG, :NOTICE, :JOIN, :PART, :QUIT, :KICK, :KILL]
|
16
|
-
Row = Struct.new(:oid, :time, :channel, :nick, :type, :text)
|
18
|
+
MessageTypes = [:PRIVMSG, :NOTICE, :JOIN, :PART, :QUIT, :KICK, :KILL, :NICK, :TOPIC]
|
19
|
+
Row = Struct.new(:oid, :time, :channel, :nick, :type, :text, :identified)
|
17
20
|
def Row.from_row(row)
|
18
|
-
oid, time, channel, nick, type, text = *row
|
19
|
-
new(oid.to_i, Time.at(
|
21
|
+
oid, time, channel, nick, type, text, identified = *row
|
22
|
+
new(oid.to_i, Time.at(time.to_i), channel, nick, MessageTypes[type.to_i], text, identified=="1")
|
20
23
|
end
|
21
24
|
|
22
25
|
class IRCLogger
|
26
|
+
include Log::Comfort
|
27
|
+
|
23
28
|
def initialize(db, channels)
|
24
29
|
@db_file = db
|
25
30
|
@db = SQLite3::Database.new(db)
|
31
|
+
@logger = nil
|
26
32
|
@db.execute %q{
|
27
33
|
CREATE TABLE IF NOT EXISTS messages(
|
28
|
-
oid
|
29
|
-
time
|
30
|
-
channel
|
31
|
-
nick
|
32
|
-
type
|
33
|
-
text
|
34
|
+
oid INTEGER PRIMARY KEY AUTOINCREMENT,
|
35
|
+
time INTEGER,
|
36
|
+
channel TEXT,
|
37
|
+
nick TEXT,
|
38
|
+
type INTEGER,
|
39
|
+
text TEXT,
|
40
|
+
identified INTEGER
|
34
41
|
)
|
35
42
|
}
|
36
43
|
@insert = @db.prepare %q{
|
37
44
|
INSERT INTO messages
|
38
|
-
(time, channel, nick, type, text)
|
39
|
-
VALUES (:time, :channel, :nick, :type, :text)
|
45
|
+
(time, channel, nick, type, text, identified)
|
46
|
+
VALUES (:time, :channel, :nick, :type, :text, :identified)
|
40
47
|
}
|
41
48
|
File.write(channels, {}.to_yaml) unless File.exist?(channels)
|
42
49
|
@channels = YAML.load_file(channels)
|
@@ -58,6 +65,10 @@ class IRCLogger
|
|
58
65
|
}
|
59
66
|
end
|
60
67
|
|
68
|
+
def logged_channels
|
69
|
+
@channels.keys
|
70
|
+
end
|
71
|
+
|
61
72
|
def logged?(channel)
|
62
73
|
@channels.has_key?(channel)
|
63
74
|
end
|
@@ -67,7 +78,7 @@ class IRCLogger
|
|
67
78
|
end
|
68
79
|
|
69
80
|
def select(statement=nil, *values)
|
70
|
-
query = "SELECT * FROM messages #{statement}"
|
81
|
+
debug(query = "SELECT * FROM messages #{statement}")
|
71
82
|
if block_given? then
|
72
83
|
@db.execute(query, *values) { |row|
|
73
84
|
yield(Row.from_row(row))
|
@@ -80,26 +91,67 @@ class IRCLogger
|
|
80
91
|
end
|
81
92
|
|
82
93
|
def find(args={}, &block)
|
83
|
-
where
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
94
|
+
select(where(args), &block)
|
95
|
+
end
|
96
|
+
|
97
|
+
def find_first(*args)
|
98
|
+
case args.length
|
99
|
+
when 0, 1
|
100
|
+
if Integer === args.first then
|
101
|
+
select("LIMIT #{args.first}")
|
102
|
+
else
|
103
|
+
select(where(args.first)+" LIMIT 1").first
|
104
|
+
end
|
105
|
+
when 2
|
106
|
+
select(where(args.last)+" LIMIT #{args.first}")
|
107
|
+
else
|
108
|
+
raise ArgumentError, "0, 1 or 2 arguments accepted"
|
92
109
|
end
|
93
|
-
|
94
|
-
|
110
|
+
end
|
111
|
+
|
112
|
+
def find_last(*args)
|
113
|
+
case args.length
|
114
|
+
when 0, 1
|
115
|
+
if Integer === args.first then
|
116
|
+
select("ORDER BY time DESC LIMIT #{args.first}").reverse
|
117
|
+
else
|
118
|
+
select(where(args.first)+" ORDER BY time DESC LIMIT 1").first
|
119
|
+
end
|
120
|
+
when 2
|
121
|
+
select( where(args.last)+" ORDER BY time DESC LIMIT #{args.first}").reverse
|
122
|
+
else
|
123
|
+
raise ArgumentError, "0, 1 or 2 arguments accepted"
|
95
124
|
end
|
96
|
-
|
97
|
-
|
125
|
+
end
|
126
|
+
|
127
|
+
def where(args=nil, connected='AND')
|
128
|
+
where = sub_where(args || {}, connected)
|
129
|
+
where.empty? ? "" : 'WHERE '+where.join(' AND ')
|
130
|
+
end
|
131
|
+
|
132
|
+
def sub_where(args={}, connected='AND')
|
133
|
+
where = []
|
134
|
+
where << field_equals_values('nick', args[:nick]) if args[:nick]
|
135
|
+
where << field_equals_values('channel', args[:channel]) if args[:channel]
|
136
|
+
where << field_within('time', args[:time].begin.to_i, args[:time].end.to_i) if args[:time]
|
137
|
+
if args[:type] then
|
138
|
+
if Array === args[:type] then
|
139
|
+
args[:type] = args[:type].map { |e| MessageTypes.index(e).to_s }
|
140
|
+
else
|
141
|
+
args[:type] = MessageTypes.index(args[:type]).to_s
|
142
|
+
end
|
143
|
+
where << field_equals_values('type', args[:type])
|
98
144
|
end
|
99
|
-
|
145
|
+
where << field_like_values('text', args[:text]) if args[:text]
|
146
|
+
where
|
100
147
|
end
|
101
148
|
|
102
|
-
def
|
149
|
+
def field_within(field, lower, upper)
|
150
|
+
"(#{field} >= #{SQLite3::Database.quote(lower)} AND " \
|
151
|
+
"#{field} <= #{SQLite3::Database.quote(upper)})"
|
152
|
+
end
|
153
|
+
|
154
|
+
def field_like_values(field, values)
|
103
155
|
if Array === values then
|
104
156
|
values.map { |e| "#{field} LIKE '#{SQLite3::Database.quote(e)}'" }.join(" AND ")
|
105
157
|
else
|
@@ -111,12 +163,12 @@ class IRCLogger
|
|
111
163
|
if Array === values then
|
112
164
|
is_in(field, values)
|
113
165
|
else
|
114
|
-
"#{field}
|
166
|
+
"#{field} == '#{SQLite3::Database.quote(values)}'"
|
115
167
|
end
|
116
168
|
end
|
117
169
|
|
118
170
|
def is_in(field, values)
|
119
|
-
"#{field} IN ('#{values.map { |e| SQLite3::Database.quote(
|
171
|
+
"#{field} IN ('#{values.map { |e| SQLite3::Database.quote(e) }.join('\', \'') }')"
|
120
172
|
end
|
121
173
|
end
|
122
174
|
|
@@ -124,75 +176,103 @@ def self.on_load
|
|
124
176
|
logger = IRCLogger.new(@path.base+'/log.sqlite', @path.base+'/channels.yaml')
|
125
177
|
|
126
178
|
subscribe(:PRIVMSG, -10, MessageTypes.index(:PRIVMSG)) { |listener, message, type|
|
127
|
-
next unless logger.logged?(message.channel.to_str)
|
179
|
+
next unless message.channel and logger.logged?(message.channel.to_str)
|
128
180
|
logger.insert(
|
129
|
-
:time
|
130
|
-
:channel
|
131
|
-
:nick
|
132
|
-
:type
|
133
|
-
:text
|
181
|
+
:time => Time.now.to_i,
|
182
|
+
:channel => message.channel.to_str,
|
183
|
+
:nick => message.from.nick,
|
184
|
+
:type => type,
|
185
|
+
:text => message.text,
|
186
|
+
:identified => message.identified? ? 1 : 0
|
134
187
|
)
|
135
188
|
}
|
136
189
|
subscribe(:NOTICE, -10, MessageTypes.index(:NOTICE)) { |listener, message, type|
|
137
|
-
next unless logger.logged?(message.channel.to_str)
|
190
|
+
next unless message.channel and logger.logged?(message.channel.to_str)
|
138
191
|
logger.insert(
|
139
|
-
:time
|
140
|
-
:channel
|
141
|
-
:nick
|
142
|
-
:type
|
143
|
-
:text
|
192
|
+
:time => Time.now.to_i,
|
193
|
+
:channel => message.channel.to_str,
|
194
|
+
:nick => message.from.nick,
|
195
|
+
:type => type,
|
196
|
+
:text => message.text,
|
197
|
+
:identified => message.identified? ? 1 : 0
|
144
198
|
)
|
145
199
|
}
|
146
200
|
subscribe(:JOIN, -10, MessageTypes.index(:JOIN)) { |listener, message, type|
|
147
201
|
next unless logger.logged?(message.channel.to_str)
|
148
202
|
logger.insert(
|
149
|
-
:time
|
150
|
-
:channel
|
151
|
-
:nick
|
152
|
-
:type
|
153
|
-
:text
|
203
|
+
:time => Time.now.to_i,
|
204
|
+
:channel => message.channel.to_str,
|
205
|
+
:nick => message.from.nick,
|
206
|
+
:type => type,
|
207
|
+
:text => nil,
|
208
|
+
:identified => 0
|
154
209
|
)
|
155
210
|
}
|
156
211
|
subscribe(:PART, -10, MessageTypes.index(:PART)) { |listener, message, type|
|
157
212
|
next unless logger.logged?(message.channel.to_str)
|
158
213
|
logger.insert(
|
159
|
-
:time
|
160
|
-
:channel
|
161
|
-
:nick
|
162
|
-
:type
|
163
|
-
:text
|
214
|
+
:time => Time.now.to_i,
|
215
|
+
:channel => message.channel.to_str,
|
216
|
+
:nick => message.from.nick,
|
217
|
+
:type => type,
|
218
|
+
:text => message.text,
|
219
|
+
:identified => 0
|
164
220
|
)
|
165
221
|
}
|
166
222
|
subscribe(:QUIT, -10, MessageTypes.index(:QUIT)) { |listener, message, type|
|
167
|
-
next unless logger.logged?(message.channel.to_str)
|
168
223
|
logger.insert(
|
169
|
-
:time
|
170
|
-
:channel
|
171
|
-
:nick
|
172
|
-
:type
|
173
|
-
:text
|
224
|
+
:time => Time.now.to_i,
|
225
|
+
:channel => "",
|
226
|
+
:nick => message.from.nick,
|
227
|
+
:type => type,
|
228
|
+
:text => message.text,
|
229
|
+
:identified => 0
|
174
230
|
)
|
175
231
|
}
|
176
232
|
subscribe(:KICK, -10, MessageTypes.index(:KICK)) { |listener, message, type|
|
177
233
|
next unless logger.logged?(message.channel.to_str)
|
178
234
|
logger.insert(
|
179
|
-
:time
|
180
|
-
:channel
|
181
|
-
:nick
|
182
|
-
:type
|
183
|
-
:text
|
235
|
+
:time => Time.now.to_i,
|
236
|
+
:channel => message.channel.to_str,
|
237
|
+
:nick => message.from.nick,
|
238
|
+
:type => type,
|
239
|
+
:text => message.text,
|
240
|
+
:identified => 0
|
184
241
|
)
|
185
242
|
}
|
186
243
|
subscribe(:KILL, -10, MessageTypes.index(:KILL)) { |listener, message, type|
|
187
244
|
next unless logger.logged?(message.channel.to_str)
|
188
245
|
logger.insert(
|
189
|
-
:time
|
190
|
-
:channel
|
191
|
-
:nick
|
192
|
-
:type
|
193
|
-
:text
|
246
|
+
:time => Time.now.to_i,
|
247
|
+
:channel => message.channel.to_str,
|
248
|
+
:nick => message.from.nick,
|
249
|
+
:type => type,
|
250
|
+
:text => message.text,
|
251
|
+
:identified => 0
|
252
|
+
)
|
253
|
+
}
|
254
|
+
subscribe(:NICK, -10, MessageTypes.index(:NICK)) { |listener, message, type|
|
255
|
+
logger.insert(
|
256
|
+
:time => Time.now.to_i,
|
257
|
+
:channel => "",
|
258
|
+
:nick => message.old_nick,
|
259
|
+
:type => type,
|
260
|
+
:text => message.from.nick,
|
261
|
+
:identified => 0
|
262
|
+
)
|
263
|
+
}
|
264
|
+
subscribe(:TOPIC, -10, MessageTypes.index(:TOPIC)) { |listener, message, type|
|
265
|
+
next unless logger.logged?(message.channel.to_str)
|
266
|
+
logger.insert(
|
267
|
+
:time => Time.now.to_i,
|
268
|
+
:channel => message.channel.to_str,
|
269
|
+
:nick => message.from.nick,
|
270
|
+
:type => type,
|
271
|
+
:text => message.text,
|
272
|
+
:identified => 0
|
194
273
|
)
|
195
274
|
}
|
196
275
|
|
276
|
+
|
197
277
|
register(logger)
|
198
278
|
end
|