rbot 0.9.9
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/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")
|