butler 1.8.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.
- data/CHANGELOG +4 -0
- data/GPL.txt +340 -0
- data/LICENSE.txt +52 -0
- data/README +37 -0
- data/Rakefile +334 -0
- data/bin/botcontrol +230 -0
- data/data/butler/config_template.yaml +4 -0
- data/data/butler/dialogs/backup.rb +19 -0
- data/data/butler/dialogs/botcontrol.rb +4 -0
- data/data/butler/dialogs/config.rb +1 -0
- data/data/butler/dialogs/create.rb +53 -0
- data/data/butler/dialogs/delete.rb +3 -0
- data/data/butler/dialogs/en/backup.yaml +6 -0
- data/data/butler/dialogs/en/botcontrol.yaml +5 -0
- data/data/butler/dialogs/en/create.yaml +11 -0
- data/data/butler/dialogs/en/delete.yaml +2 -0
- data/data/butler/dialogs/en/help.yaml +17 -0
- data/data/butler/dialogs/en/info.yaml +13 -0
- data/data/butler/dialogs/en/list.yaml +4 -0
- data/data/butler/dialogs/en/notyetimplemented.yaml +2 -0
- data/data/butler/dialogs/en/rename.yaml +3 -0
- data/data/butler/dialogs/en/start.yaml +3 -0
- data/data/butler/dialogs/en/sync_plugins.yaml +3 -0
- data/data/butler/dialogs/en/uninstall.yaml +5 -0
- data/data/butler/dialogs/en/unknown_command.yaml +2 -0
- data/data/butler/dialogs/help.rb +11 -0
- data/data/butler/dialogs/info.rb +27 -0
- data/data/butler/dialogs/interactive.rb +1 -0
- data/data/butler/dialogs/list.rb +10 -0
- data/data/butler/dialogs/notyetimplemented.rb +1 -0
- data/data/butler/dialogs/rename.rb +4 -0
- data/data/butler/dialogs/selectbot.rb +2 -0
- data/data/butler/dialogs/start.rb +5 -0
- data/data/butler/dialogs/sync_plugins.rb +30 -0
- data/data/butler/dialogs/uninstall.rb +17 -0
- data/data/butler/dialogs/unknown_command.rb +1 -0
- data/data/butler/plugins/core/logout.rb +41 -0
- data/data/butler/plugins/core/plugins.rb +134 -0
- data/data/butler/plugins/core/privilege.rb +103 -0
- data/data/butler/plugins/core/user.rb +166 -0
- data/data/butler/plugins/dev/eval.rb +64 -0
- data/data/butler/plugins/dev/nometa.rb +14 -0
- data/data/butler/plugins/dev/onhandlers.rb +93 -0
- data/data/butler/plugins/dev/raw.rb +36 -0
- data/data/butler/plugins/dev/rawlog.rb +77 -0
- data/data/butler/plugins/games/eightball.rb +54 -0
- data/data/butler/plugins/games/mastermind.rb +174 -0
- data/data/butler/plugins/irc/action.rb +36 -0
- data/data/butler/plugins/irc/join.rb +38 -0
- data/data/butler/plugins/irc/notice.rb +36 -0
- data/data/butler/plugins/irc/part.rb +38 -0
- data/data/butler/plugins/irc/privmsg.rb +36 -0
- data/data/butler/plugins/irc/quit.rb +36 -0
- data/data/butler/plugins/operator/deop.rb +41 -0
- data/data/butler/plugins/operator/devoice.rb +41 -0
- data/data/butler/plugins/operator/limit.rb +47 -0
- data/data/butler/plugins/operator/op.rb +41 -0
- data/data/butler/plugins/operator/voice.rb +41 -0
- data/data/butler/plugins/public/help.rb +69 -0
- data/data/butler/plugins/public/login.rb +72 -0
- data/data/butler/plugins/public/usage.rb +49 -0
- data/data/butler/plugins/service/clones.rb +56 -0
- data/data/butler/plugins/service/define.rb +47 -0
- data/data/butler/plugins/service/log.rb +183 -0
- data/data/butler/plugins/service/svn.rb +91 -0
- data/data/butler/plugins/util/cycle.rb +98 -0
- data/data/butler/plugins/util/load.rb +41 -0
- data/data/butler/plugins/util/pong.rb +29 -0
- data/data/butler/strings/random/acknowledge.en.yaml +5 -0
- data/data/butler/strings/random/gratitude.en.yaml +3 -0
- data/data/butler/strings/random/hello.en.yaml +4 -0
- data/data/butler/strings/random/ignorance.en.yaml +7 -0
- data/data/butler/strings/random/ignorance_about.en.yaml +3 -0
- data/data/butler/strings/random/insult.en.yaml +3 -0
- data/data/butler/strings/random/rejection.en.yaml +12 -0
- data/data/man/botcontrol.1 +17 -0
- data/lib/access.rb +187 -0
- data/lib/access/admin.rb +16 -0
- data/lib/access/privilege.rb +122 -0
- data/lib/access/role.rb +102 -0
- data/lib/access/savable.rb +18 -0
- data/lib/access/user.rb +180 -0
- data/lib/access/yamlbase.rb +126 -0
- data/lib/butler.rb +188 -0
- data/lib/butler/bot.rb +247 -0
- data/lib/butler/control.rb +93 -0
- data/lib/butler/dialog.rb +64 -0
- data/lib/butler/initialvalues.rb +40 -0
- data/lib/butler/irc/channel.rb +135 -0
- data/lib/butler/irc/channels.rb +96 -0
- data/lib/butler/irc/client.rb +351 -0
- data/lib/butler/irc/hostmask.rb +53 -0
- data/lib/butler/irc/message.rb +184 -0
- data/lib/butler/irc/parser.rb +125 -0
- data/lib/butler/irc/parser/commands.rb +83 -0
- data/lib/butler/irc/parser/generic.rb +343 -0
- data/lib/butler/irc/socket.rb +378 -0
- data/lib/butler/irc/string.rb +186 -0
- data/lib/butler/irc/topic.rb +15 -0
- data/lib/butler/irc/user.rb +265 -0
- data/lib/butler/irc/users.rb +112 -0
- data/lib/butler/plugin.rb +249 -0
- data/lib/butler/plugin/configproxy.rb +35 -0
- data/lib/butler/plugin/mapper.rb +85 -0
- data/lib/butler/plugin/matcher.rb +55 -0
- data/lib/butler/plugin/onhandlers.rb +70 -0
- data/lib/butler/plugin/trigger.rb +58 -0
- data/lib/butler/plugins.rb +147 -0
- data/lib/butler/version.rb +17 -0
- data/lib/cloptions.rb +217 -0
- data/lib/cloptions/adapters.rb +24 -0
- data/lib/cloptions/switch.rb +132 -0
- data/lib/configuration.rb +223 -0
- data/lib/dialogline.rb +296 -0
- data/lib/dialogline/localizations.rb +24 -0
- data/lib/durations.rb +57 -0
- data/lib/event.rb +295 -0
- data/lib/event/at.rb +64 -0
- data/lib/event/every.rb +56 -0
- data/lib/event/timed.rb +112 -0
- data/lib/installer.rb +75 -0
- data/lib/iterator.rb +34 -0
- data/lib/log.rb +68 -0
- data/lib/log/comfort.rb +85 -0
- data/lib/log/converter.rb +23 -0
- data/lib/log/entry.rb +152 -0
- data/lib/log/fakeio.rb +55 -0
- data/lib/log/file.rb +54 -0
- data/lib/log/filereader.rb +81 -0
- data/lib/log/forward.rb +49 -0
- data/lib/log/methods.rb +39 -0
- data/lib/log/nolog.rb +18 -0
- data/lib/log/splitter.rb +26 -0
- data/lib/ostructfixed.rb +26 -0
- data/lib/ruby/array/columnize.rb +38 -0
- data/lib/ruby/dir/mktree.rb +28 -0
- data/lib/ruby/enumerable/join.rb +13 -0
- data/lib/ruby/exception/detailed.rb +24 -0
- data/lib/ruby/file/append.rb +11 -0
- data/lib/ruby/file/write.rb +11 -0
- data/lib/ruby/hash/zip.rb +15 -0
- data/lib/ruby/kernel/bench.rb +15 -0
- data/lib/ruby/kernel/daemonize.rb +42 -0
- data/lib/ruby/kernel/non_verbose.rb +17 -0
- data/lib/ruby/kernel/safe_fork.rb +18 -0
- data/lib/ruby/range/stepped.rb +11 -0
- data/lib/ruby/string/arguments.rb +72 -0
- data/lib/ruby/string/chunks.rb +15 -0
- data/lib/ruby/string/post_arguments.rb +44 -0
- data/lib/ruby/string/unescaped.rb +17 -0
- data/lib/scheduler.rb +164 -0
- data/lib/scriptfile.rb +101 -0
- data/lib/templater.rb +86 -0
- data/test/cloptions.rb +134 -0
- data/test/cv.rb +28 -0
- data/test/irc/client.rb +85 -0
- data/test/irc/client_login.txt +53 -0
- data/test/irc/client_subscribe.txt +8 -0
- data/test/irc/message.rb +30 -0
- data/test/irc/messages.txt +64 -0
- data/test/irc/parser.rb +13 -0
- data/test/irc/profile_parser.rb +12 -0
- data/test/irc/users.rb +28 -0
- metadata +256 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
# See LICENSE.txt for permissions.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
#extend OnHandlers
|
|
10
|
+
trigger "login"
|
|
11
|
+
|
|
12
|
+
# FIXME, requires working OnHandlers
|
|
13
|
+
# FIXME, requires Butler::IRC::Message#answer to work with :JOIN
|
|
14
|
+
def on_join
|
|
15
|
+
if @message.from.user[0,1] == "i" then
|
|
16
|
+
# check nick->user mappings
|
|
17
|
+
if user = plugin.config["nickmap"][@message.from.nick] then
|
|
18
|
+
@message.from.
|
|
19
|
+
answer(:success)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# FIXME, log events
|
|
25
|
+
# FIXME, accept plain login, using IDENT_CAPAB
|
|
26
|
+
def on_trigger
|
|
27
|
+
return answer(usage) unless [3].include?(@message.arguments.length)
|
|
28
|
+
|
|
29
|
+
if access = @butler.access.login(*@message.arguments[1,2]) then
|
|
30
|
+
@message.from.access = access
|
|
31
|
+
answer(:success)
|
|
32
|
+
if @message.public? then
|
|
33
|
+
@message.from.access.credentials = nil
|
|
34
|
+
answer(:public_success)
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
answer(:failure)
|
|
38
|
+
answer(:public_failure) if @message.public?
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
__END__
|
|
43
|
+
---
|
|
44
|
+
:revision:
|
|
45
|
+
:plugin: 1
|
|
46
|
+
:summary:
|
|
47
|
+
en: Authenticate to the bot
|
|
48
|
+
:about:
|
|
49
|
+
:mail: "apeiros@gmx.net"
|
|
50
|
+
:version: "1.0.0"
|
|
51
|
+
:author: "Stefan Rusterholz"
|
|
52
|
+
:strings:
|
|
53
|
+
:success:
|
|
54
|
+
en: You are now authenticated.
|
|
55
|
+
:failure:
|
|
56
|
+
en: Could not authenticate you.
|
|
57
|
+
:public_success:
|
|
58
|
+
en: |
|
|
59
|
+
You authenticated yourself in public. Your password has been deleted.
|
|
60
|
+
Please set a new one immediatly using 'access password ![c(blue)]password![o]'
|
|
61
|
+
:public_failure:
|
|
62
|
+
en: |
|
|
63
|
+
You tried to authenticate yourself in public. Be aware that a public login will result in a reset password.
|
|
64
|
+
If this was similar to your real password, then please login and set a new one immediatly using 'access password ![(blue)]password![r]'
|
|
65
|
+
:usage:
|
|
66
|
+
en: |
|
|
67
|
+
![b]login![o] ![c(blue)]username password![o]
|
|
68
|
+
:help:
|
|
69
|
+
en:
|
|
70
|
+
"": |
|
|
71
|
+
Using 'login ![c(blue)]username password![o]' you can Authenticate to the bot.
|
|
72
|
+
Be aware that the bot will delete your password if you authenticate in public as a protection measure.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
# See LICENSE.txt for permissions.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
trigger "usage"
|
|
10
|
+
|
|
11
|
+
def on_trigger
|
|
12
|
+
if @message.arguments.length != 2 then
|
|
13
|
+
answer(usage)
|
|
14
|
+
elsif plugin = @butler.plugins.identify(@message.arguments[1]) then
|
|
15
|
+
answer(@butler.plugins[plugin].plugin_usage(@message))
|
|
16
|
+
else
|
|
17
|
+
answer(:no_plugin, :name => @message.arguments[1])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
__END__
|
|
22
|
+
---
|
|
23
|
+
:revision:
|
|
24
|
+
:plugin: 1
|
|
25
|
+
:summary:
|
|
26
|
+
en: Give information about elementary usage of a plugin
|
|
27
|
+
:about:
|
|
28
|
+
:mail: "apeiros@gmx.net"
|
|
29
|
+
:version: "1.0.0"
|
|
30
|
+
:author: "Stefan Rusterholz"
|
|
31
|
+
:strings:
|
|
32
|
+
:no_plugin:
|
|
33
|
+
en: |
|
|
34
|
+
No plugin named <%= name %> loaded.
|
|
35
|
+
:usage:
|
|
36
|
+
en: |
|
|
37
|
+
![b]usage![o] <![c(green)]plugin![o]>
|
|
38
|
+
:help:
|
|
39
|
+
en:
|
|
40
|
+
"": |
|
|
41
|
+
Usage provides you with elementary information on how to use a plugin-command.
|
|
42
|
+
If you need more information, use the help command.
|
|
43
|
+
"keyword": |
|
|
44
|
+
Arguments in green and embraced by <angle brackets> are keyword arguments.
|
|
45
|
+
Keyword arguments require a specific format.
|
|
46
|
+
"keyword nick": |
|
|
47
|
+
A <nick> argument must be a valid (not necessary online) IRC nickname.
|
|
48
|
+
"keyword channel": |
|
|
49
|
+
A <channel> argument must be a valid (not necessary existing) IRC channelname.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
# See LICENSE.txt for permissions.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
trigger "clones"
|
|
10
|
+
|
|
11
|
+
def on_trigger
|
|
12
|
+
strong = @message.arguments.last != "weak"
|
|
13
|
+
if (@message.arguments.length == 2 && @message.arguments[1].valid_channelname?) then
|
|
14
|
+
all_clones = @butler.channels[message.arguments[1]].clones(strong)
|
|
15
|
+
answer(:clones_in_channel, :channel => message.arguments[1], :count => all_clones.length)
|
|
16
|
+
answer_clones(all_clones)
|
|
17
|
+
else
|
|
18
|
+
all_clones = @butler.users.clones(strong)
|
|
19
|
+
answer(:all_clones, :count => all_clones.length)
|
|
20
|
+
answer_clones(all_clones)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def answer_clones(all_clones)
|
|
25
|
+
all_clones.each { |common, clones|
|
|
26
|
+
answer(:clonelist, :common => common, :clones => clones)
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
__END__
|
|
31
|
+
---
|
|
32
|
+
:revision:
|
|
33
|
+
:plugin: 1
|
|
34
|
+
:summary:
|
|
35
|
+
en: Let butler send a notice to a user or channel
|
|
36
|
+
:about:
|
|
37
|
+
:mail: "apeiros@gmx.net"
|
|
38
|
+
:version: "1.0.0"
|
|
39
|
+
:author: "Stefan Rusterholz"
|
|
40
|
+
:strings:
|
|
41
|
+
:clones_in_channel:
|
|
42
|
+
en: |
|
|
43
|
+
Clones in channel <%= channel %> (<%= count %>):
|
|
44
|
+
:all_clones:
|
|
45
|
+
en: |
|
|
46
|
+
All clones (<%= count %>):
|
|
47
|
+
:clonelist:
|
|
48
|
+
en: |
|
|
49
|
+
<%= common %>: <%= clones.map { |u| "#{u.nick}" }.join(", ") %>
|
|
50
|
+
:usage:
|
|
51
|
+
en: |
|
|
52
|
+
![b]notice![o] (![c(green)]nick![o] | ![c(green)]channel![o])
|
|
53
|
+
:help:
|
|
54
|
+
en:
|
|
55
|
+
"": |
|
|
56
|
+
Let butler send a notice to a user or channel.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
# See LICENSE.txt for permissions.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
require 'open-uri'
|
|
10
|
+
require 'hpricot'
|
|
11
|
+
require 'cgi'
|
|
12
|
+
|
|
13
|
+
Query = "http://www.google.com/search?client=butler&rls=%s&q=define:+%s&ie=UTF-8&oe=UTF-8"
|
|
14
|
+
|
|
15
|
+
trigger "define"
|
|
16
|
+
|
|
17
|
+
def on_trigger
|
|
18
|
+
word = @message.post_arguments[1]
|
|
19
|
+
doc = Hpricot(open(Query%[@message.language, CGI.escape(word)]))
|
|
20
|
+
see_also = (doc/"//div[@id='res']/font[1]/p/a")[5..-1].map { |e| e.inner_text }
|
|
21
|
+
found = (doc/"//div[@id='res']/ul/font/li").find { |e| (e/"//a").inner_text.include?("wikipedia.org") }
|
|
22
|
+
if found then
|
|
23
|
+
answer(found.inner_text.sub(%r{\w+\.wikipedia\.org/wiki/.*?$}, ''))
|
|
24
|
+
else
|
|
25
|
+
answer(:not_found, :search_string => word)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
__END__
|
|
30
|
+
---
|
|
31
|
+
:revision:
|
|
32
|
+
:plugin: 1
|
|
33
|
+
:configuration: 1
|
|
34
|
+
:summary:
|
|
35
|
+
en: "Use googles define: to find the definition of words."
|
|
36
|
+
:about:
|
|
37
|
+
:mail: "apeiros@gmx.net"
|
|
38
|
+
:version: "1.0.0"
|
|
39
|
+
:author: "Stefan Rusterholz"
|
|
40
|
+
:usage:
|
|
41
|
+
en: "![b]define![o] *search_string"
|
|
42
|
+
:help:
|
|
43
|
+
en:
|
|
44
|
+
"": "Use googles define: to find the definition of words."
|
|
45
|
+
:strings:
|
|
46
|
+
:not_found:
|
|
47
|
+
en: No search result for '<%= search_string %>'.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
# See LICENSE.txt for permissions.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
require 'sequel/sqlite'
|
|
10
|
+
|
|
11
|
+
class <<self
|
|
12
|
+
attr_reader :log_db
|
|
13
|
+
attr_reader :log_table
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
@log_db = Sequel.sqlite @butler.path.log+'/log.sqlite'
|
|
17
|
+
|
|
18
|
+
configuration(
|
|
19
|
+
"channels" => []
|
|
20
|
+
)
|
|
21
|
+
@log_db.create_table(:log) {
|
|
22
|
+
primary_key :oid, :integer
|
|
23
|
+
int :time
|
|
24
|
+
str :channel, :size => 255
|
|
25
|
+
str :nick, :size => 48
|
|
26
|
+
int :type
|
|
27
|
+
text :text
|
|
28
|
+
} unless @log_db.table_exists?(:log)
|
|
29
|
+
@log_table = @log_db[:log]
|
|
30
|
+
|
|
31
|
+
MessageTypes = [:PRIVMSG, :NOTICE, :JOIN, :PART, :QUIT, :KICK, :KILL]
|
|
32
|
+
|
|
33
|
+
trigger "log"
|
|
34
|
+
|
|
35
|
+
def on_trigger
|
|
36
|
+
case @message.arguments[1]
|
|
37
|
+
when "list"
|
|
38
|
+
answer(:list, :channels => plugin.config["channels"])
|
|
39
|
+
when "on"
|
|
40
|
+
plugin.config["channels"] |= message.arguments[2..-1]
|
|
41
|
+
answer(:activated, :channels => message.arguments[2..-1])
|
|
42
|
+
when "off"
|
|
43
|
+
plugin.config["channels"] -= message.arguments[2..-1]
|
|
44
|
+
answer(:deactivated, :channels => message.arguments[2..-1])
|
|
45
|
+
when "search"
|
|
46
|
+
text, channel, from = @message.text.match(/search (.*)(?: in channel (#\w+))?(?: from (\w+))?$/).captures
|
|
47
|
+
text = "%#{text}%" if text
|
|
48
|
+
filtered = plugin.log_table #.filter { :type == 0 || :type == 1 }
|
|
49
|
+
filtered = filtered.filter { :nick == from } if from
|
|
50
|
+
filtered = filtered.filter { :nick == channel } if channel
|
|
51
|
+
filtered = filtered.filter { :text =~ text } if text
|
|
52
|
+
count = filtered.count
|
|
53
|
+
if count.zero? then
|
|
54
|
+
answer(:no_match)
|
|
55
|
+
else
|
|
56
|
+
upper = [5,count].min
|
|
57
|
+
answer("Found (1-#{upper} of #{count}):")
|
|
58
|
+
filtered.order(:time.DESC).first(5).each_with_index { |row, index|
|
|
59
|
+
answer(
|
|
60
|
+
"#{index+1}: " \
|
|
61
|
+
"[#{Time.at(row[:time]).strftime('%Y-%m-%d %H:%M')}, " \
|
|
62
|
+
"#{row[:from]} in #{row[:channel]}] " \
|
|
63
|
+
"#{row[:text]}"
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
when "dump"
|
|
68
|
+
n = @message.arguments[2].to_i
|
|
69
|
+
n = 5 if n.zero?
|
|
70
|
+
data = plugin.log_table.order(:time.DESC).first(n)
|
|
71
|
+
answer("Dump(#{data.length}):")
|
|
72
|
+
data.each_with_index { |row, index|
|
|
73
|
+
answer(
|
|
74
|
+
"#{index+1}: " \
|
|
75
|
+
"[#{Time.at(row[:time]).strftime('%Y-%m-%d %H:%M')}, " \
|
|
76
|
+
"#{row[:from]} in #{row[:channel]}] " \
|
|
77
|
+
"#{row[:text]}"
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
else
|
|
81
|
+
answer(usage)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
subscribe(:PRIVMSG, -10, nil, MessageTypes.index(:PRIVMSG)) { |listener, message, type|
|
|
86
|
+
next unless @config["channels"].include?(message.channel.to_str)
|
|
87
|
+
@log_table << {
|
|
88
|
+
:time => Time.now.to_i,
|
|
89
|
+
:channel => message.channel.to_str,
|
|
90
|
+
:nick => message.from.nick,
|
|
91
|
+
:type => type,
|
|
92
|
+
:text => message.text
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
subscribe(:NOTICE, -10, nil, MessageTypes.index(:NOTICE)) { |listener, message, type|
|
|
96
|
+
next unless @config["channels"].include?(message.channel.to_str)
|
|
97
|
+
@log_table << {
|
|
98
|
+
:time => Time.now.to_i,
|
|
99
|
+
:channel => message.channel.to_str,
|
|
100
|
+
:nick => message.from.nick,
|
|
101
|
+
:type => type,
|
|
102
|
+
:text => message.text
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
subscribe(:JOIN, -10, nil, MessageTypes.index(:JOIN)) { |listener, message, type|
|
|
106
|
+
next unless @config["channels"].include?(message.channel.to_str)
|
|
107
|
+
@log_table << {
|
|
108
|
+
:time => Time.now.to_i,
|
|
109
|
+
:channel => message.channel.to_str,
|
|
110
|
+
:nick => message.from.nick,
|
|
111
|
+
:type => type,
|
|
112
|
+
:text => nil
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
subscribe(:PART, -10, nil, MessageTypes.index(:PART)) { |listener, message, type|
|
|
116
|
+
next unless @config["channels"].include?(message.channel.to_str)
|
|
117
|
+
@log_table << {
|
|
118
|
+
:time => Time.now.to_i,
|
|
119
|
+
:channel => message.channel.to_str,
|
|
120
|
+
:nick => message.from.nick,
|
|
121
|
+
:type => type,
|
|
122
|
+
:text => message.text
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
subscribe(:QUIT, -10, nil, MessageTypes.index(:QUIT)) { |listener, message, type|
|
|
126
|
+
next unless @config["channels"].include?(message.channel.to_str)
|
|
127
|
+
@log_table << {
|
|
128
|
+
:time => Time.now.to_i,
|
|
129
|
+
:channel => message.channel.to_str,
|
|
130
|
+
:nick => message.from.nick,
|
|
131
|
+
:type => type,
|
|
132
|
+
:text => message.text
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
subscribe(:KICK, -10, nil, MessageTypes.index(:KICK)) { |listener, message, type|
|
|
136
|
+
next unless @config["channels"].include?(message.channel.to_str)
|
|
137
|
+
@log_table << {
|
|
138
|
+
:time => Time.now.to_i,
|
|
139
|
+
:channel => message.channel.to_str,
|
|
140
|
+
:nick => message.from.nick,
|
|
141
|
+
:type => type,
|
|
142
|
+
:text => message.text
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
subscribe(:KILL, -10, nil, MessageTypes.index(:KILL)) { |listener, message, type|
|
|
146
|
+
next unless @config["channels"].include?(message.channel.to_str)
|
|
147
|
+
@log_table << {
|
|
148
|
+
:time => Time.now.to_i,
|
|
149
|
+
:channel => message.channel.to_str,
|
|
150
|
+
:nick => message.from.nick,
|
|
151
|
+
:type => type,
|
|
152
|
+
:text => message.text
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
__END__
|
|
157
|
+
---
|
|
158
|
+
:revision:
|
|
159
|
+
:plugin: 1
|
|
160
|
+
:configuration: 1
|
|
161
|
+
:summary:
|
|
162
|
+
en: Log channel messages
|
|
163
|
+
:about:
|
|
164
|
+
:mail: "apeiros@gmx.net"
|
|
165
|
+
:version: "1.0.0"
|
|
166
|
+
:author: "Stefan Rusterholz"
|
|
167
|
+
:usage:
|
|
168
|
+
en: "![b]log![o] 'list'"
|
|
169
|
+
:help:
|
|
170
|
+
en:
|
|
171
|
+
"": Log channel messages.
|
|
172
|
+
:strings:
|
|
173
|
+
:no_match:
|
|
174
|
+
en: "No match found."
|
|
175
|
+
:list:
|
|
176
|
+
en: |
|
|
177
|
+
Logging is active for: <%= channels.join(', ') %>.
|
|
178
|
+
:activated:
|
|
179
|
+
en: |
|
|
180
|
+
Logging activated in: <%= channels.join(', ') %>.
|
|
181
|
+
:deactivated:
|
|
182
|
+
en: |
|
|
183
|
+
Logging deactivated in: <%= channels.join(', ') %>.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
# See LICENSE.txt for permissions.
|
|
5
|
+
#++
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
require 'open-uri'
|
|
10
|
+
require 'hpricot'
|
|
11
|
+
require 'cgi'
|
|
12
|
+
|
|
13
|
+
configuration(
|
|
14
|
+
"frequency" => 900,
|
|
15
|
+
"repositories" => {}
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
def self.current_revision(repo)
|
|
19
|
+
(Hpricot.XML(`svn info --xml #{repo}`)/"info/entry").first.attributes["revision"].to_i
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.changes(repo, from, to=nil)
|
|
23
|
+
range = to ? "#{from}:#{to}" : from.to_s
|
|
24
|
+
doc = Hpricot.XML(`svn log -r #{range} --xml #{repo}`)
|
|
25
|
+
(doc/"log/logentry").map { |entry|
|
|
26
|
+
"#{(entry/'author').inner_text}, " \
|
|
27
|
+
"r#{entry.attributes['revision']}: " \
|
|
28
|
+
"#{(entry/'msg').inner_text.gsub("\n", ' ')}"
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
every(@config["frequency"]) do
|
|
33
|
+
repositories = @config["repositories"]
|
|
34
|
+
repositories.each { |repo, data|
|
|
35
|
+
cr, lr = current_revision(repo), data[:revision]
|
|
36
|
+
if cr > lr then
|
|
37
|
+
data[:revision] = cr
|
|
38
|
+
@config["repositories"] = repositories
|
|
39
|
+
changed = changes(repo, lr+1, cr).join("\n")
|
|
40
|
+
@butler.irc.privmsg(changed, *data[:channels])
|
|
41
|
+
end
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
trigger "svn"
|
|
46
|
+
|
|
47
|
+
def on_trigger
|
|
48
|
+
repos = plugin.config["repositories"]
|
|
49
|
+
case arguments(1)
|
|
50
|
+
when "add"
|
|
51
|
+
repo = @message.arguments[2]
|
|
52
|
+
repos[repo] = {
|
|
53
|
+
:revision => plugin.current_revision(repo),
|
|
54
|
+
:channels => @message.arguments[3..-1]
|
|
55
|
+
}
|
|
56
|
+
plugin.config["repositories"] = repos
|
|
57
|
+
answer(:added, :repository => repo)
|
|
58
|
+
|
|
59
|
+
when "remove"
|
|
60
|
+
repo = @message.arguments[2]
|
|
61
|
+
repos.delete(repo)
|
|
62
|
+
plugin.config["repositories"] = repos
|
|
63
|
+
answer(:removed, :repository => repo)
|
|
64
|
+
|
|
65
|
+
else
|
|
66
|
+
answer(usage)
|
|
67
|
+
end
|
|
68
|
+
#
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
__END__
|
|
72
|
+
---
|
|
73
|
+
:revision:
|
|
74
|
+
:plugin: 1
|
|
75
|
+
:configuration: 1
|
|
76
|
+
:summary:
|
|
77
|
+
en: "Poll repositories for changes and publicate them."
|
|
78
|
+
:about:
|
|
79
|
+
:mail: "apeiros@gmx.net"
|
|
80
|
+
:version: "1.0.0"
|
|
81
|
+
:author: "Stefan Rusterholz"
|
|
82
|
+
:usage:
|
|
83
|
+
en: "![b]svn![o] 'add' repository channel ..."
|
|
84
|
+
:help:
|
|
85
|
+
en:
|
|
86
|
+
"": "Poll repositories for changes and publicate them."
|
|
87
|
+
:strings:
|
|
88
|
+
:added:
|
|
89
|
+
en: Added repository <%= repository %>.
|
|
90
|
+
:removed:
|
|
91
|
+
en: Added repository <%= repository %>.
|