rbot 0.9.9
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +16 -0
- data/COPYING +21 -0
- data/ChangeLog +418 -0
- data/INSTALL +8 -0
- data/README +44 -0
- data/REQUIREMENTS +34 -0
- data/TODO +5 -0
- data/Usage_en.txt +129 -0
- data/bin/rbot +81 -0
- data/data/rbot/contrib/plugins/figlet.rb +20 -0
- data/data/rbot/contrib/plugins/ri.rb +83 -0
- data/data/rbot/contrib/plugins/stats.rb +232 -0
- data/data/rbot/contrib/plugins/vandale.rb +49 -0
- data/data/rbot/languages/dutch.lang +73 -0
- data/data/rbot/languages/english.lang +75 -0
- data/data/rbot/languages/french.lang +39 -0
- data/data/rbot/languages/german.lang +67 -0
- data/data/rbot/plugins/autoop.rb +68 -0
- data/data/rbot/plugins/autorejoin.rb +16 -0
- data/data/rbot/plugins/cal.rb +15 -0
- data/data/rbot/plugins/dice.rb +81 -0
- data/data/rbot/plugins/eightball.rb +19 -0
- data/data/rbot/plugins/excuse.rb +470 -0
- data/data/rbot/plugins/fish.rb +61 -0
- data/data/rbot/plugins/fortune.rb +22 -0
- data/data/rbot/plugins/freshmeat.rb +98 -0
- data/data/rbot/plugins/google.rb +51 -0
- data/data/rbot/plugins/host.rb +14 -0
- data/data/rbot/plugins/httpd.rb.disabled +35 -0
- data/data/rbot/plugins/insult.rb +258 -0
- data/data/rbot/plugins/karma.rb +85 -0
- data/data/rbot/plugins/lart.rb +181 -0
- data/data/rbot/plugins/math.rb +122 -0
- data/data/rbot/plugins/nickserv.rb +89 -0
- data/data/rbot/plugins/nslookup.rb +43 -0
- data/data/rbot/plugins/opme.rb +19 -0
- data/data/rbot/plugins/quakeauth.rb +51 -0
- data/data/rbot/plugins/quotes.rb +321 -0
- data/data/rbot/plugins/remind.rb +228 -0
- data/data/rbot/plugins/roshambo.rb +54 -0
- data/data/rbot/plugins/rot13.rb +10 -0
- data/data/rbot/plugins/roulette.rb +147 -0
- data/data/rbot/plugins/rss.rb.disabled +414 -0
- data/data/rbot/plugins/seen.rb +89 -0
- data/data/rbot/plugins/slashdot.rb +94 -0
- data/data/rbot/plugins/spell.rb +36 -0
- data/data/rbot/plugins/tube.rb +71 -0
- data/data/rbot/plugins/url.rb +88 -0
- data/data/rbot/plugins/weather.rb +649 -0
- data/data/rbot/plugins/wserver.rb +71 -0
- data/data/rbot/plugins/xmlrpc.rb.disabled +52 -0
- data/data/rbot/templates/keywords.rbot +4 -0
- data/data/rbot/templates/lart/larts +98 -0
- data/data/rbot/templates/lart/praises +5 -0
- data/data/rbot/templates/levels.rbot +30 -0
- data/data/rbot/templates/users.rbot +1 -0
- data/lib/rbot/auth.rb +203 -0
- data/lib/rbot/channel.rb +54 -0
- data/lib/rbot/config.rb +363 -0
- data/lib/rbot/dbhash.rb +112 -0
- data/lib/rbot/httputil.rb +141 -0
- data/lib/rbot/ircbot.rb +808 -0
- data/lib/rbot/ircsocket.rb +185 -0
- data/lib/rbot/keywords.rb +433 -0
- data/lib/rbot/language.rb +69 -0
- data/lib/rbot/message.rb +256 -0
- data/lib/rbot/messagemapper.rb +262 -0
- data/lib/rbot/plugins.rb +291 -0
- data/lib/rbot/post-install.rb +8 -0
- data/lib/rbot/rbotconfig.rb +36 -0
- data/lib/rbot/registry.rb +271 -0
- data/lib/rbot/rfc2812.rb +1104 -0
- data/lib/rbot/timer.rb +201 -0
- data/lib/rbot/utils.rb +83 -0
- data/setup.rb +1360 -0
- metadata +129 -0
data/INSTALL
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Just run rbot, it'll ask you for any core information it needs before it can
|
2
|
+
start, after that you can configure everything else online using the config
|
3
|
+
module.
|
4
|
+
|
5
|
+
You can maintain multiple configurations at once. Start rbot with the
|
6
|
+
location you want it to store runtime data in. By default, running rbot
|
7
|
+
uses the ~/.rbot config directory. If you run 'rbot /path/to/foo', then the
|
8
|
+
configuration will be stored to and read from there instead.
|
data/README
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
rbot README
|
2
|
+
===========
|
3
|
+
|
4
|
+
rbot is a ruby IRC bot. Think of him as a ruby bot framework with a highly
|
5
|
+
modular design based around plugins.
|
6
|
+
|
7
|
+
rbot features
|
8
|
+
=============
|
9
|
+
|
10
|
+
* Runtime configuration via irc chat
|
11
|
+
* User authentication and access levels for using different bot features
|
12
|
+
* Built in infobot-style keywords. See example session below.
|
13
|
+
* Support for underlying fact database (infobot fact files), which can
|
14
|
+
be overridden or supplemented by runtime keyword controls
|
15
|
+
* Multi-language support - comes with english, dutch and german definitions
|
16
|
+
so far - more translations welcome
|
17
|
+
* Powerful plugin architecture, comes with plugins for:
|
18
|
+
o DNS queries
|
19
|
+
o Babelfish translation
|
20
|
+
o Google searching
|
21
|
+
o Excuse generation
|
22
|
+
o Insult generation
|
23
|
+
o Karma
|
24
|
+
o Checking the weather
|
25
|
+
o Querying slashdot
|
26
|
+
o Doing Math
|
27
|
+
o Per-channel quote storage, searching and retrieval
|
28
|
+
o Reminders
|
29
|
+
o rot13 translation
|
30
|
+
o Check the spelling of a word
|
31
|
+
o Webserver Server: header examination
|
32
|
+
o RPG dice rolling
|
33
|
+
o larting people
|
34
|
+
o conversation stats
|
35
|
+
o more...
|
36
|
+
|
37
|
+
Thanks are owed to the infobot developers - several of rbot's features are
|
38
|
+
inspired by infobot and so are some of the default plugins. Thanks are also
|
39
|
+
owed to RADKade1, as rbot's quote plugin is a direct reimplementation of his
|
40
|
+
"quotesaq" - simply because it's a great quote interface.
|
41
|
+
|
42
|
+
Mainly, rbot's fun to play with, although the plugin architecture can be used
|
43
|
+
to write very useful modules
|
44
|
+
|
data/REQUIREMENTS
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
Ruby modules needed for rbot
|
2
|
+
============================
|
3
|
+
|
4
|
+
Core requirements
|
5
|
+
bdb (berkley db) http://www.ruby-lang.org/en/raa-list.rhtml?name=bdb
|
6
|
+
(which requires libdb2 or better, from
|
7
|
+
www.sleepycat.com)
|
8
|
+
net/http 1.1+
|
9
|
+
socket
|
10
|
+
uri
|
11
|
+
|
12
|
+
Plugin requirements
|
13
|
+
(these are all optional, if you don't have them, the plugins just won't
|
14
|
+
function)
|
15
|
+
|
16
|
+
babelfish, wserver:
|
17
|
+
net/http 1.2+
|
18
|
+
|
19
|
+
slashdot, freshmeat, rss:
|
20
|
+
REXML
|
21
|
+
|
22
|
+
External programs needed for rbot
|
23
|
+
=================================
|
24
|
+
|
25
|
+
Plugin requirements
|
26
|
+
(These are all optional)
|
27
|
+
|
28
|
+
host plugin:
|
29
|
+
host(1)
|
30
|
+
|
31
|
+
spell plugin:
|
32
|
+
ispell(1)
|
33
|
+
|
34
|
+
|
data/TODO
ADDED
data/Usage_en.txt
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
Installing Programs with setup.rb
|
2
|
+
=================================
|
3
|
+
|
4
|
+
Quick Start
|
5
|
+
-----------
|
6
|
+
|
7
|
+
Type this (You might needs super user previledge):
|
8
|
+
|
9
|
+
($ su)
|
10
|
+
# ruby setup.rb
|
11
|
+
|
12
|
+
If you want to install a program in to your home directory
|
13
|
+
($HOME), use following instead:
|
14
|
+
|
15
|
+
$ ruby setup.rb all --prefix=$HOME
|
16
|
+
|
17
|
+
|
18
|
+
Detailed Installtion Process
|
19
|
+
----------------------------
|
20
|
+
|
21
|
+
setup.rb invokes installation by three steps. There are
|
22
|
+
"config", "setup" and "install". You can invoke each steps
|
23
|
+
separately as following:
|
24
|
+
|
25
|
+
$ ruby setup.rb config
|
26
|
+
$ ruby setup.rb setup
|
27
|
+
# ruby setup.rb install
|
28
|
+
|
29
|
+
You can controll installation process by giving detailed
|
30
|
+
options for each tasks. For example, --bin-dir=$HOME/bin
|
31
|
+
let setup.rb install commands in $HOME/bin.
|
32
|
+
|
33
|
+
For details, see "Task Options".
|
34
|
+
|
35
|
+
Global Options
|
36
|
+
--------------
|
37
|
+
|
38
|
+
"Global Option" is a command line option which you can use
|
39
|
+
for all tasks. You must give a global option before any task
|
40
|
+
name.
|
41
|
+
|
42
|
+
-q,--quiet
|
43
|
+
suppress message outputs
|
44
|
+
--verbose
|
45
|
+
output messages verbosely (default)
|
46
|
+
-h,--help
|
47
|
+
prints help and quit
|
48
|
+
-v,--version
|
49
|
+
prints version and quit
|
50
|
+
--copyright
|
51
|
+
prints copyright and quit
|
52
|
+
|
53
|
+
Tasks
|
54
|
+
-----
|
55
|
+
These are acceptable tasks:
|
56
|
+
all
|
57
|
+
Invokes `config', `setup', then `install'.
|
58
|
+
Task options for all is same with config.
|
59
|
+
config
|
60
|
+
Checks and saves configurations.
|
61
|
+
show
|
62
|
+
Prints current configurations.
|
63
|
+
setup
|
64
|
+
Compiles ruby extentions.
|
65
|
+
install
|
66
|
+
Installs files.
|
67
|
+
clean
|
68
|
+
Removes created files.
|
69
|
+
distclean
|
70
|
+
Removes all created files.
|
71
|
+
|
72
|
+
Task Options for CONFIG/ALL
|
73
|
+
---------------------------
|
74
|
+
|
75
|
+
--prefix=PATH
|
76
|
+
a prefix of the installing directory path
|
77
|
+
--stdruby=PATH
|
78
|
+
the directory for standard ruby libraries
|
79
|
+
--siterubycommon=PATH
|
80
|
+
the directory for version-independent non-standard
|
81
|
+
ruby libraries
|
82
|
+
--siteruby=PATH
|
83
|
+
the directory for non-standard ruby libraries
|
84
|
+
--bindir=PATH
|
85
|
+
the directory for commands
|
86
|
+
--rbdir=PATH
|
87
|
+
the directory for ruby scripts
|
88
|
+
--sodir=PATH
|
89
|
+
the directory for ruby extentions
|
90
|
+
--datadir=PATH
|
91
|
+
the directory for shared data
|
92
|
+
--rubypath=PATH
|
93
|
+
path to set to #! line
|
94
|
+
--rubyprog=PATH
|
95
|
+
the ruby program using for installation
|
96
|
+
--makeprog=NAME
|
97
|
+
the make program to compile ruby extentions
|
98
|
+
--without-ext
|
99
|
+
forces to setup.rb never to compile/install
|
100
|
+
ruby extentions.
|
101
|
+
--rbconfig=PATH
|
102
|
+
your rbconfig.rb to load
|
103
|
+
|
104
|
+
You can view default values of these options by typing
|
105
|
+
|
106
|
+
$ ruby setup.rb --help
|
107
|
+
|
108
|
+
|
109
|
+
If there's the directory named "packages",
|
110
|
+
You can also use these options:
|
111
|
+
--with=NAME,NAME,NAME...
|
112
|
+
Package names which you want to install.
|
113
|
+
--without=NAME,NAME,NAME...
|
114
|
+
Package names which you do not want to install.
|
115
|
+
|
116
|
+
[NOTE] You can pass options for extconf.rb like this:
|
117
|
+
|
118
|
+
ruby setup.rb config -- --with-tklib=/usr/lib/libtk-ja.so.8.0
|
119
|
+
|
120
|
+
|
121
|
+
Task Options for INSTALL
|
122
|
+
------------------------
|
123
|
+
|
124
|
+
--no-harm
|
125
|
+
prints what to do and done nothing really.
|
126
|
+
--prefix=PATH
|
127
|
+
The prefix of the installing directory path.
|
128
|
+
This option may help binary package maintainers.
|
129
|
+
A default value is an empty string.
|
data/bin/rbot
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright (C) 2002 Tom Gilbert.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to
|
7
|
+
# deal in the Software without restriction, including without limitation the
|
8
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
9
|
+
# sell copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies of the Software and its documentation and acknowledgment shall be
|
14
|
+
# given in the documentation and software packages that this Software was
|
15
|
+
# used.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
20
|
+
# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
21
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
22
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
$VERBOSE=true
|
25
|
+
|
26
|
+
require 'etc'
|
27
|
+
require 'getoptlong'
|
28
|
+
require 'fileutils'
|
29
|
+
|
30
|
+
$version="0.9.9"
|
31
|
+
$opts = Hash.new
|
32
|
+
|
33
|
+
orig_opts = ARGV.dup
|
34
|
+
|
35
|
+
opts = GetoptLong.new(
|
36
|
+
["--debug", "-d", GetoptLong::NO_ARGUMENT],
|
37
|
+
["--help", "-h", GetoptLong::NO_ARGUMENT],
|
38
|
+
["--trace", "-t", GetoptLong::REQUIRED_ARGUMENT],
|
39
|
+
["--version", "-v", GetoptLong::NO_ARGUMENT]
|
40
|
+
)
|
41
|
+
|
42
|
+
$debug = false
|
43
|
+
opts.each {|opt, arg|
|
44
|
+
$debug = true if(opt == "--debug")
|
45
|
+
$opts[opt.sub(/^-+/, "")] = arg
|
46
|
+
}
|
47
|
+
|
48
|
+
if ($opts["trace"])
|
49
|
+
set_trace_func proc { |event, file, line, id, binding, classname|
|
50
|
+
if classname.to_s == $opts["trace"]
|
51
|
+
printf "TRACE: %8s %s:%-2d %10s %8s\n", event, File.basename(file), line, id, classname
|
52
|
+
end
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
begin
|
57
|
+
require 'rbot/ircbot'
|
58
|
+
rescue LoadError => e
|
59
|
+
puts "Error: couldn't find the rbot/ircbot module for loading\n - did you install rbot using install.rb?"
|
60
|
+
exit 2
|
61
|
+
end
|
62
|
+
|
63
|
+
if ($opts["version"])
|
64
|
+
puts "rbot #{$version}"
|
65
|
+
exit 0
|
66
|
+
end
|
67
|
+
|
68
|
+
if ($opts["help"])
|
69
|
+
puts "usage: rbot [options] [config directory]"
|
70
|
+
puts " -h, --help this message"
|
71
|
+
puts " -v, --version version information"
|
72
|
+
puts " -d, --debug enable debug messages"
|
73
|
+
puts "config directory defaults to ~/.rbot"
|
74
|
+
exit 0
|
75
|
+
end
|
76
|
+
|
77
|
+
if(bot = Irc::IrcBot.new(ARGV.shift, :argv => orig_opts))
|
78
|
+
# just run the bot
|
79
|
+
bot.mainloop
|
80
|
+
end
|
81
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class FigletPlugin < Plugin
|
2
|
+
def help(plugin, topic="")
|
3
|
+
"figlet [<message>] => print using figlet"
|
4
|
+
end
|
5
|
+
def privmsg(m)
|
6
|
+
case m.params
|
7
|
+
when nil
|
8
|
+
m.reply "incorrect usage: " + help(m.plugin)
|
9
|
+
return
|
10
|
+
when (/^-/)
|
11
|
+
m.reply "incorrect usage: " + help(m.plugin)
|
12
|
+
return
|
13
|
+
else
|
14
|
+
m.reply Utils.safe_exec("/usr/bin/figlet", "-k", "-f", "mini", m.params)
|
15
|
+
return
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
plugin = FigletPlugin.new
|
20
|
+
plugin.register("figlet")
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# Author: Michael Brailsford <brailsmt@yahoo.com>
|
2
|
+
# aka brailsmt
|
3
|
+
# Purpose: To respond to requests for information from the ri command line
|
4
|
+
# utility.
|
5
|
+
|
6
|
+
class RiPlugin < Plugin
|
7
|
+
|
8
|
+
@@handlers = {
|
9
|
+
"ri" => "ri_handler",
|
10
|
+
"msgri" => "msgri_handler"
|
11
|
+
}
|
12
|
+
|
13
|
+
#{{{
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
@cache = Hash.new
|
17
|
+
end
|
18
|
+
#}}}
|
19
|
+
#{{{
|
20
|
+
def privmsg(m)
|
21
|
+
if not m.params
|
22
|
+
m.reply "uhmm... whatever"
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
meth = self.method(@@handlers[m.plugin])
|
27
|
+
meth.call(m)
|
28
|
+
end
|
29
|
+
#}}}
|
30
|
+
#{{{
|
31
|
+
def cleanup
|
32
|
+
@cache = nil
|
33
|
+
end
|
34
|
+
#}}}
|
35
|
+
#{{{
|
36
|
+
def ri_handler(m)
|
37
|
+
response = ""
|
38
|
+
if @cache[m.params]
|
39
|
+
response = @cache[m.params]
|
40
|
+
else
|
41
|
+
IO.popen("-") {|p|
|
42
|
+
if(p)
|
43
|
+
response = p.readlines.join "\n"
|
44
|
+
@cache[m.params] = response
|
45
|
+
else
|
46
|
+
$stderr = $stdout
|
47
|
+
exec("ri", m.params)
|
48
|
+
end
|
49
|
+
}
|
50
|
+
@cache[m.params] = response
|
51
|
+
end
|
52
|
+
|
53
|
+
@bot.say m.sourcenick, response
|
54
|
+
m.reply "Finished \"ri #{m.params}\""
|
55
|
+
end
|
56
|
+
#}}}
|
57
|
+
#{{{
|
58
|
+
def msgri_handler(m)
|
59
|
+
response = ""
|
60
|
+
tell_nick, query = m.params.split()
|
61
|
+
if @cache[query]
|
62
|
+
response = @cache[query]
|
63
|
+
else
|
64
|
+
IO.popen("-") {|p|
|
65
|
+
if(p)
|
66
|
+
response = p.readlines.join "\n"
|
67
|
+
@cache[m.params] = response
|
68
|
+
else
|
69
|
+
$stderr = $stdout
|
70
|
+
exec("ri", query)
|
71
|
+
end
|
72
|
+
}
|
73
|
+
@cache[query] = response
|
74
|
+
end
|
75
|
+
|
76
|
+
@bot.say tell_nick, response
|
77
|
+
m.reply "Finished telling #{tell_nick} about \"ri #{query}\""
|
78
|
+
end
|
79
|
+
#}}}
|
80
|
+
end
|
81
|
+
plugin = RiPlugin.new
|
82
|
+
plugin.register("ri")
|
83
|
+
plugin.register("msgri")
|
@@ -0,0 +1,232 @@
|
|
1
|
+
# Author: Michael Brailsford <brailsmt@yahoo.com>
|
2
|
+
# aka brailsmt
|
3
|
+
# Purpose: Provides the ability to track various tokens that are spoken in a
|
4
|
+
# channel.
|
5
|
+
# Copyright: 2002 Michael Brailsford. All rights reserved.
|
6
|
+
# License: This plugin is licensed under the BSD license. The terms of
|
7
|
+
# which follow.
|
8
|
+
#
|
9
|
+
# Redistribution and use in source and binary forms, with or without
|
10
|
+
# modification, are permitted provided that the following conditions
|
11
|
+
# are met:
|
12
|
+
#
|
13
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
#
|
16
|
+
# 2. Redistributions in binary form must reproduce the above copyright
|
17
|
+
# notice, this list of conditions and the following disclaimer in the
|
18
|
+
# documentation and/or other materials provided with the distribution.
|
19
|
+
|
20
|
+
class StatsPlugin < Plugin
|
21
|
+
|
22
|
+
@@commands = {
|
23
|
+
"stats" => "handle_stats",
|
24
|
+
"track" => "handle_track",
|
25
|
+
"untrack" => "handle_untrack",
|
26
|
+
"listtokens" => "handle_listtokens",
|
27
|
+
"rmabuser" => "handle_rmabuser"
|
28
|
+
}
|
29
|
+
|
30
|
+
#{{{
|
31
|
+
def initialize
|
32
|
+
super
|
33
|
+
@listen = true
|
34
|
+
@channels = Hash.new
|
35
|
+
#check to see if a stats token file already exists for this channel...
|
36
|
+
Dir["#{@bot.botclass}/stats/*"].each { |fname|
|
37
|
+
channel = File.basename fname
|
38
|
+
tokens = Hash.new
|
39
|
+
IO.foreach(fname) { |line|
|
40
|
+
if line =~ /^(\S+)\s*<=>(.*)/
|
41
|
+
tokens[$1] = parse_token_stats $2
|
42
|
+
end
|
43
|
+
}
|
44
|
+
@channels[channel] = tokens
|
45
|
+
}
|
46
|
+
end
|
47
|
+
#}}}
|
48
|
+
#{{{
|
49
|
+
def cleanup
|
50
|
+
@channels = nil
|
51
|
+
end
|
52
|
+
#}}}
|
53
|
+
#{{{
|
54
|
+
def help(plugin, topic="")
|
55
|
+
"Stats: The stats plugin tracks various tokens from users in the channel. The tokens are only tracked if it is the only thing on a line.\nUsage: stats <token> -- lists the stats for <token>\n [un]track <token> -- Adds or deletes <token> from the list of tokens\n listtokens -- lists the tokens that are currently being tracked"
|
56
|
+
end
|
57
|
+
#}}}
|
58
|
+
#{{{
|
59
|
+
def privmsg(m)
|
60
|
+
if not m.params and not m.plugin =~ /listtokens/
|
61
|
+
m.reply "What a crazy fool! Did you mean |help stats?"
|
62
|
+
return
|
63
|
+
end
|
64
|
+
|
65
|
+
meth = self.method(@@commands[m.plugin])
|
66
|
+
meth.call(m)
|
67
|
+
end
|
68
|
+
#}}}
|
69
|
+
#{{{
|
70
|
+
def save
|
71
|
+
Dir.mkdir("#{@bot.botclass}/stats") if not FileTest.directory?("#{@bot.botclass}/stats")
|
72
|
+
#save the tokens to a file...
|
73
|
+
@channels.each_pair { |channel, tokens|
|
74
|
+
if not tokens.empty?
|
75
|
+
File.open("#{@bot.botclass}/stats/#{channel}", "w") { |f|
|
76
|
+
tokens.each { |token, datahash|
|
77
|
+
f.puts "#{token} <=> #{datahash_to_s(datahash)}"
|
78
|
+
}
|
79
|
+
}
|
80
|
+
else
|
81
|
+
File.delete "#{@bot.botclass}/stats/#{channel}"
|
82
|
+
end
|
83
|
+
}
|
84
|
+
end
|
85
|
+
#}}}
|
86
|
+
#{{{
|
87
|
+
def listen(m)
|
88
|
+
if not m.private?
|
89
|
+
tokens = @channels[m.target]
|
90
|
+
if not @@commands[m.plugin]
|
91
|
+
tokens.each_pair { |key, hsh|
|
92
|
+
if not m.message.scan(/#{Regexp.escape(key)}/).empty?
|
93
|
+
if hsh[m.sourcenick]
|
94
|
+
hsh[m.sourcenick] += 1
|
95
|
+
else
|
96
|
+
hsh[m.sourcenick] = 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
#This is the old code {{{
|
103
|
+
# if not m.private?
|
104
|
+
# tokens = @channels[m.target]
|
105
|
+
# hsh = tokens[m.message]
|
106
|
+
# if hsh
|
107
|
+
# if hsh[m.sourcenick]
|
108
|
+
# hsh[m.sourcenick] += 1
|
109
|
+
# else
|
110
|
+
# hsh[m.sourcenick] = 1
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
# end }}}
|
114
|
+
end
|
115
|
+
#}}}
|
116
|
+
#The following are helper functions for the plugin {{{
|
117
|
+
def datahash_to_s(dhash)
|
118
|
+
rv = ""
|
119
|
+
dhash.each { |key, val|
|
120
|
+
rv << "#{key}:#{val} "
|
121
|
+
}
|
122
|
+
rv.chomp
|
123
|
+
end
|
124
|
+
|
125
|
+
def parse_token_stats(stats)
|
126
|
+
rv = Hash.new
|
127
|
+
stats.split(" ").each { |nickstat|
|
128
|
+
nick, stat = nickstat.split ":"
|
129
|
+
rv[nick] = stat.to_i
|
130
|
+
}
|
131
|
+
rv
|
132
|
+
end
|
133
|
+
#}}}
|
134
|
+
#The following are handler methods for dealing with each command from IRC {{{
|
135
|
+
#{{{
|
136
|
+
def handle_stats(m)
|
137
|
+
if not m.private?
|
138
|
+
total = 0
|
139
|
+
tokens = @channels[m.target]
|
140
|
+
hsh = tokens[m.params]
|
141
|
+
msg1 = ""
|
142
|
+
if not hsh.empty?
|
143
|
+
sorted = hsh.sort { |i, j| j[1] <=> i[1] }
|
144
|
+
sorted.each { |a|
|
145
|
+
total += a[1]
|
146
|
+
}
|
147
|
+
|
148
|
+
msg = "Stats for #{m.params}. Said #{total} times. The top sayers are "
|
149
|
+
if sorted[0..2]
|
150
|
+
msg << "#{sorted[0].join ':'}" if sorted[0]
|
151
|
+
msg << ", #{sorted[1].join ':'}" if sorted[1]
|
152
|
+
msg << ", and #{sorted[2].join ':'}" if sorted[2]
|
153
|
+
msg << "."
|
154
|
+
|
155
|
+
msg1 << "#{m.sourcenick} has said it "
|
156
|
+
if hsh[m.sourcenick]
|
157
|
+
msg1 << "#{hsh[m.sourcenick]} times."
|
158
|
+
else
|
159
|
+
msg1 << "0 times."
|
160
|
+
end
|
161
|
+
else
|
162
|
+
msg << "#{m.params} has not been said yet!"
|
163
|
+
end
|
164
|
+
@bot.action m.replyto, msg
|
165
|
+
@bot.action m.replyto, msg1 if msg1
|
166
|
+
else
|
167
|
+
m.reply "#{m.params} is not currently being tracked."
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
#}}}
|
172
|
+
#{{{
|
173
|
+
def handle_track(m)
|
174
|
+
if not m.private?
|
175
|
+
if @channels[m.target]
|
176
|
+
tokens = @channels[m.target]
|
177
|
+
else
|
178
|
+
tokens = Hash.new
|
179
|
+
@channels[m.target] = tokens
|
180
|
+
end
|
181
|
+
tokens[m.params] = Hash.new
|
182
|
+
m.reply "now tracking #{m.params}"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
#}}}
|
186
|
+
#{{{
|
187
|
+
def handle_untrack(m)
|
188
|
+
if not m.private?
|
189
|
+
toks = @channels[m.target]
|
190
|
+
if toks.has_key? m.params
|
191
|
+
toks.delete m.params
|
192
|
+
m.reply "no longer tracking #{m.params}"
|
193
|
+
else
|
194
|
+
m.reply "Are your signals crossed? Since when have I tracked that?"
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
toks = nil
|
199
|
+
end
|
200
|
+
#}}}
|
201
|
+
#{{{
|
202
|
+
def handle_listtokens(m)
|
203
|
+
if not m.private? and not @channels.empty?
|
204
|
+
tokens = @channels[m.target]
|
205
|
+
unless tokens.empty?
|
206
|
+
toks = ""
|
207
|
+
tokens.each_key { |k|
|
208
|
+
toks << "#{k} "
|
209
|
+
}
|
210
|
+
@bot.action m.replyto, "is currently keeping stats for: #{toks}"
|
211
|
+
else
|
212
|
+
@bot.action m.replyto, "is not currently keeping stats for anything"
|
213
|
+
end
|
214
|
+
elsif not m.private?
|
215
|
+
@bot.action m.replyto, "is not currently keeping stats for anything"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
#}}}
|
219
|
+
#{{{
|
220
|
+
def handle_rmabuser(m)
|
221
|
+
m.reply "This feature has not yet been implemented"
|
222
|
+
end
|
223
|
+
#}}}
|
224
|
+
#}}}
|
225
|
+
|
226
|
+
end
|
227
|
+
plugin = StatsPlugin.new
|
228
|
+
plugin.register("stats")
|
229
|
+
plugin.register("track")
|
230
|
+
plugin.register("untrack")
|
231
|
+
plugin.register("listtokens")
|
232
|
+
#plugin.register("rmabuser")
|