mirror of
https://github.com/reality/dbot.git
synced 2024-11-30 16:09:27 +01:00
Merge branch 'master' of git://github.com/reality/depressionbot into weboverhaul
Conflicts: modules/quotes/quotes.js modules/users/users.js run.js
This commit is contained in:
commit
f91fc99d35
18
LICENCE
Normal file
18
LICENCE
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Copyright (c) 2012 Luke Slater (tinmachin3@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
108
README.md
108
README.md
@ -3,8 +3,8 @@
|
|||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Depressionbot is an IRC bot which aims to be the fanciest IRC bot around - On
|
Depressionbot is an IRC bot which aims to be the fanciest IRC bot around - On
|
||||||
the general standard of software fanciness, dbot is rated as being '81% the same
|
the general standard of software fanciness, dbot is statistically rated as being
|
||||||
as bathing in fine, fine grape juice.'
|
'82% the same as bathing in fine, fine grape juice.'
|
||||||
|
|
||||||
Please note that this documentation is not complete and is a work in progress,
|
Please note that this documentation is not complete and is a work in progress,
|
||||||
given I started it rather a long time after I began development of the project.
|
given I started it rather a long time after I began development of the project.
|
||||||
@ -18,108 +18,10 @@ Requirements:
|
|||||||
handles the IRC protocol.
|
handles the IRC protocol.
|
||||||
- Various modules have their own requirements also.
|
- Various modules have their own requirements also.
|
||||||
|
|
||||||
### JSBot
|
### External Modules
|
||||||
|
|
||||||
JSBot can be imported by running the following commands in the cloned repository:
|
JSBot and externally developed modules can be imported by running the following
|
||||||
|
commands in the cloned repository:
|
||||||
|
|
||||||
git submodule init
|
git submodule init
|
||||||
git submodule update
|
git submodule update
|
||||||
|
|
||||||
## Modules:
|
|
||||||
|
|
||||||
### Command
|
|
||||||
|
|
||||||
This handles the command execution logic for DBot.
|
|
||||||
|
|
||||||
1. Does the input match a command key in *dbot.commands* ?
|
|
||||||
2. Is there a quote category which matches the first part of the input
|
|
||||||
(*~category*)?
|
|
||||||
3. Is there a command name similar to to the first part of the input (*~name*)
|
|
||||||
in *dbot.commands*?
|
|
||||||
|
|
||||||
This is the only module which is force loaded, even if it's not in the
|
|
||||||
configuration.
|
|
||||||
|
|
||||||
### Quotes
|
|
||||||
|
|
||||||
This is the original reason that DBot was created, stores and displays quotes.
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
|
|
||||||
- _~q category_ - Display a random quote from a given category.
|
|
||||||
- _~qadd category=newquote_ - Add a new quote to the database.
|
|
||||||
- _~qstats_ - Show a list of the biggest quote categories.
|
|
||||||
- _~qsearch category needle_ - Search for a quote in a given category.
|
|
||||||
- _~rmlast [category]_ - Remove the last quote added to a given category, or the
|
|
||||||
last quote added.
|
|
||||||
- _~rm category quote_ - Remove a given quote from the given category.
|
|
||||||
- _~qcount category_ - Show the number of quotes stored in the given category.
|
|
||||||
- _~rq_ - Show a random quote from a random category.
|
|
||||||
- _~d_ - Show a quote from the category which matches the bot's name.
|
|
||||||
- _~link category_ - Create a link to the page on the web interface which displays the
|
|
||||||
given category's quotes.
|
|
||||||
- _~qprune_ - Delete empty quote categories.
|
|
||||||
|
|
||||||
Unfortunately, this module is fairly highly coupled with certain other areas of
|
|
||||||
the program. I am working on this, but note, for example, that one can still
|
|
||||||
access quotes with the *~category* syntax even if the quotes module isn't
|
|
||||||
loaded.
|
|
||||||
|
|
||||||
### Admin
|
|
||||||
|
|
||||||
Various administration functionality such as banning users, hot-reloading the
|
|
||||||
code and ordering him to talk. Note that commands added here are handled with
|
|
||||||
their own listener, rather than being part of the command logic which is handled
|
|
||||||
by the Command module. Functionality in this module can be slightly unsafe as
|
|
||||||
not much error checking on the input is performed.
|
|
||||||
|
|
||||||
TODO: Add summaries for each command in this module.
|
|
||||||
|
|
||||||
### Spelling
|
|
||||||
|
|
||||||
Will attempt to correct a users' spelling by using the levenshtein distance
|
|
||||||
algorithm. One corrects the spelling of their previous message by simply posting
|
|
||||||
a message with their correction and an asterisk:
|
|
||||||
|
|
||||||
> user: I am a tutrle.
|
|
||||||
> user: *turtle
|
|
||||||
user meant: I am a turtle.
|
|
||||||
|
|
||||||
The regular expression for this module also accepts two asterisks at the
|
|
||||||
beginning of the correction, or at the end; it also accepts several words as the
|
|
||||||
correction and deals with these fairly intelligently. Users may also attempt
|
|
||||||
to correct another users like so:
|
|
||||||
|
|
||||||
> userone: I am a tutrle.
|
|
||||||
> usertwo: userone: *turtle
|
|
||||||
> usertwo thinks userone meant: I am a turtle.
|
|
||||||
|
|
||||||
### JS
|
|
||||||
|
|
||||||
This module provides two commands which allow the execution of Javascript code.
|
|
||||||
For regular users, there is the *~js* command, which is completely sandboxed,
|
|
||||||
but can still be used for calculation and the like.
|
|
||||||
|
|
||||||
> ~js Array(16).join('wat'-1) + " Batman!";
|
|
||||||
'NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN Batman!'
|
|
||||||
|
|
||||||
This feature is fairly safe as the user doesn't have access to anything
|
|
||||||
dangerous, and is safe from infinite loops or locking DBot up because the code
|
|
||||||
which is run is killed if it does not finish within a short amount of time.
|
|
||||||
|
|
||||||
For administrators, the incredibly useful *~ajs* command is also available. The
|
|
||||||
input for this command is simply 'eval'-ed and therefore has full access to
|
|
||||||
DBot's memory. Of course, this is incredibly unsafe, but I find it rather fun;
|
|
||||||
remember to only give extremely trusted friends administrator access to DBot, as
|
|
||||||
there's nothing to stop them wiping the database or something similar - if
|
|
||||||
you're worried about that kind of thing, do not load this module.
|
|
||||||
|
|
||||||
However, it's useful for many things, such as administrative activity for
|
|
||||||
which there isn't a command in the admin module. For example, you could hot-add
|
|
||||||
a new administrator like this:
|
|
||||||
|
|
||||||
> ~ajs dbot.admin.push('batman');
|
|
||||||
2
|
|
||||||
|
|
||||||
You can also use this for debugging, or even adding new commands while DBot is
|
|
||||||
running.
|
|
||||||
|
57
modules/admin/README.md
Normal file
57
modules/admin/README.md
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
## Admin
|
||||||
|
|
||||||
|
Administrator functionality.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
Various administration functionality such as banning users, hot-reloading the
|
||||||
|
code and ordering him to talk. Note that commands added here are handled with
|
||||||
|
their own listener, rather than being part of the command logic which is handled
|
||||||
|
by the Command module. Functionality in this module can be slightly unsafe as
|
||||||
|
not everything is thoroughly sanity checked.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
#### join [#channel]
|
||||||
|
Join the given channel.
|
||||||
|
|
||||||
|
#### part [#channel]
|
||||||
|
Leave the given channel.
|
||||||
|
|
||||||
|
#### opme [#channel]
|
||||||
|
Gives the caller ops in a given channel if possible. If called without a
|
||||||
|
channel, it will attempt to give the caller ops in the current channel.
|
||||||
|
|
||||||
|
#### greload
|
||||||
|
Perform a git pull, and then execute the 'reload' command. Saves a lot of time
|
||||||
|
updating!
|
||||||
|
|
||||||
|
#### reload
|
||||||
|
Reload all of the modules currently in use by DBot. By using this, all module
|
||||||
|
functionality should be reloadable and replaceable without having to restart the
|
||||||
|
bot or interrupt the connection to the server.
|
||||||
|
|
||||||
|
#### say [#channel] [message]
|
||||||
|
Have DBot post the given message in the given channel (uses the server from
|
||||||
|
which you are sending the message). You may replace channel with '@' to have him
|
||||||
|
post the message in the current channel. Channel may also be replaced with a
|
||||||
|
nick on the server.
|
||||||
|
|
||||||
|
#### load [module]
|
||||||
|
Load a new module. This works by adding a module name to the roster and then
|
||||||
|
triggering a reload of all modules, at which point the new module is actually
|
||||||
|
loaded by the standard DBot process.
|
||||||
|
|
||||||
|
#### unload [module]
|
||||||
|
Unload a currently loaded module. This removes the module, and then triggers a
|
||||||
|
reload of all modules.
|
||||||
|
|
||||||
|
#### ban [user] [command]
|
||||||
|
Ban a user from using a command. Command may be replaced with '\*,' which will
|
||||||
|
ban a user from use of all commands. Users banned from all commands will still
|
||||||
|
be subject to module listeners.
|
||||||
|
|
||||||
|
#### unban [user] [command]
|
||||||
|
Unban a user from using a given command. If a user was previously banned using
|
||||||
|
the '\*' wildcard, they may also be unbanned from such by replacing command with
|
||||||
|
an asterisk here as well.
|
@ -13,7 +13,7 @@ var admin = function(dbot) {
|
|||||||
'join': function(event) {
|
'join': function(event) {
|
||||||
var channel = event.params[1];
|
var channel = event.params[1];
|
||||||
if(event.allChannels.hasOwnProperty(channel)) {
|
if(event.allChannels.hasOwnProperty(channel)) {
|
||||||
event.reply("I'm already in that channel.");
|
event.reply(dbot.t('already_in_channel', {'channel': channel}));
|
||||||
} else {
|
} else {
|
||||||
dbot.instance.join(event, channel);
|
dbot.instance.join(event, channel);
|
||||||
event.reply(dbot.t('join', {'channel': channel}));
|
event.reply(dbot.t('join', {'channel': channel}));
|
||||||
@ -24,7 +24,7 @@ var admin = function(dbot) {
|
|||||||
'part': function(event) {
|
'part': function(event) {
|
||||||
var channel = event.params[1];
|
var channel = event.params[1];
|
||||||
if(!event.allChannels.hasOwnProperty(channel)) {
|
if(!event.allChannels.hasOwnProperty(channel)) {
|
||||||
event.reply("I'm not in that channel.");
|
event.reply(dbot.t('not_in_channel', {'channel': channel}));
|
||||||
} else {
|
} else {
|
||||||
event.instance.part(event, channel);
|
event.instance.part(event, channel);
|
||||||
event.reply(dbot.t('part', {'channel': channel}));
|
event.reply(dbot.t('part', {'channel': channel}));
|
||||||
@ -44,9 +44,11 @@ var admin = function(dbot) {
|
|||||||
|
|
||||||
// Do a git pull and reload
|
// Do a git pull and reload
|
||||||
'greload': function(event) {
|
'greload': function(event) {
|
||||||
var child = exec("git pull", function (error, stdout, stderr) {
|
exec("git pull", function (error, stdout, stderr) {
|
||||||
event.reply(dbot.t('gpull'));
|
exec("git submodule update", function (error, stdout, stderr) {
|
||||||
commands.reload(event);
|
event.reply(dbot.t('gpull'));
|
||||||
|
commands.reload(event);
|
||||||
|
}.bind(this));
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ var admin = function(dbot) {
|
|||||||
event.reply(dbot.t('reload'));
|
event.reply(dbot.t('reload'));
|
||||||
},
|
},
|
||||||
|
|
||||||
// Say something in a channel (TODO probably doesn't work.)
|
// Say something in a channel
|
||||||
'say': function(event) {
|
'say': function(event) {
|
||||||
var channel = event.params[1];
|
var channel = event.params[1];
|
||||||
if(event.params[1] === "@") {
|
if(event.params[1] === "@") {
|
||||||
@ -116,13 +118,6 @@ var admin = function(dbot) {
|
|||||||
} else {
|
} else {
|
||||||
event.reply(dbot.t('unban_error', {'user': username}));
|
event.reply(dbot.t('unban_error', {'user': username}));
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
// Lock quote category so quotes can't be removed
|
|
||||||
'lock': function(event) {
|
|
||||||
var category = event.params[1];
|
|
||||||
dbot.db.locks.push(category);
|
|
||||||
event.reply(dbot.t('qlock', {'category': category}));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"dbKeys": [ "bans", "locks" ]
|
"dbKeys": [ "bans" ],
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/admin/README.md"
|
||||||
}
|
}
|
||||||
|
@ -64,5 +64,11 @@
|
|||||||
"spanish": "Cerrado la categoría: {category}",
|
"spanish": "Cerrado la categoría: {category}",
|
||||||
"na'vi": "{category}ìri oel 'upxareti fmoli",
|
"na'vi": "{category}ìri oel 'upxareti fmoli",
|
||||||
"welsh": "Categori wedi cloi: {category}"
|
"welsh": "Categori wedi cloi: {category}"
|
||||||
|
},
|
||||||
|
"already_in_channel": {
|
||||||
|
"english": "I'm already in {channel}"
|
||||||
|
},
|
||||||
|
"not_in_channel": {
|
||||||
|
"english": "I'm not in {channel}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
modules/command/README.md
Normal file
14
modules/command/README.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
## Command
|
||||||
|
|
||||||
|
Handles the command execution logic for DBot.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
1. Does the input match a command key in *dbot.commands* ?
|
||||||
|
2. Is there a quote category which matches the first part of the input
|
||||||
|
(*~category*)?
|
||||||
|
3. Is there a command name similar to to the first part of the input (*~name*)
|
||||||
|
in *dbot.commands*?
|
||||||
|
|
||||||
|
This is the only module which is force loaded, even if it's not specified in
|
||||||
|
the configuration file.
|
@ -57,10 +57,34 @@ var command = function(dbot) {
|
|||||||
'~usage': function(event) {
|
'~usage': function(event) {
|
||||||
var commandName = event.params[1];
|
var commandName = event.params[1];
|
||||||
if(dbot.usage.hasOwnProperty(commandName)) {
|
if(dbot.usage.hasOwnProperty(commandName)) {
|
||||||
event.reply('Usage for ' + commandName + ': ' +
|
event.reply(dbot.t('usage', {
|
||||||
dbot.usage[commandName]);
|
'command': commandName,
|
||||||
|
'usage': dbot.usage[commandName]
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
event.reply('No usage information for ' + commandName);
|
event.reply(dbot.t('no_usage_info', {
|
||||||
|
'command': commandName
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'~help': function(event) {
|
||||||
|
var moduleName = event.params[1];
|
||||||
|
if(!dbot.modules.hasOwnProperty(moduleName)) {
|
||||||
|
var moduleName = dbot.commandMap[moduleName];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(moduleName && dbot.config[moduleName].hasOwnProperty('help')) {
|
||||||
|
var help = dbot.config[moduleName].help;
|
||||||
|
event.reply(dbot.t('help_link', {
|
||||||
|
'module': moduleName,
|
||||||
|
'link': help
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
if(!moduleName) {
|
||||||
|
moduleName = event.params[1];
|
||||||
|
}
|
||||||
|
event.reply(dbot.t('no_help', { 'module': moduleName }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
3
modules/command/config.json
Normal file
3
modules/command/config.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md"
|
||||||
|
}
|
@ -10,5 +10,17 @@
|
|||||||
"spanish": "Sintaxis no válida. Iniciar incineración.",
|
"spanish": "Sintaxis no válida. Iniciar incineración.",
|
||||||
"na'vi": "Ngeyä pamrel keyawr lu. Nga skxawng lu.",
|
"na'vi": "Ngeyä pamrel keyawr lu. Nga skxawng lu.",
|
||||||
"welsh": "Cystrawen annilys. Cychwyn orfflosgiad"
|
"welsh": "Cystrawen annilys. Cychwyn orfflosgiad"
|
||||||
|
},
|
||||||
|
"usage": {
|
||||||
|
"english": "Usage for {command}: {usage}."
|
||||||
|
},
|
||||||
|
"no_usage_info": {
|
||||||
|
"english": "No usage information found for {command}."
|
||||||
|
},
|
||||||
|
"help_link": {
|
||||||
|
"english": "Help for {module}: {link}"
|
||||||
|
},
|
||||||
|
"no_help": {
|
||||||
|
"english": "No help found for {module}."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
26
modules/ignore/README.md
Normal file
26
modules/ignore/README.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
## Ignore
|
||||||
|
|
||||||
|
Ignore modules.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
Commands with which users can choose to ignore listeners and commands from
|
||||||
|
certain modules persistently, by storing their choices in the database. This is
|
||||||
|
an interface for the JSBot ignoreTag functionality which actually implements
|
||||||
|
the ignoration.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
All modules may return with them an 'ignorable' property, which defines whether
|
||||||
|
or not their functionality may be ignored by users.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
#### ~ignore [module]
|
||||||
|
Ignore a given module. If the user does not specify a module, or provides an
|
||||||
|
invalid one a list of modules which are available to ignore will be given.
|
||||||
|
|
||||||
|
#### ~unignore [module]
|
||||||
|
Unignore a previously ignored module. If the user does not specify a module, or
|
||||||
|
provides an invalid choice a list of modules which are currently ignored will be
|
||||||
|
given.
|
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"dbKeys": [ "ignores" ]
|
"dbKeys": [ "ignores" ],
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md"
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,11 @@
|
|||||||
var ignore = function(dbot) {
|
var ignore = function(dbot) {
|
||||||
var commands = {
|
var commands = {
|
||||||
'~ignore': function(event) {
|
'~ignore': function(event) {
|
||||||
var ignorableModules = [];
|
var ignorableModules = dbot.modules.filter(function(module) {
|
||||||
for(var i=0;i<dbot.modules.length;i++) {
|
if(module.ignorable != null && module.ignorable == true) {
|
||||||
if(dbot.modules[i].ignorable != null && dbot.modules[i].ignorable == true) {
|
return true;
|
||||||
ignorableModules.push(dbot.modules[i].name);
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
var module = event.params[1];
|
var module = event.params[1];
|
||||||
|
|
||||||
if(module === undefined) {
|
if(module === undefined) {
|
||||||
|
40
modules/js/README.md
Normal file
40
modules/js/README.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
## JS
|
||||||
|
|
||||||
|
Run JavaScript.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
This module provides two commands which allow the execution of Javascript code
|
||||||
|
from the bot.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
#### ~js [code]
|
||||||
|
For regular users, there is the *~js* command, which is completely sandboxed,
|
||||||
|
but can still be used for calculation and the like.
|
||||||
|
|
||||||
|
> ~js Array(16).join('wat'-1) + " Batman!";
|
||||||
|
'NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN Batman!'
|
||||||
|
|
||||||
|
This feature is fairly safe as the user doesn't have access to anything
|
||||||
|
dangerous, and is safe from infinite loops or locking DBot up because the code
|
||||||
|
which is run is killed if it does not finish within a short amount of time.
|
||||||
|
|
||||||
|
#### ~ajs [code]
|
||||||
|
For administrators, the incredibly useful *~ajs* command is also available. The
|
||||||
|
input for this command is simply 'eval'-ed and therefore has full access to
|
||||||
|
DBot's memory. Of course, this is incredibly unsafe, but I find it rather fun;
|
||||||
|
remember to only give extremely trusted friends administrator access to your
|
||||||
|
DBot instance, as there's nothing to stop them wiping the database or probably
|
||||||
|
even your hard drive - if you're worried about that kind of thing, do not load
|
||||||
|
this module.
|
||||||
|
|
||||||
|
However, it's useful for many things, such as administrative activity for
|
||||||
|
which there isn't a command in the admin module. For example, you could hot-add
|
||||||
|
a new administrator like this:
|
||||||
|
|
||||||
|
> ~ajs dbot.admin.push('batman');
|
||||||
|
2
|
||||||
|
|
||||||
|
You can also use it for debugging, or even adding new commands while DBot is
|
||||||
|
running.
|
3
modules/js/config.json
Normal file
3
modules/js/config.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/js/README.md"
|
||||||
|
}
|
17
modules/kick/README.md
Normal file
17
modules/kick/README.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
## Kick
|
||||||
|
|
||||||
|
Kicking and kicking-related accessories.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
This module counts the number of times people are kicked from and kick people
|
||||||
|
from channels, and provides commands for viewing this data. It also has the bot
|
||||||
|
attempt to rejoin the channel if it is kicked.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
#### ~kickcount [username]
|
||||||
|
Show the number of times a given user has been kicked and has kicked other
|
||||||
|
people.
|
||||||
|
|
||||||
|
#### ~kickstats
|
||||||
|
Show a list of top kickers and kickees.
|
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"dbKeys": [ "kicks", "kickers" ]
|
"dbKeys": [ "kicks", "kickers" ],
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/kick/README.md"
|
||||||
}
|
}
|
||||||
|
21
modules/link/README.md
Normal file
21
modules/link/README.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
## Link
|
||||||
|
|
||||||
|
Retrieves page titles.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
This module stores the last posted link in each channel, and provides a command
|
||||||
|
for retrieving the title of a given link or the last posted link in the channel.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
#### autoTitle: false
|
||||||
|
If this is set to true, the bot will automatically post the titles of links as
|
||||||
|
they are posted in the channel.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
#### ~title [link]
|
||||||
|
If called with a link, the bot will attempt to find and return the title of that
|
||||||
|
page. If called without a link, the bot will attempt the same on the last link
|
||||||
|
which was posted in the current channel.
|
4
modules/link/config.json
Normal file
4
modules/link/config.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"autoTitle": false,
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/link/README.md"
|
||||||
|
}
|
@ -7,6 +7,19 @@ var request = require('request');
|
|||||||
var link = function(dbot) {
|
var link = function(dbot) {
|
||||||
var urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
|
var urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
|
||||||
var links = {};
|
var links = {};
|
||||||
|
var fetchTitle = function(event, link) {
|
||||||
|
request(link, function (error, response, body) {
|
||||||
|
if(!error && response.statusCode == 200) {
|
||||||
|
body = body.replace(/(\r\n|\n\r|\n)/gm, " ");
|
||||||
|
var title = body.valMatch(/<title>(.*)<\/title>/, 2);
|
||||||
|
if(title) {
|
||||||
|
event.reply(title[1]);
|
||||||
|
} else {
|
||||||
|
event.reply(dbot.t('title_not_found'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var commands = {
|
var commands = {
|
||||||
'~title': function(event) {
|
'~title': function(event) {
|
||||||
@ -17,18 +30,7 @@ var link = function(dbot) {
|
|||||||
link = urlMatches[0];
|
link = urlMatches[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fetchTitle(event, link);
|
||||||
request(link, function (error, response, body) {
|
|
||||||
if(!error && response.statusCode == 200) {
|
|
||||||
body = body.replace(/(\r\n|\n\r|\n)/gm, " ");
|
|
||||||
var title = body.valMatch(/<title>(.*)<\/title>/, 2);
|
|
||||||
if(title) {
|
|
||||||
event.reply(title[1]);
|
|
||||||
} else {
|
|
||||||
event.reply('no title found');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,6 +43,10 @@ var link = function(dbot) {
|
|||||||
var urlMatches = event.message.match(urlRegex);
|
var urlMatches = event.message.match(urlRegex);
|
||||||
if(urlMatches !== null) {
|
if(urlMatches !== null) {
|
||||||
links[event.channel.name] = urlMatches[0];
|
links[event.channel.name] = urlMatches[0];
|
||||||
|
|
||||||
|
if(dbot.config.link.autoTitle == true) {
|
||||||
|
fetchTitle(event, urlMatches[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'on': 'PRIVMSG'
|
'on': 'PRIVMSG'
|
||||||
|
5
modules/link/strings.json
Normal file
5
modules/link/strings.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"title_not_found": {
|
||||||
|
"english": "No page title found."
|
||||||
|
}
|
||||||
|
}
|
35
modules/poll/README.md
Normal file
35
modules/poll/README.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
## Poll
|
||||||
|
|
||||||
|
Pollers gonna poll.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
This module allows creation of and voting in polls, with associated
|
||||||
|
functionality.
|
||||||
|
|
||||||
|
Note that while in terms of the interface all votes are anonymous, users'
|
||||||
|
voting choices are stored in the database for the purpose of users being
|
||||||
|
able to change their votes. Therefore an admin can technically go delving in
|
||||||
|
the database to see users' voting choices.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
#### ~newpoll [pollname] options=[each,poll,option] [Poll Description]
|
||||||
|
Creates a new poll with the given name, options and descriptions. From this
|
||||||
|
point people will be able to use the ~vote command to cast their vote in the
|
||||||
|
poll.
|
||||||
|
|
||||||
|
#### ~addoption [pollname] [newoption]
|
||||||
|
Using this command you can add a given option to a poll you are the creator of.
|
||||||
|
|
||||||
|
#### ~rmoption [pollname] [optiontoremove]
|
||||||
|
Using this command you can remove a given option from a poll you are the creator
|
||||||
|
of.
|
||||||
|
|
||||||
|
#### ~vote [pollname] [option]
|
||||||
|
Cast your vote for the given option in the given poll. If you have already cast
|
||||||
|
your vote in the given poll, your vote will be changed to the new option you
|
||||||
|
have provided.
|
||||||
|
|
||||||
|
#### ~pdesc [pollname]
|
||||||
|
Show the full description for a given poll name along with its available voting
|
||||||
|
options.
|
3
modules/poll/config.json
Normal file
3
modules/poll/config.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/poll/README.md"
|
||||||
|
}
|
@ -1,25 +0,0 @@
|
|||||||
var puns = function(dbot) {
|
|
||||||
var name = 'puns';
|
|
||||||
var dbot = dbot;
|
|
||||||
|
|
||||||
return {
|
|
||||||
'name': name,
|
|
||||||
'ignorable': true,
|
|
||||||
|
|
||||||
'listener': function(event) {
|
|
||||||
event.user = dbot.cleanNick(event.user);
|
|
||||||
if(dbot.config.moduleNames.include('quotes') &&
|
|
||||||
dbot.db.quoteArrs.hasOwnProperty(event.user)) {
|
|
||||||
event.message = '~q ' + event.user;
|
|
||||||
event.action = 'PRIVMSG';
|
|
||||||
event.params = event.message.split(' ');
|
|
||||||
dbot.instance.emit(event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'on': 'JOIN'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.fetch = function(dbot) {
|
|
||||||
return puns(dbot);
|
|
||||||
};
|
|
68
modules/quotes/README.md
Normal file
68
modules/quotes/README.md
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
## Quotes
|
||||||
|
|
||||||
|
Stores and displays quotes.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
This is the original reason that DBot was created, stores and displays quotes.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
#### rmLimit: 10
|
||||||
|
Amount of quotes which can be removed before admin approval is required.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
#### ~q [category]
|
||||||
|
Display a random quote from a given category.
|
||||||
|
|
||||||
|
#### ~qadd [category] = [quote]
|
||||||
|
Add a new quote to the database.
|
||||||
|
|
||||||
|
#### ~qstats
|
||||||
|
Show a list of the biggest quote categories.
|
||||||
|
|
||||||
|
#### ~qsearch [category] = [needle]
|
||||||
|
Search a category for quotes including the given text.
|
||||||
|
|
||||||
|
#### ~rmlast [category]
|
||||||
|
Remove the last quote added to a given category.
|
||||||
|
|
||||||
|
#### ~rmstatus
|
||||||
|
Show how many quotes are currently in the removal cache, and whether they will
|
||||||
|
be randomly removed.
|
||||||
|
|
||||||
|
#### ~rm [category] = [quote]
|
||||||
|
Remove a given quote from the given category.
|
||||||
|
|
||||||
|
#### ~qcount [category]
|
||||||
|
Show the number of quotes stored in the given category, or if called without a
|
||||||
|
category it will show the total number of quotes in the database.
|
||||||
|
|
||||||
|
#### ~rq
|
||||||
|
Show a random quote from the database.
|
||||||
|
|
||||||
|
#### ~link [category]
|
||||||
|
Show a link to the page on the web interface which shows this category's quotes.
|
||||||
|
|
||||||
|
### Admin-only Commands
|
||||||
|
|
||||||
|
#### ~rmconfirm
|
||||||
|
Confirm that the quotes currently in the removal cache are okay to be removed,
|
||||||
|
and permanently delete them.
|
||||||
|
|
||||||
|
#### ~rmdeny
|
||||||
|
Re-instate the quotes that are currently in the removal cache back into the main
|
||||||
|
quote database.
|
||||||
|
|
||||||
|
### Removal Spam Protection
|
||||||
|
|
||||||
|
When quotes are removed using either the ~rm or ~rmlast commands, the quotes are
|
||||||
|
removed from the main database, but are stored in a removal cache which is cleared
|
||||||
|
out ten minutes from the last time a quote was removed from the database. If the
|
||||||
|
number of quotes removed from the database reaches a certain limit (as per rmLimit
|
||||||
|
in config, default 10) then the counter is removed and the cache will not be deleted
|
||||||
|
automatically. In such a case, a DBot admin needs to either run the ~rmconfim command
|
||||||
|
to have the removal cache cleared, or ~rmdeny to re-instate all of the quotes in
|
||||||
|
the removal cache back into the main quote database. This is to stop mass
|
||||||
|
removal from the database without limiting the user interface.
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"dbKeys": [ "quoteArrs" ],
|
"dbKeys": [ "quoteArrs" ],
|
||||||
"rmLimit": 10
|
"rmLimit": 10,
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/quotes/README.md"
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,26 @@ var quotes = function(dbot) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var api = {
|
||||||
|
'getQuote': function(category) {
|
||||||
|
var key = category.trim().toLowerCase();
|
||||||
|
var altKey;
|
||||||
|
if(key.split(' ').length > 0) {
|
||||||
|
altKey = key.replace(/ /g, '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(key.charAt(0) !== '_') { // lol
|
||||||
|
if(quotes.hasOwnProperty(key)) {
|
||||||
|
return interpolatedQuote(key);
|
||||||
|
} else if(quotes.hasOwnProperty(altKey)) {
|
||||||
|
return interpolatedQuote(altKey);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var commands = {
|
var commands = {
|
||||||
// Alternative syntax to ~q
|
// Alternative syntax to ~q
|
||||||
'~': function(event) {
|
'~': function(event) {
|
||||||
@ -101,19 +121,11 @@ var quotes = function(dbot) {
|
|||||||
// Retrieve quote from a category in the database.
|
// Retrieve quote from a category in the database.
|
||||||
'~q': function(event) {
|
'~q': function(event) {
|
||||||
var key = event.input[1].trim().toLowerCase();
|
var key = event.input[1].trim().toLowerCase();
|
||||||
var altKey;
|
var quote = api.getQuote(event.input[1]);
|
||||||
if(key.split(' ').length > 0) {
|
if(quote) {
|
||||||
altKey = key.replace(/ /g, '_');
|
event.reply(key + ': ' + quote);
|
||||||
}
|
} else {
|
||||||
|
event.reply(dbot.t('category_not_found', {'category': key}));
|
||||||
if(key.charAt(0) !== '_') { // lol
|
|
||||||
if(quotes.hasOwnProperty(key)) {
|
|
||||||
event.reply(key + ': ' + interpolatedQuote(key));
|
|
||||||
} else if(quotes.hasOwnProperty(altKey)) {
|
|
||||||
event.reply(altKey + ': ' + interpolatedQuote(altKey));
|
|
||||||
} else {
|
|
||||||
event.reply(dbot.t('category_not_found', {'category': key}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -157,17 +169,13 @@ var quotes = function(dbot) {
|
|||||||
if(rmAllowed == true || dbot.config.admins.include(event.user)) {
|
if(rmAllowed == true || dbot.config.admins.include(event.user)) {
|
||||||
var key = event.input[1].trim().toLowerCase();
|
var key = event.input[1].trim().toLowerCase();
|
||||||
if(quotes.hasOwnProperty(key)) {
|
if(quotes.hasOwnProperty(key)) {
|
||||||
if(!dbot.db.locks.include(key) || dbot.config.admins.include(event.user)) {
|
var quote = quotes[key].pop();
|
||||||
var quote = quotes[key].pop();
|
if(quotes[key].length === 0) {
|
||||||
if(quotes[key].length === 0) {
|
delete quotes[key];
|
||||||
delete quotes[key];
|
|
||||||
}
|
|
||||||
resetRemoveTimer(event, key, quote);
|
|
||||||
|
|
||||||
event.reply(dbot.t('removed_from', {'quote': quote, 'category': key}));
|
|
||||||
} else {
|
|
||||||
event.reply(dbot.t('locked_category', {'category': q[1]}));
|
|
||||||
}
|
}
|
||||||
|
resetRemoveTimer(event, key, quote);
|
||||||
|
|
||||||
|
event.reply(dbot.t('removed_from', {'quote': quote, 'category': key}));
|
||||||
} else {
|
} else {
|
||||||
event.reply(dbot.t('no_quotes', {'category': q[1]}));
|
event.reply(dbot.t('no_quotes', {'category': q[1]}));
|
||||||
}
|
}
|
||||||
@ -182,22 +190,18 @@ var quotes = function(dbot) {
|
|||||||
var quote = event.input[2];
|
var quote = event.input[2];
|
||||||
|
|
||||||
if(quotes.hasOwnProperty(key)) {
|
if(quotes.hasOwnProperty(key)) {
|
||||||
if(!dbot.db.locks.include(key)) {
|
var category = quotes[key];
|
||||||
var category = quotes[key];
|
var index = category.indexOf(quote);
|
||||||
var index = category.indexOf(quote);
|
if(index !== -1) {
|
||||||
if(index !== -1) {
|
category.splice(index, 1);
|
||||||
category.splice(index, 1);
|
if(category.length === 0) {
|
||||||
if(category.length === 0) {
|
delete quotes[key];
|
||||||
delete quotes[key];
|
|
||||||
}
|
|
||||||
resetRemoveTimer(event, key, quote);
|
|
||||||
|
|
||||||
event.reply(dbot.t('removed_from', {'category': key, 'quote': quote}));
|
|
||||||
} else {
|
|
||||||
event.reply(dbot.t('q_not_exist_under', {'category': key, 'quote': quote}));
|
|
||||||
}
|
}
|
||||||
|
resetRemoveTimer(event, key, quote);
|
||||||
|
|
||||||
|
event.reply(dbot.t('removed_from', {'category': key, 'quote': quote}));
|
||||||
} else {
|
} else {
|
||||||
event.reply(dbot.t('locked_category', {'category': key}));
|
event.reply(dbot.t('q_not_exist_under', {'category': key, 'quote': quote}));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
event.reply(dbot.t('category_not_found', {'category': key}));
|
event.reply(dbot.t('category_not_found', {'category': key}));
|
||||||
@ -295,11 +299,10 @@ var quotes = function(dbot) {
|
|||||||
'ignorable': true,
|
'ignorable': true,
|
||||||
'commands': commands,
|
'commands': commands,
|
||||||
'pages': pages,
|
'pages': pages,
|
||||||
|
'api': api,
|
||||||
|
|
||||||
'listener': function(event) {
|
'listener': function(event) {
|
||||||
// Reality Once listener
|
if(event.action == 'PRIVMSG') {
|
||||||
if((dbot.db.ignores.hasOwnProperty(event) &&
|
|
||||||
dbot.db.ignores[event.user].include(name)) == false) {
|
|
||||||
if(event.user == 'reality') {
|
if(event.user == 'reality') {
|
||||||
var once = event.message.valMatch(/^I ([\d\w\s,'-]* once)/, 2);
|
var once = event.message.valMatch(/^I ([\d\w\s,'-]* once)/, 2);
|
||||||
} else {
|
} else {
|
||||||
@ -307,28 +310,19 @@ var quotes = function(dbot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(once) {
|
if(once) {
|
||||||
if((dbot.db.bans.hasOwnProperty('~qadd') &&
|
event.message = '~qadd realityonce=reality ' + once[1];
|
||||||
dbot.db.bans['~qadd'].include(event.user)) ||
|
event.action = 'PRIVMSG';
|
||||||
dbot.db.bans['*'].include(event.user)) {
|
event.params = event.message.split(' ');
|
||||||
event.reply(dbot.t('command_ban', {'user': event.user}));
|
dbot.instance.emit(event);
|
||||||
} else {
|
}
|
||||||
if(!dbot.db.quoteArrs.hasOwnProperty('realityonce')) {
|
} else if(event.action == 'JOIN') {
|
||||||
dbot.db.quoteArrs['realityonce'] = [];
|
var userQuote = api.getQuote(event.user)
|
||||||
}
|
if(userQuote) {
|
||||||
if(dbot.db.quoteArrs['realityonce'].include('reality ' + once[1] + '.')) {
|
event.reply(event.user + ': ' + api.getQuote(event.user));
|
||||||
event.reply(event.user + ': reality has already done that once.');
|
|
||||||
} else {
|
|
||||||
dbot.db.quoteArrs['realityonce'].push('reality ' + once[1] + '.');
|
|
||||||
addStack.push('realityonce');
|
|
||||||
rmAllowed = true;
|
|
||||||
event.reply('\'reality ' + once[1] + '.\' saved.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'on': ['PRIVMSG', 'JOIN']
|
||||||
'on': 'PRIVMSG'
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
19
modules/report/README.md
Normal file
19
modules/report/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
## Report
|
||||||
|
|
||||||
|
Report users
|
||||||
|
|
||||||
|
### Description
|
||||||
|
This module provides a command which allows users to report other users in a
|
||||||
|
channel to the operators of the channel, as well as posting an alert in the
|
||||||
|
administrative channel. It can be done either anonymously or publicly in the
|
||||||
|
channel.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
#### ~report [#channel] [username] [reason for reporting]
|
||||||
|
Report a user in a channel for a reason. This command can either be run publicly
|
||||||
|
in a channel or anonymously in a PM to the bot. The result of using this command
|
||||||
|
will be that all of the users which are currently marked as operators in the
|
||||||
|
reporting channel will receive a PM telling them a user has been reported, by
|
||||||
|
whom, in which channel and why. If there is an administrative channel for the
|
||||||
|
reporting channel (e.g. ##channel), the report will be posted there as well.
|
3
modules/report/config.json
Normal file
3
modules/report/config.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/report/README.md"
|
||||||
|
}
|
@ -21,18 +21,21 @@ var report = function(dbot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(var i=0;i<ops.length;i++) {
|
for(var i=0;i<ops.length;i++) {
|
||||||
dbot.say(event.server, ops[i],
|
dbot.say(event.server, ops[i], dbot.t('report', {
|
||||||
'Attention: ' + event.user + ' has reported ' +
|
'reporter': event.user,
|
||||||
nick + ' in ' + channelName + '. The reason ' +
|
'reported': nick,
|
||||||
'given was: "' + reason + '."');
|
'channel': channelName,
|
||||||
|
'reason': reason
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
event.reply('Thank you, ' + nick + ' has been reported the channel administrators.');
|
event.reply(dbot.t('reported', { 'reported': nick }));
|
||||||
} else {
|
} else {
|
||||||
event.reply('User is not in that channel.');
|
event.reply(dbot.t('user_not_found', { 'reported': nick,
|
||||||
|
'channel': channelName }));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
event.reply('I am not in that channel.');
|
event.reply(dbot.t('not_in_channel', { 'channel': channelName }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
modules/report/strings.json
Normal file
14
modules/report/strings.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"report": {
|
||||||
|
"english": "Attention: {reporter} has reported {reported} in {channel}. The reason given was: \"{reason}.\""
|
||||||
|
},
|
||||||
|
"reported": {
|
||||||
|
"english": "Thank you, {reported} has been reported to the channel administrators."
|
||||||
|
},
|
||||||
|
"user_not_found": {
|
||||||
|
"english": "{reported} does not appear to be in {channel}."
|
||||||
|
},
|
||||||
|
"not_in_channel": {
|
||||||
|
"english": "I am not present in {channel}."
|
||||||
|
}
|
||||||
|
}
|
22
modules/spelling/README.md
Normal file
22
modules/spelling/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
## Spelling
|
||||||
|
|
||||||
|
Fix your spelling.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
Will attempt to correct a users' spelling by using the levenshtein distance
|
||||||
|
algorithm. One corrects the spelling of their previous message by simply posting
|
||||||
|
a message with their correction and an asterisk:
|
||||||
|
|
||||||
|
> user: I am a tutrle.
|
||||||
|
> user: *turtle
|
||||||
|
user meant: I am a turtle.
|
||||||
|
|
||||||
|
The regular expression for this module also accepts two asterisks at the
|
||||||
|
beginning of the correction, or at the end; it also accepts several words as the
|
||||||
|
correction and deals with these fairly intelligently. Users may also attempt
|
||||||
|
to correct another users like so:
|
||||||
|
|
||||||
|
> userone: I am a tutrle.
|
||||||
|
> usertwo: userone: *turtle
|
||||||
|
> usertwo thinks userone meant: I am a turtle.
|
3
modules/spelling/config.json
Normal file
3
modules/spelling/config.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"help": "http://github.com/reality/depressionbot/blob/master/modules/spelling/README.md"
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
Subproject commit 8867e3592ea03b85093a5ab79017efb26c9156be
|
Subproject commit cedfdb09ed857476298ba16eb90e3131f033ba60
|
20
modules/users/strings.json
Normal file
20
modules/users/strings.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"alias": {
|
||||||
|
"english": "{alias} is an alias of {user}"
|
||||||
|
},
|
||||||
|
"primary": {
|
||||||
|
"english": "{user} is a primary user with {count} aliases."
|
||||||
|
},
|
||||||
|
"unknown_alias": {
|
||||||
|
"english": "{alias} does not currently exist as an alias or known user."
|
||||||
|
},
|
||||||
|
"aliasparentset": {
|
||||||
|
"english": "{newParent} is now the parent user, and {newAlias} is an alias."
|
||||||
|
},
|
||||||
|
"unprimary_error": {
|
||||||
|
"english": "One of those users isn't currently recorded as a primary user."
|
||||||
|
},
|
||||||
|
"merged_users": {
|
||||||
|
"english": "{old_user} and their aliases have been merged into {new_user}."
|
||||||
|
}
|
||||||
|
}
|
@ -4,15 +4,26 @@
|
|||||||
*/
|
*/
|
||||||
var users = function(dbot) {
|
var users = function(dbot) {
|
||||||
var knownUsers = dbot.db.knownUsers;
|
var knownUsers = dbot.db.knownUsers;
|
||||||
var getServerUsers = function(event) {
|
var getServerUsers = function(server) {
|
||||||
if(!knownUsers.hasOwnProperty(event.server)) {
|
if(!knownUsers.hasOwnProperty(server)) {
|
||||||
knownUsers[event.server] = { 'users': [], 'aliases': {} };
|
knownUsers[server] = { 'users': [], 'aliases': {} };
|
||||||
}
|
}
|
||||||
return knownUsers[event.server];
|
return knownUsers[server];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var updateAliases = function(event, oldUser, newUser) {
|
||||||
|
var knownUsers = getServerUsers(event.server);
|
||||||
|
for(var alias in knownUsers.aliases) {
|
||||||
|
if(knownUsers.aliases.hasOwnProperty(alias)) {
|
||||||
|
if(knownUsers.aliases[alias] === oldUser) {
|
||||||
|
knownUsers.aliases[alias] = newUser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dbot.instance.addListener('366', 'users', function(event) {
|
dbot.instance.addListener('366', 'users', function(event) {
|
||||||
var knownUsers = getServerUsers(event);
|
var knownUsers = getServerUsers(event.server);
|
||||||
for(var nick in event.channel.nicks) {
|
for(var nick in event.channel.nicks) {
|
||||||
if(!knownUsers.users.include(nick) && !knownUsers.aliases.hasOwnProperty(nick) &&
|
if(!knownUsers.users.include(nick) && !knownUsers.aliases.hasOwnProperty(nick) &&
|
||||||
event.channel.nicks.hasOwnProperty(nick)) {
|
event.channel.nicks.hasOwnProperty(nick)) {
|
||||||
@ -80,33 +91,113 @@ var users = function(dbot) {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
var api = {
|
||||||
'name': 'users',
|
'resolveUser': function(server, nick, useLowercase) {
|
||||||
'ignorable': false,
|
var knownUsers = getServerUsers(server);
|
||||||
|
var user = nick;
|
||||||
|
if(!knownUsers.users.include(nick) && knownUsers.aliases.hasOwnProperty(nick)) {
|
||||||
|
user = knownUsers.aliases[nick];
|
||||||
|
}
|
||||||
|
|
||||||
'commands': {
|
if(useLowercase) user = user.toLowerCase();
|
||||||
'~alias': function(event) {
|
return user;
|
||||||
var knownUsers = getServerUsers(event);
|
}
|
||||||
var alias = event.params[1].trim();
|
};
|
||||||
if(knownUsers.aliases.hasOwnProperty(alias)) {
|
|
||||||
event.reply(alias + ' is an alias of ' + knownUsers.aliases[alias]);
|
var commands = {
|
||||||
|
'~alias': function(event) {
|
||||||
|
var knownUsers = getServerUsers(event.server);
|
||||||
|
var alias = event.params[1].trim();
|
||||||
|
if(knownUsers.users.include(alias)) {
|
||||||
|
var aliasCount = 0;
|
||||||
|
knownUsers.aliases.each(function(primaryUser) {
|
||||||
|
if(primaryUser == alias) aliasCount += 1;
|
||||||
|
}.bind(this));
|
||||||
|
event.reply(dbot.t('primary', { 'user': alias, 'count': aliasCount }));
|
||||||
|
} else if(knownUsers.aliases.hasOwnProperty(alias)) {
|
||||||
|
event.reply(dbot.t('alias', { 'alias': alias,
|
||||||
|
'user': knownUsers.aliases[alias] }));
|
||||||
|
} else {
|
||||||
|
event.reply(dbot.t('unknown_alias', { 'alias': alias }));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'~setaliasparent': function(event) {
|
||||||
|
if(dbot.config.admins.include(event.user)) {
|
||||||
|
var knownUsers = getServerUsers(event.server);
|
||||||
|
var newParent = event.params[1];
|
||||||
|
|
||||||
|
if(knownUsers.aliases.hasOwnProperty(newParent)) {
|
||||||
|
var newAlias = knownUsers.aliases[newParent];
|
||||||
|
|
||||||
|
// Replace users entry with new primary user
|
||||||
|
var usersIndex = knownUsers.users.indexOf(newAlias);
|
||||||
|
knownUsers.users.splice(usersIndex, 1);
|
||||||
|
knownUsers.users.push(newParent);
|
||||||
|
|
||||||
|
// Remove alias for new parent & add alias for new alias
|
||||||
|
delete knownUsers.aliases[newParent];
|
||||||
|
knownUsers.aliases[newAlias] = newParent;
|
||||||
|
|
||||||
|
// Update aliases to point to new primary user
|
||||||
|
updateAliases(event, newAlias, newParent);
|
||||||
|
|
||||||
|
event.reply(dbot.t('aliasparentset', { 'newParent': newParent,
|
||||||
|
'newAlias': newAlias }));
|
||||||
|
|
||||||
|
dbot.api.stats.fixStats(event.server, newAlias);
|
||||||
} else {
|
} else {
|
||||||
event.reply(alias + ' is not known as an alias to me.');
|
event.reply(dbot.t('unknown_alias', { 'alias': newParent}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'~mergeusers': function(event) {
|
||||||
|
if(dbot.config.admins.include(event.user)) {
|
||||||
|
var knownUsers = getServerUsers(event.server);
|
||||||
|
var primaryUser = event.params[1];
|
||||||
|
var secondaryUser = event.params[2];
|
||||||
|
|
||||||
|
if(knownUsers.users.include(primaryUser) && knownUsers.users.include(secondaryUser)) {
|
||||||
|
knownUsers.users.splice(knownUsers.users.indexOf(secondaryUser), 1);
|
||||||
|
knownUsers.aliases[secondaryUser] = primaryUser;
|
||||||
|
updateAliases(event, secondaryUser, primaryUser);
|
||||||
|
|
||||||
|
event.reply(dbot.t('merged_users', {
|
||||||
|
'old_user': secondaryUser,
|
||||||
|
'new_user': primaryUser
|
||||||
|
}));
|
||||||
|
|
||||||
|
dbot.api.stats.fixStats(event.server, secondaryUser);
|
||||||
|
} else {
|
||||||
|
event.reply(dbot.t('unprimary_error'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
'name': 'users',
|
||||||
|
'ignorable': false,
|
||||||
|
'commands': commands,
|
||||||
|
'api': api,
|
||||||
'pages': pages,
|
'pages': pages,
|
||||||
|
|
||||||
'listener': function(event) {
|
'listener': function(event) {
|
||||||
var knownUsers = getServerUsers(event);
|
var knownUsers = getServerUsers(event.server);
|
||||||
if(event.action == 'JOIN') {
|
if(event.action == 'JOIN') {
|
||||||
if(!knownUsers.users.include(event.user)) {
|
if(!knownUsers.users.include(event.user)) {
|
||||||
knownUsers.users.push(event.user);
|
knownUsers.users.push(event.user);
|
||||||
}
|
}
|
||||||
} else if(event.action == 'NICK') {
|
} else if(event.action == 'NICK') {
|
||||||
var newNick = event.params.substr(1);
|
var newNick = event.params.substr(1);
|
||||||
knownUsers.aliases[newNick] = event.user;
|
if(knownUsers.aliases.hasOwnProperty(event.user)) {
|
||||||
|
knownUsers.aliases[newNick] = knownUsers.aliases[event.user];
|
||||||
|
} else {
|
||||||
|
if(!knownUsers.users.include(newNick)) {
|
||||||
|
knownUsers.aliases[newNick] = event.user;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'on': ['JOIN', 'NICK'],
|
'on': ['JOIN', 'NICK'],
|
||||||
|
7
modules/web/README.md
Normal file
7
modules/web/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
## Web
|
||||||
|
|
||||||
|
Web interface
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
It's a web interface for DBot. What of it?
|
@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"webHost": "localhost",
|
"webHost": "localhost",
|
||||||
"webPort": 8080
|
"webPort": 8090
|
||||||
}
|
}
|
||||||
|
10
modules/youare/README.md
Normal file
10
modules/youare/README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
## youare
|
||||||
|
|
||||||
|
You're a loser!
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
This module occasionally comes back and says "You're a x" when somebody goes "y
|
||||||
|
is x" or "y are x," with the intention of annoying people who are calling
|
||||||
|
something crap. Warning: this module occasionally causes the bot to be nice to
|
||||||
|
people.
|
13
run.js
13
run.js
@ -117,9 +117,10 @@ DBot.prototype.reloadModules = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.rawModules = [];
|
this.rawModules = [];
|
||||||
this.modules = [];
|
|
||||||
this.pages = {};
|
this.pages = {};
|
||||||
|
this.modules = {};
|
||||||
this.commands = {};
|
this.commands = {};
|
||||||
|
this.api = {};
|
||||||
this.commandMap = {}; // Map of which commands belong to which modules
|
this.commandMap = {}; // Map of which commands belong to which modules
|
||||||
this.usage = {};
|
this.usage = {};
|
||||||
this.timers.clearTimers();
|
this.timers.clearTimers();
|
||||||
@ -209,6 +210,11 @@ DBot.prototype.reloadModules = function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load module API
|
||||||
|
if(module.api) {
|
||||||
|
this.api[module.name] = module.api;
|
||||||
|
}
|
||||||
|
|
||||||
// Load the module usage data
|
// Load the module usage data
|
||||||
try {
|
try {
|
||||||
var usage = JSON.parse(fs.readFileSync(moduleDir + 'usage.json', 'utf-8'));
|
var usage = JSON.parse(fs.readFileSync(moduleDir + 'usage.json', 'utf-8'));
|
||||||
@ -241,7 +247,10 @@ DBot.prototype.reloadModules = function() {
|
|||||||
// Invalid or no string info
|
// Invalid or no string info
|
||||||
}
|
}
|
||||||
|
|
||||||
this.modules.push(module);
|
module.toString = function() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
this.modules[module.name] = module;
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.log(this.t('module_load_error', {'moduleName': name}));
|
console.log(this.t('module_load_error', {'moduleName': name}));
|
||||||
if(this.config.debugMode) {
|
if(this.config.debugMode) {
|
||||||
|
15
snippets.js
15
snippets.js
@ -204,7 +204,15 @@ Object.prototype.filter = function(fun) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Object.prototype.each = function(fun) {
|
||||||
|
for(var key in this) {
|
||||||
|
if(this.hasOwnProperty(key)) {
|
||||||
|
fun(this[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*** Integer ***/
|
/*** Integer ***/
|
||||||
|
|
||||||
@ -263,3 +271,8 @@ Number.prototype.numberFormat = function(dec_places){
|
|||||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep);
|
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep);
|
||||||
return parts.join(dec_point);
|
return parts.join(dec_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://simonwillison.net/2006/Jan/20/escape/#p-6
|
||||||
|
String.prototype.escape = function() {
|
||||||
|
return this.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user