mirror of
https://github.com/reality/dbot.git
synced 2025-08-02 17:37:27 +02:00
Compare commits
No commits in common. "master" and "v0.3.9" have entirely different histories.
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
# Ignore the user config files
|
||||
config.json
|
||||
db.json
|
||||
|
||||
# ignore npm
|
||||
|
11
.gitmodules
vendored
11
.gitmodules
vendored
@ -1,6 +1,9 @@
|
||||
[submodule "jsbot"]
|
||||
path = jsbot
|
||||
url = git://github.com/reality/jsbot.git
|
||||
path = jsbot
|
||||
url = git://github.com/reality/jsbot.git
|
||||
[submodule "modules/github"]
|
||||
path = modules/github
|
||||
url = git://github.com/zuzak/dbot-github.git
|
||||
path = modules/github
|
||||
url = git://github.com/zuzak/dbot-github.git
|
||||
[submodule "modules/stats"]
|
||||
path = modules/stats
|
||||
url = git@github.com:SamStudio8/dbot-stats.git
|
||||
|
33
README.md
33
README.md
@ -11,27 +11,18 @@ given I started it rather a long time after I began development of the project.
|
||||
Please don't judge me too harshly for this as I am, in fact, mildly allergic to
|
||||
writing documentation.
|
||||
|
||||
## Getting Started
|
||||
Requirements:
|
||||
|
||||
To get started with DBot, you first need to decide on a database system to use.
|
||||
DBot uses the [databank](http://github.com/e14n/databank) library, and each
|
||||
module can be configured to use any database driver databank supports in its
|
||||
respective config.json file. There is currently no default database driver
|
||||
option.
|
||||
- Node JS
|
||||
- [JSBot](http://github.com/reality/JSBot "JSBot"), a Javascript library which
|
||||
handles the IRC protocol
|
||||
- Underscore JS library
|
||||
- Various modules have their own requirements also.
|
||||
|
||||
The default for all modules is the 'redis' driver, and you can simply install
|
||||
the Redis server to get going.
|
||||
### External Modules
|
||||
|
||||
Once you have that set up, you can install DBot's dependencies, configure and
|
||||
run the bot for the first time with the following command:
|
||||
|
||||
```
|
||||
./install
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
|
||||
If you have used a previous version of DBot, then you can migrate most data
|
||||
using the [dbot-migrate](https://github.com/reality/dbot-migrate) module.
|
||||
Instructions on how to run this are included in the repository - remember to
|
||||
remove db.json after migration, otherwise the instance will be slow!
|
||||
JSBot and externally developed modules can be imported by running the following
|
||||
commands in the cloned repository:
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
3
VERSION
3
VERSION
@ -1,6 +1,5 @@
|
||||
dbot version 0.5-dev
|
||||
depressionbot version 0.4-dev
|
||||
|
||||
this.db.search('releases', { 'name': 'jimbletron' }, function(result) { "RELEASE" });
|
||||
"the database is a grilled cheese"
|
||||
_.each(dbot.modules, function(module) { "RESCORE EVERYTHING" });
|
||||
"He called his bot depressionbot, and that's when he was happy."
|
||||
|
@ -15,13 +15,10 @@
|
||||
"admins": [ "batman" ],
|
||||
"moderators": [ "whatever" ],
|
||||
"power_users": [],
|
||||
"moduleNames": [ "ignore", "admin", "command", "dice", "js", "kick", "quotes", "spelling", "users", "youare", "timers", "sstats", "link" ],
|
||||
"moduleNames": [ "ignore", "admin", "command", "dice", "js", "kick", "quotes", "spelling", "youare", "timers", "stats", "users", "link" ],
|
||||
"language": "en",
|
||||
"debugMode": false,
|
||||
"debugLevel": 1,
|
||||
"dbType": "redis",
|
||||
"redisPort": 6379,
|
||||
"timezone": "Europe/London",
|
||||
"repoRoot": "https://github.com/reality/depressionbot/",
|
||||
"version": "Depressionbot IRC bot 0.5-dev - Lovingly crafted by The DepressionBot Foundation (a charity arm of the Official Aberystwyth Open Source International Development League)."
|
||||
"version": "Depressionbot IRC bot 0.4-dev - Lovingly crafted by The DepressionBot Foundation (a charity arm of the Official Aberystwyth Open Source International Development League)."
|
||||
}
|
||||
|
33
database.js
33
database.js
@ -1,33 +0,0 @@
|
||||
var databank = require('databank'),
|
||||
Databank = databank.Databank,
|
||||
DatabankObject = databank.DatabankObject,
|
||||
_ = require('underscore')._;
|
||||
|
||||
/**
|
||||
* Multiplex databank objects
|
||||
*/
|
||||
var DatabaseDriver = function(config) {
|
||||
this.config = config;
|
||||
this.databank = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Connect to or create a new DataBank
|
||||
*/
|
||||
DatabaseDriver.prototype.createDB = function(name, driver, schema, callback) {
|
||||
var params = { 'schema': schema };
|
||||
|
||||
if(driver == 'redis' && _.has(this.config, 'redisPort')) params.port = this.config.redisPort;
|
||||
if(driver == 'disk') params.dir = 'db';
|
||||
|
||||
this.databank = Databank.get(driver, params);
|
||||
this.databank.connect({}, function(err) {
|
||||
if(err) {
|
||||
console.log('Didn\'t manage to connect to the data source - ' + err);
|
||||
} else {
|
||||
callback(this.databank);
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
exports.DatabaseDriver = DatabaseDriver;
|
48
install
48
install
@ -1,48 +0,0 @@
|
||||
#!/bin/bash
|
||||
cat LICENCE
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
command -v node > /dev/null
|
||||
if [[ $? -gt 0 ]]; then
|
||||
echo 'node.js is not installed. Please install it before running install.sh.'
|
||||
exit 1
|
||||
fi
|
||||
command -v npm > /dev/null
|
||||
if [[ $? -gt 0 ]]; then
|
||||
echo 'npm is not installed. Please install it before running install.sh'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
npm install googlemaps humanize feedparser node-units tvdb method-override 500px process async wordnik node-uuid underscore request request-promise-native vm2 express moment-timezone moment jade databank databank-redis ent passport passport-local password-hash connect-flash
|
||||
|
||||
cd public/
|
||||
wget https://github.com/twbs/bootstrap/releases/download/v3.3.2/bootstrap-3.3.2-dist.zip
|
||||
unzip bootstrap-3.3.2-dist.zip
|
||||
mv bootstrap-3.3.2-dist bootstrap
|
||||
rm bootstrap-3.3.2-dist.zip
|
||||
|
||||
mkdir d3
|
||||
cd d3
|
||||
wget https://github.com/mbostock/d3/releases/download/v3.5.5/d3.zip
|
||||
unzip d3.zip
|
||||
rm d3.zip
|
||||
|
||||
cd ../..
|
||||
|
||||
if [ ! -f config.json ];
|
||||
then
|
||||
echo 'Creating configuration file...'
|
||||
cp config.json.sample config.json
|
||||
$EDITOR config.json # Open config file with EDITOR variable, but if not available:
|
||||
if [[ $? != 0 ]]; then vim config.json; fi # Find the return code from previous command, if failed then use vim to edit.
|
||||
fi
|
||||
|
||||
read -p "Setup complete. Run dbot now? [y/N]"
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
echo 'Okay. To run the bot, use "node run.js"'
|
||||
exit
|
||||
fi
|
||||
node run.js
|
||||
|
46
install.sh
Executable file
46
install.sh
Executable file
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
cat LICENCE
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
if [ ! -e /usr/bin/node ] && [ ! -e /usr/local/bin/node ];
|
||||
then
|
||||
echo 'node.js is not installed. Please install it before running install.sh.'
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -e /usr/bin/npm ] && [ ! -e /usr/local/bin/npm ];
|
||||
then
|
||||
echo 'npm is not installed. Please install it before running install.sh'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
npm install wordnik ent underscore request sandbox express moment jade@0.25
|
||||
|
||||
cd public/
|
||||
wget http://twitter.github.com/bootstrap/assets/bootstrap.zip
|
||||
unzip bootstrap.zip
|
||||
rm bootstrap.zip
|
||||
|
||||
mkdir d3
|
||||
cd d3
|
||||
wget http://d3js.org/d3.v3.zip
|
||||
unzip d3.v3.zip
|
||||
rm d3.v3.zip
|
||||
|
||||
cd ../..
|
||||
|
||||
if [ ! -f config.json ];
|
||||
then
|
||||
echo 'Creating configuration file...'
|
||||
cp config.json.sample config.json
|
||||
vim config.json
|
||||
fi
|
||||
|
||||
read -p "Setup complete. Run depressionbot now? [y/N]"
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]
|
||||
then
|
||||
echo 'Okay. To run the bot, use "node run.js"'
|
||||
exit
|
||||
fi
|
||||
node run.js
|
||||
|
2
jsbot
2
jsbot
@ -1 +1 @@
|
||||
Subproject commit 4e6af64655674ba1a331910f3ed35b935eaba147
|
||||
Subproject commit 11cbb75b504fbb703450a2f8c938d5a81680109c
|
@ -1,28 +0,0 @@
|
||||
## FOO
|
||||
|
||||
bar.
|
||||
|
||||
### Description
|
||||
|
||||
This module provides a command which allows users to foobar.
|
||||
|
||||
### Dependencies
|
||||
|
||||
It has following dependencies:
|
||||
+ [foo](link)
|
||||
|
||||
### config.json
|
||||
|
||||
foo
|
||||
```
|
||||
```
|
||||
|
||||
### Commands
|
||||
|
||||
|
||||
#### ~foo [(bar]
|
||||
|
||||
Example:
|
||||
+ ~foo bar
|
||||
|
||||
### TODO
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"foo": true,
|
||||
"foo": "bar"
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Module Name: foo
|
||||
* Description: bar.
|
||||
* Requires: foo [bar]
|
||||
*/
|
||||
|
||||
var _ = require('underscore')._,
|
||||
bar = require('foo');//dependencies
|
||||
|
||||
var foo = function(dbot) { //name of module
|
||||
|
||||
this.ApiRoot = 'API_ROOT_HERE';
|
||||
|
||||
this.internalAPI = {
|
||||
//code for internal api here
|
||||
};
|
||||
|
||||
this.api = {
|
||||
//code for api here
|
||||
};
|
||||
|
||||
this.commands = {
|
||||
//code for commands here
|
||||
};
|
||||
|
||||
this.onLoad = function() {
|
||||
//code for stuff to be done on load here
|
||||
};
|
||||
|
||||
this.onDestroy = function() {
|
||||
//stuff to be done on destroy here
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new foo(dbot); //name of module
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"foo": {
|
||||
"en": "{output} bar"
|
||||
},
|
||||
"foo2": {
|
||||
"en": "Something went wrong :( Example:'~foo bar'"
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"~foo": "~foo [bar]"
|
||||
}
|
@ -26,15 +26,6 @@ channel, it will attempt to give the caller ops in the current channel.
|
||||
Perform a git pull, and then execute the 'reload' command. Saves a lot of time
|
||||
updating!
|
||||
|
||||
#### version [module]
|
||||
Shows the git version of the currently loaded revision of DBot. If module is
|
||||
provided, it will attempt to get the revision of the module (this is only useful
|
||||
for submodules).
|
||||
|
||||
#### status [module]
|
||||
Show the recorded status for a given module, this is helpful for debugging
|
||||
issues when loading or for checking if a module is loaded.
|
||||
|
||||
#### 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
|
||||
@ -55,18 +46,12 @@ loaded by the standard DBot process.
|
||||
Unload a currently loaded module. This removes the module, and then triggers a
|
||||
reload of all modules.
|
||||
|
||||
#### setconfig [path] [value]
|
||||
Set a config value at path to be a certain value persistently. For example, if
|
||||
you want to change the web module to listen on port 9001, you can run _setconfig
|
||||
web.webPort 9001_.
|
||||
#### 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.
|
||||
|
||||
#### pushconfig [path] [value]
|
||||
Push a new value to an existing config array. For example, if you want to add
|
||||
the user 'batman62' to the DBot moderators, you can run _pushconfig moderators
|
||||
batman62_.
|
||||
|
||||
#### showconfig [path]
|
||||
Use this to explore and view the DBot configuration. If called without a path,
|
||||
it will display the config keys in the root; if the path is a subkey, it will
|
||||
show all config keys under that key. If you give it an actual key, it'll show you
|
||||
the currently effective config value.
|
||||
#### 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.
|
||||
|
@ -1,62 +1,12 @@
|
||||
/**
|
||||
* Module Name: Admin
|
||||
* Description: Set of commands which only one who is a DepressionBot
|
||||
* administrator can run.
|
||||
* administrator can run - as such, it has its own command execution listener.
|
||||
*/
|
||||
var fs = require('fs'),
|
||||
_ = require('underscore')._;
|
||||
|
||||
var admin = function(dbot) {
|
||||
this.internalAPI = {
|
||||
'getCurrentConfig': function(configKey, callback) {
|
||||
var configPath = dbot.config;
|
||||
configKey = configKey.split('.');
|
||||
|
||||
for(var i=0;i<configKey.length;i++) {
|
||||
if(_.has(configPath, configKey[i])) {
|
||||
configPath = configPath[configKey[i]];
|
||||
} else {
|
||||
configPath = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
callback(configPath);
|
||||
},
|
||||
|
||||
'setConfig': function(configKey, newOption, callback) {
|
||||
var configPath = dbot.customConfig,
|
||||
oldOption = null;
|
||||
configKey = configKey.split('.');
|
||||
|
||||
for(var i=0;i<configKey.length-1;i++) {
|
||||
if(!_.has(configPath, configKey[i])) {
|
||||
configPath[configKey[i]] = {};
|
||||
}
|
||||
configPath = configPath[configKey[i]];
|
||||
}
|
||||
|
||||
if(_.has(configPath, configKey[i])) {
|
||||
oldOption = configPath[configKey[i]];
|
||||
}
|
||||
configPath[configKey[i]] = newOption;
|
||||
|
||||
this.internalAPI.saveConfig();
|
||||
dbot.reloadModules();
|
||||
callback(null, oldOption);
|
||||
}.bind(this),
|
||||
|
||||
'saveConfig': function() {
|
||||
var config = dbot.customConfig;
|
||||
fs.writeFileSync('config.json', JSON.stringify(config, null, ' '));
|
||||
}
|
||||
};
|
||||
|
||||
this.onLoad = function() {
|
||||
dbot.api.timers.addTimer(60000, function() {
|
||||
dbot.save(function() {});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
|
@ -1,12 +1,49 @@
|
||||
var fs = require('fs'),
|
||||
_ = require('underscore')._,
|
||||
sys = require('sys'),
|
||||
process = require('process'),
|
||||
exec = require('child_process').exec;
|
||||
|
||||
var commands = function(dbot) {
|
||||
var noChangeConfig = [ 'servers', 'name', 'moduleNames' ];
|
||||
|
||||
|
||||
var getCurrentConfig = function(configKey) {
|
||||
var defaultConfigPath = dbot.config;
|
||||
var userConfigPath = dbot.db.config;
|
||||
|
||||
if(configKey) {
|
||||
var configKey = configKey.split('.');
|
||||
for(var i=0;i<configKey.length-1;i++) {
|
||||
if(_.has(defaultConfigPath, configKey[i])) {
|
||||
if(!_.has(userConfigPath, configKey[i])) {
|
||||
userConfigPath[configKey[i]] = {};
|
||||
}
|
||||
userConfigPath = userConfigPath[configKey[i]];
|
||||
defaultConfigPath = defaultConfigPath[configKey[i]];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var currentOption;
|
||||
if(configKey && configKey.length != 1) {
|
||||
configKey = _.last(configKey);
|
||||
if(_.has(userConfigPath, configKey) && !_.isUndefined(userConfigPath[configKey])) {
|
||||
currentOption = userConfigPath[configKey];
|
||||
} else if(_.has(defaultConfigPath, configKey)) {
|
||||
currentOption = defaultConfigPath[configKey];
|
||||
}
|
||||
} else {
|
||||
currentOption = defaultConfigPath[configKey];
|
||||
}
|
||||
|
||||
return {
|
||||
'user': userConfigPath,
|
||||
'default': defaultConfigPath,
|
||||
'value': currentOption
|
||||
};
|
||||
};
|
||||
|
||||
var commands = {
|
||||
// Join a channel
|
||||
'~join': function(event) {
|
||||
@ -41,23 +78,16 @@ var commands = function(dbot) {
|
||||
dbot.instance.mode(event, channel, ' +o ' + event.user);
|
||||
},
|
||||
|
||||
// Op via OperServ in order to work with channels dbot is not joined to, or joined to without having +o itself
|
||||
'~forceopme': function(event) {
|
||||
var channel = event.params[1];
|
||||
|
||||
if(!_.has(event.allChannels, channel)) {
|
||||
channel = event.channel.name;
|
||||
}
|
||||
dbot.say('tripsit', 'OperServ', ' MODE ' + channel + ' +o ' + event.user);
|
||||
},
|
||||
|
||||
// Do a git pull and reload
|
||||
'~greload': function(event) {
|
||||
exec("git pull", function (error, stdout, stderr) {
|
||||
exec("git submodule update", function (error, stdout, stderr) {
|
||||
event.reply(dbot.t('gpull'));
|
||||
commands['~reload'](event);
|
||||
commands['~version'](event);
|
||||
event.message = '~version';
|
||||
event.action = 'PRIVMSG';
|
||||
event.params = event.message.split(' ');
|
||||
dbot.instance.emit(event);
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
@ -90,15 +120,9 @@ var commands = function(dbot) {
|
||||
if(_.has(dbot.status, moduleName)) {
|
||||
var status = dbot.status[moduleName];
|
||||
if(status === true) {
|
||||
event.reply(dbot.t('status_good', {
|
||||
'module': moduleName,
|
||||
'reason': status
|
||||
}));
|
||||
event.reply(dbot.t("status_good",{"module":moduleName, "reason": status}));
|
||||
} else {
|
||||
event.reply(dbot.t('status_bad', {
|
||||
'module': moduleName,
|
||||
'reason': status
|
||||
}));
|
||||
event.reply(dbot.t("status_bad",{"module":moduleName, "reason": status}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t("status_unloaded"));
|
||||
@ -109,9 +133,7 @@ var commands = function(dbot) {
|
||||
'~reload': function(event) {
|
||||
dbot.db = JSON.parse(fs.readFileSync('db.json', 'utf-8'));
|
||||
dbot.reloadModules();
|
||||
process.nextTick(function() {
|
||||
event.reply(dbot.t('reload'));
|
||||
});
|
||||
event.reply(dbot.t('reload'));
|
||||
},
|
||||
|
||||
// Say something in a channel
|
||||
@ -128,21 +150,18 @@ var commands = function(dbot) {
|
||||
'~load': function(event) {
|
||||
var moduleName = event.params[1];
|
||||
if(!_.include(dbot.config.moduleNames, moduleName)) {
|
||||
dbot.customConfig.moduleNames.push(moduleName);
|
||||
this.internalAPI.saveConfig();
|
||||
dbot.config.moduleNames.push(moduleName);
|
||||
dbot.reloadModules();
|
||||
process.nextTick(function() {
|
||||
if(dbot.status[moduleName] === true) {
|
||||
event.reply(dbot.t('load_module', { 'moduleName': moduleName }));
|
||||
} else {
|
||||
event.reply(dbot.t('load_failed', { 'module': moduleName }));
|
||||
}
|
||||
});
|
||||
if(dbot.status[moduleName] === true) {
|
||||
event.reply(dbot.t('load_module', {'moduleName': moduleName}));
|
||||
} else {
|
||||
event.reply(dbot.t("load_failed",{"module": moduleName}));
|
||||
}
|
||||
} else {
|
||||
if(moduleName == 'web') {
|
||||
event.reply(dbot.t('already_loaded_web'));
|
||||
} else {
|
||||
event.reply(dbot.t('already_loaded', { 'moduleName': moduleName }));
|
||||
event.reply(dbot.t('already_loaded', {'moduleName': moduleName}));
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -157,170 +176,98 @@ var commands = function(dbot) {
|
||||
var cacheKey = require.resolve(moduleDir + moduleName);
|
||||
delete require.cache[cacheKey];
|
||||
} catch(err) { }
|
||||
|
||||
dbot.customConfig.moduleNames = _.without(dbot.config.moduleNames, moduleName);
|
||||
this.internalAPI.saveConfig();
|
||||
dbot.config.moduleNames = _.without(dbot.config.moduleNames, moduleName);
|
||||
dbot.reloadModules();
|
||||
|
||||
process.nextTick(function() {
|
||||
event.reply(dbot.t('unload_module', { 'moduleName': moduleName }));
|
||||
});
|
||||
event.reply(dbot.t('unload_module', {'moduleName': moduleName}));
|
||||
} else {
|
||||
event.reply(dbot.t('unload_error', { 'moduleName': moduleName }));
|
||||
event.reply(dbot.t('unload_error', {'moduleName': moduleName}));
|
||||
}
|
||||
},
|
||||
|
||||
/*** Config options ***/
|
||||
|
||||
'~setconfig': function(event) {
|
||||
var configPath = event.input[1],
|
||||
newOption = event.input[2];
|
||||
var configPathString = event.params[1],
|
||||
configKey = _.last(configPathString.split('.')),
|
||||
newOption = event.params[2];
|
||||
|
||||
event.reply(event.input[1]);
|
||||
if(!_.include(noChangeConfig, configKey)) {
|
||||
var configPath = getCurrentConfig(configPathString);
|
||||
|
||||
if(!_.include(noChangeConfig, configPath)) {
|
||||
this.internalAPI.getCurrentConfig(configPath, function(config) {
|
||||
if(config !== null) {
|
||||
// Convert to boolean type if config item boolean
|
||||
if(_.isBoolean(config)) {
|
||||
newOption = (newOption == "true");
|
||||
}
|
||||
if(configPath == false || _.isUndefined(configPath.value)) {
|
||||
event.reply(dbot.t("no_config_key"));
|
||||
return;
|
||||
}
|
||||
var currentOption = configPath.value;
|
||||
|
||||
// Convert to integer type is config item integer
|
||||
if(_.isNumber(config)) {
|
||||
newOption = parseInt(newOption);
|
||||
}
|
||||
// Convert to boolean type if config item boolean
|
||||
if(_.isBoolean(currentOption)) {
|
||||
newOption = (newOption == "true");
|
||||
}
|
||||
|
||||
if(_.isArray(config)) {
|
||||
event.reply(dbot.t("config_array", { "alternate": "pushconfig" }));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t("no_config_key", {'path': configPath}));
|
||||
configPath = configPath.split('.');
|
||||
if(_.has(dbot.config.modules, configPath[0])) {
|
||||
configPath.splice(0, 0, 'modules');
|
||||
event.input[1] = configPath.join('.');
|
||||
commands['~setconfig'](event);
|
||||
return;
|
||||
} else {
|
||||
event.reply(dbot.t('new_config_key', { 'key': configPath }));
|
||||
}
|
||||
}
|
||||
// Convert to integer type is config item integer
|
||||
if(_.isNumber(currentOption)) {
|
||||
newOption = parseInt(newOption);
|
||||
}
|
||||
|
||||
this.internalAPI.setConfig(configPath, newOption, function(err) {
|
||||
event.reply(configPath + ": " + config + " -> " + newOption);
|
||||
});
|
||||
}.bind(this));
|
||||
if(_.isArray(currentOption)) {
|
||||
event.reply(dbot.t("config_array",{"alternate": "pushconfig"}));
|
||||
}
|
||||
|
||||
event.reply(configPathString + ": " + currentOption + " -> " + newOption);
|
||||
configPath['user'][configKey] = newOption;
|
||||
dbot.reloadModules();
|
||||
} else {
|
||||
event.reply(dbot.t("config_lock"));
|
||||
}
|
||||
},
|
||||
|
||||
'~pushconfig': function(event) {
|
||||
var configPath = event.input[1],
|
||||
newOption = event.input[2];
|
||||
var configPathString = event.params[1],
|
||||
configKey = _.last(configPathString.split('.')),
|
||||
newOption = event.params[2];
|
||||
|
||||
if(!_.include(noChangeConfig, configPath)) {
|
||||
this.internalAPI.getCurrentConfig(configPath, function(config) {
|
||||
if(config !== null) {
|
||||
if(_.isArray(config)) {
|
||||
event.reply(configPath + ": " + config + " << " + newOption);
|
||||
config.push(newOption);
|
||||
this.internalAPI.setConfig(configPath, config, function(err) {});
|
||||
} else {
|
||||
event.reply(dbot.t("config_array", { "alternate": "setconfig" }));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t("no_config_key", { 'path': configPath }));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t("config_lock"));
|
||||
}
|
||||
},
|
||||
if(!_.include(noChangeConfig, configKey)) {
|
||||
var configPath = getCurrentConfig(configPathString);
|
||||
if(configPath == false || _.isUndefined(configPath.value)) {
|
||||
event.reply(dbot.t("no_config_key"));
|
||||
return;
|
||||
}
|
||||
var currentArray = configPath.value;
|
||||
|
||||
'~rmconfig': function(event) {
|
||||
var configPath = event.input[1],
|
||||
rmOption = event.input[2];
|
||||
if(!_.isArray(currentArray)) {
|
||||
event.reply(dbot.t("config_array",{"alternate": "setconfig"}));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!_.include(noChangeConfig, configPath)) {
|
||||
this.internalAPI.getCurrentConfig(configPath, function(config) {
|
||||
if(config !== null) {
|
||||
if(_.isArray(config)) {
|
||||
event.reply(configPath + ": " + config + " - " + rmOption);
|
||||
config = _.without(config, rmOption)
|
||||
this.internalAPI.setConfig(configPath, config, function(err) {});
|
||||
} else {
|
||||
event.reply(dbot.t("config_array", { "alternate": "nope" }));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t("no_config_key", { 'path': configPath }));
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t("config_lock"));
|
||||
event.reply(configPathString + ": " + currentArray + " << " + newOption);
|
||||
currentArray.push(newOption);
|
||||
dbot.reloadModules();
|
||||
}
|
||||
},
|
||||
|
||||
'~showconfig': function(event) {
|
||||
var configPath = event.params[1];
|
||||
if(configPath.indexOf('servers') != -1) { return false; }
|
||||
if(configPath) {
|
||||
this.internalAPI.getCurrentConfig(configPath, function(config) {
|
||||
if(config !== null) {
|
||||
if(_.isArray(config)) {
|
||||
event.reply(dbot.t("config_keys_location", {
|
||||
"path": configPath,
|
||||
"value": config
|
||||
}));
|
||||
} else if(_.isObject(config)) {
|
||||
event.reply(dbot.t("config_keys_location", {
|
||||
"path": configPath,
|
||||
"value": _.keys(config)
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t("config_keys_location", {
|
||||
"path": configPath,
|
||||
"value": config
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t("no_config_key", {'path': configPath}));
|
||||
var configPathString = event.params[1];
|
||||
var configPath = getCurrentConfig(configPathString);
|
||||
|
||||
if(configPathString) {
|
||||
var configKey = _.last(configPathString.split('.'));
|
||||
if(!configKey) {
|
||||
event.reply(dbot.t("no_config_path"));
|
||||
return;
|
||||
}
|
||||
|
||||
configPath = configPath.split('.');
|
||||
if(_.has(dbot.config.modules, configPath[0])) {
|
||||
configPath.splice(0, 0, 'modules');
|
||||
} else {
|
||||
configPath.pop();
|
||||
}
|
||||
|
||||
event.params[1] = configPath.join('.');
|
||||
commands['~showconfig'](event);
|
||||
}
|
||||
}.bind(this));
|
||||
if(_.isArray(configPath.value)) {
|
||||
event.reply(configKey + ': ' + configPath.value);
|
||||
} else if(_.isObject(configPath.value)) {
|
||||
event.reply(dbot.t("config_keys_location",{"path":configPathString,"value":Object.keys(configPath.value)}));
|
||||
} else {
|
||||
event.reply(configKey + ': ' + configPath.value);
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t("config_keys_location", {
|
||||
"path": "root",
|
||||
"value": _.keys(dbot.config)
|
||||
}));
|
||||
event.reply(dbot.t("config_keys_location",{"path":"root","value":Object.keys(configPath['default'])}));
|
||||
}
|
||||
},
|
||||
|
||||
'~savemodules': function(event) {
|
||||
fs.readFile('config.json', 'utf-8', function(err, config) {
|
||||
config = JSON.parse(config);
|
||||
config.moduleNames = _.keys(dbot.modules);
|
||||
fs.writeFile('config.json', JSON.stringify(config, null, ' '), function() {
|
||||
event.reply(dbot.t('modules_saved', { 'modules': _.keys(dbot.modules) }));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
'~die': function(event) {
|
||||
event.reply('BRB coconut hunting...');
|
||||
setTimeout(3000, function() {
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -328,18 +275,11 @@ var commands = function(dbot) {
|
||||
command.access = 'admin';
|
||||
});
|
||||
|
||||
commands['~showconfig'].access = 'admin';
|
||||
commands['~join'].access = 'power_user';
|
||||
commands['~part'].access = 'power_user';
|
||||
commands['~showconfig'].access = 'moderator';
|
||||
commands['~join'].access = 'moderator';
|
||||
commands['~part'].access = 'moderator';
|
||||
commands['~opme'].access = 'moderator';
|
||||
commands['~forceopme'].access = 'power_user';
|
||||
commands['~say'].access = 'power_user';
|
||||
commands['~pushconfig'].access = 'moderator';
|
||||
commands['~rmconfig'].access = 'moderator';
|
||||
|
||||
commands['~pushconfig'].regex = [/pushconfig ([^ ]+) ([^ ]+)/, 3];
|
||||
commands['~rmconfig'].regex = [/rmconfig ([^ ]+) ([^ ]+)/, 3];
|
||||
commands['~setconfig'].regex = [/setconfig ([^ ]+) ([^ ]+)/, 3];
|
||||
commands['~say'].access = 'moderator';
|
||||
|
||||
return commands;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"ignorable": false,
|
||||
"dbType": "redis",
|
||||
"dependencies": [ "command" ]
|
||||
"dependencies": [ "command" ],
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/admin/README.md"
|
||||
}
|
||||
|
@ -5,9 +5,7 @@
|
||||
"na'vi": "fpxäkìm {channel}(nemfa)",
|
||||
"cy": "Wedi ymuno {channel}",
|
||||
"nl": "{channel} binnengekomen",
|
||||
"de": "{channel} beigetreten",
|
||||
"fr": "{channel} rejoint",
|
||||
"it": "Aderito a {channel}"
|
||||
"de": "{channel} beigetreten"
|
||||
},
|
||||
"part": {
|
||||
"en": "Left {channel}",
|
||||
@ -15,9 +13,7 @@
|
||||
"na'vi": "Hum {channel}",
|
||||
"cy": "Wedi gadael {channel}",
|
||||
"nl": "{channel} verlaten",
|
||||
"de": "{channel} verlassen",
|
||||
"fr": "{channel} quitté",
|
||||
"it": "uscito da {channel}"
|
||||
"de": "{channel} verlassen"
|
||||
},
|
||||
"gpull": {
|
||||
"en": "Git pulled that shit.",
|
||||
@ -25,9 +21,7 @@
|
||||
"na'vi": "Gìtìl fì'uti stamarsìm.",
|
||||
"cy": "Wedi tynnu git yr cach na i gyd",
|
||||
"nl": "Git heeft die zooi binnengehaald.",
|
||||
"de": "Git hat es gezogen",
|
||||
"fr": "Git a pullé cette merde",
|
||||
"it": "Git ha pullato questa coglionata"
|
||||
"de": "Git hat es gezogen"
|
||||
},
|
||||
"reload": {
|
||||
"en": "Reloaded that shit.",
|
||||
@ -35,9 +29,7 @@
|
||||
"na'vi": "Oel fìuti stìyeftxaw.",
|
||||
"cy": "Ail-lwytho'r cach na",
|
||||
"nl": "Die zooi opnieuw geladen.",
|
||||
"de": "Neu geladen",
|
||||
"fr": "Bordel rechargé",
|
||||
"it": "Ricaricato questa puttanata"
|
||||
"de": "Neu geladen"
|
||||
},
|
||||
"load_module": {
|
||||
"en": "Loaded new module: {moduleName}",
|
||||
@ -45,9 +37,7 @@
|
||||
"na'vi": "Oel {moduleName}it amip stìyeftxaw.",
|
||||
"cy": "Wedi llwytho modiwl newydd: {moduleName}",
|
||||
"nl": "Nieuwe module geladen: {moduleName}",
|
||||
"de": "Neues Modul geladen: {moduleName}",
|
||||
"fr": "Nouveau module chargé : {moduleName}",
|
||||
"it": "Caricato nuovo modulo: {moduleName}"
|
||||
"de": "Neues Modul geladen: {moduleName}"
|
||||
},
|
||||
"unload_module": {
|
||||
"en": "Turned off module: {moduleName}",
|
||||
@ -55,9 +45,7 @@
|
||||
"na'vi": "Oel {moduleName} tswìya'.",
|
||||
"cy": "Wedi troi ffwrdd y modiwl: {moduleName}",
|
||||
"nl": "Module uitgeschakeld: {moduleName}",
|
||||
"de": "Modul ausgeschaltet: {moduleName}",
|
||||
"fr": "Module déchargé : {moduleName}",
|
||||
"it": "Inabilitato modulo: {moduleName}"
|
||||
"de": "Modul ausgeschaltet: {moduleName}"
|
||||
},
|
||||
"unload_error": {
|
||||
"en": "{moduleName} isn't loaded. Idiot.",
|
||||
@ -65,9 +53,7 @@
|
||||
"na'vi": "Oel {moduleName}it omum. Nga skxawng lu.",
|
||||
"cy": "Di {moduleName} ddim wedi llwytho. Twpsyn",
|
||||
"nl": "{moduleName} is niet geladen. Idioot.",
|
||||
"de": "{moduleName} ist nicht geladen, du Idiot.",
|
||||
"fr": "{moduleName} n'est pas chargé. Idiot.",
|
||||
"it": "{moduleName} non è caricato. Idiota"
|
||||
"de": "{moduleName} ist nicht geladen, du Idiot."
|
||||
},
|
||||
"banned": {
|
||||
"en": "{user} banned from {command}",
|
||||
@ -75,9 +61,7 @@
|
||||
"na'vi": "{command}ìri {user} ke tung.",
|
||||
"cy": "{user} wedi ei gohurio o {command}",
|
||||
"nl": "{user} mag {command} niet meer gebruiken",
|
||||
"de": "{user} wurde von {command} gebannt",
|
||||
"fr": "{user} a été interdit d'utiliser {command}",
|
||||
"it": "{user} bandito da {command}"
|
||||
"de": "{user} wurde von {command} gebannt"
|
||||
},
|
||||
"unbanned": {
|
||||
"en": "{user} unbanned from {command}",
|
||||
@ -85,9 +69,7 @@
|
||||
"na'vi": "{command}ìri {user} tung set.",
|
||||
"cy": "{user} wedi ei dad-wahardd o {command}",
|
||||
"nl": "{user} mag {command} weer gebruiken",
|
||||
"de": "{user} wurde von {command} entbannt",
|
||||
"fr": "{user} peut de nouveau utiliser {command}",
|
||||
"it": "{user} riammesso da {command}"
|
||||
"de": "{user} wurde von {command} entbannt"
|
||||
},
|
||||
"unban_error": {
|
||||
"en": "{user} wasn't banned from that command, fool.",
|
||||
@ -95,9 +77,7 @@
|
||||
"na'vi": "{user} fìtsu'oti tamung srekrr, nga skxawng lu.",
|
||||
"cy": "Nid oedd {user} wedi ei wahardd o'r gorchymyn yna, twpsyn",
|
||||
"nl": "{user} mag dat commando sowieso al gebruiken, mafketel.",
|
||||
"de": "{user} wurde nicht von {command} gebannt, du Trottel",
|
||||
"fr": "{user} n'a pas été interdit d'utiliser cette commande, imbécile.",
|
||||
"it": "{user} non è stato bandito da utilizzare questo commando, imbecille."
|
||||
"de": "{user} wurde nicht von {command} gebannt, du Trottel"
|
||||
},
|
||||
"qlock": {
|
||||
"en": "Locked quote category: {category}",
|
||||
@ -105,126 +85,84 @@
|
||||
"na'vi": "{category}ìri oel 'upxareti fmoli",
|
||||
"cy": "Categori wedi cloi: {category}",
|
||||
"nl": "Quote categorie vergrendeld: {category}",
|
||||
"de": "Zitat-Kategorie geschlossen: {category}",
|
||||
"fr": "Catégorie de citations verrouillée : {category}",
|
||||
"it": "Categoria di citazione bloccata : {category}"
|
||||
"de": "Zitat-Kategorie geschlossen: {category}"
|
||||
},
|
||||
"already_in_channel": {
|
||||
"en": "I'm already in {channel}",
|
||||
"na'vi": "Oel {channel}it tok li",
|
||||
"cy": "Rydw i eisoes yn {channel}",
|
||||
"nl": "Ik ben al in {channel}",
|
||||
"de": "Ich bin schon in {channel}",
|
||||
"fr": "Je suis déjà dans {channel}",
|
||||
"it": "Sono già in {channel}"
|
||||
"de": "Ich bin schon in {channel}"
|
||||
},
|
||||
"not_in_channel": {
|
||||
"en": "I'm not in {channel}",
|
||||
"na'vi": "Oel {channel}it ke tok",
|
||||
"cy": "Rydw i ddim yn {channel}",
|
||||
"nl": "Ik ben niet aanwezig in {channel}",
|
||||
"de": "Ich bin noch nicht in {channel}",
|
||||
"fr": "Je ne suis pas dans {channel}",
|
||||
"it": "Non sono in {channel}"
|
||||
"de": "Ich bin noch nicht in {channel}"
|
||||
},
|
||||
"already_loaded_web": {
|
||||
"en": "WHY CAN'T I LOAD ALL THIS WEB? (web already loaded)",
|
||||
"na'vi": "PELUN OEL KE TSUN OMUM FÌWETIT NÌWOTX (wetìri oe omum li)",
|
||||
"cy": "PAM ALLA I DDIM YN LWYTHO POB Y WE? (We eisoes yn lwytho)",
|
||||
"nl": "AL DIT WEB WORDT ME TOCH EEN BEETJE TE VEEL! (web is al geladen)",
|
||||
"de": "WARUM KANN DAS NICHT GELADEN WERDEN? (bereits geladen)",
|
||||
"fr": "POURQUOI EST-CE QUE JE PEUX PAS CHARGER TOUT CE WEB? (web déjà chargé)",
|
||||
"it": "PERCHÉ NON POSSO CARICARE TUTTE QUESTO WEB? (web già caricato)"
|
||||
"de": "WARUM KANN DAS NICHT GELADEN WERDEN? (bereits geladen)"
|
||||
},
|
||||
"already_loaded": {
|
||||
"en": "{moduleName} is already loaded.",
|
||||
"na'vi": "Oel omum teri {moduleName}it li.",
|
||||
"cy": "{moduleName} eisoes yn lwytho",
|
||||
"nl": "{moduleName} is al geladen.",
|
||||
"de": "{moduleName} ist bereits geladen.",
|
||||
"fr": "{moduleName} est déjà chargé.",
|
||||
"it": "{moduleName} già caricato."
|
||||
"de": "{moduleName} ist bereits geladen."
|
||||
},
|
||||
"no_version": {
|
||||
"en": "No version information or queried module not loaded.",
|
||||
"cy": "Dim gwybodaeth fersiwn neu modiwl holodd dim yn lwytho",
|
||||
"de": "Keine Informationen verfügbar oder gewünschtes Modul wurde noch nicht geladen.",
|
||||
"fr": "Aucune information de version ou module demandé non chargé.",
|
||||
"it": "Informazione sulla versione non è disponibile o modulo richiesto non ancora caricato"
|
||||
"de": "Keine Informationen verfügbar oder gewünschtes Modul wurde noch nicht geladen."
|
||||
},
|
||||
"status_good": {
|
||||
"en": "{module} status: Shit looks good",
|
||||
"cy": "{module} statws: Cachu yn edrych yn dda",
|
||||
"de": "Sieht gut aus",
|
||||
"fr": "Statut de {module}: Cette merde tourne bien",
|
||||
"it": "Stato di {modulo}: Funky gallo come sono bello stamattina"
|
||||
"de": "Sieht gut aus"
|
||||
},
|
||||
"status_bad": {
|
||||
"en": "{module} status: Failed to load: {reason}",
|
||||
"cy": "{module} statws: Methu i lwytho: {reason}",
|
||||
"de": "{module} Status: Konnte nicht geladen werden: {reason}",
|
||||
"fr": "Statut de {module}: échec de chargement : {reason}",
|
||||
"it": "Stato di {module}: Caricamento fallito: {reason}"
|
||||
"de": "{module} Status: Konnte nicht geladen werden: {reason}"
|
||||
},
|
||||
"status_unloaded": {
|
||||
"en": "Either that module wasn't on the roster or shit is totally fucked.",
|
||||
"cy": "Naill ai heb fod modiwl oedd ar y rhestr, neu cachu yn gwbl torrodd",
|
||||
"de": "Entweder ist das Modul nicht auf der Liste oder die Kacke ist am dampfen",
|
||||
"fr": "Soit ce module n'est pas sur la liste, soit tout est complètement niqué",
|
||||
"it": "O questo modulo non è sulla lista, o sono cazzi amari"
|
||||
"de": "Entweder ist das Modul nicht auf der Liste oder die Kacke ist am dampfen"
|
||||
},
|
||||
"load_failed": {
|
||||
"en": "Failed to load {module}. See 'status {module}'.",
|
||||
"cy": "Methu i lwytho {module}. Gwelwch 'status {module}'.",
|
||||
"de": "Konnte {module} nicht laden. Siehe 'status {module}'.",
|
||||
"fr": "Echec du chargement de {module}. Voir 'status {module}'.",
|
||||
"it": "Caricamento di {module} non riuscito. Vedi 'stato {module}'."
|
||||
"de": "Konnte {module} nicht laden. Siehe 'status {module}'."
|
||||
},
|
||||
"no_config_key": {
|
||||
"en": "{path} doesn't exist bro",
|
||||
"cy": "{path} cyfluniad yn bodoli, fy mrawd",
|
||||
"de": "{path} existiert nicht, Bruder",
|
||||
"fr": "{path} n'existe pas, fréro",
|
||||
"it": "{path} non esiste, fratello"
|
||||
"en": "Config key doesn't exist bro",
|
||||
"cy": "Nid yw allwedd cyfluniad yn bodoli, fy mrawd",
|
||||
"de": "Einstellung existiert nicht, Bruder"
|
||||
},
|
||||
"config_array": {
|
||||
"en": "Config option is an array. Try '{alternate}'.",
|
||||
"cy": "Opsiwn cyfluniad ydy'r amrywiaeth. Rhowch gynnig ar '{alternate}'.",
|
||||
"de": "Einstellung ist ein Array, probiere '{alternate}' aus.",
|
||||
"fr": "L'option de configuration est un array. Essaye '{alternate}'.",
|
||||
"it": "L'opzione di configurazione è un array. Prova '{alternate}'."
|
||||
"de": "Einstellung ist ein Array, probiere '{alternate}' aus."
|
||||
},
|
||||
"config_lock": {
|
||||
"en": "This config option cannot be altered while the bot is running.",
|
||||
"cy": "Ni all yr opsiwn cyfluniad yn cael ei newid tra bod y bot yn rhedeg.",
|
||||
"de": "Diese Option kann während der Benutzung des Bots nicht verändert werden",
|
||||
"fr": "Cette option de configuration ne peut pas être changée pendant que le bot est activé.",
|
||||
"it": "Questa opzione di configurazione non può essere alterata mentre il bot è attivo."
|
||||
"de": "Diese Option kann während der Benutzung des Bots nicht verändert werden"
|
||||
},
|
||||
"no_config_path": {
|
||||
"en": "Config path doesn't exist bro",
|
||||
"cy": "Nid yw llwybr cyfluniad yn bodoli, fy mrawd",
|
||||
"de": "Konfigurationspfad nicht vorhanden, Bruder",
|
||||
"fr": "Le chemin de configuration n'existe pas, fréro",
|
||||
"it": "Percorso di configurazione non esiste, fratello"
|
||||
},
|
||||
"new_config_key": {
|
||||
"en": "Warning: Creating new config key: {key}.",
|
||||
"fr": "Attention : création d'une nouvelle clé de configuration : {key}.",
|
||||
"it": "Attenzione : Creazione di una nuova chiave di configurazione: {key}.",
|
||||
"de": "Achtung: Neuer Konfigurationsschlüssel erstellt: {key}."
|
||||
"de": "Konfigurationspfad nicht vorhanden, Bruder"
|
||||
},
|
||||
"config_keys_location": {
|
||||
"en": "Config keys in {path}: {value}",
|
||||
"cy": "Allweddi cyfluniad yn {path}: {value}",
|
||||
"de": "Die Konfiguration in {path}: {value}",
|
||||
"fr": "Clés de configuration dans {path}: {value}",
|
||||
"it": "Chiave di configurazione in {path}: {value}"
|
||||
},
|
||||
"modules_saved": {
|
||||
"en": "Currently loaded modules now default: {modules}",
|
||||
"fr": "Les modules actuellement chargés sont maintenant chargés par défaut : {modules}",
|
||||
"it": "I moduli attualmente caricati sono adesso predefiniti: {modules}",
|
||||
"de": "Die derzeit geladenen Module sind nun der Standart: {modules}"
|
||||
"de": "Die Konfiguration in {path}: {value}"
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
/**
|
||||
* Name: Announce
|
||||
* Description: Announce things every now and again
|
||||
*/
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var announce = function(dbot) {
|
||||
this.announces = dbot.config.modules.announce.announces;
|
||||
this.lineCount = 0;
|
||||
this.lastAnnounce = {};
|
||||
_.each(dbot.config.servers, function(v, k) {
|
||||
this.lastAnnounce[k] = {};
|
||||
_.each(this.announces[k], function(announce, channel) {
|
||||
this.lastAnnounce[k][channel] = announce.distance;
|
||||
}, this)
|
||||
}, this);
|
||||
|
||||
this.listener = function(event) {
|
||||
if(_.has(this.lastAnnounce[event.server], event.channel)) {
|
||||
this.lastAnnounce[event.server][event.channel]--;
|
||||
if(this.lastAnnounce[event.server][event.channel] == 0) {
|
||||
var announce = this.config.announces[event.server][event.channel];
|
||||
this.lastAnnounce[event.server][event.channel] = announce.distance;
|
||||
|
||||
dbot.api.quotes.getQuote(announce.category, function(quote) {
|
||||
if(quote) {
|
||||
dbot.say(event.server, event.channel, quote);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
this.on = 'PRIVMSG';
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new announce(dbot);
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"announces": {
|
||||
"aberwiki": {
|
||||
"#test": {
|
||||
"category": "test",
|
||||
"distance": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -51,9 +51,6 @@ var api = function(dbot) {
|
||||
if(callbackIndex != -1) {
|
||||
args[callbackIndex] = function() {
|
||||
body.data = Array.prototype.slice.call(arguments, 0);
|
||||
if(_.isObject(body.data[0]) && _.has(body.data[0], 'err')) {
|
||||
body.err = body.data[0].err;
|
||||
}
|
||||
res.json(body);
|
||||
};
|
||||
func.apply(null, args);
|
||||
|
@ -1,16 +0,0 @@
|
||||
var april = function(dbot) {
|
||||
this.listener = function(event) {
|
||||
var match = event.message.match(/^i'?( a)?m (an? )?([^ ]+)/i);
|
||||
if(match) {
|
||||
dbot.say(event.server, 'operserv', 'svsnick ' + event.user + ' ' + match[3]);
|
||||
setTimeout(function() {
|
||||
event.reply('Hi ' + match[3] + ', I\'m ' + dbot.config.name + '!');
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
this.on = 'PRIVMSG';
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new april(dbot);
|
||||
};
|
@ -1,157 +0,0 @@
|
||||
/**
|
||||
* Module Name: atheme
|
||||
* Description: atheme mode references & retrieve channel flags
|
||||
*/
|
||||
var _ = require('underscore')._,
|
||||
async = require('async');
|
||||
|
||||
var atheme = function(dbot) {
|
||||
this.flagStack = {};
|
||||
this.hostStack = {};
|
||||
|
||||
this.api = {
|
||||
'getChannelFlags': function(server, channel, callback) {
|
||||
if(!_.has(this.flagStack, server)) this.flagStack[server] = {};
|
||||
if(_.has(this.flagStack[server], channel)) { // Already an active flag call
|
||||
this.flagStack[server][channel].callbacks.push(callback);
|
||||
} else {
|
||||
this.flagStack[server][channel] = {
|
||||
'flags': {},
|
||||
'callbacks': [ callback ],
|
||||
'timeout': null,
|
||||
'working': false
|
||||
};
|
||||
}
|
||||
|
||||
dbot.say(server, 'chanserv', 'FLAGS ' + channel);
|
||||
this.flagStack[server][channel].timeout = setTimeout(function() { // Delete callback if no response
|
||||
if(_.has(this.flagStack[server], channel) && this.flagStack[server][channel].working == false) {
|
||||
_.each(this.flagStack[server][channel].callbacks, function(callback) {
|
||||
callback(true, null);
|
||||
});
|
||||
delete this.flagStack[server][channel];
|
||||
}
|
||||
}.bind(this), 20000);
|
||||
},
|
||||
|
||||
'getVHosts': function(server, mask, callback) {
|
||||
if(!_.has(this.hostStack, server)) this.hostStack[server] = {};
|
||||
if(_.has(this.hostStack[server], mask)) { // Already an active host call
|
||||
this.hostStack[server][channel].callbacks.push(callback);
|
||||
} else {
|
||||
this.hostStack[server][mask] = {
|
||||
'users': [],
|
||||
'callbacks': [ callback ],
|
||||
'timeout': null
|
||||
};
|
||||
}
|
||||
|
||||
dbot.say(server, 'hostserv', 'LISTVHOST ' + mask);
|
||||
this.hostStack[server][mask].timeout = setTimeout(function() { // Delete callback if no response
|
||||
if(_.has(this.hostStack[server], mask)) {
|
||||
_.each(this.hostStack[server][mask].callbacks, function(callback) {
|
||||
callback(true, null);
|
||||
});
|
||||
delete this.hostStack[server][mask];
|
||||
}
|
||||
}.bind(this), 5000);
|
||||
}
|
||||
};
|
||||
|
||||
this.commands = {
|
||||
'~chanserv': function(event) {
|
||||
if(_.has(this.config.chanserv, event.input[1])) {
|
||||
event.reply('ChanServ flag ' + event.input[1] + ': ' + this.config.chanserv[event.input[1]]);
|
||||
} else {
|
||||
event.reply('I don\'t know anything about ' + event.input[1]);
|
||||
}
|
||||
},
|
||||
|
||||
'~chanmode': function(event) {
|
||||
if(_.has(this.config.chanmodes, event.input[1])) {
|
||||
event.reply('Channel Mode ' + event.input[1] + ': ' + this.config.chanmodes[event.input[1]]);
|
||||
} else {
|
||||
event.reply('I don\'t know anything about ' + event.input[1]);
|
||||
}
|
||||
}
|
||||
};
|
||||
this.commands['~chanserv'].regex = [/^chanserv (\+.)/, 2];
|
||||
this.commands['~chanmode'].regex = [/^chanmode (\+.)/, 2];
|
||||
|
||||
this.listener = function(event) {
|
||||
if(event.action === 'NOTICE') {
|
||||
if(event.user === 'ChanServ') {
|
||||
var flags = event.params.match(/(\d+)\s+([^ ]+)\s+(\+\w+)\s+\((\#[\w\.]+)\)/),
|
||||
end = event.params.match(/end of \u0002(\#[\w\.]+)\u0002 flags listing/i);
|
||||
|
||||
if(flags && _.has(this.flagStack[event.server], flags[4])) {
|
||||
this.flagStack[event.server][flags[4]].flags[flags[2]] = flags[3];
|
||||
} else if(end) {
|
||||
if(_.has(this.flagStack[event.server], end[1])) {
|
||||
this.flagStack[event.server][end[1]].working = true;
|
||||
// Parse wildcard hostmasks to nicks
|
||||
var allFlags = this.flagStack[event.server][end[1]].flags,
|
||||
hostMasks = {};
|
||||
|
||||
_.each(allFlags, function(f, u) { // TODO: combine to one loop
|
||||
if(u.indexOf('*!*@') !== -1) {
|
||||
hostMasks[u] = f;
|
||||
delete allFlags[u];
|
||||
}
|
||||
});
|
||||
async.each(_.keys(hostMasks), function(hostMask, done) {
|
||||
this.api.getVHosts(event.server, hostMask.split('@')[1], function(err, users) {
|
||||
_.each(users, function(user) {
|
||||
allFlags[user] = hostMasks[hostMask];
|
||||
});
|
||||
done();
|
||||
});
|
||||
}.bind(this), function() {
|
||||
_.each(this.flagStack[event.server][end[1]].callbacks, function(callback) {
|
||||
callback(null, this.flagStack[event.server][end[1]].flags);
|
||||
}.bind(this));
|
||||
clearTimeout(this.flagStack[event.server][end[1]].timeout);
|
||||
delete this.flagStack[event.server][end[1]];
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
} else if(event.user === 'HostServ') {
|
||||
_.each(this.hostStack[event.server], function(el, mask) {
|
||||
if(event.params.match(mask)) {
|
||||
var user = event.params.match(/- ([^ ]+)/),
|
||||
end = event.params.match(/matches for pattern/);
|
||||
|
||||
if(user) {
|
||||
this.hostStack[event.server][mask].users.push(user[1]);
|
||||
} else if(end) {
|
||||
_.each(this.hostStack[event.server][mask].callbacks, function(callback) {
|
||||
callback(null, this.hostStack[event.server][mask].users);
|
||||
}, this);
|
||||
clearTimeout(this.hostStack[event.server][mask].timeout);
|
||||
delete this.hostStack[event.server][mask];
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
} else { // PRIVMSG
|
||||
console.log(event.message);
|
||||
var akill = event.message.match(/([^ ]+) AKILL:ADD: ([^ ]+) \(reason: (.+)(\) )\(duration: ([^,)]+)/);
|
||||
if(event.channel == '#services' && akill) {
|
||||
console.log(akill);
|
||||
var channel = dbot.config.servers[event.server].admin_channel;
|
||||
dbot.api.users.getUser(akill[1] + '.' + event.server, function(err, user) {
|
||||
dbot.api.report.notify('ban', 'tripsit', user, channel, dbot.t('akill', {
|
||||
'host': akill[2],
|
||||
'reason': akill[3],
|
||||
'duration': akill[5]
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
this.on = ['NOTICE', 'PRIVMSG'];
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new atheme(dbot);
|
||||
};
|
@ -1,50 +0,0 @@
|
||||
{
|
||||
"chanserv": {
|
||||
"+v": "Enables use of the voice/devoice commands.",
|
||||
"+V": "Enables automatic voice.",
|
||||
"+h": "Enables use of the halfop/dehalfop commands.",
|
||||
"+H": "Enables automatic halfop.",
|
||||
"+o": "Enables use of the op/deop commands.",
|
||||
"+O": "Enables automatic op.",
|
||||
"+a": "Enables use of the protect/deprotect commands.",
|
||||
"+q": "Enables use of the owner/deowner commands.",
|
||||
"+s": "Enables use of the set command.",
|
||||
"+i": "Enables use of the invite and getkey commands.",
|
||||
"+r": "Enables use of the kick, kickban, ban and unban commands.",
|
||||
"+r": "Enables use of the ban and unban commands.",
|
||||
"+r": "Enables use of the unban command.",
|
||||
"+R": "Enables use of the recover and clear commands.",
|
||||
"+f": "Enables modification of channel access lists.",
|
||||
"+t": "Enables use of the topic and topicappend commands.",
|
||||
"+A": "Enables viewing of channel access lists.",
|
||||
"+S": "Marks the user as a successor.",
|
||||
"+F": "Grants full founder access.",
|
||||
"+b": "Enables automatic kickban."
|
||||
},
|
||||
"chanmodes": {
|
||||
"+b": "channel ban",
|
||||
"+c": "colour filter",
|
||||
"+e": "ban exemption",
|
||||
"+f": "channel forwarding",
|
||||
"+F": "allow anybody to forward to this",
|
||||
"+g": "allow anybody to invite",
|
||||
"+i": "invite only",
|
||||
"+I": "invite exception (invex)",
|
||||
"+j": "join throttling",
|
||||
"+k": "key (channel password)",
|
||||
"+l": "channel member limit",
|
||||
"+L": "large ban list",
|
||||
"+m": "moderated",
|
||||
"+n": "no external messages",
|
||||
"+o": "channel operator",
|
||||
"+p": "paranoid channel",
|
||||
"+P": "permanent channel",
|
||||
"+q": "quiet",
|
||||
"+Q": "block forwarded users",
|
||||
"+r": "block unidentified",
|
||||
"+s": "secret channel",
|
||||
"+t": "topic limit",
|
||||
"+v": "voice",
|
||||
"+z": "reduced moderation"
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"akill": {
|
||||
"en": "{host} has been AKilled for {duration} due to \"{reason}\""
|
||||
}
|
||||
}
|
@ -21,17 +21,6 @@ Command flow:
|
||||
This is the only module which is force loaded, even if it's not specified in
|
||||
the configuration file.
|
||||
|
||||
### Config
|
||||
|
||||
#### useNickserv: false
|
||||
Use the nickserv module to ensure a user is logged into their account before
|
||||
running any elevated commands. Note you will still have to load and configure
|
||||
the nickserv module yourself.
|
||||
|
||||
#### accessOutput: false
|
||||
Show a message to a user if they attempt to run a command they don't have the
|
||||
access level for.
|
||||
|
||||
### Commands
|
||||
|
||||
#### ~usage [command]
|
||||
|
@ -2,52 +2,64 @@ var _ = require('underscore')._;
|
||||
|
||||
var api = function(dbot) {
|
||||
return {
|
||||
'isBanned': function(user, command) {
|
||||
var banned = false;
|
||||
if(_.has(dbot.db.bans, user)) {
|
||||
if(_.include(dbot.db.bans[user], command) ||
|
||||
_.include(dbot.db.bans[user], dbot.commands[command].module) ||
|
||||
_.include(dbot.db.bans[user], '*')) {
|
||||
banned = true;
|
||||
}
|
||||
}
|
||||
return banned;
|
||||
},
|
||||
|
||||
/**
|
||||
* Does the user have the correct access level to use the command?
|
||||
*/
|
||||
'hasAccess': function(event, command, callback) {
|
||||
var accessNeeded = dbot.commands[command].access,
|
||||
allowedNicks,
|
||||
user = event.rUser;
|
||||
'hasAccess': function(server, user, command, callback) {
|
||||
var accessNeeded = dbot.commands[command].access;
|
||||
|
||||
if(_.isUndefined(accessNeeded) || accessNeeded == null) {
|
||||
return callback(true);
|
||||
} else if(!_.isFunction(accessNeeded)) {
|
||||
if(_.has(dbot.access, accessNeeded)) {
|
||||
accessNeeded = dbot.access[accessNeeded];
|
||||
if(accessNeeded == 'admin' || accessNeeded == 'moderator' || accessNeeded == 'power_user') {
|
||||
var allowedNicks = dbot.config.admins;
|
||||
if(accessNeeded == 'moderator') allowedNicks = _.union(allowedNicks, dbot.config.moderators);
|
||||
if(accessNeeded == 'power_user') allowedNicks = _.union(allowedNicks, dbot.config.power_users);
|
||||
|
||||
if(!_.include(allowedNicks, user)) {
|
||||
callback(false);
|
||||
} else {
|
||||
return callback(true);
|
||||
if(_.has(dbot.modules, 'nickserv') && this.config.useNickserv == true) {
|
||||
dbot.api.nickserv.auth(server, user, function(result) {
|
||||
callback(result);
|
||||
});
|
||||
} else {
|
||||
callback(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
allowedNicks = accessNeeded(event);
|
||||
|
||||
if(!_.include(allowedNicks, user.primaryNick) && !_.include(allowedNicks, user.currentNick)) {
|
||||
callback(false);
|
||||
} else {
|
||||
if(_.has(dbot.modules, 'nickserv') && this.config.useNickserv == true) {
|
||||
dbot.api.nickserv.auth(user.server, user.currentNick, function(result, primary) {
|
||||
if(result == true && primary == user.primaryNick) {
|
||||
callback(true);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback(true);
|
||||
}
|
||||
callback(true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Is item (user or channel) ignoring command?
|
||||
*/
|
||||
'isIgnoring': function(item, command) {
|
||||
var module = dbot.commands[command].module;
|
||||
return (_.has(dbot.db.ignores, item) &&
|
||||
(_.include(dbot.db.ignores[item], module) ||
|
||||
_.include(dbot.db.ignores[item], '*')));
|
||||
},
|
||||
|
||||
/**
|
||||
* Apply Regex to event message, store result. Return false if it doesn't
|
||||
* apply.
|
||||
*/
|
||||
'applyRegex': function(commandName, event) {
|
||||
var applies = false;
|
||||
event.message = event.message.substring(1);
|
||||
if(_.has(dbot.commands[commandName], 'regex')) {
|
||||
var cRegex = dbot.commands[commandName].regex;
|
||||
if(_.isArray(cRegex) && cRegex.length === 2) {
|
||||
if(_.isArray(cRegex) && cRegex.length == 2) {
|
||||
var q = event.message.valMatch(cRegex[0], cRegex[1]);
|
||||
if(q) {
|
||||
applies = true;
|
||||
@ -64,6 +76,16 @@ var api = function(dbot) {
|
||||
applies = true;
|
||||
}
|
||||
return applies;
|
||||
},
|
||||
|
||||
'addHook': function(command, callback) {
|
||||
console.log('adding hook');
|
||||
if(_.has(dbot.commands, command)) {
|
||||
if(!_.has(dbot.commands[command], 'hooks')) {
|
||||
dbot.commands[command].hooks = [];
|
||||
}
|
||||
dbot.commands[command].hooks.push(callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -4,158 +4,70 @@
|
||||
* command and then runs that command, given the user isn't banned from or
|
||||
* ignoring that command.
|
||||
*/
|
||||
var _ = require('underscore')._,
|
||||
cDomain = require('domain').create();
|
||||
|
||||
var _ = require('underscore')._;
|
||||
var command = function(dbot) {
|
||||
this.dbot = dbot;
|
||||
|
||||
/**
|
||||
* Run the appropriate command given the input.
|
||||
*/
|
||||
this.listener = function(event) {
|
||||
var commandName = event.params[0];
|
||||
if(commandName.charAt(0) != this.config.commandPrefix || this.config.passiveMode == true) {
|
||||
return;
|
||||
}
|
||||
commandName = commandName.substring(1);
|
||||
|
||||
this.api.hasAccess(event, commandName, function(hasAccess) {
|
||||
dbot.api.ignore.isUserIgnoring(event.rUser, commandName, function(isIgnoring) {
|
||||
dbot.api.ignore.isUserBanned(event.rUser, commandName, function(isBanned) {
|
||||
if(!_.has(dbot.commands, commandName)) {
|
||||
if(_.has(dbot.modules, 'quotes')) {
|
||||
commandName = '~';
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(isBanned) {
|
||||
if(this.config.banOutput && commandName != this.config.commandPrefix) {
|
||||
event.reply(dbot.t('command_ban', {'user': event.user}));
|
||||
}
|
||||
} else if(!hasAccess) {
|
||||
if(this.config.accessOutput) {
|
||||
event.reply(dbot.t('access_denied', { 'user': event.user }));
|
||||
}
|
||||
} else if(!isIgnoring && _.has(dbot.commands, commandName) && !dbot.commands[commandName].disabled) {
|
||||
if(!_.has(dbot.commands, commandName)) {
|
||||
if(_.has(dbot.modules, 'quotes')) {
|
||||
var key = event.message.substring(1);
|
||||
dbot.api.quotes.getInterpolatedQuote(event.server,
|
||||
event.channel.name, event.user, key, function(quote) {
|
||||
if(quote) {
|
||||
event.reply(key + ': ' + quote);
|
||||
} else if(_.has(dbot.modules, 'spelling')) {
|
||||
var commands = _.keys(dbot.commands),
|
||||
winner = false,
|
||||
closestMatch = Infinity;
|
||||
|
||||
_.each(commands, function(command) {
|
||||
var distance = dbot.api.spelling.distance(commandName, command);
|
||||
if(distance < closestMatch) {
|
||||
closestMatch = distance;
|
||||
winner = command;
|
||||
}
|
||||
});
|
||||
|
||||
if(closestMatch < 1) {
|
||||
event.reply(commandName + ' not found. Did you mean ' + winner + '?');
|
||||
return;
|
||||
} else if(_.has(dbot.modules, 'quotes')) {
|
||||
dbot.api.link.udLookup(key, function(word, definition) {
|
||||
if(word) {
|
||||
event.reply(key + '[UD]: ' + definition);
|
||||
} else {
|
||||
event.reply(dbot.t('category_not_found', { 'category': key }));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if(this.api.isBanned(event.user, commandName)) {
|
||||
event.reply(dbot.t('command_ban', {'user': event.user}));
|
||||
} else {
|
||||
this.api.hasAccess(event.server, event.user, commandName, function(result) {
|
||||
if(result) {
|
||||
if(!this.api.isIgnoring(event.user, commandName) &&
|
||||
!this.api.isIgnoring(event.channel, commandName) &&
|
||||
dbot.commands[commandName].disabled !== true) {
|
||||
if(this.api.applyRegex(commandName, event)) {
|
||||
try {
|
||||
var command = dbot.commands[commandName];
|
||||
var results = command.apply(dbot.modules[command.module], [event]);
|
||||
if(_.has(command, 'hooks') && results !== false) {
|
||||
_.each(command['hooks'], function(hook) {
|
||||
hook.apply(hook.module, _.values(results));
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch(err) {
|
||||
if(dbot.config.debugMode == true) {
|
||||
var stack = err.stack.split('\n').slice(1, dbot.config.debugLevel + 1);
|
||||
|
||||
if(this.api.applyRegex(commandName, event)) {
|
||||
try {
|
||||
cDomain.run(function() {
|
||||
var command = dbot.commands[commandName],
|
||||
results;
|
||||
if(_.has(command, 'resolver')) {
|
||||
event.res = [];
|
||||
command.resolver(event, function(err) {
|
||||
if(!err) {
|
||||
results = command.apply(dbot.modules[command.module], [event]);
|
||||
}
|
||||
event.reply('- Error in ' + commandName + ':');
|
||||
event.reply('- Message: ' + err);
|
||||
|
||||
_.each(stack, function(stackLine, index) {
|
||||
event.reply('- Stack[' + index + ']: ' +
|
||||
stackLine.trim());
|
||||
});
|
||||
} else {
|
||||
results = command.apply(dbot.modules[command.module], [event]);
|
||||
}
|
||||
});
|
||||
} catch(err) {
|
||||
if(dbot.config.debugMode == true) {
|
||||
var stack = err.stack.split('\n').slice(1, dbot.config.debugLevel + 1);
|
||||
|
||||
event.reply('- Error in ' + commandName + ':');
|
||||
event.reply('- Message: ' + err);
|
||||
|
||||
_.each(stack, function(stackLine, index) {
|
||||
event.reply('- Stack[' + index + ']: ' +
|
||||
stackLine.trim());
|
||||
});
|
||||
}
|
||||
}
|
||||
if(!_.include(['reload', 'load', 'unload', 'setconfig'], commandName)) dbot.api.event.emit('command', [ event ]);
|
||||
} else {
|
||||
if(commandName !== this.config.commandPrefix) {
|
||||
if(_.has(dbot.usage, commandName)) {
|
||||
event.reply('Usage: ' + dbot.usage[commandName]);
|
||||
} else {
|
||||
event.reply(dbot.t('syntax_error'));
|
||||
dbot.api.event.emit('command', [ event ]);
|
||||
dbot.save();
|
||||
} else {
|
||||
if(commandName !== '~') {
|
||||
if(_.has(dbot.usage, commandName)) {
|
||||
event.reply('Usage: ' + dbot.usage[commandName]);
|
||||
} else {
|
||||
event.reply(dbot.t('syntax_error'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this);
|
||||
this.on = 'PRIVMSG';
|
||||
|
||||
this.onLoad = function() {
|
||||
// Not sure this is the right place for this. Perhaps they should be in
|
||||
// another file?
|
||||
|
||||
cDomain.on('error', function(err) {
|
||||
console.log(err); // Hmm
|
||||
if(_.has(dbot.modules, 'log')) {
|
||||
// can't really get context
|
||||
var server = _.keys(dbot.config.servers)[0];
|
||||
dbot.api.log.log(server, dbot.config.name, '[\u00034ERR\u000f] ' + err.message);
|
||||
}
|
||||
});
|
||||
|
||||
dbot.access = {
|
||||
'admin': function(event) {
|
||||
return dbot.config.admins;
|
||||
},
|
||||
|
||||
'moderator': function(event) {
|
||||
return [].concat(dbot.access.admin(event), dbot.config.moderators);
|
||||
},
|
||||
|
||||
'power_user': function(event) {
|
||||
return [].concat(dbot.access.admin(event), dbot.access.moderator(event), dbot.config.power_users);
|
||||
},
|
||||
|
||||
'voice': function(event) {
|
||||
return [].concat(dbot.access.admin(event), dbot.access.moderator(event), dbot.access.power_user(event),
|
||||
_.chain(event.channel.nicks)
|
||||
.filter(function(nick) {
|
||||
return nick.op == true || nick.voice == true;
|
||||
})
|
||||
.pluck('name')
|
||||
.value());
|
||||
}
|
||||
};
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
|
@ -2,8 +2,8 @@ var _ = require('underscore')._,
|
||||
request = require('request');
|
||||
|
||||
var commands = function(dbot) {
|
||||
var commands = {
|
||||
'usage': function(event) {
|
||||
return {
|
||||
'~usage': function(event) {
|
||||
var commandName = event.params[1];
|
||||
if(_.has(dbot.usage, commandName)) {
|
||||
event.reply(dbot.t('usage', {
|
||||
@ -39,8 +39,8 @@ var commands = function(dbot) {
|
||||
var moduleName = event.params[1];
|
||||
if(!moduleName || !_.has(dbot.modules, moduleName)) {
|
||||
event.reply(dbot.t('usage', {
|
||||
'command': this.config.commandPrefix + 'help',
|
||||
'usage': this.config.commandPrefix + 'help [module]'
|
||||
'command': '~help',
|
||||
'usage': '~help [module]'
|
||||
}));
|
||||
event.reply(dbot.t('loaded_modules', {
|
||||
'modules': _.keys(dbot.modules).join(', ')
|
||||
@ -48,8 +48,8 @@ var commands = function(dbot) {
|
||||
} else {
|
||||
var helpLink = dbot.config.repoRoot +
|
||||
'blob/master/modules/' + moduleName + '/README.md';
|
||||
if(dbot.config.modules[moduleName].help) {
|
||||
helpLink = dbot.config.modules[moduleName].help;
|
||||
if(dbot.config[moduleName].help) {
|
||||
helpLink = dbot.config[moduleName].help;
|
||||
}
|
||||
|
||||
// TODO: Check it exists
|
||||
@ -60,9 +60,6 @@ var commands = function(dbot) {
|
||||
}
|
||||
}
|
||||
};
|
||||
commands['usage'].regex = [/usage ([^ ]+)/, 2];
|
||||
|
||||
return commands;
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
|
@ -1,9 +1,6 @@
|
||||
{
|
||||
"ignorable": false,
|
||||
"dependencies": [ "event", "ignore", "users" ],
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/command/README.md",
|
||||
"useNickserv": false,
|
||||
"accessOutput": false,
|
||||
"banOutput": false,
|
||||
"passiveMode": false,
|
||||
"commandPrefix": "~"
|
||||
"dbKeys": [ "ignores", "bans" ]
|
||||
}
|
||||
|
@ -1,78 +1,55 @@
|
||||
{
|
||||
"command_ban": {
|
||||
"en": "{user} is banned from using this command. Commence incineration.",
|
||||
"es": "{user} está prohibido de usar esta instrucción. urrently loaded modules now default: {modules}.",
|
||||
"es": "{user} está prohibido de usar esta instrucción. Comenzar incineración.",
|
||||
"na'vi": "Tsu'ori {user} ke tung. Nga skxawng lu.",
|
||||
"cy": "Mae {user} wedi ei gohurio gan ddefnyddio'r gorchymun yma. Cychwyn orfflosgiad",
|
||||
"nl": "{user} mag dit commando niet meer gebruiken. Bereid het verbrandingsritueel voor.",
|
||||
"de": "{user} darf diesen Befehl nicht benutzen. Verbrennung einleiten",
|
||||
"fr": "{user} est interdit d'utiliser cette commande. Commencer l'incinération.",
|
||||
"it": "A {user} è stato interdetto di utilizzare questo commando. Iniziare incenerimento."
|
||||
"de": "{user} wurde von diesem Befehl gebannt. Verbrennung einleiten"
|
||||
},
|
||||
"syntax_error": {
|
||||
"syntax_error": {
|
||||
"en": "Invalid syntax. Initiate incineration.",
|
||||
"es": "Sintaxis no válida. Iniciar incineración.",
|
||||
"na'vi": "Ngeyä pamrel keyawr lu. Nga skxawng lu.",
|
||||
"cy": "Cystrawen annilys. Cychwyn orfflosgiad",
|
||||
"nl": "Ongeldige syntax. Bereid het verbrandingsritueel voor.",
|
||||
"de": "Syntax ungültig. Verbrennung einleiten",
|
||||
"fr": "Syntaxe invalide. Initier l'incinération.",
|
||||
"it": "Sintassi non valida. Iniziare incenerimento"
|
||||
"de": "Syntax ungültig. Verbrennung einleiten"
|
||||
},
|
||||
"usage": {
|
||||
"en": "Usage for {command}: {usage}.",
|
||||
"na'vi": "Nga tsun sivar ìlä {command}: {usage}.",
|
||||
"cy": "Defnydd o {command}: {usage}.",
|
||||
"nl": "{command} wordt op de volgende manier gebruikt: {usage}.",
|
||||
"de": "Benutzung von {command}: [usage}.",
|
||||
"fr": "Utilisation de {command}: {usage}.",
|
||||
"it": "Utilizzo di {command}: {usage}."
|
||||
"de": "Benutzung von {command}: [usage}."
|
||||
},
|
||||
"no_usage_info": {
|
||||
"en": "No usage information found for {command}.",
|
||||
"na'vi": "Oel ke tsun sivar {comamnd}it",
|
||||
"cy": "Ni chanfuwyd gwybodaeth am ddefnydd o {command}",
|
||||
"nl": "Geen gebruiksinformatie gevonden voor {command}.",
|
||||
"de": "Keine Gebrauchsanweisung gefunden für {command}.",
|
||||
"fr": "Aucune information d'utilisation trouvée pour {command}",
|
||||
"it": "Nessuna informazione d' utilizzo trovata per {command}"
|
||||
"de": "Keine Gebrauchsanweisung gefunden für {command}."
|
||||
},
|
||||
"help_link": {
|
||||
"en": "Help for {module}: {link}",
|
||||
"na'vi": "{module}ä srungìl {link} it tok",
|
||||
"cy": "Cymorth am {module}: {link}",
|
||||
"nl": "Hulp voor {module}: {link}",
|
||||
"de": "Hilfe für {module}: {link}",
|
||||
"fr": "Aide pour {module}: {link}",
|
||||
"it": "Aiuto per {module}: {link}"
|
||||
"de": "Hilfe für {module}: {link}"
|
||||
},
|
||||
"no_help": {
|
||||
"en": "No help found for {module}.",
|
||||
"na'vi": "Fì{module}ìri oel ke tsun run srungit",
|
||||
"cy": "Ni chanfuwyd cymorth am {module}",
|
||||
"nl": "Geen hulp gevonden voor {module}.",
|
||||
"de": "Keine Hilfe gefunden für {module}.",
|
||||
"fr": "Aucune aide trouvée pour {module}.",
|
||||
"it": "Nessun aiuto trovato per {module}."
|
||||
"de": "Keine Hilfe gefunden für {module}."
|
||||
},
|
||||
"loaded_modules": {
|
||||
"en": "Loaded modules: {modules}.",
|
||||
"cy": "Modiwlau sy'n lwythodd: {modules}.",
|
||||
"nl": "Geladen modules: {modules}.",
|
||||
"de": "Module geladen: {modules}.",
|
||||
"fr": "Modules chargés: {modules}.",
|
||||
"it": "Moduli caricati: {modules}."
|
||||
},
|
||||
"access_denied": {
|
||||
"en": "{user}: You don't have the access level to run this command.",
|
||||
"fr": "{user}: Vous n'avez pas le niveau d'accès requis pour utiliser cette commande.",
|
||||
"it": "{user}: Non hai il livello d'accesso neccessario per utilizzare questo commando.",
|
||||
"de": "{user}: Du hast nicht die notwendigen Rechte um diesen Befehl zu benutzen."
|
||||
"de": "Module geladen: {modules}."
|
||||
},
|
||||
"module_commands": {
|
||||
"en": "Commands in {module}: {commands}.",
|
||||
"fr": "Commandes de {module}: {commands}.",
|
||||
"it": "Commandi di {module}: {commands}.",
|
||||
"de": "Befehle in {module}: {commands}."
|
||||
"en": "Commands in {module}: {commands}."
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
## Crypto
|
||||
|
||||
Cryptography!
|
||||
|
||||
### Description
|
||||
This module calculates different hashes or ciphertexts for some algorithms.
|
||||
|
||||
### Commands
|
||||
|
||||
#### ~hash [algorithm] [text]
|
||||
Calculate the hash of the given text using [algorithm].
|
||||
|
||||
#### ~random [number]
|
||||
Gives [number] bytes of cryptographically strong pseudo-random data as hex string.
|
||||
|
@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Module Name: Crypto
|
||||
* Description: Allows the magic of cryptography to take place.
|
||||
*/
|
||||
|
||||
var cr = require('crypto');
|
||||
|
||||
var crypto = function(dbot) {
|
||||
this.commands = {
|
||||
'~hash': function(event) {
|
||||
var hash = event.params[1];
|
||||
try {
|
||||
var h = cr.createHash(hash);
|
||||
var tohash = event.params.splice(2, event.params.length-1).join(' ');
|
||||
h.update(tohash);
|
||||
event.reply(hash+" of \""+tohash+"\" is: "+h.digest('hex'));
|
||||
} catch(err) {
|
||||
event.reply(err);
|
||||
}
|
||||
},
|
||||
'~randomdata': function(event) {
|
||||
try {
|
||||
var count = parseInt(event.params[1]);
|
||||
if(count > 222) {
|
||||
event.reply("Sorry man, I can't paste that much random data.");
|
||||
return;
|
||||
}
|
||||
cr.randomBytes(count, function(err,buf) {
|
||||
if(err) {
|
||||
event.reply(err);
|
||||
return;
|
||||
}
|
||||
event.reply(buf.toString('hex'));
|
||||
});
|
||||
} catch (err) {
|
||||
event.reply(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new crypto(dbot);
|
||||
};
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"~md5": "~md5 [text]",
|
||||
"~sha1": "~sha1 [text]",
|
||||
"~sha256": "~sha256 [text]",
|
||||
"~aes": "~aes \"[text]\" \"[key]\""
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"outputChannel": "#realitree"
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var cspeed = function(dbot) {
|
||||
this.watches = dbot.db.cspeed;
|
||||
this.outputChannel = dbot.config.modules.cspeed.outputChannel;
|
||||
this.counts = {};
|
||||
|
||||
this.api = {
|
||||
'getCounts': function(callback) {
|
||||
callback(this.counts);
|
||||
}
|
||||
};
|
||||
this.api['getCounts'].external = true;
|
||||
this.api['getCounts'].extMap = [ 'callback' ];
|
||||
|
||||
this.commands = {
|
||||
'addlpmwatch': function(event) {
|
||||
var channel = event.params[1];
|
||||
var key = event.server + '.' + channel;
|
||||
|
||||
if(!_.has(this.watches, key)) {
|
||||
this.watches[key] = {
|
||||
'server': event.server,
|
||||
'channel': channel
|
||||
}; // to be extended with warn nums etc
|
||||
|
||||
this.counts[key] = 0;
|
||||
dbot.api.timers.addTimer(60000, function() {
|
||||
dbot.say(event.server, this.outputChannel, channel + ' currently : ' + this.counts[key] + ' LPM');
|
||||
this.counts[key] = 0;
|
||||
}.bind(this));
|
||||
|
||||
event.reply('Added speed watch for ' + channel);
|
||||
} else {
|
||||
event.reply('Already watching that channel');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.listener = function(event) {
|
||||
var key = event.server + '.' + event.channel;
|
||||
if(_.has(this.watches, key)) {
|
||||
this.counts[key]++;
|
||||
}
|
||||
}.bind(this);
|
||||
this.on = 'PRIVMSG';
|
||||
|
||||
this.onLoad = function() {
|
||||
var watches = dbot.db.cspeed;
|
||||
_.each(watches, function(watch) {
|
||||
var key = watch.server + '.' + watch.channel;
|
||||
this.counts[key] = 0;
|
||||
dbot.api.timers.addTimer(60000, function() {
|
||||
dbot.say(watch.server, dbot.db.cspeed.outputChannel, watch.channel + ': ' + this.counts[key] + 'LPM');
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new cspeed(dbot);
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
{
|
||||
"ignorable": true
|
||||
"ignorable": true,
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/ctcp/README.md"
|
||||
}
|
||||
|
@ -1,36 +1,22 @@
|
||||
var ctcp = function(dbot) {
|
||||
this.listener = function(event) {
|
||||
var matches = event.message.match(/\u0001[\w]+\u0001/);
|
||||
if(matches) {
|
||||
// We need the CTCP command
|
||||
var question = matches[0];
|
||||
// Cut \u0001 characters from command
|
||||
question = question.slice(1,question.length-1);
|
||||
switch(question) {
|
||||
case 'CLIENTINFO':
|
||||
event.replyNotice("\u0001CLIENTINFO SOURCE VERSION USERINFO\u0001");
|
||||
break;
|
||||
case 'FINGER':
|
||||
event.replyNotice("\u0001FINGER STOP FINGERING ME BRO\u0001");
|
||||
break;
|
||||
case 'SOURCE':
|
||||
event.replyNotice("\u0001SOURCE "+dbot.config.repoRoot+"\u0001");
|
||||
break;
|
||||
case 'TIME':
|
||||
var d = new Date();
|
||||
event.replyNotice("\u0001TIME "+d.toISOString()+"\u0001");
|
||||
break;
|
||||
case 'USERINFO':
|
||||
event.replyNotice("\u0001USERINFO "+dbot.config.name+"\u0001");
|
||||
break;
|
||||
case 'VERSION':
|
||||
event.replyNotice("\u0001VERSION "+dbot.config.version+"\u0001");
|
||||
break;
|
||||
default:
|
||||
event.replyNotice("\u0001"+question+" Idk what you want. Try CLIENTINFO.\u0001");
|
||||
}
|
||||
var commands = {
|
||||
"\x01VERSION\x01": function(event) {
|
||||
// the current client version
|
||||
event.replyNotice("\x01VERSION " + dbot.config.version + "\x01");
|
||||
},
|
||||
"\x01CLIENTINFO\x01": function(event){
|
||||
// a list of all supported CTCP commands
|
||||
event.replyNotice("\x01CLIENTINFO SOURCE VERSION USERINFO\x01");
|
||||
},
|
||||
"\x01SOURCE\x01": function(event){
|
||||
event.replyNotice("\x01SOURCE https://github.com/reality/depressionbot\x01");
|
||||
},
|
||||
"\x01USERINFO\x01": function(event){
|
||||
// a "witty" saying set by the user
|
||||
event.replyNotice("\z01USERINFO " + dbot.config.name + "\x01");
|
||||
}
|
||||
};
|
||||
}
|
||||
this.commands = commands;
|
||||
this.on = 'PRIVMSG';
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"username": "youruserhere",
|
||||
"password": "yourpasswordhere",
|
||||
"dependencies": [ "link" ],
|
||||
"dependencies": [ "command" ],
|
||||
"ignorable": true,
|
||||
"dentQuotes": true,
|
||||
"api": "http://quitter.se/"
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/dent/README.md",
|
||||
"dentQuotes": false
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ var request = require('request');
|
||||
_ = require('underscore')._;
|
||||
|
||||
var dent = function(dbot) {
|
||||
this.dbot = dbot;
|
||||
this.StatusRegex = {
|
||||
identica: /\bhttps?:\/\/identi\.ca\/notice\/(\d+)\b/ig,
|
||||
twitter: /\bhttps?:\/\/twitter\.com\/\w+\/status\/(\d+)\b/ig
|
||||
@ -14,14 +15,14 @@ var dent = function(dbot) {
|
||||
|
||||
this.api = {
|
||||
'post': function(content) {
|
||||
var username = this.config.username,
|
||||
password = this.config.password,
|
||||
var username = dbot.config.dent.username,
|
||||
password = dbot.config.dent.password,
|
||||
info,
|
||||
auth = "Basic " +
|
||||
new Buffer(username + ":" + password).toString("base64");
|
||||
|
||||
request.post({
|
||||
'url': this.config.api + '/statuses/update.json?status=' +
|
||||
'url': 'http://identi.ca/api/statuses/update.json?status=' +
|
||||
escape(content),
|
||||
'headers': {
|
||||
'Authorization': auth
|
||||
@ -33,7 +34,7 @@ var dent = function(dbot) {
|
||||
}
|
||||
};
|
||||
|
||||
this.lookup = function(id, service, callback) {
|
||||
this.lookup = function(event, id, service) {
|
||||
request({
|
||||
url: this.StatusAPI[service],
|
||||
qs: {"id": id},
|
||||
@ -41,7 +42,7 @@ var dent = function(dbot) {
|
||||
}, function(error, response, body) {
|
||||
if (!error && response.statusCode == 200) {
|
||||
if (_.has(body, 'text')) {
|
||||
callback(service + " [" + body.user.screen_name + '] ' + body.text);
|
||||
event.reply(service + " [" + body.user.screen_name + '] ' + body.text);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -53,11 +54,11 @@ var dent = function(dbot) {
|
||||
event.reply('Dent posted (probably).');
|
||||
}
|
||||
};
|
||||
this.commands['~dent'].regex = [/^dent (.+)$/, 2];
|
||||
this.commands['~dent'].regex = [/^~dent (.+)$/, 2];
|
||||
|
||||
this.onLoad = function() {
|
||||
if(this.config.dentQuotes === true && _.has(dbot.modules, 'quotes')) {
|
||||
dbot.api.event.addHook('qadd', function(key, text) {
|
||||
if(dbot.config.dent.dentQuotes === true && _.has(dbot.modules, 'quotes')) {
|
||||
dbot.api.command.addHook('~qadd', function(key, text) {
|
||||
if(text.indexOf('~~') == -1) {
|
||||
this.api.post(key + ': ' + text);
|
||||
}
|
||||
@ -65,8 +66,8 @@ var dent = function(dbot) {
|
||||
}
|
||||
|
||||
for(s in this.StatusRegex) {
|
||||
dbot.api.link.addHandler(s, this.StatusRegex[s], function(matches, name, callback) {
|
||||
this.lookup(matches[1], name, callback);
|
||||
dbot.api.link.addHandler(s, this.StatusRegex[s], function(event, matches, name) {
|
||||
this.lookup(event, matches[1], name);
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this);
|
||||
|
@ -17,14 +17,14 @@ var parseDiceSpec = function (specString) {
|
||||
var normalizeDiceSpec = function (specString) {
|
||||
var diceSpec = parseDiceSpec(specString);
|
||||
|
||||
if (diceSpec["sides"] > 10000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (diceSpec["count"] > 1000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (diceSpec["sides"] > 10000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (diceSpec["count"] > 1000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (diceSpec["count"] > 1) {
|
||||
var count = diceSpec["count"];
|
||||
} else {
|
||||
@ -74,7 +74,7 @@ var dice = function(dbot) {
|
||||
event.reply(rolls[i][0] + ": invalid dice spec");
|
||||
} else {
|
||||
if (rolls[i][1].length > 1) {
|
||||
var total = " (total " + _.reduce(rolls[i][1], function(memo, num){ return memo + num; }, 0);
|
||||
var total = " (total " + rolls[i][1].sum();
|
||||
if (rolls[i][2] != 0) {
|
||||
if (rolls[i][2] > 0) {
|
||||
total += " + ";
|
||||
|
3
modules/dns/config.json
Normal file
3
modules/dns/config.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/dns/README.md"
|
||||
}
|
@ -2,40 +2,13 @@
|
||||
* Module Name: DNS
|
||||
* Description: Performs and reports on basic DNS functions.
|
||||
*/
|
||||
var dnsm = require('dns'),
|
||||
request = require('request'),
|
||||
http = require('http');
|
||||
var dnsmod = require('dns');
|
||||
|
||||
var dns = function(dbot) {
|
||||
if(!_.has(dbot.db, 'ip')) {
|
||||
dbot.db.ip = {};
|
||||
}
|
||||
var ips = dbot.db.ip;
|
||||
|
||||
this.api = {
|
||||
'getGeoIp': function(ip, callback) {
|
||||
if(_.has(ips, ip)) {
|
||||
body = ips[ip];
|
||||
callback(ip + ' is located in '+ body.city + ', ' + body.country + '. Hostname: ' + body.hostname + '. ISP: ' + body.org);
|
||||
} else {
|
||||
request.get('http://ipinfo.io/'+ip, {
|
||||
'json': true
|
||||
}, function(err, res, body) {
|
||||
if(!err && body) {
|
||||
callback(ip + ' is located in '+ body.city + ', ' + body.country + '. Hostname: ' + body.hostname + '. ISP: ' + body.org);
|
||||
} else {
|
||||
callback('No info about ' + ip);
|
||||
}
|
||||
ips[ip] = body;
|
||||
});
|
||||
}
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
var commands = {
|
||||
'~lookup': function(event) {
|
||||
domain = event.params[1];
|
||||
dnsm.lookup(domain, function (error, addr) {
|
||||
dnsmod.lookup(domain, function (error, addr) {
|
||||
if (error) {
|
||||
event.reply(dbot.t("lookup-error",{"domain": domain, "code": error.code}));
|
||||
} else {
|
||||
@ -43,52 +16,20 @@ var dns = function(dbot) {
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'~rdns': function(event) {
|
||||
ip = event.params[1];
|
||||
dnsm.reverse(ip, function (error, domain) {
|
||||
dnsmod.reverse(ip, function (error, domain) {
|
||||
if (error) {
|
||||
event.reply(dbot.t("rdns-error",{"domain": domain, "ip": ip, "error": error.code}));
|
||||
} else {
|
||||
event.reply(dbot.t("rdns",{"domain": domain, "ip": ip}));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'~geoip': function(event) {
|
||||
var ip = event.params[1];
|
||||
this.api.getGeoIp(ip, function(result) { event.reply(result); });
|
||||
},
|
||||
|
||||
'~dnsbl': function(event) {
|
||||
var revIp = event.input[1].trim().split('.').reverse().join('.');
|
||||
dnsm.lookup(revIp + '.cbl.abuseat.org', function(err, res) {
|
||||
if(!err && res) {
|
||||
event.reply(event.input[1] + ' is listed as an abusive IP.');
|
||||
} else {
|
||||
event.reply(event.input[1] + ' does not seem to be a Naughty Nancy.');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
commands['~dnsbl'].regex = [/^dnsbl ([\d\w\s\.-]*)/, 2];
|
||||
this.commands = commands;
|
||||
|
||||
if(dbot.config.modules.dns.dnsblconn == true) {
|
||||
this.listener = function(event) {
|
||||
if(event.message.match('CLICONN')) {
|
||||
var ip = event.message.match('CLICONN ([^ ]+).*?((?:[0-9]{1,3}\.){3}[0-9]{1,3}) users');
|
||||
revIp = ip[2].trim().split('.').reverse().join('.');
|
||||
dbot.say(event.server, '#dnsbl', 'DEBUG: Looking up ' + ip[2] + ' for ' + ip[1] + ' @ ' + revIp);
|
||||
dnsm.lookup(revIp + '.cbl.abuseat.org', function(err, res) {
|
||||
if(!err && res) {
|
||||
dbot.say(event.server, '#dnsbl', 'ALERT: ' + ip[1] + ' connecting from ' + ip[2] + ' may well be NAUGHTY.');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
this.on = 'NOTICE';
|
||||
}
|
||||
this.on = 'PRIVMSG';
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
|
@ -3,30 +3,21 @@
|
||||
"en": "{domain} is \u000303AVAILABLE! \u000314({code})",
|
||||
"cy": "{domain} \u000303AR GAEL! \u000314({code})",
|
||||
"nl": "{domain} is \u000303BESCHIKBAAR! \u000314({code})",
|
||||
"de": "{domain} ist \u000303VERFÜGBAR! \u000314({code})",
|
||||
"fr": "{domain} est \u000303DISPONIBLE! \u000314({code})",
|
||||
"it": "{domain} è \u000303DISPONIBILE! \u000314({code})"
|
||||
"de": "{domain} ist \u000303VERFÜGBAR! \u000314({code})"
|
||||
},
|
||||
"lookup": {
|
||||
"en": "{domain} is \u000305TAKEN! \u000314({address})",
|
||||
"cy": "Dydy {domain} \u000305DDIM AR GAEL! \u000314({address})",
|
||||
"nl": "{domain} is \u000305BEZET! \u000314({address})",
|
||||
"de": "{domain} ist \u000305BELEGT! \u000314({address})",
|
||||
"fr": "{domain} est \u000305PRIS! \u000314({address})",
|
||||
"it": "{domain} èt \u000305RISERVATO! \u000314({address})"
|
||||
"de": "{domain} ist \u000305BELEGT! \u000314({address})"
|
||||
},
|
||||
"rdns": {
|
||||
"en": "{ip} \u2192 {domain}",
|
||||
"fr": "{ip} \u2192 {domain}",
|
||||
"it": "{ip} \u2192 {domain}",
|
||||
"de":"{ip} \u2192 {domain}"
|
||||
"en": "{ip} \u2192 {domain}"
|
||||
},
|
||||
"rdns-error": {
|
||||
"en": "Unable to lookup {ip}. \u000314({error})",
|
||||
"cy": "Methu am-edrych {ip}. \u000314({error})",
|
||||
"nl": "{ip} kan niet worden opgezocht. \u000314({error})",
|
||||
"de": "Kann {ip} nicht auflösen. \u000314({error})",
|
||||
"fr": "Impossible de rechercher {ip}. \u000314({error})",
|
||||
"it": "Non è possibile cercare {ip}. \u000314({error})"
|
||||
"de": "Kann {ip} nicht auflösen. \u000314({error})"
|
||||
}
|
||||
}
|
||||
|
3
modules/event/config.json
Normal file
3
modules/event/config.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/event/README.md"
|
||||
}
|
3
modules/flashy/config.json
Normal file
3
modules/flashy/config.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"help": "https://github.com/reality/depressionbot/blob/master/modules/flashy/README.md"
|
||||
}
|
@ -37,7 +37,7 @@ var flashy = function(dbot) {
|
||||
}
|
||||
};
|
||||
|
||||
this.commands['~flashy'].regex = [/^flashy ([^ ]+) (.+)$/, 3];
|
||||
this.commands['~flashy'].regex = [/^~flashy ([^ ]+) (.+)$/, 3];
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
|
@ -10,7 +10,7 @@ var pages = function(dbot) {
|
||||
res.render('flashy', {
|
||||
'name': dbot.config.name,
|
||||
'colour': colour,
|
||||
'text': decodeURIComponent(req.params.text)
|
||||
'text': req.params.text
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"outputPrefix": "\u000311food\u000f",
|
||||
"api_key": "http://food2fork.com/about/api"
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/**
|
||||
* Module name: Food
|
||||
* Description: recipe search
|
||||
*/
|
||||
|
||||
var _ = require('underscore')._,
|
||||
request = require('request');
|
||||
|
||||
var food = function(dbot) {
|
||||
this.commands = {
|
||||
'~recipe': function(event) {
|
||||
request.get('http://food2fork.com/api/search', {
|
||||
'qs': {
|
||||
'key': this.config.api_key,
|
||||
'q': event.input[1]
|
||||
},
|
||||
'json': true
|
||||
}, function(error, response, body) {
|
||||
if(_.isObject(body) && _.has(body, 'recipes') && body.recipes.length > 0) {
|
||||
var num = _.random(0, body.recipes.length - 1),
|
||||
recipe = body.recipes[num];
|
||||
|
||||
event.reply(dbot.t('recipe', {
|
||||
'title': recipe.title,
|
||||
'link': recipe.source_url
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('no_recipe'));
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
this.commands['~recipe'].regex = [/^recipe (.+)$/, 2];
|
||||
|
||||
this.listener = function(event) {
|
||||
var match = event.message.match(new RegExp(dbot.config.name + ': what should i (have|eat|make)\\??( for (dinner|lunch|breakfast))?\\??', 'i'));
|
||||
if(match) {
|
||||
var page = _.random(0, 200);
|
||||
request.get('http://food2fork.com/api/search', {
|
||||
'qs': {
|
||||
'key': this.config.api_key,
|
||||
'page': page
|
||||
},
|
||||
'json': true
|
||||
}, function(error, response, body) {
|
||||
if(_.isObject(body) && _.has(body, 'recipes') && body.recipes.length > 0) {
|
||||
var num = _.random(0, body.recipes.length - 1),
|
||||
recipe = body.recipes[num];
|
||||
|
||||
event.reply(event.user + ': You should make ' + recipe.title + '. See: ' + recipe.source_url);
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this);
|
||||
this.on = 'PRIVMSG';
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new food(dbot);
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"recipe": {
|
||||
"en": "{title} - {link}"
|
||||
},
|
||||
"no_recipe": {
|
||||
"en": "No recipes found."
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
## 500px
|
||||
|
||||
Adds various 500px functionality.
|
||||
|
||||
### Description
|
||||
|
||||
This module provides a command which allows users to search for a random popular 500px photo.
|
||||
|
||||
### Dependencies
|
||||
|
||||
It has following dependencies:
|
||||
+ [node-500px](https://github.com/ro-ka/node-500px)
|
||||
|
||||
### config.json
|
||||
|
||||
ignorable and consumerKey has to be configurated. It can be obtained at http://developers.500px.com
|
||||
```
|
||||
{
|
||||
"ignorable": true,
|
||||
"api_key": "CONSUMERKEY_HERE"
|
||||
}
|
||||
```
|
||||
|
||||
### Commands
|
||||
|
||||
|
||||
~r500px
|
||||
Responds with a random popular 500px photo.
|
||||
Example:
|
||||
+ ~r500px
|
||||
|
||||
### TODO
|
||||
|
||||
Photo by user etc.
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"ignorable": true,
|
||||
"api_key": "CONSUMERKEY_HERE"
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/**
|
||||
* Module Name: 500px
|
||||
* Description: Adds various 500px functionality.
|
||||
* Requires: node-500px [http://mjgil.github.io/five-px/]
|
||||
*/
|
||||
|
||||
var _ = require('underscore')._,
|
||||
API500px = require('500px').API500px;
|
||||
|
||||
var fpx = function(dbot) {
|
||||
this.commands = {
|
||||
'~r500px': function(event) {
|
||||
var random = Math.floor(Math.random() * 30);
|
||||
this.api500px.photos.getPopular({'sort': 'created_at', 'rpp': '30'}, function(error, results) {
|
||||
if (error) {
|
||||
event.reply(dbot.t('5px_error'));
|
||||
console.log(error);
|
||||
} else {
|
||||
var name = results.photos[random].name,
|
||||
id = results.photos[random].id;
|
||||
event.reply(dbot.t('5px_result',{'name':name,'id':id}));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
this.onLoad = function() {
|
||||
this.api500px = new API500px(this.config.api_key);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new fpx(dbot);
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"5px_result":{
|
||||
"en": "{name} - http://500px.com/photo/{id}"
|
||||
},
|
||||
"5px_error": {
|
||||
"en": "Something went wrong :( Example: '~r500px'"
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"~r500px": "~r500px"
|
||||
}
|
1
modules/github
Submodule
1
modules/github
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 5f4e3dc8335000e97af528fee289b880a3c99e81
|
@ -1,18 +0,0 @@
|
||||
Copyright (c) 2013 Douglas Gardner <douglas@chippy.ch>
|
||||
|
||||
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.
|
@ -1,28 +0,0 @@
|
||||
## Github
|
||||
|
||||
Grabs interesting data from the GitHub API.
|
||||
|
||||
### Description
|
||||
|
||||
This module for [depressionbot](https://github.com/reality/depressionbot) takes some interesting information about Github and parses it in a pleasing manner.
|
||||
|
||||
### Configuration
|
||||
#### defaultrepo
|
||||
When repository information is lacking from the command, this repository will be used.
|
||||
#### sortorder
|
||||
Defines the behaviour of ~issue when no arguments are given. Options are ``created``, ``updated``, or ``comments``.
|
||||
### Commands
|
||||
#### ~commits
|
||||
Returns the number of commits in the repository of the current depressionbot instance.
|
||||
#### ~gstatus
|
||||
Returns the [current status of Github](https://status.github.com), and a message explaining the current state of affairs.
|
||||
#### ~issue (user/repo) [id]
|
||||
Gives information about the isse pecified, from the default repository if one is not explicitly stated.
|
||||
#### ~milestone [milestone name]
|
||||
Returns milestone progress for any given milestone, with a link to the milestone in question.
|
||||
#### ~repo (repo name)
|
||||
Returns information about the repo given as a parameter. The repo should be specified as ``user/name``; for example, ``twitter/snowflake``.
|
||||
#### ~repocount [user]
|
||||
Returns the number of public Github repositories for the specified user.
|
||||
### Dependencies
|
||||
* [request](https://github.com/mikeal/request/):``$ npm install request``
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"dependencies": [ "command" ],
|
||||
"ignorable": true,
|
||||
"help": "http://github.com/zuzak/dbot-github/blob/master/README.md",
|
||||
"defaultrepo": "reality/dbot",
|
||||
"sortorder": "updated",
|
||||
"useragent": "reality/depressionbot github module"
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
/**
|
||||
* Module Name: Github
|
||||
* Description: Retrieves interesting Github information
|
||||
*/
|
||||
var request = require('request'),
|
||||
exec = require('child_process').exec;
|
||||
|
||||
var github = function(dbot) {
|
||||
this.api = {
|
||||
"githubStatus": function(callback){
|
||||
var reqUrl = "https://status.github.com/api/last-message.json";
|
||||
request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
callback(JSON.parse(body));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var commands = {
|
||||
'~repocount': function(event) {
|
||||
var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos";
|
||||
request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
if(response.statusCode == "200") {
|
||||
var result = JSON.parse(body);
|
||||
event.reply(dbot.t("repocount",{"user": event.params[1], "count": result.length}));
|
||||
} else {
|
||||
event.reply(dbot.t("usernotfound"));
|
||||
}
|
||||
});
|
||||
},
|
||||
'~repo': function(event) {
|
||||
var repo = event.params[1];
|
||||
if (typeof repo == 'undefined') {
|
||||
repo = this.config.defaultrepo;
|
||||
}
|
||||
|
||||
var reqUrl = "https://api.github.com/";
|
||||
reqUrl += "repos/" + repo;
|
||||
request({"url": reqUrl, "headers": {"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
|
||||
var data = JSON.parse(body);
|
||||
if (data["fork"]) {
|
||||
event.reply(dbot.t("forkedrepo",data));
|
||||
} else {
|
||||
event.reply(dbot.t("unforkedrepo",data));
|
||||
}
|
||||
// TODO: move this shizz into an api call
|
||||
var longurl = "http://github.com/" + repo;
|
||||
event.reply(dbot.t('location')+" "+longurl);
|
||||
});
|
||||
},
|
||||
'~gstatus': function(event) {
|
||||
data = this.api.githubStatus(function(data){
|
||||
event.reply(dbot.t("status"+data["status"]));
|
||||
event.reply(data["body"]);
|
||||
}.bind(this));
|
||||
},
|
||||
'~milestone': function(event) {
|
||||
var repo = this.config.defaultrepo;
|
||||
var name = event.params[1];
|
||||
if (event.params[2]){
|
||||
repo = name;
|
||||
name = event.params[2];
|
||||
}
|
||||
var reqUrl = "https://api.github.com/repos/";
|
||||
reqUrl += repo + "/milestones";
|
||||
|
||||
request({"url": reqUrl, "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
var data = JSON.parse(body);
|
||||
for (var section in data) {
|
||||
var milestone = data[section];
|
||||
if (milestone["title"] == name){
|
||||
var str = "Milestone " + milestone["title"];
|
||||
var progress = milestone["closed_issues"] / (milestone["open_issues"] + milestone["closed_issues"]);
|
||||
progress = Math.round(progress*100);
|
||||
var bar = "[";
|
||||
for (var i = 10; i < 100; i += 10) {
|
||||
if ((progress/i) > 1) {
|
||||
bar += "█";
|
||||
} else {
|
||||
bar += " ";
|
||||
}
|
||||
}
|
||||
bar += "]";
|
||||
str += " is " + bar + progress + "% complete";
|
||||
|
||||
event.reply(str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
'~repocount': function(event) {
|
||||
// TODO: add handling for non existent user
|
||||
var reqUrl = "https://api.github.com/users/" + event.params[1] + "/repos";
|
||||
request({"url": reqUrl,"headers": { "User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
var result = JSON.parse(body);
|
||||
event.reply(event.params[1] + " has " + result.length + " public repositories.");
|
||||
});
|
||||
},
|
||||
'~grate': function(event) {
|
||||
request.get({"url":"https://api.github.com/rate_limit", "headers":{"User-Agent": this.config.useragent}}, function(error, response, body) {
|
||||
var data = JSON.parse(body);
|
||||
if (data.message){
|
||||
event.reply(data.message);
|
||||
} else {
|
||||
event.reply(data.rate.remaining + " requests of " + data.rate.limit + " remaining.");
|
||||
}
|
||||
});
|
||||
},
|
||||
'~issue': function(event) {
|
||||
var repo, issue, randflag;
|
||||
if (isNaN(event.params[1]) && event.params[1]){ // if ~issue foo/bar
|
||||
repo = event.params[1];
|
||||
issue = event.params[2];
|
||||
} else {
|
||||
repo = this.config.defaultrepo;
|
||||
issue = event.params[1];
|
||||
}
|
||||
|
||||
if (issue == "*" || issue == "random" || issue == "0") {
|
||||
issue = "";
|
||||
randflag = true;
|
||||
} else if (!issue) { // issue is undefined
|
||||
issue = "";
|
||||
} else {
|
||||
issue = "/" + issue; // got to be a better way
|
||||
}
|
||||
|
||||
var reqUrl = "https://api.github.com/repos/" + repo + "/issues" +
|
||||
issue + "?sort=" + this.config.sortorder;
|
||||
request.get({"url": reqUrl, headers: { "User-Agent": this.config.useragent}}, function(error,response, body) {
|
||||
if (response.statusCode == "200") {
|
||||
var data = JSON.parse(body);
|
||||
if (!issue){
|
||||
if (randflag) {
|
||||
data = data[Math.floor(Math.random() * data.length)];
|
||||
} else {
|
||||
data = data[0];
|
||||
}
|
||||
}
|
||||
if (_.has(data["pull_request"], "html_url")){
|
||||
data["pull_request"] = " with code";
|
||||
} else {
|
||||
data["pull_request"] = "";
|
||||
}
|
||||
if (data["state"]=="open") {
|
||||
data["state"] = "\u000303" + data["state"];
|
||||
} else {
|
||||
data["state"] = "\u000304" + data["state"];
|
||||
}
|
||||
var labels = "";
|
||||
for (var i=0; i < data["labels"].length; i++) { // for-in doesn't like me
|
||||
var color = "\u0003" + (parseInt(data["labels"][i]["color"],16) % 15);
|
||||
labels += " " + color + data["labels"][i]["name"];
|
||||
}
|
||||
data["label"] = labels;
|
||||
event.reply(dbot.t("issue",data));
|
||||
event.reply(data["html_url"]);
|
||||
} else {
|
||||
event.reply(dbot.t("issuenotfound"));
|
||||
}
|
||||
});
|
||||
},
|
||||
'~commits': function(event) {
|
||||
exec("git rev-list --all | wc -l", function(error, stdout, stderr) {
|
||||
stdout = stdout.trim();
|
||||
request({"url":"http://numbersapi.com/" + stdout + "?fragment&default=XXX"}, function(error, response, body){
|
||||
if (body != "XXX"){
|
||||
event.reply(dbot.t("commitcountfun",{"fact": body, "count": stdout}));
|
||||
} else {
|
||||
// nothing fun about the number, let's try the year
|
||||
request({"url":"http://numbersapi.com/" + stdout + "/year?fragment&default=XXX"}, function(error, response, body){
|
||||
if (body != "XXX"){
|
||||
event.reply(dbot.t("commitcountyear",{"fact": body, "count": stdout}));
|
||||
} else {
|
||||
event.reply(dbot.t("commitcountboring",{"count": stdout}));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
this.commands = commands;
|
||||
|
||||
this.on = 'PRIVMSG';
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new github(dbot);
|
||||
};
|
@ -1,94 +0,0 @@
|
||||
{
|
||||
"repocount": {
|
||||
"en": "{user} has {count} public repos.",
|
||||
"cy": "Mae {count} archifdai cyhoeddus gan {user}.",
|
||||
"de": "{user} hat {count} öffnetliche Repos.",
|
||||
"fr": "{user} a {count} dépôt(s) public(s).",
|
||||
"it": "{user} ha {count} deposito/i pubblico/i."
|
||||
},
|
||||
"statusgood": {
|
||||
"en": "\u000309Shit's fine",
|
||||
"cy": "\u000309Cachu'n ddirwy",
|
||||
"de": "\u000309Alles in Ordnung",
|
||||
"fr": "\u000309Cette merde tourne bien",
|
||||
"it": "\u000309Funziona a meraviglia."
|
||||
},
|
||||
"statusminor": {
|
||||
"en": "\u000308Shit's touchy",
|
||||
"cy": "\u000308Cachu'n fregus",
|
||||
"de": "\u000308Kleinere Probleme vorhanden",
|
||||
"fr": "\u000308Cette merde a un petit problème",
|
||||
"it": "\u000308Piccoli problemi all' orizzonte"
|
||||
},
|
||||
"statusmajor": {
|
||||
"en": "\u000304Shit's fucked:",
|
||||
"cy": "\u000304Cachu wedi cyrraedd y ffan:",
|
||||
"de": "\u000304Du bist am Arsch",
|
||||
"fr": "\u000304Cette merde est foutue : ",
|
||||
"it": "\u000304Sei nella merda : "
|
||||
},
|
||||
"location": {
|
||||
"en": "You can find that shit at:",
|
||||
"cy": "Gallwch ddod o hyd y cachu yn:",
|
||||
"de": "Kann gefunden werden unter:",
|
||||
"fr": "Tu peux trouver cette merde ici : ",
|
||||
"it": "Puoi trovare questa coglionata a: "
|
||||
},
|
||||
"forkedrepo": {
|
||||
"en": "{name} is a forked {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]",
|
||||
"cy": "{name} ydy archif {language} fforchog gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]",
|
||||
"de": "{name} ist eine geteilte {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]",
|
||||
"fr": "{name} est un dépôt fourché {language} avec {open_issues} problème(s) non résolu(s) [{forks}F {watchers}W]",
|
||||
"it": "{name} è un deposito biforcato {language} con {open_issues} problema/i irrisolto/i [{forks}F {watchers}W]"
|
||||
},
|
||||
"unforkedrepo": {
|
||||
"en": "{name} is a {language} repo with {open_issues} unresolved issues [{forks}F {watchers}W]",
|
||||
"cy": "{name} ydy archif {language} gyda {open_issues} materion heb eu datrys [{forks}F {watchers}W]",
|
||||
"de": "{name} ist eine {language} Repo mit {open_issues} ungelösten Problemen [{forks}F {watchers}W]",
|
||||
"fr": "{name} est un dépôt {language} avec {open_issues} problème(s) non résolu(s) [{forks}F {watchers}W]",
|
||||
"it": "{name} è un deposito {language} con {open_issues} problema/i irrisolto/i [{forks}F {watchers}W]"
|
||||
},
|
||||
"usernotfound": {
|
||||
"en": "User not found.",
|
||||
"cy": "Defnyddiwr heb ei ganfod.",
|
||||
"de": "Benutzer nicht gefunden.",
|
||||
"fr": "Utilisateur non trouvé.",
|
||||
"it": "Utente non trovato."
|
||||
},
|
||||
"issuenotfound": {
|
||||
"en": "Unable to find that issue.",
|
||||
"cy": "Wedi methu dod o hyd mater hwnnw",
|
||||
"de": "Kann dieses Problem nicht finden.",
|
||||
"fr": "Impossible de trouver ce problème.",
|
||||
"it": "Impossibile trovare questo problema."
|
||||
},
|
||||
"issue": {
|
||||
"en": "Issue \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}",
|
||||
"cy": "Mater \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} sylwadau]{label}",
|
||||
"de": "Problem \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} comments]{label}",
|
||||
"fr": "Problème \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} commentaires]{label}",
|
||||
"it": "Problema \u000308{number}\u0003: {title} [{state}{pull_request}\u000315; {comments} commento/i]{label}"
|
||||
},
|
||||
"commitcountboring": {
|
||||
"en": "My code has been committed {count} times.",
|
||||
"cy": "Mae fy cod wedi cael ei gyflawni ar {count} adegau.",
|
||||
"de": "Mein Code wurde {count} mal bestätigt.",
|
||||
"fr": "Mon code a été modifié {count} fois.",
|
||||
"it": "Il mio codice è stato modificato {count} volta/e."
|
||||
},
|
||||
"commitcountfun": {
|
||||
"en": "My repository has the same number of commits as {fact} ({count}).",
|
||||
"cy": "Yr un nifer o ymrwymo fel {fact} gan fy archif ({count}).",
|
||||
"de": "Meine Repository hat die gleiche Anzahl Commits wie {fact} ({count}).",
|
||||
"fr": "Mon dépôt a le même nombre de modifications que {fact} ({count}).",
|
||||
"it": "Il mio deposito ha lo stesso numero di modifiche come {fact} ({count})."
|
||||
},
|
||||
"commitcountyear": {
|
||||
"en": "My repository's commits number {count}, the year that {fact}.",
|
||||
"cy": "Nifer o ymrwymo gan fy archif: {count}, y flwyddyn y {fact}.",
|
||||
"de": "Anzahl der Commits in meinem Repository {count}, des Jahres {fact}",
|
||||
"fr": "Mon dépot compte {count} modifications, l'année où {fact}.",
|
||||
"it": "Il mio deposito ha {count} modifica/che, l' anno che {fact}."
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
/**
|
||||
* Module Name: Google Maps
|
||||
* Description: GMaps and ting
|
||||
*/
|
||||
var gm = require('googlemaps'),
|
||||
_ = require('underscore')._;
|
||||
|
||||
var gmaps = function(dbot) {
|
||||
this.commands = {
|
||||
'~from': function(event) {
|
||||
var from = event.input[1],
|
||||
to = event.input[2],
|
||||
departureNow = Math.floor((new Date()).getTime()/1000);
|
||||
|
||||
gm.directions(from, to, function(err, result) {
|
||||
if(!err && result && result.status !== 'ZERO_RESULTS') {
|
||||
event.reply('If you leave right now, it will take ' + result.routes[0].legs[0].duration.text + ' to get from ' + from + ' to ' + to + ' via public transport.');
|
||||
} else {
|
||||
event.reply('Apparently one cannot get from ' + from + ' to ' + to + ' using public transport. Do you accept the challenge?');
|
||||
}
|
||||
}, 'false', 'transit', null, null,null, null, null, departureNow);
|
||||
}
|
||||
};
|
||||
this.commands['~from'].regex = [/^from (.*) to (.*)/, 3];
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new gmaps(dbot);
|
||||
};
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"api_key": "sethere",
|
||||
"outputPrefix": "\u00033goodreads\u000f"
|
||||
}
|
@ -1,293 +0,0 @@
|
||||
/**
|
||||
* Module Name: GoodReads
|
||||
* Description: Interacts with the GoodReads API to provide book-oriented functionality to dbot
|
||||
*/
|
||||
|
||||
var util = require('util'),
|
||||
_ = require('underscore')._,
|
||||
rp = require('request-promise-native'),
|
||||
parseString = util.promisify(require('xml2js').parseString);
|
||||
|
||||
var GoodReads = function(dbot) {
|
||||
this.apiRoot = 'https://www.goodreads.com';
|
||||
|
||||
this.internalAPI = {
|
||||
'outputError': (evt, e) => {
|
||||
switch(e) {
|
||||
case 'goodreads-error': evt.reply('Error talking to GoodReads.'); return;
|
||||
case 'book-not-found': evt.reply(dbot.t('gr_nobook')); return;
|
||||
case 'no-description': evt.reply('No description was found for the book you asked for.'); return;
|
||||
case 'author-not-found': evt.reply(dbot.t('gr_noauthor')); return;
|
||||
}
|
||||
|
||||
console.log(e);
|
||||
evt.reply('Something went wrong and I don\'t know what.');
|
||||
},
|
||||
|
||||
'formatProfile': profile => {
|
||||
var shelves = {};
|
||||
_.each(profile.user_shelves.user_shelf, shelf => {
|
||||
shelves[shelf.name] = shelf.book_count['_'];
|
||||
});
|
||||
profile.user_shelves = shelves;
|
||||
return profile;
|
||||
}
|
||||
};
|
||||
|
||||
this.api = {
|
||||
'findBook': async term => {
|
||||
//https://www.goodreads.com/search/index.xml
|
||||
var body = await rp({
|
||||
uri: this.apiRoot + '/search/index.xml',
|
||||
qs: {
|
||||
key: this.config.api_key,
|
||||
q: term.split(' ').join('+')
|
||||
}
|
||||
});
|
||||
|
||||
var response = await parseString(body, { explicitArray: false });
|
||||
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
|
||||
|
||||
var result = response.GoodreadsResponse.search.results;
|
||||
if(!result || !_.has(result, 'work')) throw 'book-not-found';
|
||||
if(!result.work[0]) throw 'book-not-found';
|
||||
|
||||
return {
|
||||
id: result.work[0].best_book.id['_'],
|
||||
title: result.work[0].best_book.title,
|
||||
author: result.work[0].best_book.author.name,
|
||||
rating: result.work[0].average_rating
|
||||
};
|
||||
},
|
||||
|
||||
'getSummaryForBook': async id => {
|
||||
//https://www.goodreads.com/book/show.xml
|
||||
var body = await rp({
|
||||
uri: this.apiRoot + '/book/show.xml',
|
||||
qs: {
|
||||
key: this.config.api_key,
|
||||
id: id
|
||||
}
|
||||
});
|
||||
|
||||
var response = await parseString(body, { explicitArray: false });
|
||||
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
|
||||
|
||||
var result = response.GoodreadsResponse.book;
|
||||
if(!result) throw 'book-not-found';
|
||||
if(!_.has(result, 'description')) throw 'no-description';
|
||||
|
||||
return result.description;
|
||||
},
|
||||
|
||||
'findAuthor': async term => {
|
||||
//https://www.goodreads.com/api/author_url/<ID>
|
||||
var body = await rp({
|
||||
url: this.apiRoot + '/api/author_url/' + term,
|
||||
qs: {
|
||||
key: this.config.api_key
|
||||
}
|
||||
});
|
||||
|
||||
var response = await parseString(body, {explicitArray: false });
|
||||
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
|
||||
|
||||
var result = response.GoodreadsResponse.author;
|
||||
if(!result) throw 'author-not-found';
|
||||
|
||||
return {
|
||||
id: result['$'].id,
|
||||
author: result.name
|
||||
};
|
||||
},
|
||||
|
||||
'getProfileById': async id => {
|
||||
//https://www.goodreads.com/user/show.xml
|
||||
try {
|
||||
var body = await rp({
|
||||
url: this.apiRoot + '/user/show.xml',
|
||||
qs: {
|
||||
key: this.config.api_key,
|
||||
id: id
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
if(e.statusCode && e.statusCode == 404) {
|
||||
throw 'user-not-found';
|
||||
return;
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
var response = await parseString(body, { explicitArray: false });
|
||||
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
|
||||
|
||||
var result = response.GoodreadsResponse.user;
|
||||
if(!result) throw 'user-not-found';
|
||||
|
||||
return this.internalAPI.formatProfile(result);
|
||||
},
|
||||
|
||||
'getProfileByName': async username => {
|
||||
//https://www.goodreads.com/user/show.xml
|
||||
try {
|
||||
var body = await rp({
|
||||
url: this.apiRoot + '/user/show.xml',
|
||||
qs: {
|
||||
key: this.config.api_key,
|
||||
username: username
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
if(e.statusCode && e.statusCode == 404) {
|
||||
throw 'user-not-found';
|
||||
return;
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
|
||||
var response = await parseString(body, { explicitArray: false });
|
||||
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
|
||||
|
||||
var result = response.GoodreadsResponse.user;
|
||||
if(!result) throw 'user-not-found';
|
||||
|
||||
return this.internalAPI.formatProfile(result);
|
||||
},
|
||||
|
||||
'getShelfForUserId': async (id, shelf) => {
|
||||
//https://www.goodreads.com/review/list.xml?v=2
|
||||
var body = await rp({
|
||||
url: this.apiRoot + '/review/list.xml',
|
||||
qs: {
|
||||
v: '2',
|
||||
key: this.config.api_key,
|
||||
id: id,
|
||||
shelf: shelf
|
||||
}
|
||||
});
|
||||
|
||||
var response = await parseString(body, { explicitArray: false });
|
||||
if(!_.has(response, 'GoodreadsResponse')) throw 'goodreads-error';
|
||||
|
||||
let result = response.GoodreadsResponse.reviews.review;
|
||||
if(!result) return [];
|
||||
|
||||
if(!_.isArray(result)) {
|
||||
result = [result];
|
||||
}
|
||||
|
||||
return _.map(result, r => {
|
||||
return {
|
||||
id: r.book.id['_'],
|
||||
title: r.book.title_without_series
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.commands = {
|
||||
'~book' : async evt => {
|
||||
try {
|
||||
var book = await this.api.findBook(evt.input[1]);
|
||||
evt.reply(dbot.t('gr_book', {
|
||||
author: book.author,
|
||||
title: book.title,
|
||||
rating: book.rating,
|
||||
link: this.apiRoot + '/book/show/' + book.id
|
||||
}));
|
||||
}
|
||||
catch(e) { this.internalAPI.outputError(evt, e); }
|
||||
},
|
||||
|
||||
'~booksummary': async evt => {
|
||||
try {
|
||||
var book = await this.api.findBook(evt.input[1]);
|
||||
var summary = await this.api.getSummaryForBook(book.id);
|
||||
evt.reply(dbot.t('gr_summary', {
|
||||
title: book.title,
|
||||
summary: summary,
|
||||
link: this.apiRoot + '/book/show/' + book.id
|
||||
}));
|
||||
}
|
||||
catch(e) { this.internalAPI.outputError(evt, e); }
|
||||
},
|
||||
|
||||
'~author' : async evt => {
|
||||
try {
|
||||
evt.reply(dbot.t('gr_author', await this.api.findAuthor(evt.input[1])));
|
||||
}
|
||||
catch(e) { this.internalAPI.outputError(evt, e); }
|
||||
},
|
||||
|
||||
'~reading': async (evt, profile) => {
|
||||
try {
|
||||
let books = await this.api.getShelfForUserId(profile.id, 'currently-reading');
|
||||
var booksCount = books.length;
|
||||
if(!booksCount) {
|
||||
evt.reply(dbot.t('gr_not_reading', { user: evt.rUser.currentNick }));
|
||||
return;
|
||||
}
|
||||
|
||||
let tooMany = booksCount > 5;
|
||||
if (tooMany) books = _.sample(books, 5);
|
||||
|
||||
evt.reply(dbot.t('gr_is_reading', { user: evt.rUser.currentNick, count: booksCount }));
|
||||
_.each(books, b => {
|
||||
evt.reply(ostr = b.title + ' - https://www.goodreads.com/book/show/' + b.id);
|
||||
});
|
||||
|
||||
if (tooMany) {
|
||||
evt.reply('... And ' + (booksCount - 5) + ' more - https://www.goodreads.com/review/list/' + profile.id + '?shelf=currently-reading');
|
||||
}
|
||||
}
|
||||
catch(e) { this.internalAPI.outputError(evt, e); }
|
||||
}
|
||||
};
|
||||
|
||||
this.commands['~book'].regex = [/^book (.*)/, 2];
|
||||
this.commands['~booksummary'].regex = [/^booksummary (.*)/, 2];
|
||||
this.commands['~author'].regex = [/^author ([\d\w\s-]*)/, 2];
|
||||
|
||||
this.commands['~reading'].requiresProfile = true;
|
||||
|
||||
_.each(this.commands, ((cmd, cmdName) => {
|
||||
if(cmd.requiresProfile) {
|
||||
this.commands[cmdName] = (async evt => {
|
||||
var grUsername = evt.rProfile.goodreads;
|
||||
|
||||
if(!grUsername) {
|
||||
evt.reply(evt.rUser.currentNick + ': Set a Goodreads username with "~set goodreads username"');
|
||||
return;
|
||||
}
|
||||
|
||||
let grId = evt.rProfile.goodreads_id;
|
||||
|
||||
try {
|
||||
var profile;
|
||||
if(grId) {
|
||||
profile = await this.api.getProfileById(grId);
|
||||
} else {
|
||||
profile = await this.api.getProfileByName(grUsername);
|
||||
grId = profile.id;
|
||||
dbot.api.profile.setProperty(evt.server, evt.user, 'goodreads_id', grId, function(){});
|
||||
}
|
||||
|
||||
await cmd(evt, profile);
|
||||
}
|
||||
catch(e) {
|
||||
if(e === 'user-not-found') evt.reply('User not found. Is your GoodReads username set correctly?');
|
||||
else this.internalAPI.outputError(evt, e);
|
||||
}
|
||||
}).bind(this);
|
||||
}
|
||||
}).bind(this))
|
||||
|
||||
}
|
||||
|
||||
|
||||
exports.fetch = dbot => new GoodReads(dbot);
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"gr_book": {
|
||||
"en": "[{title} by {author} - {rating}] - {link}"
|
||||
},
|
||||
"gr_summary": {
|
||||
"en": "[{title}] - {summary} - {link}"
|
||||
},
|
||||
"gr_author": {
|
||||
"en": "[{author}] - https://www.goodreads.com/author/show/{id}"
|
||||
},
|
||||
"gr_nobook": {
|
||||
"en": "No book by that name was found."
|
||||
},
|
||||
"gr_noauthor": {
|
||||
"en": "No author by that name was found."
|
||||
},
|
||||
"gr_not_reading": {
|
||||
"en": "{user} is not currently reading any books."
|
||||
},
|
||||
"gr_is_reading": {
|
||||
"en": "{user} is currently reading the following {count} books:"
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"~book": "~book [bookname] - returns the title, author, rating, and GoodReads link",
|
||||
"~booksummary": "~booksummary [bookname] - returns the summary for the requested book",
|
||||
"~author": "~author [authorname] - returns the GoodReads link for the requested author",
|
||||
"~reading": "~reading - displays up to 5 of the books you are currently reading"
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var api = function(dbot) {
|
||||
return {
|
||||
// Is user ignoring command/module?
|
||||
'isUserIgnoring': function(user, item, callback) {
|
||||
this.internalAPI.isUserImpeded(user, item, 'ignores', callback);
|
||||
},
|
||||
|
||||
// Is user banned from command/module?
|
||||
'isUserBanned': function(user, item, callback) {
|
||||
this.internalAPI.isUserImpeded(user, item, 'bans', callback);
|
||||
},
|
||||
|
||||
// Is channel ignoring module?
|
||||
// TODO: Command support
|
||||
'isChannelIgnoring': function(channelName, item, callback) {
|
||||
var isIgnoring = false,
|
||||
channel = false;
|
||||
|
||||
this.db.search('channel_ignores', {
|
||||
'server': server,
|
||||
'name': channel
|
||||
}, function(result) {
|
||||
channel = result;
|
||||
}, function(err) {
|
||||
if(!err && channel && _.include(channel.ignores, item)) {
|
||||
isIgnoring = true;
|
||||
}
|
||||
callback(isIgnoring);
|
||||
});
|
||||
},
|
||||
|
||||
// Resolve a nick and return their user and ignores object
|
||||
'getUserIgnores': function(user, callback) {
|
||||
this.db.read('ignores', user.id, function(err, ignores) {
|
||||
if(!err && ignores) {
|
||||
callback(false, ignores);
|
||||
} else {
|
||||
callback(true, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return api(dbot);
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"ignorable": false,
|
||||
"dependencies": [ "users" ],
|
||||
"dependencies": [ "command" ],
|
||||
"dbKeys": [ "ignores", "bans" ],
|
||||
"dbType": "redis"
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/ignore/README.md"
|
||||
}
|
||||
|
@ -5,35 +5,15 @@
|
||||
* this information, since that actually performs the ignorance. Also provides
|
||||
* commands for moderators to choose the bot to ignore certain channels.
|
||||
*/
|
||||
var _ = require('underscore')._,
|
||||
databank = require('databank'),
|
||||
uuid = require('node-uuid'),
|
||||
NoSuchThingError = databank.NoSuchThingError;
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var ignore = function(dbot) {
|
||||
this.internalAPI = {
|
||||
'isUserImpeded': function(user, item, by, callback) {
|
||||
this.api.getUserIgnores(user, function(err, ignores) {
|
||||
var isImpeded = false;
|
||||
if(!err && ignores) {
|
||||
if(_.has(dbot.commands, item) && !_.include(ignores[by], item)) {
|
||||
item = dbot.commands[item].module;
|
||||
}
|
||||
if(_.include(ignores[by], item) || _.include(ignores[by], '*')) {
|
||||
isImpeded = true;
|
||||
}
|
||||
}
|
||||
callback(isImpeded);
|
||||
});
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
var commands = {
|
||||
'~ignore': function(event) {
|
||||
var module = event.params[1];
|
||||
var ignorableModules = _.chain(dbot.modules)
|
||||
.filter(function(module, name) {
|
||||
return dbot.config.modules[module].ignorable === true;
|
||||
return dbot.config[module].ignorable === true;
|
||||
})
|
||||
.pluck('name')
|
||||
.value();
|
||||
@ -45,30 +25,21 @@ var ignore = function(dbot) {
|
||||
}));
|
||||
} else {
|
||||
if(module == '*' || _.include(ignorableModules, module)) {
|
||||
this.api.getUserIgnores(event.rUser, function(err, ignores) {
|
||||
if(!ignores) {
|
||||
ignores = {
|
||||
'id': event.rUser.id,
|
||||
'ignores': [],
|
||||
'bans': []
|
||||
};
|
||||
if(_.has(dbot.db.ignores, event.user) && _.include(dbot.db.ignores[event.user], module)) {
|
||||
event.reply(dbot.t('already_ignoring', { 'user': event.user }));
|
||||
} else {
|
||||
if(_.has(dbot.db.ignores, module)) {
|
||||
dbot.db.ignores[event.user].push(module);
|
||||
} else {
|
||||
dbot.db.ignores[event.user] = [module];
|
||||
}
|
||||
|
||||
if(!_.include(ignores.ignores, module)) {
|
||||
ignores.ignores.push(module);
|
||||
this.db.save('ignores', event.rUser.id, ignores, function(err) {
|
||||
if(!err) {
|
||||
dbot.instance.ignoreTag(event.user, module);
|
||||
event.reply(dbot.t('ignored', {
|
||||
'user': event.user,
|
||||
'module': module
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('already_ignoring', { 'user': event.user }));
|
||||
}
|
||||
}.bind(this));
|
||||
dbot.instance.ignoreTag(event.user, module);
|
||||
event.reply(dbot.t('ignored', {
|
||||
'user': event.user,
|
||||
'module': module
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_ignore', { 'user': event.user }));
|
||||
}
|
||||
@ -76,192 +47,139 @@ var ignore = function(dbot) {
|
||||
},
|
||||
|
||||
'~unignore': function(event) {
|
||||
var ignoredModules = [];
|
||||
if(_.has(dbot.db.ignores, event.user)) {
|
||||
ignoredModules = dbot.db.ignores[event.user];
|
||||
}
|
||||
var module = event.params[1];
|
||||
|
||||
this.api.getUserIgnores(event.rUser, function(err, ignores) {
|
||||
if(err || !ignores || _.isUndefined(module)) {
|
||||
if(ignores) {
|
||||
event.reply(dbot.t('unignore_usage', {
|
||||
'user': event.user,
|
||||
'modules': ignores.ignores.join(', ')
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('empty_unignore_usage', {
|
||||
'user': event.user
|
||||
}));
|
||||
}
|
||||
if(_.isUndefined(module)) {
|
||||
event.reply(dbot.t('unignore_usage', {
|
||||
'user': event.user,
|
||||
'modules': ignoredModules.join(', ')
|
||||
}));
|
||||
} else {
|
||||
if(_.include(ignoredModules, module)) {
|
||||
dbot.db.ignores[event.user].splice(dbot.db.ignores[event.user].indexOf(module), 1);
|
||||
dbot.instance.removeIgnore(event.user, module)
|
||||
event.reply(dbot.t('unignored', {
|
||||
'user': event.user,
|
||||
'module': module
|
||||
}));
|
||||
} else {
|
||||
if(_.include(ignores.ignores, module)) {
|
||||
ignores.ignores = _.without(ignores.ignores, module);
|
||||
this.db.save('ignores', event.rUser.id, ignores, function(err) {
|
||||
if(!err) {
|
||||
dbot.instance.removeIgnore(event.user, module)
|
||||
event.reply(dbot.t('unignored', {
|
||||
'user': event.user,
|
||||
'module': module
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_unignore', { 'user': event.user }));
|
||||
}
|
||||
event.reply(dbot.t('invalid_unignore', { 'user': event.user }));
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
'~ban': function(event) {
|
||||
var nick = event.input[1],
|
||||
item = event.input[2];
|
||||
var user = event.params[1];
|
||||
var module = event.params[2];
|
||||
|
||||
if(item == '*' || _.include(dbot.config.moduleNames, item) || _.include(dbot.commands, item)) {
|
||||
dbot.api.users.resolveUser(event.server, nick, function(err, user) {
|
||||
this.api.getUserIgnores(user, function(err, ignores) {
|
||||
if(!ignores) {
|
||||
ignores = {
|
||||
'id': user.id,
|
||||
'ignores': [],
|
||||
'bans': []
|
||||
};
|
||||
}
|
||||
if(_.isUndefined(user) || _.isUndefined(module)) {
|
||||
event.reply(dbot.t('ban_usage', {'user': event.user}));
|
||||
return;
|
||||
}
|
||||
|
||||
if(module == '*' || _.include(dbot.config.moduleNames, module) || _.include(dbot.commands, module)) {
|
||||
if(_.has(dbot.db.bans, user) && _.include(dbot.db.bans[user], module)) {
|
||||
event.reply(dbot.t('already_banned', {
|
||||
'user': event.user,
|
||||
'banned': user
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!_.include(ignores.bans, item)) {
|
||||
ignores.bans.push(item);
|
||||
this.db.save('ignores', user.id, ignores, function(err) {
|
||||
if(!err) {
|
||||
event.reply(dbot.t('banned_success', {
|
||||
'user': event.user,
|
||||
'banned': nick,
|
||||
'module': item
|
||||
}));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('already_banned', {
|
||||
'user': event.user,
|
||||
'banned': nick
|
||||
}));
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
if(_.has(dbot.db.bans, event.params[1])) {
|
||||
dbot.db.bans[event.params[1]].push(module);
|
||||
} else {
|
||||
dbot.db.bans[event.params[1]] = [module];
|
||||
}
|
||||
|
||||
event.reply(dbot.t('banned_success', {
|
||||
'user': event.user,
|
||||
'banned': user,
|
||||
'module': module
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_ban', { 'user': event.user }));
|
||||
event.reply(dbot.t('invalid_ban', {'user': event.user}));
|
||||
}
|
||||
},
|
||||
|
||||
'~unban': function(event) {
|
||||
var nick = event.input[1],
|
||||
item = event.input[2];
|
||||
var bannedModules = [];
|
||||
|
||||
dbot.api.users.resolveUser(event.server, nick, function(err, user) {
|
||||
this.api.getUserIgnores(user, function(err, ignores) {
|
||||
if(err || !ignores) {
|
||||
event.reply(dbot.t('invalid_unban', {
|
||||
'user': event.user,
|
||||
'banned': nick
|
||||
}));
|
||||
} else {
|
||||
if(_.include(ignores.bans, item)) {
|
||||
ignores.bans = _.without(ignores.bans, item);
|
||||
this.db.save('ignores', user.id, ignores, function(err) {
|
||||
event.reply(dbot.t('unbanned_success', {
|
||||
'user': event.user,
|
||||
'banned': nick,
|
||||
'module': item
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_unban', {
|
||||
'user': event.user,
|
||||
'banned': nick
|
||||
}));
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
var user = event.params[1];
|
||||
var module = event.params[2];
|
||||
|
||||
if(_.isUndefined(user) || _.isUndefined(module)) {
|
||||
event.reply(dbot.t('unban_usage', {'user': event.user}));
|
||||
} else {
|
||||
if(_.has(dbot.db.bans, user) && _.include(dbot.db.bans[user], module)) {
|
||||
dbot.db.bans[user].splice(dbot.db.bans[user].indexOf(module), 1);
|
||||
|
||||
event.reply(dbot.t('unbanned_success', {
|
||||
'user': event.user,
|
||||
'banned': user,
|
||||
'module': module
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('invalid_unban', {
|
||||
'user': event.user,
|
||||
'banned': user
|
||||
}));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'~ignorechannel': function(event) {
|
||||
var channelName = event.input[1],
|
||||
module = event.input[2];
|
||||
var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]);
|
||||
var module = event.params[2];
|
||||
|
||||
// Ignoring the value of 'ignorable' at the moment
|
||||
if(module == '*' || _.include(dbot.config.moduleNames, module)) {
|
||||
var channel = false;
|
||||
|
||||
this.db.search('channel_ignores', {
|
||||
'server': event.server,
|
||||
'name': channelName
|
||||
}, function(result) {
|
||||
channel = result;
|
||||
}, function(err) {
|
||||
if(!channel) {
|
||||
var id = uuid.v4();
|
||||
channel = {
|
||||
'id': id,
|
||||
'server': event.server,
|
||||
'name': channelName,
|
||||
'ignores': []
|
||||
};
|
||||
}
|
||||
|
||||
if(!_.include(channel.ignores, module)) {
|
||||
channel.ignores.push(module);
|
||||
this.db.save('channel_ignores', channel.id, channel, function(err) {
|
||||
dbot.instance.ignoreTag(channel.name, module);
|
||||
event.reply(dbot.t('ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channelName
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('already_ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channelName
|
||||
}));
|
||||
}
|
||||
}.bind(this));
|
||||
if(!_.has(dbot.db.ignores, channel)) dbot.db.ignores[channel] = [];
|
||||
if(!_.include(dbot.db.ignores[channel], module)) {
|
||||
dbot.db.ignores[channel].push(module);
|
||||
dbot.instance.ignoreTag(channel, module);
|
||||
event.reply(dbot.t('ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channel
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('already_ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channel
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('module_not_exist', { 'module': module }));
|
||||
}
|
||||
},
|
||||
|
||||
'~unignorechannel': function(event) {
|
||||
var channelName = event.input[1],
|
||||
module = event.input[2],
|
||||
channel = false;
|
||||
var channel = ((event.params[1] == '@') ? event.channel.name : event.params[1]);
|
||||
var module = event.params[2];
|
||||
|
||||
this.db.search('channel_ignores', {
|
||||
'server': event.server,
|
||||
'name': channelName
|
||||
}, function(result) {
|
||||
channel = result;
|
||||
}, function(err) {
|
||||
if(channel && _.include(channel.ignores, module)) {
|
||||
channel.ignores = _.without(channel.ignores, module);
|
||||
this.db.save('channel_ignores', channel.id, channel, function(err) {
|
||||
dbot.instance.removeIgnore(channel.name, module);
|
||||
event.reply(dbot.t('unignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channelName
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
event.reply(dbot.t('not_ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channelName
|
||||
}));
|
||||
}
|
||||
}.bind(this));
|
||||
if(!_.has(dbot.db.ignores, channel)) dbot.db.ignores[channel] = [];
|
||||
if(_.include(dbot.db.ignores[channel], module)) {
|
||||
dbot.db.ignores[channel] = _.without(dbot.db.ignores[channel], module);
|
||||
dbot.instance.removeIgnore(channel, module);
|
||||
event.reply(dbot.t('unignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channel
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('not_ignoring_channel', {
|
||||
'module': module,
|
||||
'channel': channel
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
commands['~ban'].regex = [/^ban ([^ ]+) ([^ ]+)$/, 3];
|
||||
commands['~unban'].regex = [/^unban ([^ ]+) ([^ ]+)$/, 3];
|
||||
commands['~ignorechannel'].regex = [/^ignorechannel ([^ ]+) ([^ ]+)$/, 3];
|
||||
commands['~unignorechannel'].regex = [/^unignorechannel ([^ ]+) ([^ ]+)$/, 3];
|
||||
|
||||
commands['~ban'].access = 'power_user';
|
||||
commands['~unban'].access = 'power_user';
|
||||
commands['~ban'].access = 'moderator';
|
||||
commands['~unban'].access = 'moderator';
|
||||
commands['~ignorechannel'].access = 'moderator';
|
||||
commands['~unignorechannel'].access = 'moderator';
|
||||
|
||||
@ -269,34 +187,12 @@ var ignore = function(dbot) {
|
||||
|
||||
this.onLoad = function() {
|
||||
dbot.instance.clearIgnores();
|
||||
|
||||
this.db.scan('ignores', function(ignores) {
|
||||
dbot.api.users.getUser(ignores.id, function(err, user) {
|
||||
if(user) {
|
||||
_.each(ignores.ignores, function(module) {
|
||||
dbot.instance.ignoreTag(user.currentNick, module);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, function(err) { });
|
||||
|
||||
this.db.scan('channel_ignores', function(channel) {
|
||||
_.each(channel.ignores, function(module) {
|
||||
dbot.instance.ignoreTag(channel.name, module);
|
||||
});
|
||||
}, function(err) { });
|
||||
|
||||
dbot.api.event.addHook('new_current_nick', function(user, oldNick) {
|
||||
this.api.getUserIgnores(user, function(err, ignores) {
|
||||
if(ignores) {
|
||||
_.each(ignores.ignores, function(module) {
|
||||
dbot.instance.removeIgnore(oldNick, module);
|
||||
dbot.instance.ignoreTag(user.currentNick, module);
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
_.each(dbot.db.ignores, function(ignores, item) {
|
||||
_.each(ignores, function(ignore) {
|
||||
dbot.instance.ignoreTag(item, ignore);
|
||||
}, this);
|
||||
}, this);
|
||||
};
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
|
@ -5,9 +5,7 @@
|
||||
"na'vi": "{user}: Sar: ~ignore ['u]. U, nga ke tìng mikyun: {modules}.",
|
||||
"cy": "{user}: Defnydd: ~ignore [modiwl]. Modiwlau a allech anwybyddu yw: {modules}.",
|
||||
"nl": "{user}: Gebruik: ~ignore [module]. Modules die negeert kunnen worden zijn: {modules}.",
|
||||
"de": "{user}: Benutzung: ~ignore [module]. Module, die ausgeschaltet werden können: {modules}.",
|
||||
"fr": "{user}: Utilisation: ~ignore [module]. Les modules que vous pouvez ignorer sont: {modules}.",
|
||||
"it": "{user}: Uso: ~ignore [module]. I moduli che puoi ignorare sono: {modules}."
|
||||
"de": "{user}: Benutzung: ~ignore [module]. Module, die ignoriert werden können: {modules}."
|
||||
},
|
||||
"already_ignoring": {
|
||||
"en": "{user}: You're already ignoring that module.",
|
||||
@ -15,9 +13,7 @@
|
||||
"na'vi": "{user}: 'uri nga ke tìng mikyun srekrr.",
|
||||
"cy": "{user}: Mi rwyt ti'n anwybyddu'r modiwl yna'n barod.",
|
||||
"nl": "{user}: Je negeert deze module al.",
|
||||
"de": "{user}: Dieses Modul ist bereits ausgeschaltet.",
|
||||
"fr": "{user}: Vous ignorez déjà ce module.",
|
||||
"it": "{user}: Stai già ignorando questo modulo"
|
||||
"de": "{user}: Dieses Modul wird bereits ignoriert."
|
||||
},
|
||||
"ignored": {
|
||||
"en": "{user}: Now ignoring {module}.",
|
||||
@ -25,9 +21,7 @@
|
||||
"na'vi": "{user}: Nga ke terìng mikyun {module}ne set.",
|
||||
"cy": "{user}: Nawr yn anwybyddu {module}",
|
||||
"nl": "{user}: {module} wordt nu genegeerd.",
|
||||
"de": "{user}: {module} wird nun ausgeschaltet.",
|
||||
"fr": "{user}: {module} désormais ignoré.",
|
||||
"it": "{user}: {module} sarà adesso ignorato"
|
||||
"de": "{user}: {module} wird nun ignoriert."
|
||||
},
|
||||
"invalid_ignore": {
|
||||
"en": "{user}: That isn't a valid module name.",
|
||||
@ -35,9 +29,7 @@
|
||||
"na'vi": "{user}: Tsatstxo eyawr ke lu.",
|
||||
"cy": "{user}: Nid oedd hwna'n modiwl dilys",
|
||||
"nl": "{user}: Dat is geen geldige modulenaam.",
|
||||
"de": "{user}: Dies ist kein Name eines Moduls.",
|
||||
"fr": "{user}: Ceci ne correspond pas à un nom de module valide.",
|
||||
"it": "{user}: Questo non è un nome di modulo valido"
|
||||
"de": "{user}: Dies ist nicht der Name eines Moduls."
|
||||
},
|
||||
"unignore_usage": {
|
||||
"en": "{user}: Usage: ~unignore [module]. Modules you are currently ignoring: {modules}.",
|
||||
@ -45,19 +37,7 @@
|
||||
"na'vi": "{user}: Sar: ~unignore ['u]. Uri, nga ke terìng mikyun: {modules}.",
|
||||
"cy": "{user}: Defnydd: ~unignore [modiwl]. Modiwlau rydech yn anwybyddu ar hyn o bryd: {modules}",
|
||||
"nl": "{user}: Gebruik: ~unignore [module]. Modules die momenteel worden genegeerd: {modules}.",
|
||||
"de": "{user}: Benutzung: ~unignore [module]. Module, die im Moment ausgeschaltet sind: {modules}.",
|
||||
"fr": "{user}: Utilisation: ~unignore [module]. Modules que vous ignorez actuellement: {modules}.",
|
||||
"it": "{user}: Uso: ~unignore [module]. Module che ignori attualmente: {modules}."
|
||||
},
|
||||
"empty_unignore_usage": {
|
||||
"en": "{user}: Usage: ~unignore [module].",
|
||||
"es": "{user}: Modo de empleo: ~unignore [módulo].",
|
||||
"na'vi": "{user}: Sar: ~unignore ['u].",
|
||||
"cy": "{user}: Defnydd: ~unignore [modiwl].",
|
||||
"nl": "{user}: Gebruik: ~unignore [module].",
|
||||
"de": "{user}: Benutzung: ~unignore [module].",
|
||||
"fr": "{user}: Utilisation: ~unignore [module].",
|
||||
"it": "{user}: Uso: ~unignore [module]."
|
||||
"de": "{user}: Benutzung: ~unignore [module]. Module, die im Moment ignoriert werden: {modules}."
|
||||
},
|
||||
"invalid_unignore": {
|
||||
"en": "{user}: You're not ignoring that module or it doesn't exist.",
|
||||
@ -65,9 +45,7 @@
|
||||
"na'vi":"{user}: Nga terìng mikyun fu fì'ul fìtsengit ke tok.",
|
||||
"cy": "{user}: Nid wyt ti'n anwybyddu'r modiwl yna neu nid yw e'n bodoli",
|
||||
"nl": "{user}: Deze module bestaat niet of wordt niet genegeerd.",
|
||||
"de": "{user}: Dieses Modul ist entweder ausgeschaltet oder existiert nicht.",
|
||||
"fr": "{user}: Vous n'ignorez pas ce module ou il n'existe pas.",
|
||||
"it": "{user}: Non stai ignorando questo modulo o non esiste."
|
||||
"de": "{user}: Dieses Modul wird entweder nicht ignoriert oder existiert nicht."
|
||||
},
|
||||
"unignored": {
|
||||
"en": "{user}: No longer ignoring {module}.",
|
||||
@ -75,109 +53,83 @@
|
||||
"na'vi": "{user}: Nga terìng mikyun {module}ne set",
|
||||
"cy": "{user}: Ddim yn anwybyddu {module} bellach",
|
||||
"nl": "{user}: {module} wordt niet langer genegeerd.",
|
||||
"de": "{user}: {module} ist nicht länger ausgeschaltet.",
|
||||
"fr": "{user}: {module} n'est plus ignoré à présent.",
|
||||
"it": "{user}: {module} non viene attualmente più ignorato"
|
||||
"de": "{user}: {module} wird nicht länger ignoriert."
|
||||
},
|
||||
"ban_usage": {
|
||||
"en": "{user}: Usage: ~ban [user] [module/command]. Use * for all modules and commands.",
|
||||
"cy": "{user}: Defnydd: ~ban [defnyddiwr] [modiwl/gorchymyn]. Defnyddio * am pob modiwlau a gorchmynion.",
|
||||
"nl": "{user}: Gebruik: ~ban [gebruiker] [module/commando]. Gebruik * voor alle modules en alle commandos.",
|
||||
"de": "{user}: Benutzung ~ban [Benutzer] [module/Befehl]. Benutze * für alle Module und Befehle.",
|
||||
"fr": "{user}: Utilisation: ~ban [user] [module/command]. Utilisez * pour tous les modules et commandes.",
|
||||
"it": "{user}: Uso: ~ban [user] [module/command]. Utilizza * per tutti i moduli e commandi."
|
||||
"de": "{user}: Benutzung ~ban [Benutzer] [module/Befehl]. Benutze * für alle Module und Befehle."
|
||||
},
|
||||
"already_banned": {
|
||||
"en": "{user}: {banned} is already banned from that module.",
|
||||
"cy": "{user}: {banned} eisoes wedi ei wahardd o'r modiwl.",
|
||||
"nl": "{user}: {banned} is al geband van deze module.",
|
||||
"de": "{user}: {banned} ist bereits von diesem Modul gebannt.",
|
||||
"fr": "{user}: {banned} est déjà interdit d'utiliser ce module.",
|
||||
"it": "{user}: {banned} è già bandito da usare questo modulo."
|
||||
"de": "{user}: {banned} ist bereits von diesem Modul gebannt."
|
||||
},
|
||||
"banned_success": {
|
||||
"en": "{user}: {banned} is now banned from {module}.",
|
||||
"cy": "{user}: {banned} ei wahardd yn awr am {module}.",
|
||||
"nl": "{user}: {banned} mag {module} nu niet meer gebruiken.",
|
||||
"de": "{user}: {banned} ist nun von {module} gebannt.",
|
||||
"fr": "{user}: {banned} est maintenant interdit d'utiliser {module}.",
|
||||
"it": "{user}: {banned} è stato adesso bandito da usare {module}."
|
||||
"de": "{user}: {banned} ist nun von {module} gebannt."
|
||||
},
|
||||
"invalid_ban": {
|
||||
"en": "{user}: That isn't a valid module name.",
|
||||
"cy": "{user}: Nid oedd hwna'n modiwl dilys",
|
||||
"nl": "{user}: Dat is geen geldige modulenaam.",
|
||||
"de": "{user}: Dies ist kein Name eines Moduls.",
|
||||
"fr": "{user}: Ceci n'est pas un nom de module valide.",
|
||||
"it": "{user}: Queso non è il nome di un modulo valido."
|
||||
"de": "{user}: Dies ist nicht der Name eines Moduls."
|
||||
},
|
||||
"unban_usage": {
|
||||
"en": "{user}: Usage: ~unban [user] [module].",
|
||||
"cy": "{user}: Defnydd: ~unban [defnyddiwr] [modiwl].",
|
||||
"nl": "{user}: Gebruik: ~unban [gebruiker] [module].",
|
||||
"de": "{user}: Benutzung: ~unban [Benutzer] [module].",
|
||||
"fr": "{user}: Utilisation: ~unban [user] [module].",
|
||||
"it": "{user}: Uso: ~unban [user] [module]."
|
||||
"de": "{user}: Benutzung: ~unban [Benutzer] [module]."
|
||||
},
|
||||
"invalid_unban": {
|
||||
"en": "{user}: {banned} is not banned from that module or it doesn't exist.",
|
||||
"cy": "{user}: Nid oedd {banned} wedi ei wahardd o'r modiwl, neu nid yw'n bodoli.",
|
||||
"nl": "{user}: {banned} is niet geband van die module of de module bestaat niet.",
|
||||
"de": "{user}: {banned} ist von diesem Modul nicht gebannt, oder es existiert nicht.",
|
||||
"fr": "{user}: {banned} n'est pas interdit d'utiliser ce module, ou il n'existe pas.",
|
||||
"it": "{user}: {banned} non è stato bandito da questo modulo o non esiste."
|
||||
"de": "{user}: {banned} ist von diesem Modul nicht gebannt, oder es existiert nicht."
|
||||
},
|
||||
"unbanned_success": {
|
||||
"en": "{user}: {banned} is no longer banned from {module}.",
|
||||
"cy": "{user}: Nid yw {banned} yn cael ei wahardd mwyach.",
|
||||
"nl": "{user}: {banned} mag {module} weer gebruiken.",
|
||||
"de": "{user}: {banned} wurde von {module} entbannt.",
|
||||
"fr": "{user}: {banned} n'est plus interdit d'utiliser {module}.",
|
||||
"it": "{user}: {banned} non è più bandito dall' utilizzare {module}."
|
||||
"de": "{user}: {banned} wurde von {module} entbannt."
|
||||
},
|
||||
"ignoring_channel": {
|
||||
"en": "Now ignoring {module} in {channel}.",
|
||||
"na'vi": "Oe ke stayawm {module}ur mì {channel}",
|
||||
"cy": "Bellach yn anwybyddu {module} yn {channel}.",
|
||||
"nl": "{module} wordt nu genegeerd in {channel}.",
|
||||
"de": "{module} in {channel} ist nun ausgeschaltet.",
|
||||
"fr": "{module} dans {channel} maintenant ignoré.",
|
||||
"it": "{module} in {channel} viene adesso ignorato."
|
||||
"de": "{module} in [channel} wird nun ignoriert."
|
||||
},
|
||||
"already_ignoring_channel": {
|
||||
"en": "Already ignoring {module} in {channel}.",
|
||||
"na'vi": "Oe ke stayawm {module}ur mì {channel} li",
|
||||
"cy": "Eisoes anwybyddu {module} yn {channel}",
|
||||
"nl": "{module} wordt al genegeerd in {channel}.",
|
||||
"de": "{module} in {channel} ist bereits ausgeschaltet.",
|
||||
"fr": "{module} dans {channel} déjà ignoré.",
|
||||
"it": "{module} in {channel} già ignorato."
|
||||
"de": "{module} in {channel} wird bereits ignoriert."
|
||||
},
|
||||
"module_not_exist": {
|
||||
"en": "{module} isn't loaded or doesn't exist.",
|
||||
"na'vi": "Oel ke omum teri {module}it fu {module} ke fkeytok",
|
||||
"cy": "Dydy {module} ddim yn lwythodd, neu ddim yn bodoli.",
|
||||
"nl": "{module} is niet geladen of bestaat niet.",
|
||||
"de": "{module} ist nicht geladen oder existiert nicht.",
|
||||
"fr": "{module} n'est pas chargé ou n'existe pas.",
|
||||
"it": "{module} non caricato o non esiste"
|
||||
"de": "{module} ist nicht geladen oder existiert nicht."
|
||||
},
|
||||
"unignoring_channel": {
|
||||
"en": "No longer ignoring {module} in {channel}.",
|
||||
"na'vi": "Oel stayawm {module}ur mì {channel} set.",
|
||||
"cy": "Nid anwybyddu {module} yn {channel} mwyach.",
|
||||
"nl": "{module} wordt niet meer genegeerd in {channel}.",
|
||||
"de": "{module} in {channel} ist nicht länger ausgeschaltet.",
|
||||
"fr": "{module} dans {channel} n'est plus ignoré à présent.",
|
||||
"it": "{module} in {channel} non viene più ignorato."
|
||||
"de": "{module} in {channel} wird nicht länger ignoriert."
|
||||
},
|
||||
"not_ignoring_channel": {
|
||||
"en": "{module} wasn't being ignored in {channel}.",
|
||||
"na'vi": "Oel stayawm {module}ur mì {channel} li.",
|
||||
"cy": "Nid yw {module} yn cael ei anwybyddu yn {channel}.",
|
||||
"nl": "{module} werd niet genegeerd in {channel}.",
|
||||
"de": "{module} war in {channel} nicht ausgeschaltet.",
|
||||
"fr": "{module} n'était pas ignoré dans {channel}.",
|
||||
"it": "{module} non veniva ignorato in {channel}"
|
||||
"de": "{module} wurde in {channel} nicht ignoriert."
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
{
|
||||
"dbKeys": [ "imgur" ],
|
||||
"dependencies": [ "web", "api", "link" ],
|
||||
"dependencies": [ "web", "api" ],
|
||||
"imagelength": 5,
|
||||
"ricachelength": 7,
|
||||
"nsfwwarn": true,
|
||||
"apikey": "86fd3a8da348b65",
|
||||
"highscore": "ricount",
|
||||
|
@ -5,29 +5,14 @@
|
||||
|
||||
var _ = require('underscore')._,
|
||||
request = require('request'),
|
||||
async = require('async'),
|
||||
crypto = require('crypto'),
|
||||
humanise = require('humanize');
|
||||
crypto = require('crypto');
|
||||
|
||||
var imgur = function(dbot) {
|
||||
this.ApiRoot = 'https://api.imgur.com/3/';
|
||||
this.ExcludeRes = [
|
||||
{ 'w': 800, 'h': 600 },
|
||||
{ 'w': 1024, 'h': 768 },
|
||||
{ 'w': 1280, 'h': 768 },
|
||||
{ 'w': 1280, 'h': 960 },
|
||||
{ 'w': 1366, 'h': 768 },
|
||||
{ 'w': 1600, 'h': 900 },
|
||||
{ 'w': 1680, 'h': 1050 },
|
||||
{ 'w': 1920, 'h': 1080 },
|
||||
{ 'w': 1024, 'h': 640 }
|
||||
];
|
||||
this.riCache = [];
|
||||
|
||||
this.db = dbot.db.imgur;
|
||||
this.internalAPI = {
|
||||
'infoString': function(imgData) {
|
||||
info = '';
|
||||
if(!_.isUndefined(imgData) && _.has(imgData, 'data') && !_.isUndefined(imgData.data.type)) {
|
||||
if(imgData && _.has(imgData, 'data') && !_.isUndefined(imgData.data.type)) {
|
||||
imgData = imgData.data;
|
||||
if(imgData.title) {
|
||||
info += imgData.title + ' - ';
|
||||
@ -43,8 +28,6 @@ var imgur = function(dbot) {
|
||||
}
|
||||
info += imgData.views + ' views (';
|
||||
info += imgData.width + 'x' + imgData.height + ')';
|
||||
|
||||
info += ' ('+humanise.filesize(imgData.size)+')';
|
||||
}
|
||||
|
||||
return info;
|
||||
@ -52,13 +35,13 @@ var imgur = function(dbot) {
|
||||
|
||||
'albumInfoString': function(albumData) {
|
||||
var info = '';
|
||||
if(!_.isUndefined(albumData) && _.has(albumData, 'data') && !_.isUndefined(albumData.data.id)) {
|
||||
if(albumData && _.has(albumData, 'data') && !_.isUndefined(albumData.data.id)) {
|
||||
albumData = albumData.data;
|
||||
if(albumData.title) {
|
||||
info += albumData.title + ' - ';
|
||||
}
|
||||
if(albumData.description) {
|
||||
info += albumData.description.split('\n')[0] + ' is ';
|
||||
info += albumData.description + ' is ';
|
||||
}
|
||||
info += 'an album with ' + albumData.images_count + ' images ';
|
||||
info += 'and ' + albumData.views + ' views';
|
||||
@ -71,7 +54,7 @@ var imgur = function(dbot) {
|
||||
|
||||
'galleryInfoString': function(galData) {
|
||||
var info = '';
|
||||
if(!_.isUndefined(galData) && _.has(galData, 'data') && !_.isUndefined(galData.data.is_album)) {
|
||||
if(galData && _.has(galData, 'data') && !_.isUndefined(galData.data.is_album)) {
|
||||
if(galData.data.is_album === true) {
|
||||
info = this.internalAPI.albumInfoString(galData);
|
||||
} else {
|
||||
@ -93,52 +76,30 @@ var imgur = function(dbot) {
|
||||
var testSlug = random(5);
|
||||
var testUrl = 'http://i.imgur.com/' +
|
||||
testSlug +
|
||||
'.' + ext[_.random(0, ext.length - 1)],
|
||||
fbman = false;
|
||||
dbot.db.imgur.totalHttpRequests += 1;
|
||||
|
||||
request(testUrl, function(error, response, body) {
|
||||
'.' + ext[_.random(0, ext.length - 1)];
|
||||
this.db.totalHttpRequests += 1;
|
||||
var image = request(testUrl, function(error, response, body) {
|
||||
// 492 is body.length of a removed image
|
||||
if(!error && response.statusCode == 200 && body.length != 492) {
|
||||
dbot.db.imgur.totalImages += 1;
|
||||
this.db.totalImages += 1;
|
||||
var hash = crypto.createHash('md5').update(body).digest("hex");
|
||||
if(_.has(dbot.modules, 'quotes')){
|
||||
// autoadd: {"abcdef": "facebookman"}
|
||||
if(_.has(dbot.config.modules.imgur.autoadd,hash)){
|
||||
fbman = true;
|
||||
var category = this.config.autoadd[hash];
|
||||
if(_.has(dbot.config.imgur.autoadd,hash)){
|
||||
var category = dbot.config.imgur.autoadd[hash];
|
||||
if (_.contains(category, testUrl)){
|
||||
// there's probably less than 62^5 chance of this happening
|
||||
} else {
|
||||
dbot.api.quotes.addQuote(category, testUrl,
|
||||
dbot.config.name, function() { });
|
||||
if(!_.has(dbot.db.quoteArrs, category)) dbot.db.quoteArrs[category] = [];
|
||||
dbot.db.quoteArrs[category].push(testUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
callback(testUrl, testSlug, hash, fbman);
|
||||
callback(testUrl, testSlug,hash);
|
||||
} else {
|
||||
this.api.getRandomImage(callback);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'getGoodRandomImage': function(callback) {
|
||||
this.api.getRandomImage(function(url, slug, hash, fbman) {
|
||||
this.api.getImageInfo(slug, function(imgData) {
|
||||
if(!_.isUndefined(imgData) &&
|
||||
imgData.data &&
|
||||
imgData.data.height > 500 && imgData.data.width > 500 &&
|
||||
!_.any(this.ExcludeRes, function(res) {
|
||||
return imgData.data.height == res.h && imgData.data.width == res.w;
|
||||
})) {
|
||||
callback(url, imgData);
|
||||
} else if(fbman === true) {
|
||||
callback(url, imgData);
|
||||
} else {
|
||||
this.api.getGoodRandomImage(callback);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'getImageInfoString': function(slug, callback) {
|
||||
@ -152,10 +113,10 @@ var imgur = function(dbot) {
|
||||
'url': 'https://api.imgur.com/3/image/' + slug + '.json',
|
||||
'json': true,
|
||||
'headers': {
|
||||
'Authorization': 'Client-ID ' + this.config.apikey
|
||||
'Authorization': 'Client-ID ' + dbot.config.imgur.apikey
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
dbot.db.imgur.totalApiRequests += 1;
|
||||
this.db.totalApiRequests += 1;
|
||||
callback(body);
|
||||
}.bind(this));
|
||||
},
|
||||
@ -165,7 +126,7 @@ var imgur = function(dbot) {
|
||||
'url': 'https://api.imgur.com/3/album/' + slug + '.json',
|
||||
'json': true,
|
||||
'headers': {
|
||||
'Authorization': 'Client-ID ' + this.config.apikey
|
||||
'Authorization': 'Client-ID ' + dbot.config.imgur.apikey
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
this.db.totalApiRequests += 1;
|
||||
@ -178,7 +139,7 @@ var imgur = function(dbot) {
|
||||
'url': 'https://api.imgur.com/3/gallery/' + slug + '.json',
|
||||
'json': true,
|
||||
'headers': {
|
||||
'Authorization': 'Client-ID ' + this.config.apikey
|
||||
'Authorization': 'Client-ID ' + dbot.config.imgur.apikey
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
this.db.totalApiRequests += 1;
|
||||
@ -193,95 +154,17 @@ var imgur = function(dbot) {
|
||||
|
||||
this.commands = {
|
||||
'~ri': function(event) {
|
||||
var local = event.user;
|
||||
if(event.params[1]) {
|
||||
local = event.params.splice(1, event.params.length - 1).join(' ').trim();
|
||||
}
|
||||
|
||||
var postImage = function(link, imgData) {
|
||||
var info = this.internalAPI.infoString(imgData);
|
||||
event.reply('['+this.config.outputPrefix + '] ' + local + ': ' + link + ' [' + info + ']');
|
||||
}.bind(this);
|
||||
var newCacheImage = function(link, imgData) {
|
||||
this.riCache.push([link, imgData]);
|
||||
}.bind(this);
|
||||
var callback = postImage;
|
||||
|
||||
if(this.riCache.length > 0) {
|
||||
var image = this.riCache.pop();
|
||||
postImage(image[0], image[1]);
|
||||
callback = newCacheImage;
|
||||
}
|
||||
|
||||
this.api.getGoodRandomImage(callback);
|
||||
},
|
||||
|
||||
// Legacy RI
|
||||
'~lri': function(event) {
|
||||
var local = event.user;
|
||||
if(event.params[1]) {
|
||||
local = event.params.splice(1, event.params.length - 1).join(' ').trim();
|
||||
}
|
||||
this.api.getRandomImage(function(link, slug) {
|
||||
this.api.getImageInfo(slug, function(imgData) {
|
||||
var info = this.internalAPI.infoString(imgData);
|
||||
event.reply('['+this.config.outputPrefix + '] ' + local + ': ' + link + ' [' + info + ']');
|
||||
event.reply(event.user + ': ' + link + ' [' + info + ']');
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
// Super RI
|
||||
'~sri': function(event) {
|
||||
var local = event.user;
|
||||
if(event.params[1]) {
|
||||
local = event.params.splice(1, event.params.length - 1).join(' ').trim();
|
||||
}
|
||||
request.get({
|
||||
'url': this.ApiRoot + 'gallery/random/random/',
|
||||
'json': true,
|
||||
'headers': {
|
||||
'Authorization': 'Client-ID ' + this.config.apikey
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
if(!_.isUndefined(body) && body.data && body.data[0] != undefined) {
|
||||
var num = _.random(0, body.data.length - 1);
|
||||
this.api.getGalleryInfo(body.data[num].id, function(gal) {
|
||||
event.reply('['+this.config.outputPrefix + '] ' + local + ': ' + gal.data.link + ' [' +
|
||||
this.internalAPI.galleryInfoString(gal) + ']');
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~imgur': function(event) {
|
||||
var term = event.input[1];
|
||||
request.get({
|
||||
'url': this.ApiRoot + 'gallery/search/',
|
||||
'json': true,
|
||||
'headers': {
|
||||
'Authorization': 'Client-ID ' + this.config.apikey
|
||||
},
|
||||
'qs': {
|
||||
'q': term
|
||||
}
|
||||
}, function(err, response, body) {
|
||||
if(!_.isUndefined(body) && body.data && body.data[0] != undefined) {
|
||||
var num = _.random(0, body.data.length - 1);
|
||||
this.api.getGalleryInfo(body.data[num].id, function(gal) {
|
||||
event.reply(dbot.t('imgurinfo', {
|
||||
'info': this.internalAPI.galleryInfoString(gal)
|
||||
}) + ' - ' + gal.data.link);
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply(dbot.t('imgur_noresults'));
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
this.commands['~imgur'].regex = [/^imgur ([\d\w\s-]*)/, 2];
|
||||
|
||||
this.onLoad = function() {
|
||||
var imgurHandler = function(matches, name, callback) {
|
||||
var imgurHandler = function(event, matches, name) {
|
||||
if(matches[1]) {
|
||||
var dataCallback = function(data) {
|
||||
var info;
|
||||
@ -293,7 +176,7 @@ var imgur = function(dbot) {
|
||||
info = this.internalAPI.galleryInfoString(data);
|
||||
}
|
||||
|
||||
if(info) callback(dbot.t('imgurinfo', { 'info': info }));
|
||||
if(info) event.reply(dbot.t('imgurinfo', { 'info': info }));
|
||||
}.bind(this);
|
||||
|
||||
if(name == 'imgurimage') {
|
||||
@ -311,17 +194,9 @@ var imgur = function(dbot) {
|
||||
dbot.api.link.addHandler('imgurimage', /https?:\/\/i\.imgur\.com\/([a-zA-Z0-9]+)\.([jpg|png|gif])/, imgurHandler);
|
||||
dbot.api.link.addHandler('imgurimage', /https?:\/\/imgur\.com\/([a-zA-Z0-9]+)/, imgurHandler);
|
||||
|
||||
async.times(this.config.ricachelength, function(n, next) {
|
||||
this.api.getGoodRandomImage(function(link, imgData) {
|
||||
this.riCache.push([ link, imgData ]);
|
||||
next();
|
||||
}.bind(this));
|
||||
}.bind(this), function() {});
|
||||
|
||||
if(!_.has(dbot.db.imgur, 'totalHttpRequests')) dbot.db.imgur.totalHttpRequests = 0;
|
||||
if(!_.has(dbot.db.imgur, 'totalApiRequests')) dbot.db.imgur.totalApiRequests = 0;
|
||||
if(!_.has(dbot.db.imgur, 'totalImages')) dbot.db.imgur.totalImages = 0;
|
||||
this.db = dbot.db.imgur;
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,13 @@ var _ = require('underscore')._;
|
||||
var pages = function(dbot) {
|
||||
return {
|
||||
'/imgur/random': function(req, res) {
|
||||
var highScore = 0;
|
||||
var quoteCat = dbot.db.quoteArrs[dbot.config.imgur.highscore],
|
||||
highScore = 0;
|
||||
|
||||
if(quoteCat) {
|
||||
highScore = _.last(quoteCat);
|
||||
}
|
||||
|
||||
res.render('imgurr', { "highscore" : highScore });
|
||||
},
|
||||
|
||||
|
@ -4,19 +4,9 @@
|
||||
"na'vi": "kxawm ke wivìntxu evengur",
|
||||
"cy": "Gallai fod yn anniogel ar gwaith",
|
||||
"nl": "bevat mogelijk gevoelige beelden",
|
||||
"de": "Könnte 18+ Material enthalten",
|
||||
"fr": "peut être risqué pour le travail (NSFW)",
|
||||
"it": "può essere rischioso al lavoro (NSFW)"
|
||||
"de": "Könnte 18+ Material enthalten"
|
||||
},
|
||||
"imgurinfo": {
|
||||
"en": "[{info}]",
|
||||
"de": "[{info}]",
|
||||
"fr": "[{info}]",
|
||||
"it": "[{info}]"
|
||||
},
|
||||
"imgur_noresults": {
|
||||
"en": "No results found.",
|
||||
"de": "Kein Suchergebnis.",
|
||||
"it": "Nessun risultato"
|
||||
"en": "[{info}]"
|
||||
}
|
||||
}
|
||||
|
@ -5,5 +5,6 @@
|
||||
}
|
||||
},
|
||||
"dependencies": [ "command" ],
|
||||
"ignorable": true
|
||||
"ignorable": true,
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/js/README.md"
|
||||
}
|
||||
|
@ -4,38 +4,31 @@
|
||||
* the channel. Also allows admins to run un-sandboxed Javascript code with
|
||||
* access to the DepressionBot instance memory.
|
||||
*/
|
||||
var VM = require('vm2').VM;
|
||||
var vm = require('vm');
|
||||
var sbox = require('sandbox');
|
||||
|
||||
var js = function(dbot) {
|
||||
var commands = {
|
||||
// Run JS code sandboxed, return result to channel.
|
||||
'~js': function(event) {
|
||||
try {
|
||||
var s = new VM({timeout: 1000, sandbox: {}});
|
||||
event.reply(s.run(event.input[1]));
|
||||
} catch(err) { event.reply(err); }
|
||||
var s = new sbox();
|
||||
s.run(event.input[1], function(output) {
|
||||
event.reply(output.result);
|
||||
}.bind(this));
|
||||
} catch(err) {}
|
||||
},
|
||||
|
||||
// Run JS code un-sandboxed, with access to DBot memory (admin-only).
|
||||
'~ajs': function(event) {
|
||||
var callback = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
for(var i=0;i<args.length;i++) {
|
||||
var arg = args[i];
|
||||
if(_.isObject(arg) && !_.isArray(arg)) {
|
||||
arg = '[object Object]: ' + _.keys(arg).join(', ');
|
||||
}
|
||||
event.reply('Callback[' + i + ']: ' + arg);
|
||||
}
|
||||
};
|
||||
var ret = eval(event.input[1]);
|
||||
if(ret !== undefined) {
|
||||
event.reply(ret);
|
||||
}
|
||||
}
|
||||
};
|
||||
commands['~js'].regex = [/^js (.*)/, 2];
|
||||
commands['~ajs'].regex = [/^ajs (.*)/, 2];
|
||||
commands['~js'].regex = [/^~js (.*)/, 2];
|
||||
commands['~ajs'].regex = [/^~ajs (.*)/, 2];
|
||||
commands['~ajs'].access = 'admin';
|
||||
|
||||
this.name = 'js';
|
||||
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"announce": [ { "server": "tripsit", "name": "#dbot" } ],
|
||||
"dbKeys": [ "karma" ],
|
||||
"dbType": "redis"
|
||||
}
|
@ -1,201 +0,0 @@
|
||||
/**
|
||||
* Module Name: Karma
|
||||
* Description: Thanking, with Karma!
|
||||
*/
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var karma = function(dbot) {
|
||||
this.lastKarma = {};
|
||||
|
||||
this.internalAPI = {
|
||||
'getKarma': function(item, callback) {
|
||||
this.db.read('karma', item.toLowerCase(), callback);
|
||||
}.bind(this),
|
||||
|
||||
'setKarma': function(item, value, callback) {
|
||||
this.db.save('karma', item.toLowerCase(), {
|
||||
'item': item.toLowerCase(),
|
||||
'karma': value
|
||||
}, callback);
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
this.commands = {
|
||||
'karma': function(event) {
|
||||
var item = event.params[1] || event.user;
|
||||
this.internalAPI.getKarma(item, function(err, karma) {
|
||||
if(!err && karma) {
|
||||
karma = karma.karma;
|
||||
} else {
|
||||
karma = 0;
|
||||
}
|
||||
|
||||
event.reply(dbot.t('karma', {
|
||||
'item': item,
|
||||
'karma': karma
|
||||
}));
|
||||
});
|
||||
},
|
||||
|
||||
'setkarma': function(event) {
|
||||
var item = event.params[1],
|
||||
value = parseInt(event.params[2]);
|
||||
|
||||
this.internalAPI.setKarma(item, value, function(err, karma) {
|
||||
event.reply(dbot.t('newkarma', {
|
||||
'item': item,
|
||||
'value': value
|
||||
}));
|
||||
});
|
||||
},
|
||||
|
||||
'unkarmaiest': function(event) {
|
||||
var karmas = {};
|
||||
this.db.scan('karma', function(karma) {
|
||||
if(karma && !_.isUndefined(karma.item)) {
|
||||
karmas[karma.item] = karma.karma;
|
||||
}
|
||||
}.bind(this), function(err) {
|
||||
var qSizes = _.chain(karmas)
|
||||
.pairs()
|
||||
.sortBy(function(category) { return category[1]; })
|
||||
.first(10)
|
||||
.value();
|
||||
|
||||
var qString = 'Unkarmaiest: ';
|
||||
for(var i=0;i<qSizes.length;i++) {
|
||||
qString += qSizes[i][0] + " (" + qSizes[i][1] + "), ";
|
||||
}
|
||||
|
||||
event.reply(qString.slice(0, -2));
|
||||
});
|
||||
},
|
||||
|
||||
'karmaiest': function(event) {
|
||||
var karmas = {};
|
||||
this.db.scan('karma', function(karma) {
|
||||
if(karma && !_.isUndefined(karma.item)) {
|
||||
karmas[karma.item] = karma.karma;
|
||||
}
|
||||
}.bind(this), function(err) {
|
||||
var qSizes = _.chain(karmas)
|
||||
.pairs()
|
||||
.sortBy(function(category) { return category[1]; })
|
||||
.reverse()
|
||||
.first(10)
|
||||
.value();
|
||||
|
||||
var qString = 'Karmaiest: ';
|
||||
for(var i=0;i<qSizes.length;i++) {
|
||||
qString += qSizes[i][0] + " (" + qSizes[i][1] + "), ";
|
||||
}
|
||||
|
||||
event.reply(qString.slice(0, -2));
|
||||
});
|
||||
},
|
||||
|
||||
'wattest': function(event) {
|
||||
var karmas = {};
|
||||
this.db.scan('karma', function(karma) {
|
||||
if(karma && !_.isUndefined(karma.item)) {
|
||||
if(karma.item.match(/_wat$/)) {
|
||||
karmas[karma.item] = karma.karma;
|
||||
}
|
||||
}
|
||||
}.bind(this), function(err) {
|
||||
var qSizes = _.chain(karmas)
|
||||
.pairs()
|
||||
.sortBy(function(category) { return category[1]; })
|
||||
.reverse()
|
||||
.first(10)
|
||||
.value();
|
||||
|
||||
var qString = 'Karmaiest: ';
|
||||
for(var i=0;i<qSizes.length;i++) {
|
||||
qString += qSizes[i][0] + " (" + qSizes[i][1] + "), ";
|
||||
}
|
||||
|
||||
event.reply(qString.slice(0, -2));
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
this.commands.setkarma.access = 'admin';
|
||||
|
||||
this.listener = function(event) {
|
||||
dbot.api.ignore.isUserBanned(event.rUser, 'karma', function(isBanned) {
|
||||
if(!isBanned) {
|
||||
var match = event.message.match(/^(.+)(\+\+|\-\-)$/);
|
||||
if(event.user !== dbot.config.name && match && match[1].length < 25) {
|
||||
match[1] = match[1].replace(/(\+|\-)/g,'').replace(/:/g,'').trim();
|
||||
|
||||
var timeout = 5000;
|
||||
/* if(event.channel.name == '#stims' || event.channel.name == '##meth' || event.channel.name == '##sweden') {
|
||||
timeout = 20000;
|
||||
}*/
|
||||
if(_.has(this.lastKarma, event.rUser.id) && this.lastKarma[event.rUser.id]+ timeout > Date.now()) {
|
||||
return event.reply('Try again in a few seconds : - )');
|
||||
} else if(event.rUser.currentNick.toLowerCase() === match[1].toLowerCase() || event.rUser.primaryNick.toLowerCase() === match[1].toLowerCase()) {
|
||||
return event.reply('Stop playing with yourself : - )');
|
||||
} else if(event.channel == event.user) {
|
||||
return event.reply('Don\'t be a Secretive Sally : - )');
|
||||
}
|
||||
|
||||
if(event.channel.name == '##wat') {
|
||||
match[1] = match[1].replace(/_wat$/, '');
|
||||
match[1] += '_wat';
|
||||
}
|
||||
|
||||
this.internalAPI.getKarma(match[1], function(err, karma) {
|
||||
if(!karma) {
|
||||
karma = 0;
|
||||
} else {
|
||||
karma = karma.karma;
|
||||
}
|
||||
|
||||
if(match[2] === '--') {
|
||||
if(match[1].toLowerCase() =='weed') {
|
||||
karma -= 2;
|
||||
} else {
|
||||
karma -= 1;
|
||||
}
|
||||
} else {
|
||||
if(match[1].toLowerCase() == 'weed') {
|
||||
karma += 2;
|
||||
} else {
|
||||
karma += 1;
|
||||
}
|
||||
}
|
||||
|
||||
this.internalAPI.setKarma(match[1], karma, function(err, karma) {
|
||||
this.lastKarma[event.rUser.id] = Date.now();
|
||||
var pre;
|
||||
if(karma.karma > 0) {
|
||||
pre = '[\u00039karma\u000f]';
|
||||
karma.karma = '\u00039 '+karma.karma+'\u000f';
|
||||
} else if(karma.karma < 0) {
|
||||
pre = '[\u00034karma\u000f]';
|
||||
karma.karma = '\u00034 '+karma.karma+'\u000f';
|
||||
} else {
|
||||
pre = '[\u00036karma\u000f]';
|
||||
karma.karma = '\u00036 '+karma.karma+'\u000f';
|
||||
}
|
||||
event.reply(pre + ' ' + dbot.t('newkarma', {
|
||||
'item': match[1],
|
||||
'value': karma.karma
|
||||
}));
|
||||
if(_.has(dbot.modules, 'log')) {
|
||||
dbot.api.log.logWithChannel(event.server, event.channel, event.rUser.primaryNick, event.message);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
this.on = 'PRIVMSG';
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new karma(dbot);
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"karma": {
|
||||
"en": "[karma] {item} has {karma} karma"
|
||||
},
|
||||
"newkarma": {
|
||||
"en": "{item} now has{value} karma"
|
||||
}
|
||||
}
|
@ -1,512 +1,278 @@
|
||||
var _ = require('underscore')._,
|
||||
uuid = require('node-uuid');
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var commands = function (dbot) {
|
||||
var commands = {
|
||||
/*** Kick Management ***/
|
||||
'~quiet': function (event) {
|
||||
var server = event.server,
|
||||
quieter = event.rUser,
|
||||
duration = event.input[1],
|
||||
channel = (event.input[2] || event.channel.name).trim(),
|
||||
quietee = event.input[3].trim(),
|
||||
reason = event.input[4] || "N/A";
|
||||
var commands = function(dbot) {
|
||||
var commands = {
|
||||
/*** Kick Management ***/
|
||||
'~quiet': function(event) {
|
||||
var server = event.server,
|
||||
quieter = event.user,
|
||||
minutes = event.input[1],
|
||||
channel = event.input[2],
|
||||
quietee = event.input[3].trim();
|
||||
|
||||
this.api.quietUser(server, quieter, duration, channel, quietee, reason, function (response) {
|
||||
event.reply(response);
|
||||
});
|
||||
},
|
||||
|
||||
'~timeout': function (event) {
|
||||
var server = event.server,
|
||||
quieter = event.rUser,
|
||||
duration = this.config.timeoutTime,
|
||||
channel = event.channel.name,
|
||||
quietee = event.input[1],
|
||||
reason = event.input[2] || "N/A";
|
||||
|
||||
reason += ' #timeout';
|
||||
|
||||
dbot.api.users.resolveUser(server, quietee, function (err, user) {
|
||||
if (!err && user) {
|
||||
if (!_.has(this.recentTimeouts, user.id)) {
|
||||
this.recentTimeouts[user.id] = 0;
|
||||
}
|
||||
|
||||
this.recentTimeouts[user.id] += 1;
|
||||
setTimeout(function () {
|
||||
this.recentTimeouts[user.id] -= 1;
|
||||
if (this.recentTimeouts[user.id] == 0) {
|
||||
delete this.recentTimeouts[user.id];
|
||||
if(_.isUndefined(channel)) {
|
||||
channel = event.channel.name;
|
||||
}
|
||||
}
|
||||
.bind(this), 3600000);
|
||||
channel = channel.trim();
|
||||
|
||||
if (this.recentTimeouts[user.id] == 3) {
|
||||
duration = null;
|
||||
reason += ' #permatimeout';
|
||||
dbot.say(event.server, dbot.config.servers[event.server].admin_channel, quietee + ' has been given three timeouts in the last hour, and so has been quieted indefinitely in ' + channel + '. Please review.');
|
||||
}
|
||||
|
||||
this.api.quietUser(server, quieter, duration, channel, quietee, reason, function (response) {
|
||||
event.reply(response);
|
||||
});
|
||||
}
|
||||
}
|
||||
.bind(this));
|
||||
},
|
||||
|
||||
'~unquiet': function (event) {
|
||||
var server = event.server,
|
||||
quieter = event.user,
|
||||
channel = (event.input[1] || event.channel.name).trim(),
|
||||
quietee = event.input[2].trim();
|
||||
|
||||
if (_.has(this.hosts[server], quietee)) {
|
||||
if (_.include(this.config.quietBans, channel)) {
|
||||
this.api.unban(server, this.hosts[server][quietee], channel);
|
||||
} else {
|
||||
this.api.unquiet(server, this.hosts[server][quietee], channel);
|
||||
}
|
||||
event.reply(dbot.t('unquieted', {
|
||||
'quietee': quietee
|
||||
}));
|
||||
dbot.api.report.notify('unquiet', server, event.rUser, channel,
|
||||
dbot.t('unquiet_notify', {
|
||||
'unquieter': quieter,
|
||||
'quietee': quietee
|
||||
}), false, quietee);
|
||||
}
|
||||
},
|
||||
|
||||
'~ckick': function (event) {
|
||||
var server = event.server,
|
||||
kicker = event.user,
|
||||
kickee = event.input[2],
|
||||
channel = event.input[1],
|
||||
reason = event.input[3];
|
||||
|
||||
if (_.isUndefined(channel)) {
|
||||
channel = event.channel.name;
|
||||
}
|
||||
channel = channel.trim();
|
||||
|
||||
this.api.kick(server, kickee, channel, reason + ' (requested by ' + kicker + ')');
|
||||
|
||||
dbot.api.report.notify('kick', server, event.rUser, channel, dbot.t('ckicked', {
|
||||
'kicker': kicker,
|
||||
'kickee': kickee,
|
||||
'reason': reason
|
||||
}), false, kickee);
|
||||
},
|
||||
|
||||
// Kick and ban from all channels on the network.
|
||||
'~nban': function (event) {
|
||||
if (!event.input)
|
||||
return;
|
||||
|
||||
var server = event.server,
|
||||
banner = event.user,
|
||||
timeout = event.input[1],
|
||||
banee = event.input[2],
|
||||
reason = event.input[3],
|
||||
adminChannel = dbot.config.servers[server].admin_channel,
|
||||
channels = _.keys(dbot.instance.connections[server].channels),
|
||||
network = event.server;
|
||||
|
||||
if (this.config.network_name[event.server]) {
|
||||
network = this.config.network_name[event.server];
|
||||
}
|
||||
|
||||
dbot.api.nickserv.getUserHost(event.server, banee, function (host) {
|
||||
// Add host record entry
|
||||
if (host) {
|
||||
var didKill = false;
|
||||
|
||||
if ((reason.match('#line') || reason.match('#specialk') || reason.match('#kline')) && _.include(dbot.access.moderator(), event.rUser.primaryNick)) {
|
||||
didKill = true;
|
||||
var t = ' !P ';
|
||||
if (timeout) {
|
||||
t = ' !T ' + timeout + ' ';
|
||||
}
|
||||
dbot.say(event.server, 'operserv', 'akill add ' + banee + t + banee + ' banned by ' + banner + ': ' + reason);
|
||||
}
|
||||
|
||||
// Do not ban if user was killed - redundant
|
||||
if(!didKill) {
|
||||
// Ban from current channel first
|
||||
this.api.ban(server, host, event.channel);
|
||||
this.api.kick(server, banee, event.channel, reason +
|
||||
' (network-wide ban)');
|
||||
channels = _.without(channels, event.channel);
|
||||
if (!_.isUndefined(adminChannel)) {
|
||||
channels = _.without(channels, adminChannel);
|
||||
if(!_.isUndefined(minutes)) {
|
||||
minutes = parseFloat(minutes.trim());
|
||||
var msTimeout = new Date(new Date().getTime() + (minutes * 60000));
|
||||
dbot.api.timers.addTimeout(msTimeout, function() {
|
||||
this.api.unquiet(server, quietee, channel);
|
||||
}.bind(this));
|
||||
event.reply(dbot.t('tquieted', {
|
||||
'quietee': quietee,
|
||||
'minutes': minutes
|
||||
}));
|
||||
} else {
|
||||
adminChannel = event.channel.name;
|
||||
event.reply(dbot.t('quieted', { 'quietee': quietee }));
|
||||
}
|
||||
|
||||
// Ban the user from all channels
|
||||
var i = 0;
|
||||
var banChannel = function (channels) {
|
||||
if (i >= channels.length)
|
||||
return;
|
||||
var channel = channels[i];
|
||||
this.api.ban(server, host, channel);
|
||||
this.api.kick(server, banee, channel, reason +
|
||||
' (network-wide ban)');
|
||||
i++;
|
||||
banChannel(channels);
|
||||
this.api.quiet(server, quietee, channel);
|
||||
},
|
||||
|
||||
'~unquiet': function(event) {
|
||||
var server = event.server,
|
||||
quieter = event.user,
|
||||
channel = event.input[1],
|
||||
quietee = event.input[2].trim();
|
||||
|
||||
if(_.isUndefined(channel)) {
|
||||
channel = event.channel.name;
|
||||
}
|
||||
.bind(this);
|
||||
banChannel(channels);
|
||||
}
|
||||
channel = channel.trim();
|
||||
|
||||
this.hosts[event.server][banee] = host;
|
||||
this.api.unquiet(server, quietee, channel);
|
||||
event.reply(dbot.t('unquieted', { 'quietee': quietee }));
|
||||
},
|
||||
|
||||
// Create notify string
|
||||
if (!_.isUndefined(timeout)) {
|
||||
timeout = timeout.trim();
|
||||
'~ckick': function(event) {
|
||||
var server = event.server,
|
||||
kicker = event.user,
|
||||
kickee = event.input[2],
|
||||
channel = event.input[1],
|
||||
reason = event.input[3];
|
||||
|
||||
var msTimeout = new Date(new Date().getTime() + (parseFloat(timeout) * 3600000));
|
||||
if (_.has(dbot.modules, 'remind')) {
|
||||
msTimeout = dbot.api.remind.parseTime(timeout);
|
||||
if (!msTimeout) {
|
||||
return event.reply('Invalid time. Remember you must give e.g. 5m now.');
|
||||
}
|
||||
timeout = timeout.replace(/([\d]+)d/, '$1 days').replace(/([\d]+)h/, '$1 hours ').replace(/([\d]+)m/, '$1 minutes ').replace(/([\d]+)s/, '$1 seconds').trim();
|
||||
} else {
|
||||
timeout += ' hours';
|
||||
}
|
||||
this.api.kick(server, kickee, channel, reason + ' (requested by ' + kicker + ')');
|
||||
|
||||
// Do not schedule unbans if the user was killed as no ban was put in place
|
||||
if(!didKill) {
|
||||
if (!_.has(this.tempBans, event.server))
|
||||
this.tempBans[event.server] = {};
|
||||
this.tempBans[event.server][banee] = msTimeout;
|
||||
this.internalAPI.addTempBan(event.server, banee, msTimeout);
|
||||
}
|
||||
dbot.api.report.notify(server, channel, dbot.t('ckicked', {
|
||||
'kicker': kicker,
|
||||
'kickee': kickee,
|
||||
'channel': channel,
|
||||
'reason': reason
|
||||
}));
|
||||
},
|
||||
|
||||
var notifyString = dbot.t('tbanned', {
|
||||
'network': network,
|
||||
'~cban': function(event) {
|
||||
var server = event.server,
|
||||
banner = event.user,
|
||||
banee = event.input[2],
|
||||
channel = event.input[1],
|
||||
reason = event.input[3];
|
||||
|
||||
this.api.ban(server, banee, channel);
|
||||
this.api.kick(server, kickee, channel, reason + ' (requested by ' + banner + ')');
|
||||
|
||||
dbot.api.report.notify(server, channel, dbot.t('cbanned', {
|
||||
'banner': banner,
|
||||
'banee': banee,
|
||||
'hours': timeout,
|
||||
'host': host,
|
||||
'channel': channel,
|
||||
'reason': reason
|
||||
});
|
||||
} else {
|
||||
var notifyString = dbot.t('nbanned', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'banee': banee,
|
||||
'host': host,
|
||||
'reason': reason
|
||||
});
|
||||
}
|
||||
|
||||
// Add db entry documenting ban
|
||||
if (this.config.document_bans) {
|
||||
var id = uuid.v4();
|
||||
var banRecord = {
|
||||
'id': id,
|
||||
'time': new Date().getTime(),
|
||||
'server': server,
|
||||
'banee': banee,
|
||||
'banner': banner,
|
||||
'host': host,
|
||||
'reason': reason
|
||||
};
|
||||
this.db.save('nbans', id, banRecord, function () {});
|
||||
}
|
||||
|
||||
// Notify moderators, banee
|
||||
if (!_.isUndefined(adminChannel)) {
|
||||
channels = _.without(channels, adminChannel);
|
||||
} else {
|
||||
adminChannel = event.channel.name;
|
||||
}
|
||||
|
||||
dbot.api.report.notify('ban', server, event.rUser, adminChannel, notifyString, false, banee);
|
||||
dbot.say(event.server, adminChannel, notifyString);
|
||||
|
||||
if (!_.isUndefined(timeout)) {
|
||||
dbot.say(event.server, banee, dbot.t('tbanned_notify', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'reason': reason,
|
||||
'hours': timeout,
|
||||
'admin_channel': adminChannel
|
||||
}));
|
||||
} else {
|
||||
dbot.say(event.server, banee, dbot.t('nbanned_notify', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'reason': reason,
|
||||
'hours': timeout,
|
||||
'admin_channel': adminChannel
|
||||
}));
|
||||
}
|
||||
|
||||
// err
|
||||
dbot.say(event.server, 'NickServ', 'FREEZE ' + banee + ' ON ' + reason);
|
||||
} else {
|
||||
event.reply(dbot.t('no_user', {
|
||||
'user': banee
|
||||
}));
|
||||
}
|
||||
}
|
||||
.bind(this));
|
||||
},
|
||||
},
|
||||
|
||||
'~nunban': function (event) {
|
||||
var unbanee = event.params[1],
|
||||
host = event.params[2] || undefined,
|
||||
unbanner = event.rUser;
|
||||
// Kick and ban from all channels on the network.
|
||||
'~nban': function(event) {
|
||||
if(!event.input) return;
|
||||
|
||||
this.api.networkUnban(event.server, unbanee, unbanner, host, function (err) {
|
||||
if (err) {
|
||||
event.reply(dbot.t('nunban_error', {
|
||||
'unbanee': unbanee
|
||||
}));
|
||||
}
|
||||
});
|
||||
},
|
||||
var server = event.server,
|
||||
banner = event.user,
|
||||
timeout = event.input[1],
|
||||
banee = event.input[2],
|
||||
reason = event.input[3],
|
||||
adminChannel = this.config.admin_channel[event.server];
|
||||
channels = dbot.config.servers[server].channels,
|
||||
network = event.server;
|
||||
|
||||
/*** Kick Stats ***/
|
||||
|
||||
// Give the number of times a given user has been kicked and has kicked
|
||||
// other people.
|
||||
'~kickcount': function (event) {
|
||||
var username = event.params[1];
|
||||
|
||||
if (!_.has(dbot.db.kicks, username)) {
|
||||
var kicks = '0';
|
||||
} else {
|
||||
var kicks = dbot.db.kicks[username];
|
||||
}
|
||||
|
||||
if (!_.has(dbot.db.kickers, username)) {
|
||||
var kicked = '0';
|
||||
} else {
|
||||
var kicked = dbot.db.kickers[username];
|
||||
}
|
||||
|
||||
event.reply(dbot.t('user_kicks', {
|
||||
'user': username,
|
||||
'kicks': kicks,
|
||||
'kicked': kicked
|
||||
}));
|
||||
},
|
||||
|
||||
// Output a list of the people who have been kicked the most and those
|
||||
// who have kicked other people the most.
|
||||
'~kickstats': function (event) {
|
||||
var orderedKickLeague = function (list, topWhat) {
|
||||
var kickArr = _.chain(list)
|
||||
.pairs()
|
||||
.sortBy(function (kick) {
|
||||
return kick[1]
|
||||
})
|
||||
.reverse()
|
||||
.first(10)
|
||||
.value();
|
||||
|
||||
var kickString = "Top " + topWhat + ": ";
|
||||
for (var i = 0; i < kickArr.length; i++) {
|
||||
kickString += kickArr[i][0] + " (" + kickArr[i][1] + "), ";
|
||||
}
|
||||
|
||||
return kickString.slice(0, -2);
|
||||
};
|
||||
|
||||
event.reply(orderedKickLeague(dbot.db.kicks, 'Kicked'));
|
||||
event.reply(orderedKickLeague(dbot.db.kickers, 'Kickers'));
|
||||
},
|
||||
|
||||
'~votequiet': function (event) {
|
||||
var target = event.input[1],
|
||||
reason = event.input[2];
|
||||
|
||||
if (_.has(event.channel.nicks, target)) {
|
||||
dbot.api.users.resolveUser(event.server, target, function (err, user) {
|
||||
if (!err && user) {
|
||||
if (_.include(dbot.access.power_user(), user.primaryNick) || target == dbot.config.name) {
|
||||
return event.reply('User is immune to votequiet.');
|
||||
if(this.config.network_name[event.server]) {
|
||||
network = this.config.network_name[event.server];
|
||||
}
|
||||
console.log(timeout);
|
||||
console.log(banee);
|
||||
console.log(reason);
|
||||
|
||||
if (!_.has(this.voteQuiets, user.id)) {
|
||||
this.voteQuiets[user.id] = {
|
||||
'user': user.id,
|
||||
'reason': reason,
|
||||
'channel': event.channel,
|
||||
'yes': [event.rUser.primaryNick],
|
||||
'no': []
|
||||
};
|
||||
event.reply(event.user + ' has started a vote to quiet ' + target + ' for "' + reason + '." Type either "~voteyes ' + target + '" or "~voteno ' + target + '" in the next 90 seconds.');
|
||||
dbot.api.nickserv.getUserHost(event.server, banee, function(host) {
|
||||
// Add host record entry
|
||||
if(host) {
|
||||
if(!_.has(this.hosts, event.server)) this.hosts[event.server] = {};
|
||||
this.hosts[event.server][banee] = host;
|
||||
|
||||
this.voteQuiets[user.id].timer = setTimeout(function () {
|
||||
var vq = this.voteQuiets[user.id];
|
||||
vq.spent = true;
|
||||
if (vq.yes.length >= 3 && vq.no.length < 2) {
|
||||
event.reply('Attempt to quiet ' + target + ' succeeded. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
|
||||
// Create notify string
|
||||
if(!_.isUndefined(timeout)) {
|
||||
timeout = parseFloat(timeout.trim());
|
||||
|
||||
var msTimeout = new Date(new Date().getTime() + (timeout * 3600000));
|
||||
if(!_.has(this.tempBans, event.server)) this.tempBans[event.server] = {};
|
||||
this.tempBans[event.server][banee] = msTimeout;
|
||||
this.internalAPI.addTempBan(event.server, banee, msTimeout);
|
||||
|
||||
this.api.quietUser(event.server, event.rUser, '10m', event.channel, target, reason + '[votequiet]', function (response) {
|
||||
clearTimeout(vq.timer);
|
||||
event.reply(response);
|
||||
});
|
||||
} else {
|
||||
event.reply('Attempt to quiet ' + target + ' failed. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
|
||||
}
|
||||
|
||||
var nString = 'A votequiet was attempted on ' + target + ' in ' + event.channel + '. It was initiated by ' + event.rUser.primaryNick + '. ' +
|
||||
vq.yes.join(', ') + ' voted yes (' + vq.yes.length + '). ';
|
||||
if (vq.no.length > 0) {
|
||||
nString += vq.no.join(', ') + ' voted no (' + vq.no.length + ').'
|
||||
}
|
||||
|
||||
dbot.api.report.notify('votequiet', event.server, event.rUser, event.channel, nString, false, target);
|
||||
|
||||
setTimeout(function () {
|
||||
delete this.voteQuiets[user.id];
|
||||
}
|
||||
.bind(this), 600000);
|
||||
}
|
||||
.bind(this), 90000);
|
||||
} else {
|
||||
if (this.voteQuiets[user.id].spent) {
|
||||
event.reply('A votequiet attempt has already been made on this user in the last 10 minutes.');
|
||||
} else {
|
||||
var vq = this.voteQuiets[user.id]
|
||||
if (!_.include(vq.yes, event.rUser.primaryNick)) {
|
||||
vq.yes.push(event.rUser.primaryNick);
|
||||
|
||||
event.reply('There is already a votequiet attempt active for this user, adding yes vote to existing poll.');
|
||||
event.reply('Voted yes on votequiet for ' + target + '. New count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
|
||||
|
||||
if (vq.yes.length == 4) {
|
||||
event.reply('Attempt to quiet ' + target + ' succeeded. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
|
||||
this.api.quietUser(event.server, event.rUser, '10m', event.channel, target, reason + '[votequiet]', function (response) {
|
||||
clearTimeout(vq.timer);
|
||||
vq.spent = true;
|
||||
setTimeout(function () {
|
||||
delete this.voteQuiets[user.id];
|
||||
}
|
||||
.bind(this), 600000);
|
||||
event.reply(response);
|
||||
});
|
||||
var notifyString = dbot.t('tbanned', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'banee': banee,
|
||||
'hours': timeout,
|
||||
'reason': reason
|
||||
});
|
||||
var quoteString = dbot.t('tban_quote', {
|
||||
'banee': banee,
|
||||
'banner': banner,
|
||||
'hours': timeout,
|
||||
'time': new Date().toUTCString(),
|
||||
'reason': reason
|
||||
});
|
||||
} else {
|
||||
var notifyString = dbot.t('nbanned', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'banee': banee,
|
||||
'reason': reason
|
||||
});
|
||||
var quoteString = dbot.t('nban_quote', {
|
||||
'banee': banee,
|
||||
'banner': banner,
|
||||
'time': new Date().toUTCString(),
|
||||
'reason': reason
|
||||
});
|
||||
}
|
||||
} else {
|
||||
event.reply('There is already a votequiet attempt active for this user, and you already voted yes!');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
event.reply('Target does not seem to be in the channel.');
|
||||
}
|
||||
}
|
||||
.bind(this));
|
||||
} else {
|
||||
event.reply('Target does not seem to be in the channel.');
|
||||
}
|
||||
},
|
||||
|
||||
'~voteyes': function (event) {
|
||||
var target = event.params[1];
|
||||
// Add qutoe category documenting ban
|
||||
if(this.config.document_bans && _.has(dbot.modules, 'quotes')) {
|
||||
dbot.db.quoteArrs['ban_' + banee.toLowerCase()] = [ quoteString ];
|
||||
notifyString += ' ' + dbot.t('quote_recorded', { 'user': banee });
|
||||
}
|
||||
|
||||
dbot.api.users.resolveUser(event.server, target, function (err, user) {
|
||||
if (!err && user) {
|
||||
if (user.id == event.rUser.id) {
|
||||
return event.reply('You cannot vote on your own silencing. Be good.');
|
||||
}
|
||||
if (_.has(this.voteQuiets, user.id) && !this.voteQuiets[user.id].spent) {
|
||||
var vq = this.voteQuiets[user.id];
|
||||
if (event.channel != vq.channel) {
|
||||
return event.reply('Vote must be in ' + vq.channel);
|
||||
}
|
||||
if (!_.include(vq.yes, event.rUser.primaryNick) && !_.include(vq.no, event.rUser.primaryNick)) {
|
||||
vq.yes.push(event.rUser.primaryNick);
|
||||
event.reply('Voted yes on votequiet for ' + target + '. New count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
|
||||
// Notify moderators, banee
|
||||
if(this.config.admin_channel[event.server]) {
|
||||
channels = _.without(channels, adminChannel);
|
||||
|
||||
if (vq.yes.length == 4) {
|
||||
event.reply('Attempt to quiet ' + target + ' succeeded. Count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
|
||||
this.api.quietUser(event.server, event.rUser, '10m', event.channel, target, vq.reason + '[votequiet]', function (response) {
|
||||
clearTimeout(vq.timer);
|
||||
vq.spent = true;
|
||||
setTimeout(function () {
|
||||
delete this.voteQuiets[user.id];
|
||||
}
|
||||
.bind(this), 600000);
|
||||
event.reply(response);
|
||||
});
|
||||
}
|
||||
dbot.api.report.notify(server, adminChannel, notifyString);
|
||||
dbot.say(event.server, adminChannel, notifyString);
|
||||
|
||||
if(!_.isUndefined(timeout)) {
|
||||
dbot.say(event.server, banee, dbot.t('tbanned_notify', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'reason': reason,
|
||||
'hours': timeout,
|
||||
'admin_channel': adminChannel
|
||||
}));
|
||||
} else {
|
||||
dbot.say(event.server, banee, dbot.t('nbanned_notify', {
|
||||
'network': network,
|
||||
'banner': banner,
|
||||
'reason': reason,
|
||||
'hours': timeout,
|
||||
'admin_channel': adminChannel
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// Ban the user from all channels
|
||||
var i = 0;
|
||||
var banChannel = function(channels) {
|
||||
if(i >= channels.length) return;
|
||||
var channel = channels[i];
|
||||
this.api.ban(server, banee, channel);
|
||||
this.api.kick(server, banee, channel, reason +
|
||||
' (network-wide ban requested by ' + banner + ')');
|
||||
setTimeout(function() {
|
||||
i++; banChannel(channels);
|
||||
}, 1000);
|
||||
}.bind(this);
|
||||
banChannel(channels);
|
||||
} else {
|
||||
event.reply(dbot.t('no_user', { 'user': banee }));
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~nunban': function(event) {
|
||||
var unbanee = event.params[1],
|
||||
unbanner = event.user;
|
||||
|
||||
this.api.networkUnban(event.server, unbanee, unbanner, function(err) {
|
||||
if(err) {
|
||||
event.reply(dbot.t('nunban_error', { 'unbanee': unbanee }));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/*** Kick Stats ***/
|
||||
|
||||
// Give the number of times a given user has been kicked and has kicked
|
||||
// other people.
|
||||
'~kickcount': function(event) {
|
||||
var username = event.params[1];
|
||||
|
||||
if(!_.has(dbot.db.kicks, username)) {
|
||||
var kicks = '0';
|
||||
} else {
|
||||
event.reply('You have already voted.');
|
||||
var kicks = dbot.db.kicks[username];
|
||||
}
|
||||
} else {
|
||||
event.reply('There is no active votequiet for this user. You can start one by typing "~votequiet ' + target + ' [reason].');
|
||||
}
|
||||
} else {
|
||||
event.reply('No idea who that is m8');
|
||||
}
|
||||
}
|
||||
.bind(this));
|
||||
},
|
||||
|
||||
'~voteno': function (event) {
|
||||
var target = event.params[1];
|
||||
|
||||
dbot.api.users.resolveUser(event.server, target, function (err, user) {
|
||||
if (!err && user) {
|
||||
if (user.id == event.rUser.id) {
|
||||
return event.reply('You cannot vote on your own silencing. Be good.');
|
||||
}
|
||||
if (_.has(this.voteQuiets, user.id) && !this.voteQuiets[user.id].spent) {
|
||||
var vq = this.voteQuiets[user.id];
|
||||
if (event.channel != vq.channel) {
|
||||
return event.reply('Vote must be in ' + vq.channel);
|
||||
}
|
||||
if (!_.include(vq.yes, event.rUser.primaryNick) && !_.include(vq.no, event.rUser.primaryNick)) {
|
||||
vq.no.push(event.rUser.primaryNick);
|
||||
event.reply('Voted no on votequiet for ' + target + '. New count: Yes (' + vq.yes.length + '). No (' + vq.no.length + ').');
|
||||
if(!_.has(dbot.db.kickers, username)) {
|
||||
var kicked = '0';
|
||||
} else {
|
||||
event.reply('You have already voted.');
|
||||
var kicked = dbot.db.kickers[username];
|
||||
}
|
||||
} else {
|
||||
event.reply('There is no active votequiet for this user. You can start one by typing "~votequiet ' + target + ' [reason].');
|
||||
}
|
||||
} else {
|
||||
event.reply('No idea who that is m8');
|
||||
|
||||
event.reply(dbot.t('user_kicks', {
|
||||
'user': username,
|
||||
'kicks': kicks,
|
||||
'kicked': kicked
|
||||
}));
|
||||
},
|
||||
|
||||
// Output a list of the people who have been kicked the most and those
|
||||
// who have kicked other people the most.
|
||||
'~kickstats': function(event) {
|
||||
var orderedKickLeague = function(list, topWhat) {
|
||||
var kickArr = _.chain(list)
|
||||
.pairs()
|
||||
.sortBy(function(kick) { return kick[1] })
|
||||
.reverse()
|
||||
.first(10)
|
||||
.value();
|
||||
|
||||
var kickString = "Top " + topWhat + ": ";
|
||||
for(var i=0;i<kickArr.length;i++) {
|
||||
kickString += kickArr[i][0] + " (" + kickArr[i][1] + "), ";
|
||||
}
|
||||
|
||||
return kickString.slice(0, -2);
|
||||
};
|
||||
|
||||
event.reply(orderedKickLeague(dbot.db.kicks, 'Kicked'));
|
||||
event.reply(orderedKickLeague(dbot.db.kickers, 'Kickers'));
|
||||
}
|
||||
}
|
||||
.bind(this));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
_.each(commands, function (command) {
|
||||
command.access = 'moderator';
|
||||
});
|
||||
_.each(commands, function(command) {
|
||||
command.access = 'moderator';
|
||||
});
|
||||
|
||||
commands['~kickcount'].access = 'regular';
|
||||
commands['~kickstats'].access = 'regular';
|
||||
commands['~votequiet'].access = 'regular';
|
||||
commands['~voteyes'].access = 'regular';
|
||||
commands['~voteno'].access = 'regular';
|
||||
commands['~quiet'].access = 'voice';
|
||||
commands['~timeout'].access = 'voice';
|
||||
commands['~unquiet'].access = 'voice';
|
||||
commands['~nban'].access = 'power_user';
|
||||
commands['~nunban'].access = 'power_user';
|
||||
commands['~kickcount'].access = 'regular';
|
||||
commands['~kickstats'].access = 'regular';
|
||||
|
||||
commands['~ckick'].regex = /^ckick (#[^ ]+ )?([^ ]+) ?(.*)?$/;
|
||||
commands['~nban'].regex = /^nban (\d[\d\.dhmsy]+)? ?([^ ]+) (.+)$/;
|
||||
commands['~quiet'].regex = /^quiet (\d[\d\.hmsy]+)? ?(#[^ ]+ )?([^ ]+) ?(.*)?$/;
|
||||
commands['~timeout'].regex = /^timeout ([^ ]+) ?(.*)?$/;
|
||||
commands['~unquiet'].regex = /^unquiet (#[^ ]+ )?([^ ]+) ?$/;
|
||||
commands['~votequiet'].regex = [/^votequiet ([^ ]+) (.+)$/, 3];
|
||||
commands['~ckick'].regex = [/^~ckick ([^ ]+) ([^ ]+) (.+)$/, 4];
|
||||
commands['~nban'].regex = /^~nban ([\d\.^ ]+)?([^ ]+) (.+)$/;
|
||||
commands['~quiet'].regex = /^~quiet ([\d\.^ ]+)?(#[^ ]+ )?([^ ]+) ?$/;
|
||||
commands['~unquiet'].regex = /^~unquiet (#[^ ]+ )?([^ ]+) ?$/;
|
||||
|
||||
return commands;
|
||||
return commands;
|
||||
};
|
||||
|
||||
exports.fetch = function (dbot) {
|
||||
return commands(dbot);
|
||||
exports.fetch = function(dbot) {
|
||||
return commands(dbot);
|
||||
};
|
||||
|
@ -1,18 +1,15 @@
|
||||
{
|
||||
"dbKeys": [ "kicks", "kickers", "hosts", "tempBans" ],
|
||||
"dependencies": [ "command", "report", "users" ],
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/kick/README.md",
|
||||
"ignorable": true,
|
||||
"countSilently": true,
|
||||
"quietBans": [
|
||||
"#wherever"
|
||||
],
|
||||
"admin_channel": {
|
||||
"aberwiki": "#fishbox"
|
||||
},
|
||||
"network_name": {
|
||||
"aberwiki": "OAOSIDL"
|
||||
},
|
||||
"chanserv": "ChanServ",
|
||||
"document_bans": false,
|
||||
"dbType": "redis",
|
||||
"requireWebLogin": true,
|
||||
"webAccess": "power_user",
|
||||
"timeoutTime": "10m"
|
||||
"document_bans": false
|
||||
}
|
||||
|
@ -1,270 +1,132 @@
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var kick = function (dbot) {
|
||||
if (!_.has(dbot.db, 'recentTimeouts')) {
|
||||
dbot.db.recentTimeouts = {};
|
||||
}
|
||||
this.recentTimeouts = dbot.db.recentTimeouts;
|
||||
|
||||
this.api = {
|
||||
'ban': function (server, host, channel) {
|
||||
dbot.instance.connections[server].send('MODE ' + channel + ' +b *!*@' + host);
|
||||
},
|
||||
|
||||
'quiet': function (server, host, channel) {
|
||||
dbot.instance.connections[server].send('MODE ' + channel + ' +q *!*@' + host);
|
||||
},
|
||||
|
||||
'unquiet': function (server, host, channel) {
|
||||
dbot.instance.connections[server].send('MODE ' + channel + ' -q *!*@' + host);
|
||||
},
|
||||
|
||||
'devoice': function (server, nick, channel) {
|
||||
dbot.instance.connections[server].send('MODE ' + channel + ' -v ' + nick);
|
||||
},
|
||||
|
||||
'voice': function (server, nick, channel) {
|
||||
dbot.instance.connections[server].send('MODE ' + channel + ' +v ' + nick);
|
||||
},
|
||||
|
||||
'kick': function (server, user, channel, msg) {
|
||||
dbot.instance.connections[server].send('KICK ' + channel + ' ' + user + ' :' + msg);
|
||||
},
|
||||
|
||||
'kill': function (server, user, reason) {
|
||||
dbot.instance.connections[server].send('kill ' + user + ' ' + reason);
|
||||
},
|
||||
|
||||
'unban': function (server, host, channel) {
|
||||
// TODO: Wrest control from chanserv
|
||||
//dbot.say(server, this.config.chanserv, 'unban ' + channel + ' *!*@' + host);
|
||||
dbot.instance.connections[server].send('MODE ' + channel + ' -b *!*@' + host);
|
||||
},
|
||||
|
||||
'quietUser': function (server, quieter, duration, channel, quietee, reason, callback) {
|
||||
dbot.api.nickserv.getUserHost(server, quietee, function (host) {
|
||||
// Add host record entry
|
||||
if (host) {
|
||||
this.hosts[server][quietee] = host;
|
||||
|
||||
if (!_.isUndefined(duration) && !_.isNull(duration)) {
|
||||
duration = duration.trim();
|
||||
var msTimeout = new Date(new Date().getTime() + (parseFloat(duration) * 60000));
|
||||
if (_.has(dbot.modules, 'remind')) {
|
||||
msTimeout = dbot.api.remind.parseTime(duration);
|
||||
if (!msTimeout) {
|
||||
return callback('Invalid time. Remember you must give e.g. 5m now.');
|
||||
}
|
||||
duration = duration.replace(/([\d]+)d/, '$1 years').replace(/([\d]+)d/, '$1 days').replace(/([\d]+)h/, '$1 hours ').replace(/([\d]+)m/, '$1 minutes ').replace(/([\d]+)s/, '$1 seconds').trim();
|
||||
} else {
|
||||
duration += ' minutes';
|
||||
}
|
||||
|
||||
var vStatus = dbot.instance.connections[server].channels[channel].nicks[quietee].voice;
|
||||
dbot.api.timers.addTimeout(msTimeout, function () {
|
||||
if (_.has(this.hosts[server], quietee)) {
|
||||
if (_.include(this.config.quietBans, channel)) {
|
||||
this.api.unban(server, this.hosts[server][quietee], channel);
|
||||
this.api.voice(server, quietee, channel);
|
||||
} else {
|
||||
this.api.unquiet(server, this.hosts[server][quietee], channel);
|
||||
}
|
||||
|
||||
dbot.api.users.resolveUser(server, dbot.config.name, function (err, user) {
|
||||
dbot.api.report.notify('unquiet', server, user, channel,
|
||||
dbot.t('unquiet_notify', {
|
||||
'unquieter': dbot.config.name,
|
||||
'quietee': quietee
|
||||
}), false, quietee);
|
||||
});
|
||||
}
|
||||
}
|
||||
.bind(this));
|
||||
callback(dbot.t('tquieted', {
|
||||
'quietee': quietee,
|
||||
'minutes': duration
|
||||
}));
|
||||
dbot.api.report.notify('quiet', server, quieter.primaryNick, channel,
|
||||
dbot.t('tquiet_notify', {
|
||||
'minutes': duration,
|
||||
'quieter': quieter.primaryNick,
|
||||
'quietee': quietee,
|
||||
'reason': reason
|
||||
}), false, quietee);
|
||||
} else {
|
||||
callback(dbot.t('quieted', {
|
||||
'quietee': quietee
|
||||
}));
|
||||
dbot.api.report.notify('quiet', server, quieter.primaryNick, channel,
|
||||
dbot.t('quiet_notify', {
|
||||
'quieter': quieter.primaryNick,
|
||||
'quietee': quietee,
|
||||
'reason': reason
|
||||
}), false, quietee);
|
||||
}
|
||||
|
||||
this.api.devoice(server, quietee, channel);
|
||||
|
||||
if (_.include(this.config.quietBans, channel)) {
|
||||
this.api.ban(server, this.hosts[server][quietee], channel);
|
||||
} else {
|
||||
this.api.quiet(server, host, channel);
|
||||
}
|
||||
|
||||
if (reason.indexOf('#warn') !== -1) {
|
||||
dbot.api.warning.warn(server, quieter, quietee,
|
||||
'Quieted in ' + channel + ' for ' + reason, channel,
|
||||
function () {});
|
||||
}
|
||||
} else {
|
||||
event.reply(dbot.t('no_user', {
|
||||
'user': quietee
|
||||
}));
|
||||
}
|
||||
}
|
||||
.bind(this));
|
||||
},
|
||||
|
||||
'networkUnban': function (server, unbanee, unbanner, manualHost, callback) {
|
||||
var channels = dbot.config.servers[server].channels,
|
||||
network = this.config.network_name[server] || server,
|
||||
adminChannel = dbot.config.servers[server].admin_channel;
|
||||
|
||||
if (!_.isUndefined(manualHost)) {
|
||||
this.hosts[server][unbanee] = manualHost;
|
||||
}
|
||||
|
||||
if (_.has(this.hosts, server) && _.has(this.hosts[server], unbanee) && _.isString(this.hosts[server][unbanee])) {
|
||||
var host = this.hosts[server][unbanee];
|
||||
|
||||
// Notify Staff
|
||||
if (_.isUndefined(adminChannel)) {
|
||||
adminChannel = event.channel.name;
|
||||
}
|
||||
|
||||
var notifyString = dbot.t('nunbanned', {
|
||||
'network': network,
|
||||
'unbanee': unbanee,
|
||||
'host': host,
|
||||
'unbanner': unbanner.currentNick
|
||||
});
|
||||
dbot.api.report.notify('unban', server, unbanner, adminChannel, notifyString, false, unbanee);
|
||||
dbot.say(server, adminChannel, notifyString);
|
||||
|
||||
// Notify Unbanee
|
||||
dbot.say(server, unbanee, dbot.t('nunban_notify', {
|
||||
'network': network,
|
||||
'unbanee': unbanee,
|
||||
'unbanner': unbanner.currentNick
|
||||
}));
|
||||
|
||||
// Unban
|
||||
var i = 0;
|
||||
var unbanChannel = function (channels) {
|
||||
if (i >= channels.length)
|
||||
return;
|
||||
var channel = channels[i];
|
||||
this.api.unban(server, host, channel);
|
||||
setTimeout(function () {
|
||||
i++;
|
||||
unbanChannel(channels);
|
||||
}, 1000);
|
||||
}
|
||||
.bind(this);
|
||||
unbanChannel(channels);
|
||||
|
||||
dbot.say(server, 'NickServ', 'FREEZE ' + unbanee + ' OFF');
|
||||
callback(null); // Success
|
||||
} else {
|
||||
// Attempt to look up the host on-the-fly
|
||||
dbot.api.nickserv.getUserHost(server, unbanee, unbanner, function (host) {
|
||||
if (host) {
|
||||
if (!_.has(this.hosts, server))
|
||||
this.hosts[server] = {};
|
||||
this.hosts[server][unbanee] = host;
|
||||
this.api.networkUnban(server, unbanee, unbanner);
|
||||
} else {
|
||||
callback(true); // No host could be found
|
||||
}
|
||||
}
|
||||
.bind(this));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.internalAPI = {
|
||||
'addTempBan': function (server, banee, timeout) {
|
||||
dbot.api.users.resolveUser(server, dbot.config.name, function (err, bot) {
|
||||
dbot.api.timers.addTimeout(timeout, function () {
|
||||
this.api.networkUnban(server, banee, bot, undefined, function (err) {});
|
||||
delete this.tempBans[server][banee];
|
||||
}
|
||||
.bind(this));
|
||||
}
|
||||
.bind(this));
|
||||
}
|
||||
.bind(this)
|
||||
};
|
||||
|
||||
this.listener = function (event) {
|
||||
if (event.kickee == dbot.config.name) {
|
||||
dbot.instance.join(event, event.channel.name);
|
||||
event.reply(dbot.t('kicked_dbot', {
|
||||
'botname': dbot.config.name
|
||||
}));
|
||||
dbot.db.kicks[dbot.config.name] += 1;
|
||||
} else {
|
||||
if (!_.has(dbot.db.kicks, event.kickee)) {
|
||||
dbot.db.kicks[event.kickee] = 1;
|
||||
} else {
|
||||
dbot.db.kicks[event.kickee] += 1;
|
||||
}
|
||||
|
||||
if (!_.has(dbot.db.kickers, event.user)) {
|
||||
dbot.db.kickers[event.user] = 1;
|
||||
} else {
|
||||
dbot.db.kickers[event.user] += 1;
|
||||
}
|
||||
|
||||
if (!this.config.countSilently) {
|
||||
event.reply(event.kickee + '-- (' + dbot.t('user_kicks', {
|
||||
'user': event.kickee,
|
||||
'kicks': dbot.db.kicks[event.kickee],
|
||||
'kicked': dbot.db.kickers[event.kickee]
|
||||
}) + ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
.bind(this);
|
||||
this.on = 'KICK';
|
||||
|
||||
this.onLoad = function () {
|
||||
if (!_.has(dbot.db, 'hosts')) {
|
||||
dbot.db.hosts = {};
|
||||
_.each(dbot.config.servers, function (v, k) {
|
||||
dbot.db.hosts[k] = {};
|
||||
}, this);
|
||||
}
|
||||
if (!_.has(dbot.db, 'tempBans'))
|
||||
dbot.db.tempBans = {};
|
||||
var kick = function(dbot) {
|
||||
this.hosts = dbot.db.hosts;
|
||||
this.tempBans = dbot.db.tempBans;
|
||||
this.voteQuiets = {};
|
||||
|
||||
this.api = {
|
||||
'ban': function(server, user, channel) {
|
||||
dbot.say(server, this.config.chanserv, 'ban ' + channel + ' ' + user);
|
||||
},
|
||||
|
||||
_.each(this.tempBans, function (bans, server) {
|
||||
_.each(bans, function (timeout, nick) {
|
||||
timeout = new Date(timeout);
|
||||
this.internalAPI.addTempBan(server, nick, timeout);
|
||||
}, this);
|
||||
}, this);
|
||||
'quiet': function(server, user, channel) {
|
||||
dbot.say(server, this.config.chanserv, 'quiet ' + channel + ' ' + user);
|
||||
},
|
||||
|
||||
if (_.has(dbot.modules, 'web')) {
|
||||
dbot.api.web.addIndexLink('/bans', 'Ban List');
|
||||
}
|
||||
}
|
||||
.bind(this);
|
||||
'unquiet': function(server, user, channel) {
|
||||
dbot.say(server, this.config.chanserv, 'unquiet ' + channel + ' ' + user);
|
||||
},
|
||||
|
||||
'kick': function(server, user, channel, msg) {
|
||||
dbot.instance.connections[server].send('KICK ' + channel + ' ' + user + ' :' + msg);
|
||||
},
|
||||
|
||||
'unban': function(server, host, channel) {
|
||||
dbot.say(server, this.config.chanserv, 'unban ' + channel + ' *!*@' + host);
|
||||
},
|
||||
|
||||
'networkUnban': function(server, unbanee, unbanner, callback) {
|
||||
var channels = dbot.config.servers[server].channels,
|
||||
network = this.config.network_name[server] || server,
|
||||
adminChannel = this.config.admin_channel[server];
|
||||
|
||||
if(_.has(this.hosts, server) && _.has(this.hosts[server], unbanee)) {
|
||||
var host = this.hosts[server][unbanee];
|
||||
|
||||
// Notify Staff
|
||||
if(!_.isUndefined(adminChannel)) {
|
||||
var notifyString = dbot.t('nunbanned', {
|
||||
'network': network,
|
||||
'unbanee': unbanee,
|
||||
'unbanner': unbanner
|
||||
});
|
||||
dbot.api.report.notify(server, adminChannel, notifyString);
|
||||
dbot.say(server, adminChannel, notifyString);
|
||||
}
|
||||
|
||||
// Notify Unbanee
|
||||
dbot.say(server, unbanee, dbot.t('nunban_notify', {
|
||||
'network': network,
|
||||
'unbanee': unbanee,
|
||||
'unbanner': unbanner
|
||||
}));
|
||||
|
||||
// Unban
|
||||
var i = 0;
|
||||
var unbanChannel = function(channels) {
|
||||
if(i >= channels.length) return;
|
||||
var channel = channels[i];
|
||||
this.api.unban(server, host, channel);
|
||||
setTimeout(function() {
|
||||
i++; unbanChannel(channels);
|
||||
}, 1000);
|
||||
}.bind(this);
|
||||
unbanChannel(channels);
|
||||
|
||||
callback(null); // Success
|
||||
} else {
|
||||
// Attempt to look up the host on-the-fly
|
||||
dbot.api.nickserv.getUserHost(server, unbanee, function(host) {
|
||||
if(host) {
|
||||
if(!_.has(this.hosts, server)) this.hosts[server] = {};
|
||||
this.hosts[server][unbanee] = host;
|
||||
this.api.networkUnban(server, unbanee, unbanner);
|
||||
} else {
|
||||
callback(true); // No host could be found
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.internalAPI = {
|
||||
'addTempBan': function(server, banee, timeout) {
|
||||
dbot.api.timers.addTimeout(timeout, function() {
|
||||
this.api.networkUnban(server, banee, dbot.config.name, function(err) {});
|
||||
delete this.tempBans[server][banee];
|
||||
}.bind(this));
|
||||
}.bind(this)
|
||||
};
|
||||
|
||||
this.listener = function(event) {
|
||||
if(event.kickee == dbot.config.name) {
|
||||
dbot.instance.join(event, event.channel);
|
||||
event.reply(dbot.t('kicked_dbot', { 'botname': dbot.config.name }));
|
||||
dbot.db.kicks[dbot.config.name] += 1;
|
||||
} else {
|
||||
if(!_.has(dbot.db.kicks, event.kickee)) {
|
||||
dbot.db.kicks[event.kickee] = 1;
|
||||
} else {
|
||||
dbot.db.kicks[event.kickee] += 1;
|
||||
}
|
||||
|
||||
if(!_.has(dbot.db.kickers, event.user)) {
|
||||
dbot.db.kickers[event.user] = 1;
|
||||
} else {
|
||||
dbot.db.kickers[event.user] += 1;
|
||||
}
|
||||
|
||||
if(!this.config.countSilently) {
|
||||
event.reply(event.kickee + '-- (' + dbot.t('user_kicks', {
|
||||
'user': event.kickee,
|
||||
'kicks': dbot.db.kicks[event.kickee],
|
||||
'kicked': dbot.db.kickers[event.kickee]
|
||||
}) + ')');
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
this.on = 'KICK';
|
||||
|
||||
this.onLoad = function() {
|
||||
_.each(this.tempBans, function(bans, server) {
|
||||
_.each(bans, function(timeout, nick) {
|
||||
timeout = new Date(timeout);
|
||||
this.internalAPI.addTempBan(server, nick, timeout);
|
||||
}, this);
|
||||
}, this);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
exports.fetch = function (dbot) {
|
||||
return new kick(dbot);
|
||||
exports.fetch = function(dbot) {
|
||||
return new kick(dbot);
|
||||
};
|
||||
|
@ -1,46 +0,0 @@
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var pages = function (dbot) {
|
||||
return {
|
||||
'/bans': function (req, res) {
|
||||
res.render('servers', {
|
||||
'servers': _.keys(dbot.config.servers)
|
||||
});
|
||||
},
|
||||
|
||||
'/underbans': function (req, res) {
|
||||
this.db.search('nbans', {
|
||||
'server': server
|
||||
}, function (ban) {
|
||||
if (ban.reason.match('#underban')) {
|
||||
bans.push(ban);
|
||||
}
|
||||
}, function () {
|
||||
res.render('bans', {
|
||||
'server': server,
|
||||
'bans': bans
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
'/bans/:server': function (req, res) {
|
||||
var server = req.params.server,
|
||||
bans = [];
|
||||
|
||||
this.db.search('nbans', {
|
||||
'server': server
|
||||
}, function (ban) {
|
||||
bans.push(ban);
|
||||
}, function () {
|
||||
res.render('bans', {
|
||||
'server': server,
|
||||
'bans': bans
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.fetch = function (dbot) {
|
||||
return pages(dbot);
|
||||
};
|
@ -5,39 +5,16 @@
|
||||
"na'vi": "Tuteol {user}it tsrame'i {kicks} hìmtxan ulte sute tsrame'i {kicked} hìmtxan.",
|
||||
"cy": "Cafwyd {user} ei gicio {kicks} gwaith ac wedi cicio pobl {kicked} gwaith.",
|
||||
"nl": "{user} is {kicks} keer gekickt en heeft anderen {kicked} keer gekickt.",
|
||||
"de": "{user} wurde {kicks} mal gekickt und hat {kicked} mal andere Benutzer gekickt.",
|
||||
"fr": "{user} a été kické {kicks} fois et a kické des personnes {kicked} fois.",
|
||||
"it": "{user} ha ricevuto {kicks} pedata/e e ha dato {kicked} pedata/e a altri utenti"
|
||||
"de": "{user} wurde {kicks} mal gekickt und hat {kicked} mal andere Benutzer gekickt."
|
||||
},
|
||||
"quieted": {
|
||||
"en": "Quieted {quietee}. Remember: don't be a coconut.",
|
||||
"fr": "{quietee} a été rendu silencieux. Rappelle-toi : ne sois pas têtu.",
|
||||
"it": "{quietee} è stato silenziato. Ricordati: non essere testardo",
|
||||
"de": "{quietee} stummgestellt. Denk dran: Sei kein Arschloch."
|
||||
"en": "Quieted {quietee}. Remember: don't be a coconut."
|
||||
},
|
||||
"tquieted": {
|
||||
"en": "Quieted {quietee} for {minutes}. Remember: don't be a coconut.",
|
||||
"fr": "{quietee} a été rendu silencieux pour {minutes} minutes. Rappelle-toi : ne sois pas têtu.",
|
||||
"it": "{quietee} è stato silenziato per {minutes} minuto/i. Ricordati: non essere testardo",
|
||||
"de": "{quietee} für {minutes} Minuten stummgestellt. Denk dran: Sei kein Arschloch."
|
||||
},
|
||||
"quiet_notify": {
|
||||
"en": "{quieter} has quieted {quietee}. The reason given was \"{reason}\".",
|
||||
"de": "{quieter} hat {quietee} stummgestellt. Der Grund ist \"{reason}\"."
|
||||
},
|
||||
"tquiet_notify": {
|
||||
"en": "{quieter} has quieted {quietee} for {minutes} minutes. The reason given was \"{reason}\".",
|
||||
"de": "{quieter} hat {quietee} für {minutes} Minuten stummgestellt. Der Grund ist \"{reason}\"."
|
||||
"en": "Quieted {quietee} for {minutes} minutes. Remember: don't be a coconut."
|
||||
},
|
||||
"unquieted": {
|
||||
"en": "Unquieted {quietee}. Remember: don't be a coconut.",
|
||||
"fr": "{quietee} peut maintenant parler. Rappelle-toi : ne sois pas têtu.",
|
||||
"it": "{quietee} può nuovamente parlare. Ricordati: non essere testardo.",
|
||||
"de": "{quietee} ist nicht mehr stummgestellt. Denk dran: Sei kein Arschloch."
|
||||
},
|
||||
"unquiet_notify": {
|
||||
"en": "{unquieter} has unquieted {quietee}.",
|
||||
"de": "{unquieter} hat Stummstellung von {quietee} aufgehoben."
|
||||
"en": "Unquieted {quietee}. Remember: don't be a coconut."
|
||||
},
|
||||
"kicked_dbot": {
|
||||
"en": "Thou shalt not kick {botname}",
|
||||
@ -45,71 +22,52 @@
|
||||
"na'vi": "Ngal {botname}it ke tsun tsrive'i",
|
||||
"cy": "Ni ddylech cicio {botname}",
|
||||
"nl": "Gij zult {botname} niet kicken",
|
||||
"de": "Du sollst {botname} nicht kicken",
|
||||
"fr": "Tu ne kickeras pas {botname}",
|
||||
"it": "Non dare pedata a {botname}"
|
||||
"de": "Du sollst {botname} nicht kicken"
|
||||
},
|
||||
"ckicked": {
|
||||
"en": "{kicker} has kicked {kickee}. The reason given was: \"{reason}\".",
|
||||
"cy": "Sylw: {kicker} wedi cicio'r {kickee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}\".",
|
||||
"de": "Achtung: {kicker} hat {kickee} von {channel} verwiesen. Grund: \"{reason}\".",
|
||||
"fr": "Attention : {kicker} a kické {kickee} de {channel}. Raison donnée : \"{reason}\".",
|
||||
"it": "Attenzione : {kicker} ha dato una pedata a {kickee} di {channel}. Motivo : \"{reason}\"."
|
||||
"en": "Attention: {kicker} has kicked {kickee} from {channel}. The reason given was: \"{reason}.\"",
|
||||
"cy": "Sylw: {kicker} wedi cicio'r {kickee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}.\"",
|
||||
"de": "Achtung: {kicker} hat {kickee} von {channel} verwiesen. Grund: \"{reason}.\""
|
||||
},
|
||||
"cbanned": {
|
||||
"en": "Attention: {banner} has banned {banee} from {channel}. The reason given was \"{reason}\".",
|
||||
"cy": "Sylw: {banner} wedi gwahardd {banee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}\".",
|
||||
"de": "Achtung: {banner} hat {banee} von {channel} gebannt. Grund: \"{reason}\".",
|
||||
"fr": "Attention : {banner} a banni {banee} de {channel}. Raison donnée : \"{reason}\".",
|
||||
"it": "Attenzione : {banner} ha bandito {banee} da {channel}. Motivo : \"{reason}\"."
|
||||
"en": "Attention: {banner} has banned {banee} from {channel}. The reason given was \"{reason}.\"",
|
||||
"cy": "Sylw: {banner} wedi gwahardd {banee} o {channel}. Y rheswm a roddwyd oedd: \"{reason}.\"",
|
||||
"de": "Achtung: {banner} hat {banee} von {channel} gebannt. Grund: \"{reason}.\""
|
||||
},
|
||||
"tbanned": {
|
||||
"en": "Attention: {banner} has banned {banee} (host: {host}) from the {network} network for {hours}. The reason given was \"{reason}\".",
|
||||
"de": "Achtung: {banner} hat {banee} vom {network} Netzwerk für {hours} Stunden verbannt. Der Grund war \"{reason}\".",
|
||||
"fr": "Attention : {banner} a banni {banee} du réseau {network} pour {hours} heures. Raison donnée : \"{reason}\".",
|
||||
"it": "Attenzione : {banner} ha bandito {banee} dalla rete {network} per {hours} ora/e. Motivo : \"{reason}\"."
|
||||
"en": "Attention: {banner} has banned {banee} from the {network} network for {hours} hours. The reason given was \"{reason}.\""
|
||||
},
|
||||
"tbanned_notify": {
|
||||
"en": "You have been banned from the {network} network for {hours} by {banner}. The reason given was \"{reason}\". You can join {admin_channel} for more information or to discuss the ban.",
|
||||
"de": "Du wurdest von {banner} im {network} Netzwerk für {hours} verbannt. Der Grund war \"{reason}\". Du kannst {admin_channel} beitreten um mehr Informatonen zu erhalten oder über die Verbannung zu diskutieren.",
|
||||
"fr": "Vous avez été banni du réseau {network} pour {hours} heures par {banner}. La raison donnée était \"{reason}\". Vous pouvez rejoindre {admin_channel} pour plus d'information or pour discuter du ban.",
|
||||
"it": "Sei stato bandito dalla rete {network} per {hours} ora/e da {banner}. Motivo: \"{reason}\". Puoi ricongiungere {admin_channel} per ulteriori informazioni o discutere sulla messa al bando."
|
||||
"en": "You have been banned from the {network} network for {hours} hours by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban."
|
||||
},
|
||||
"nbanned": {
|
||||
"en": "Attention: {banner} has banned {banee} (host: {host}) from the {network} network. The reason given was \"{reason}\".",
|
||||
"cy": "Sylw: {banner} wedi gwahardd {banee} ledled y rhwydwaith. Y rheswm a roddwyd oedd: \"{reason}\".",
|
||||
"de": "Achtung: {banner} hat {banee} auf dem gesamten Netzwerk gebannt. Grund: \"{reason}\".",
|
||||
"fr": "Attention : {banner} a banni {banee} du réseau {network}. Raison donnée : \"{reason}\".",
|
||||
"it": "Attentione : {banner} ha bandito {banee} dalla rete {network}. Motivo : \"{reason}\"."
|
||||
"en": "Attention: {banner} has banned {banee} from the {network} network. The reason given was \"{reason}.\"",
|
||||
"cy": "Sylw: {banner} wedi gwahardd {banee} ledled y rhwydwaith. Y rheswm a roddwyd oedd: \"{reason}.\"",
|
||||
"de": "Achtung: {banner} hat {banee} auf dem gesamten Netzwerk gebannt. Grund: \"{reason}.\""
|
||||
},
|
||||
"nbanned_notify": {
|
||||
"en": "You have been banned from the {network} network by {banner}. The reason given was \"{reason}\". You can join {admin_channel} for more information or to discuss the ban.",
|
||||
"de": "Du wurdest von {banner} im {network} Netzwerk verbannt. Der Grund war \"{reason}\". Du kannst {admin_channel} beitreten um mehr Informatonen zu erhalten oder über die Verbannung zu diskutieren.",
|
||||
"fr": "Vous avez été banni du réseau {network} par {banner}. La raison donnée était \"{reason}\". Vous pouvez rejoindre {admin_channel} pour plus d'information or pour discuter du ban.",
|
||||
"it": "Sei stato bandito dalla rete {network} da {banner}. Motivo: \"{reason}\". Puoi ricongiungere {admin_channel} per ulteriori informazioni o discutere sulla messa al bando."
|
||||
"en": "You have been banned from the {network} network by {banner}. The reason given was \"{reason}.\" You can join {admin_channel} for more information or to discuss the ban."
|
||||
},
|
||||
"no_user": {
|
||||
"en": "{user} doesn't seem to be online on this server.",
|
||||
"de": "{user} scheint auf diesen Server nicht online zu sein.",
|
||||
"fr": "{user} ne semble pas être connecté à ce serveur.",
|
||||
"it": "{user} sembra non essere connesso a questo server"
|
||||
"nban_quote": {
|
||||
"en": "{banee} was banned from the network by {banner} on {time}. The reason given was \"{reason}.\"",
|
||||
"cy": "Cafodd {banee} ei wahardd o'r rhwydwaith gan {banner} ar {time}. Y rheswm a roddwyd oedd: \"{reason}.\"",
|
||||
"de": "{banee} wurde von {banner} auf dem gesamten Netzwerk um {time} gebannt. Grund: \"{reason}.\""
|
||||
},
|
||||
"no_user": {
|
||||
"en": "{user} doesn't seem to be online on this server."
|
||||
},
|
||||
"nunbanned": {
|
||||
"en": "Attention: {unbanee} (host: {host}) has been unbanned from the {network} network by {unbanner}.",
|
||||
"de": "Achtung: {unbanee} wurde im {network} Netzwerk durch {unbanner} entsperrt.",
|
||||
"fr": "Attention : {unbanee} a été débanni du réseau {network} par {unbanner}.",
|
||||
"it": "Attenzione : {unbanee} è stato riammesso alla rete {network} da {unbanner}."
|
||||
"en": "Attention: {unbanee} has been unbanned from the {network} network by {unbanner}."
|
||||
},
|
||||
"nunban_notify": {
|
||||
"en": "You have been unbanned from the {network} network by {unbanner}.",
|
||||
"de": "Du wurdest im {network} Netzwerk durch {unbanner} entsperrt.",
|
||||
"fr": "Vous avez été débanni du réseau {network} par {unbanner}.",
|
||||
"it": "Sei stato riammesso alla rete {network} da {unbanner}."
|
||||
"en": "You have been unbanned from the {network} network by {unbanner}."
|
||||
},
|
||||
"nunban_error": {
|
||||
"en": "It appears {unbanee} was not banned using the ~nban command.",
|
||||
"de": "Es sieht so aus als ob {unbanee} nicht durch die Verwendung des ~nban Befehls verbannt wurde.",
|
||||
"fr": "Il semble que {unbanee} n'a pas été banni en utilisant la commande ~nban.",
|
||||
"it": "Sembar che {unbanee} non è stato bandito usano il commando ~nban."
|
||||
"en": "It appears {unbanee} was not banned using the ~nban command."
|
||||
},
|
||||
"quote_recorded": {
|
||||
"en": "This has been recorded in ~ban_{user}.",
|
||||
"cy": "Mae hyn wedi cael ei gofnodi yn ~ban_{user}.",
|
||||
"de": "Dies wurde in ~ban_{user} aufgenommen."
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
{
|
||||
"~ckick": "~ckick [#channel] [username] [reason]",
|
||||
"~cban": "~cban [#channel] [username] [reason]",
|
||||
"~nban": "~nban ([time in hours]) [username] [reason]",
|
||||
"~nban": "~nban [username] [reason]",
|
||||
"~kickstats": "~kickstats",
|
||||
"~kickcount": "~kickcount [user]",
|
||||
"~quiet": "~quiet (time) (#channel) username (reason)",
|
||||
"~unquiet": "~unquiet (#channel) username"
|
||||
"~kickcount": "~kickcount [user]"
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
{
|
||||
"action": "kill",
|
||||
"sensitivity": 10,
|
||||
"exempt": [],
|
||||
"advert_content": [
|
||||
"________ ______"
|
||||
],
|
||||
"cliconn_channel": "#dnsbl",
|
||||
"cliconn_patterns": [],
|
||||
"exempt_channels": []
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
/**
|
||||
* Module name: kill_namespam
|
||||
* Description: destroy those wot hilight too many nicks at once . usually
|
||||
* advertising their rubbish irc server (do not)
|
||||
*/
|
||||
|
||||
var _ = require('underscore')._;
|
||||
|
||||
var kill_namespam = function(dbot) {
|
||||
this.saveConfig = function() { // eugh
|
||||
dbot.customConfig.modules.kill_namespam = this.config;
|
||||
dbot.modules.admin.internalAPI.saveConfig();
|
||||
}.bind(this);
|
||||
|
||||
this.matchedKill = {};
|
||||
|
||||
this.listener = function(event) {
|
||||
if(event.action == 'PRIVMSG') {
|
||||
// Here we listen for atropos
|
||||
if(event.channel == this.config.cliconn_channel) {
|
||||
if(event.message.match('▶')) {
|
||||
var matchedPattern = _.find(this.config.cliconn_patterns,
|
||||
function(p) { try { return event.message.match(p); } catch(e) {}; }); // ok.jpg
|
||||
if(matchedPattern) {
|
||||
var nick = event.message.split(' ')[2];
|
||||
dbot.api.nickserv.getUserHost(event.server, nick, function(host) {
|
||||
var userIsAuthenticated = host && host.startsWith('tripsit/');
|
||||
if (userIsAuthenticated) {
|
||||
event.reply(dbot.t('clikill_spared', {
|
||||
'user': nick,
|
||||
'pattern': matchedPattern
|
||||
}));
|
||||
} else {
|
||||
if(!this.matchedKill[host]) {
|
||||
// Defer killing this connection until after they join a non-exempted channel
|
||||
this.matchedKill[host] = {
|
||||
ip: event.message.split(' ')[1],
|
||||
server: event.server,
|
||||
matchedPattern: matchedPattern,
|
||||
rUser: event.rUser
|
||||
};
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is the namespam
|
||||
if(event.channel == event.user) return; // return if pm
|
||||
if(_.includes(this.config.exempt, event.user)) return;
|
||||
|
||||
var message;
|
||||
var naughty = false;
|
||||
|
||||
// Check distinctive spam content match
|
||||
if(_.any(this.config.advert_content, function(spam) { return event.message.indexOf(spam) != -1; })) {
|
||||
message = dbot.t('spamcont_act', {
|
||||
'user': event.user,
|
||||
'channel': event.channel,
|
||||
'action': this.config.action
|
||||
}) + ' ' + dbot.t('sasl_hint');
|
||||
naughty = true;
|
||||
}
|
||||
|
||||
// Name highlight spam
|
||||
if(_.filter(event.message.split(' '), function(word) { return _.has(event.channel.nicks, word); }).length > this.config.sensitivity) {
|
||||
message = dbot.t('namespam_act', {
|
||||
'user': event.user,
|
||||
'channel': event.channel,
|
||||
'action': this.config.action,
|
||||
'sensitivity': this.config.sensitivity
|
||||
}) + ' ' + dbot.t('sasl_hint');
|
||||
naughty = true;
|
||||
}
|
||||
|
||||
if(naughty) {
|
||||
switch(this.config.action) {
|
||||
case 'kickban':
|
||||
dbot.api.kick.ban(event.server, event.host, event.channel);
|
||||
dbot.api.kick.kick(event.server, event.user, message);
|
||||
break;
|
||||
case 'kill':
|
||||
dbot.api.kick.kill(event.server, event.user, message);
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
||||
dbot.api.report.notify('spam', event.server, event.user, event.channel, message, event.host, event.user);
|
||||
}
|
||||
} else if (event.action == 'JOIN') {
|
||||
|
||||
if(this.matchedKill[event.host]) {
|
||||
if(this.config.exempt_channels.indexOf(event.channel) == -1) {
|
||||
var kill = this.matchedKill[event.host];
|
||||
delete this.matchedKill[event.host];
|
||||
|
||||
// Alternatively you can just do dbot.api.kick.kill(event.server, event.user, message);
|
||||
dbot.say(event.server, 'operserv', 'akill add *@'+ kill.ip +' !P Naughty Nelly Auto-kill v6.2. Matched pattern: /'+ kill.matchedPattern +'/');
|
||||
|
||||
var msg = dbot.t('clikill_act', {
|
||||
'ip': kill.ip,
|
||||
'pattern': kill.matchedPattern
|
||||
});
|
||||
dbot.api.report.notify('autokill', kill.server, kill.rUser,
|
||||
dbot.config.servers[kill.server].admin_channel, msg, kill.ip, kill.ip);
|
||||
}
|
||||
}
|
||||
} else if (event.action == 'QUIT') {
|
||||
if(this.matchedKill[event.host]) {
|
||||
delete this.matchedKill[event.host];
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
this.on = ['PRIVMSG', 'JOIN', 'QUIT'];
|
||||
|
||||
this.commands = {
|
||||
'~add_spamkill': function(event) {
|
||||
this.config.advert_content.push(event.params.slice(1).join(' '))
|
||||
this.saveConfig();
|
||||
event.reply('Users daring to utter the above to be classified as spam.');
|
||||
},
|
||||
|
||||
'~del_spamkill': function(event) {
|
||||
this.config.advert_content = _.without(this.config.advert_content, event.params.slice(1).join(' '));
|
||||
this.saveConfig();
|
||||
event.reply('Users will no longer be killed for this utterance.');
|
||||
},
|
||||
|
||||
'~add_clikill': function(event) {
|
||||
var pattern = event.params.slice(1).join(' ');
|
||||
this.config.cliconn_patterns.push(pattern);
|
||||
this.saveConfig();
|
||||
event.reply('Client connection notices matching pattern /'+ pattern +'/ shall henceforth get rekt.');
|
||||
},
|
||||
|
||||
'~del_clikill': function(event) {
|
||||
var pattern = event.params.slice(1).join(' ');
|
||||
this.config.cliconn_patterns = _.without(this.config.cliconn_patterns, pattern);
|
||||
this.saveConfig();
|
||||
event.reply('Client connection notices matching pattern /'+ pattern +'/ will no longer get rekt.');
|
||||
},
|
||||
|
||||
'~list_clikill': function(event) {
|
||||
event.reply('Currently active "cliconn" kills (to use add/del, provide the pattern, not the index, and do not include the surrounding //');
|
||||
_.each(this.config.cliconn_patterns, function(pattern, i) {
|
||||
event.reply('['+i+'] /' + pattern + '/');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
_.each(this.commands, function(c) {
|
||||
c.access = 'moderator';
|
||||
});
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new kill_namespam(dbot);
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
{
|
||||
"namespam_act": {
|
||||
"en": "{user} triggered nickname hilight anti-spam (greater than {sensitivity}). Action: {action}."
|
||||
},
|
||||
"spamcont_act": {
|
||||
"en": "{user} triggered advertising anti-spam (content). Action: {action}"
|
||||
},
|
||||
"clikill_act": {
|
||||
"en": "Added K-Line for {ip}, due to matching pattern: /{pattern}/"
|
||||
},
|
||||
"clikill_spared": {
|
||||
"en": "{user} spared from clikill matched pattern: /{pattern}/"
|
||||
},
|
||||
"sasl_hint": {
|
||||
"en": "You have been killed by our spam filter. You can avoid broad VPN filters by using SASL."
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
## LastFM
|
||||
|
||||
Adds various LastFM functionalities.
|
||||
|
||||
### Description
|
||||
|
||||
This module provides a command which allows users to show stats of LastFM and such stuff.
|
||||
|
||||
### Dependencies
|
||||
|
||||
It has following dependencies:
|
||||
+ [request](https://github.com/mikeal/request)
|
||||
+ [async](https://github.com/caolan/async)
|
||||
+ [moment](https://github.com/moment/moment)
|
||||
|
||||
### config.json
|
||||
|
||||
api_key and output prefix can be set.
|
||||
Example:
|
||||
```
|
||||
{
|
||||
"dependencies": [ "profile" ],
|
||||
"api_key": "blah",
|
||||
"outputPrefix": "\u000315,5last.fm\u000f"
|
||||
}
|
||||
```
|
||||
|
||||
### Commands
|
||||
|
||||
|
||||
#### ~lastfm [user]
|
||||
Display all scrobbles of a user.
|
||||
Example:
|
||||
+ ~lastfm reality
|
||||
|
||||
#### ~scrobbliest
|
||||
Displays the users with the most scrobbles.
|
||||
Example:
|
||||
+ ~scrobbliest
|
||||
|
||||
#### ~suggestion
|
||||
Displays a suggestion based on the listened scrobbles.
|
||||
Example:
|
||||
+ ~suggestion
|
||||
|
||||
#### ~listening
|
||||
Displays the currently/last played song of the posting user.
|
||||
Example:
|
||||
+ ~listening
|
||||
|
||||
#### ~taste [user]
|
||||
Compares two users (the posting user and the defined user).
|
||||
Example:
|
||||
+ ~taste reality
|
||||
|
||||
#### ~tastiest
|
||||
Displays the users that matches the most in music taste.
|
||||
Example:
|
||||
+ ~tastiest
|
||||
|
||||
#### ~artists [user]
|
||||
Compares two users (the posting user and the defined user) and displays their matching artists.
|
||||
Example:
|
||||
+ ~artists reality
|
||||
|
||||
### TODO
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"dependencies": [ "profile", "youtube", "spotify" ],
|
||||
"api_key": "blah",
|
||||
"outputPrefix": "\u000315,5last.fm\u000f"
|
||||
}
|
@ -1,526 +0,0 @@
|
||||
/**
|
||||
* Module Name: Last.FM
|
||||
* Description: Various lastfm functionality.
|
||||
*/
|
||||
|
||||
var _ = require('underscore')._,
|
||||
request = require('request'),
|
||||
async = require('async'),
|
||||
moment = require('moment');
|
||||
|
||||
var lastfm = function(dbot) {
|
||||
this.ApiRoot = 'http://ws.audioscrobbler.com/2.0/';
|
||||
|
||||
this.internalAPI = {
|
||||
'getLastFM': function(server, nick, callback) {
|
||||
dbot.api.profile.getProfile(server, nick, function(err, user, profile) {
|
||||
if(user) {
|
||||
if(profile && _.has(profile.profile, 'lastfm') && _.isString(profile.profile.lastfm)) {
|
||||
callback(user, profile.profile.lastfm.toLowerCase());
|
||||
} else {
|
||||
callback(user, null);
|
||||
}
|
||||
} else {
|
||||
callback(null, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.api = {
|
||||
'getRandomArtistTrack': function(mbid, callback) {
|
||||
request.get(this.ApiRoot, {
|
||||
'qs': {
|
||||
'method': 'artist.gettoptracks',
|
||||
'mbid': mbid,
|
||||
'api_key': this.config.api_key,
|
||||
'format': 'json',
|
||||
'limit': 10
|
||||
},
|
||||
'json': true
|
||||
}, function(err, res, body) {
|
||||
if(_.has(body, 'toptracks') && _.has(body.toptracks, 'track')) {
|
||||
var tracks = body.toptracks.track;
|
||||
choice = _.random(0, tracks.length - 1),
|
||||
track = tracks[choice];
|
||||
callback(null, track);
|
||||
} else {
|
||||
callback('idk', body);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getSimilarArtists': function(mbid, callback) {
|
||||
request.get(this.ApiRoot, {
|
||||
'qs': {
|
||||
'method': 'artist.getsimilar',
|
||||
'mbid': mbid,
|
||||
'api_key': this.config.api_key,
|
||||
'format': 'json',
|
||||
'limit': 10
|
||||
},
|
||||
'json': true
|
||||
}, function(err, res, body) {
|
||||
if(_.has(body, 'similarartists') && _.has(body.similarartists, 'artist')) {
|
||||
callback(null, body.similarartists.artist);
|
||||
} else {
|
||||
callback('idk', body);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'getListening': function(username, callback) {
|
||||
request.get(this.ApiRoot, {
|
||||
'qs': {
|
||||
'user': username,
|
||||
'limit': 2,
|
||||
'nowplaying': true,
|
||||
'method': 'user.getrecenttracks',
|
||||
'api_key': this.config.api_key,
|
||||
'format': 'json'
|
||||
},
|
||||
'json': true
|
||||
}, function(err, res, body) {
|
||||
if(_.has(body, 'error') && body.error == 6) {
|
||||
callback('no_user', null);
|
||||
} else if(_.has(body, 'recenttracks') && _.has(body.recenttracks, 'track')
|
||||
&& !_.isUndefined(body.recenttracks.track[0])) {
|
||||
callback(null, body.recenttracks.track[0]);
|
||||
} else {
|
||||
callback('no_listen', null);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
'tasteCompare': function(user, oUser, callback) {
|
||||
request.get(this.ApiRoot, {
|
||||
'qs': {
|
||||
'type1': 'user',
|
||||
'type2': 'user',
|
||||
'value1': user,
|
||||
'value2': oUser,
|
||||
'method': 'tasteometer.compare',
|
||||
'api_key': this.config.api_key,
|
||||
'format': 'json'
|
||||
},
|
||||
'json': true
|
||||
}, function(err, res, body) {
|
||||
console.log(body);
|
||||
if(_.has(body, 'error') && body.error == 6 || body.error == 7) {
|
||||
callback('no_user', user, null);
|
||||
} else if(_.has(body, 'comparison') && _.has(body.comparison, 'result')) {
|
||||
callback(null, body.comparison.result);
|
||||
} else {
|
||||
callback('idk', null);
|
||||
}
|
||||
});
|
||||
},
|
||||
*/
|
||||
|
||||
'getInfo': function(lfm, callback) {
|
||||
request.get(this.ApiRoot, {
|
||||
'qs': {
|
||||
'user': lfm,
|
||||
'method': 'user.getinfo',
|
||||
'api_key': this.config.api_key,
|
||||
'format': 'json'
|
||||
},
|
||||
'json': true
|
||||
}, function(err, res, body) {
|
||||
if(_.has(body, 'error') && body.error == 6 || body.error == 7) {
|
||||
callback('no_user', null);
|
||||
} else if(_.has(body, 'user')) {
|
||||
callback(null, body.user);
|
||||
} else {
|
||||
callback('idk', null);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
this.commands = {
|
||||
'~lastfm': function(event) {
|
||||
var user = event.rUser,
|
||||
lfm = event.rProfile.lastfm;
|
||||
if(event.res[0]) {
|
||||
user = event.res[0].user;
|
||||
lfm = event.res[0].lfm;
|
||||
}
|
||||
|
||||
this.api.getInfo(lfm, function(err, profile) {
|
||||
if(!err) {
|
||||
console.log(profile);
|
||||
event.reply(dbot.t('lfm_profile', {
|
||||
'user': user.currentNick,
|
||||
'plays': profile.playcount.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"),
|
||||
'date': moment(profile.registered['#text'] * 1000).format('DD/MM/YYYY'),
|
||||
'link': profile.url
|
||||
}));
|
||||
} else {
|
||||
if(err == 'no_user') {
|
||||
event.reply(dbot.t('lfm_unknown'));
|
||||
} else if(err == 'no_listen') {
|
||||
event.reply(dbot.t('no_listen', { 'user': event.user }));
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'~scrobbliest': function(event) {
|
||||
dbot.api.profile.getAllProfilesWith('lastfm', function(profiles) {
|
||||
if(profiles) {
|
||||
var plays = [];
|
||||
async.each(profiles, function(profile, done) {
|
||||
this.api.getInfo(profile.profile.lastfm, function(err, lProfile) {
|
||||
if(!err) {
|
||||
plays.push({
|
||||
'user': profile.id,
|
||||
'plays': parseInt(lProfile.playcount)
|
||||
});
|
||||
}
|
||||
done();
|
||||
});
|
||||
}.bind(this), function() {
|
||||
var scrobbliest = _.chain(plays)
|
||||
.sortBy(function(p) { return p.plays; })
|
||||
.reverse()
|
||||
.first(10)
|
||||
.value();
|
||||
|
||||
async.each(scrobbliest, function(item, done) {
|
||||
dbot.api.users.getUser(item.user, function(err, user) {
|
||||
item.user = user;
|
||||
done();
|
||||
});
|
||||
}, function() {
|
||||
var output = dbot.t('lfm_scrobbliest');
|
||||
_.each(scrobbliest, function(item) {
|
||||
output += item.user.currentNick + ' (' +
|
||||
item.plays.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,")+ '), ';
|
||||
});
|
||||
event.reply(output.slice(0, -2));
|
||||
});
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply('no suitable profiles');
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~suggestion': function(event) {
|
||||
this.api.getListening(event.rProfile.lastfm, function(err, track) {
|
||||
if(!err) {
|
||||
this.api.getSimilarArtists(track.artist.mbid, function(err, similar) {
|
||||
if(!err) {
|
||||
var choice = _.random(0, similar.length - 1);
|
||||
this.api.getRandomArtistTrack(similar[choice].mbid, function(err, track) {
|
||||
if(!err) {
|
||||
var output = dbot.t('lfm_suggestion', {
|
||||
'user': event.user,
|
||||
'name': track.name,
|
||||
'artist': track.artist.name
|
||||
});
|
||||
var term = track.name + ' ' + track.artist.name;
|
||||
|
||||
async.parallel({
|
||||
youtube: function(cb) {
|
||||
dbot.api.youtube.search(term, function(body) {
|
||||
if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) {
|
||||
var link = body.items[0].id.videoId
|
||||
if(link) {
|
||||
cb(null,"https://youtu.be/" + link);
|
||||
} else {
|
||||
cb(null, undefined);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
spotify: function(cb) {
|
||||
dbot.api.spotify.spotifySearch(term, function(body, url, uri) {
|
||||
if(body) {
|
||||
if (!dbot.modules.minify) {
|
||||
cb(null, { url: url, uri:uri });
|
||||
} else {
|
||||
dbot.modules.minify.api.minify(url, "bitly", function(mini) {
|
||||
cb(null, { url:mini || url, uri:uri });
|
||||
});
|
||||
}
|
||||
} else {
|
||||
cb(null, undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (results.youtube || results.spotify) output += " - "
|
||||
|
||||
if (results.youtube) output += results.youtube;
|
||||
if (results.spotify) {
|
||||
if (results.youtube) output += " | ";
|
||||
output += results.spotify.url + " - " + results.spotify.uri;
|
||||
}
|
||||
|
||||
event.reply(output);
|
||||
});
|
||||
} else {
|
||||
event.reply('Couldn\'t get any suggested tracks.');
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.reply('Couldn\'t find any similar artists to what you\'re listening to.');
|
||||
console.log(err);
|
||||
}
|
||||
}.bind(this));
|
||||
} else {
|
||||
if(err == 'no_user') {
|
||||
event.reply(dbot.t('lfm_unknown'));
|
||||
} else if(err == 'no_listen') {
|
||||
event.reply(dbot.t('no_listen', { 'user': event.user }));
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
'~listening': function(event) {
|
||||
var user = event.rUser,
|
||||
lfm = event.rProfile.lastfm;
|
||||
if(event.res[0]) {
|
||||
user = event.res[0].user;
|
||||
lfm = event.res[0].lfm;
|
||||
}
|
||||
|
||||
this.api.getListening(lfm, function(err, track) {
|
||||
if(!err) {
|
||||
var term = track.name + ' ' + track.artist['#text'],
|
||||
output = '';
|
||||
if(_.has(track, '@attr') && _.has(track['@attr'], 'nowplaying') && track['@attr'].nowplaying == 'true') {
|
||||
output = dbot.t('now_listening', {
|
||||
'user': user.currentNick,
|
||||
'track': track.name,
|
||||
'artist': track.artist['#text']
|
||||
});
|
||||
} else {
|
||||
output = dbot.t('last_listened', {
|
||||
'user': user.currentNick,
|
||||
'track': track.name,
|
||||
'artist': track.artist['#text']
|
||||
});
|
||||
}
|
||||
|
||||
async.parallel({
|
||||
youtube: function(cb) {
|
||||
dbot.api.youtube.search(term, function(body) {
|
||||
if(_.isObject(body) && _.has(body, 'items') && body.items.length > 0) {
|
||||
var link = body.items[0].id.videoId
|
||||
if(link) {
|
||||
cb(null,"https://youtu.be/" + link);
|
||||
} else {
|
||||
cb(null, undefined);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
spotify: function(cb) {
|
||||
dbot.api.spotify.spotifySearch(term, function(body, url, uri) {
|
||||
if(body) {
|
||||
if (!dbot.modules.minify) {
|
||||
cb(null, { url: url, uri:uri });
|
||||
} else {
|
||||
dbot.modules.minify.api.minify(url, "bitly", function(mini) {
|
||||
cb(null, { url:mini || url, uri:uri });
|
||||
});
|
||||
}
|
||||
} else {
|
||||
cb(null, undefined);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (results.youtube || results.spotify) output += " - "
|
||||
|
||||
if (results.youtube) output += results.youtube;
|
||||
if (results.spotify) {
|
||||
if (results.youtube) output += " | ";
|
||||
output += results.spotify.url + " - " + results.spotify.uri;
|
||||
}
|
||||
|
||||
event.reply(output);
|
||||
});
|
||||
|
||||
} else {
|
||||
if(err == 'no_user') {
|
||||
event.reply(dbot.t('lfm_unknown'));
|
||||
} else if(err == 'no_listen') {
|
||||
event.reply(dbot.t('no_listen', { 'user': user.currentNick }));
|
||||
}
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
'~taste': function(event) {
|
||||
var u1 = event.rUser,
|
||||
lfm1 = event.rProfile.lastfm,
|
||||
u2 = event.res[0].user,
|
||||
lfm2 = event.res[0].lfm;
|
||||
|
||||
this.api.tasteCompare(event.rProfile.lastfm, lfm2, function(err, comp) {
|
||||
if(!err) {
|
||||
var score = Math.floor(comp.score * 100);
|
||||
event.reply(dbot.t('taste_compat', {
|
||||
'user1': event.user,
|
||||
'user2': u2.currentNick,
|
||||
'score': score
|
||||
}));
|
||||
} else {
|
||||
if(err == 'no_user') {
|
||||
event.reply('Unknown Last.FM user.');
|
||||
} else {
|
||||
event.reply('Well something went wrong and I don\'t know what it means');
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'~tastiest': function(event) {
|
||||
var sortGoodScores = function(goodScores) {
|
||||
var tastiest = _.chain(goodScores)
|
||||
.sortBy(function(p) { return p.score; })
|
||||
.reverse()
|
||||
.first(10)
|
||||
.value();
|
||||
|
||||
async.each(tastiest, function(pair, done) {
|
||||
if(!_.isObject(pair.p1)) { // fix this
|
||||
dbot.api.users.getUser(pair.p1, function(err, user) {
|
||||
pair.p1 = user;
|
||||
dbot.api.users.getUser(pair.p2, function(err, user) {
|
||||
pair.p2 = user;
|
||||
done();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}, function() {
|
||||
var output = 'Most musically compatible users: ';
|
||||
_.each(tastiest, function(pair) {
|
||||
output += pair.p1.currentNick + ' & ' +
|
||||
pair.p2.currentNick + ' (' + pair.score +
|
||||
'%), ';
|
||||
});
|
||||
event.reply(output.slice(0, -2));
|
||||
});
|
||||
};
|
||||
|
||||
if(this.tastyCache && Date.now() - this.tastyCacheStamp <= 1800000) {
|
||||
sortGoodScores(this.tastyCache);
|
||||
} else {
|
||||
event.reply('Updating tasty cache... Hold onto your coconuts...');
|
||||
dbot.api.profile.getAllProfilesWith('lastfm', function(profiles) {
|
||||
if(profiles) {
|
||||
var scores = {}; // Using this structure first for easier testing in the async
|
||||
async.eachSeries(profiles, function(p1, next) {
|
||||
scores[p1.id] = {};
|
||||
async.eachSeries(profiles, function(p2, subnext) {
|
||||
if(p1.id == p2.id || p1.profile.lastfm == p2.profile.lastfm || _.has(scores, p2.id) && _.has(scores[p2.id], p1.id)) {
|
||||
subnext();
|
||||
} else {
|
||||
this.api.tasteCompare(p1.profile.lastfm, p2.profile.lastfm, function(err, comp) {
|
||||
if(!err) {
|
||||
var score = Math.floor(comp.score * 100);
|
||||
scores[p1.id][p2.id] = score;
|
||||
}
|
||||
subnext();
|
||||
});
|
||||
}
|
||||
}.bind(this), function() { next(); });
|
||||
}.bind(this), function(err) {
|
||||
// Now we better structure the scores for sorting
|
||||
var goodScores = [];
|
||||
_.each(scores, function(subscores, p1) {
|
||||
_.each(subscores, function(aScore, p2) {
|
||||
goodScores.push({
|
||||
'p1': p1,
|
||||
'p2': p2,
|
||||
'score': aScore
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.tastyCache = goodScores;
|
||||
this.tastyCacheStamp = new Date().getTime();
|
||||
sortGoodScores(goodScores);
|
||||
}.bind(this));
|
||||
} else {
|
||||
event.reply('No suitable profiles');
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
*/
|
||||
|
||||
'~artists': function(event) {
|
||||
var u1 = event.rUser,
|
||||
lfm1 = event.rProfile.lastfm,
|
||||
u2 = event.res[0].user,
|
||||
lfm2 = event.res[0].lfm;
|
||||
|
||||
this.api.tasteCompare(event.rProfile.lastfm, lfm2, function(err, comp) {
|
||||
if(!err) {
|
||||
var artists = _.pluck(comp.artists.artist, 'name').join(', ');
|
||||
event.reply(dbot.t('common_artists', {
|
||||
'user1': event.user,
|
||||
'user2': u2.currentNick,
|
||||
'common': artists
|
||||
}));
|
||||
} else {
|
||||
if(err == 'no_user') {
|
||||
event.reply(dbot.t('lfm_unknown'));
|
||||
} else {
|
||||
event.reply('Well something went wrong and I don\'t know what it means');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
//this.commands['~taste'].regex = [/^taste ([\d\w[\]{}^|\\`_-]+?)/, 2];
|
||||
this.commands['~artists'].regex = [/^artists ([\d\w[\]{}^|\\`_-]+?)/, 2];
|
||||
|
||||
_.each(this.commands, function(command) {
|
||||
command.resolver = function(event, callback) {
|
||||
if(event.rProfile && _.has(event.rProfile, 'lastfm')) {
|
||||
if(event.params[1]) {
|
||||
this.internalAPI.getLastFM(event.server, event.params[1], function(user, lfm) {
|
||||
if(user && lfm) {
|
||||
event.res.push({
|
||||
'user': user,
|
||||
'lfm': lfm
|
||||
});
|
||||
callback(false);
|
||||
} else {
|
||||
if(!user) {
|
||||
event.reply('Unknown user.');
|
||||
} else {
|
||||
event.reply(user.currentNick + ': Set a lastfm username with "~set lastfm username"');
|
||||
}
|
||||
callback(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
} else {
|
||||
event.reply(event.user + ': Set a lastfm username with "~set lastfm username"');
|
||||
callback(true);
|
||||
}
|
||||
}.bind(this);
|
||||
}, this);
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new lastfm(dbot);
|
||||
};
|
@ -1,35 +0,0 @@
|
||||
{
|
||||
"now_listening": {
|
||||
"en": "{user} is listening to {track} by {artist}",
|
||||
"de": "{user} hört {track} von {artist}"
|
||||
},
|
||||
"last_listened": {
|
||||
"en": "{user} last listened to {track} by {artist}",
|
||||
"de": "{user} hörte zuletzt {track} von {artist}"
|
||||
},
|
||||
"no_listen": {
|
||||
"en": "{user} doesn't seem to have listened to anything recently :'(",
|
||||
"de": "{user} scheint in letzter Zeit nichts gehört zu haben :'("
|
||||
},
|
||||
"taste_compat": {
|
||||
"en": "{user1} and {user2} are {score}% musically compatible!",
|
||||
"de": "{user1} und {user2} sind {score}% musikalisch kompatibel!"
|
||||
},
|
||||
"common_artists": {
|
||||
"en": "Artists {user1} and {user2} have in common: {common}",
|
||||
"de": "Künstler, die {user1} und {user2} gemeinsam haben: {common}"
|
||||
},
|
||||
"lfm_suggestion": {
|
||||
"en": "{user}: Try listening to {name} by {artist}",
|
||||
"de": "{user}: Versuche mal, {name} von {artist} anzuhören"
|
||||
},
|
||||
"lfm_profile": {
|
||||
"en": "{user} has scrobbled {plays} tracks since {date} - {link}"
|
||||
},
|
||||
"lfm_scrobbliest": {
|
||||
"en": "Users with the most played tracks: "
|
||||
},
|
||||
"lfm_unknown": {
|
||||
"en": "Unknown Last.FM user. Please set your Last.FM user by typing '~set lastfm <name>' where <name> is your Last.FM username."
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"outputPrefix": "\u00033weed\u000f",
|
||||
"app_key": "",
|
||||
"app_id": ""
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/**
|
||||
* Module name: Leafly
|
||||
* Description: Information from leafly
|
||||
*/
|
||||
|
||||
var _ = require('underscore')._,
|
||||
request = require('request');
|
||||
|
||||
var leafly = function(dbot) {
|
||||
var ApiRoot = 'http://data.leafly.com/';
|
||||
|
||||
this.commands = {
|
||||
'~strain': function(event) {
|
||||
request.post(ApiRoot + 'strains', {
|
||||
'headers': {
|
||||
'app_key': this.config.app_key,
|
||||
'app_id': this.config.app_id
|
||||
},
|
||||
'body': {
|
||||
'page': 0,
|
||||
'take': 1,
|
||||
'sort': 'rating',
|
||||
'search': event.input[1]
|
||||
},
|
||||
'json': true
|
||||
}, function(error, response, body) {
|
||||
if(_.isObject(body) && _.has(body, 'Strains') && body.Strains.length > 0) {
|
||||
var strain = body.Strains[0],
|
||||
flavours = _.pluck(strain.Flavors, 'Name').join(', ');
|
||||
|
||||
event.reply(dbot.t('strain', {
|
||||
'name': strain.Name,
|
||||
'flavours': flavours,
|
||||
'link': strain.permalink
|
||||
}));
|
||||
} else {
|
||||
event.reply(dbot.t('no_strains'));
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
this.commands['~strain'].regex = [/^strain (.+)$/, 2];
|
||||
};
|
||||
|
||||
exports.fetch = function(dbot) {
|
||||
return new leafly(dbot);
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
"strain": {
|
||||
"en": "{name} tastes of {flavours} - {link}"
|
||||
},
|
||||
"no_strains": {
|
||||
"en": "No strains found :("
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"autoTitle": true,
|
||||
"autoTitle": false,
|
||||
"dependencies": [ "command" ],
|
||||
"ignorable": true,
|
||||
"outputPrefix": "\u00032link\u000f",
|
||||
"help": "http://github.com/reality/depressionbot/blob/master/modules/link/README.md"
|
||||
|
@ -9,15 +9,15 @@ var request = require('request'),
|
||||
|
||||
var link = function(dbot) {
|
||||
this.urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
|
||||
this.links = {};
|
||||
this.links = {};
|
||||
this.handlers = [];
|
||||
|
||||
|
||||
this.api = {
|
||||
'addHandler': function(name, regex, handler) {
|
||||
this.handlers.push({
|
||||
'name': name,
|
||||
'regex': regex,
|
||||
'callback': handler
|
||||
this.handlers.push({
|
||||
'name': name,
|
||||
'regex': regex,
|
||||
'callback': handler
|
||||
});
|
||||
},
|
||||
|
||||
@ -26,8 +26,8 @@ var link = function(dbot) {
|
||||
size = 0,
|
||||
page = request(link.replace('https', 'http'), function(error, response, body) {
|
||||
if(!error && response.statusCode == 200) {
|
||||
body = body.replace(/(\r\n|\n\r|\n)/gim, " ");
|
||||
var title = body.valMatch(/<title>(.*?)<\\?\/title>/, 2);
|
||||
body = body.replace(/(\r\n|\n\r|\n)/gm, " ");
|
||||
var title = body.valMatch(/<title>(.*)<\/title>/, 2);
|
||||
if(title && title.length < 140) {
|
||||
callback(ent.decode(title[1]).trim());
|
||||
}
|
||||
@ -43,50 +43,23 @@ var link = function(dbot) {
|
||||
},
|
||||
|
||||
'udLookup': function(query, callback) {
|
||||
var reqUrl = 'http://api.urbandictionary.com/v0/define?term=' +
|
||||
encodeURI(query);
|
||||
var reqUrl = 'http://api.urbandictionary.com/v0/define?term=' +
|
||||
encodeURI(query);
|
||||
|
||||
request(reqUrl, function(error, response, body) {
|
||||
console.log(reqUrl);
|
||||
|
||||
try {
|
||||
var result = JSON.parse(body);
|
||||
if(_.has(result, 'list') && result.list.length > 0) {
|
||||
if(_.has(result, 'result_type') && result.result_type != 'no_results') {
|
||||
callback(result.list[0].word, result.list[0].definition.split('\n')[0]);
|
||||
} else {
|
||||
callback(false);
|
||||
}
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
callback(false);
|
||||
}
|
||||
} catch(err) { callback(false); }
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
'parseLink': function(link, callback) {
|
||||
var handler = false;
|
||||
for(var i=0;i<this.handlers.length;i++) {
|
||||
var matches = this.handlers[i].regex.exec(link);
|
||||
if(matches) {
|
||||
console.log(this.handlers[i].name);
|
||||
handler = this.handlers[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(handler) {
|
||||
this.handlers[i].callback(matches, this.handlers[i].name, function(parsed) {
|
||||
callback(parsed);
|
||||
});
|
||||
} else {
|
||||
this.api.getTitle(link, function(title) {
|
||||
callback(dbot.t('link', { 'link': title } ));
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var commands = {
|
||||
'~title': function(event) {
|
||||
var link = this.links[event.channel.name];
|
||||
@ -100,10 +73,9 @@ var link = function(dbot) {
|
||||
event.reply(dbot.t('link', { 'link': title} ));
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
'~xkcd': function(event) {
|
||||
//var comicId = event.params[1] || "";
|
||||
var comicId = event.params.slice(1).join(' ');
|
||||
var comicId = event.params[1] || "";
|
||||
|
||||
if(comicId == "*") {
|
||||
request("http://xkcd.com/info.0.json", function(error, response, body){
|
||||
@ -114,86 +86,27 @@ var link = function(dbot) {
|
||||
dbot.commands['~xkcd'](event);
|
||||
}
|
||||
} catch(err) { };
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (isNaN(parseInt(comicId))) {
|
||||
request({
|
||||
url: 'http://www.explainxkcd.com/wiki/api.php',
|
||||
qs: {
|
||||
action: 'query',
|
||||
format: 'json',
|
||||
generator: 'search',
|
||||
gsrwhat: 'text',
|
||||
gsrsearch: comicId,
|
||||
prop: 'info|categories',
|
||||
gsrlimit: 50
|
||||
},
|
||||
json: true
|
||||
}, function(err, res, body) {
|
||||
if(!body) {
|
||||
event.reply(dbot.t("no-hits"));
|
||||
return;
|
||||
}
|
||||
|
||||
var pages = _.values(body.query.pages);
|
||||
|
||||
// page titles must be of the format "####: $$$$$$"
|
||||
pages = _.filter(pages, p => p.title.indexOf(':') > 0);
|
||||
|
||||
if (pages.length > 0) {
|
||||
// See if any of these matches are exact title matches
|
||||
var match = false;
|
||||
_.each(pages, function(p) {
|
||||
var title = p.title.slice(p.title.indexOf(':')+2).trim();
|
||||
if(title.toLowerCase() == comicId.toLowerCase()) {
|
||||
match = p;
|
||||
}
|
||||
});
|
||||
|
||||
if (match) {
|
||||
// We got a match! Get the ID and let's get tf out of here.
|
||||
comicId = match.title.slice(0, match.title.indexOf(':'));
|
||||
} else {
|
||||
comicId = pages[0].title.slice(0, pages[0].title.indexOf(':'));
|
||||
}
|
||||
|
||||
var link = "http://xkcd.com/"+comicId+"/info.0.json";
|
||||
request(link, function(error, response, body) {
|
||||
try {
|
||||
if (response.statusCode == "200") {
|
||||
data = JSON.parse(body);
|
||||
event.reply(dbot.t("xkcd", data));
|
||||
} else {
|
||||
event.reply(dbot.t("no-hits"));
|
||||
}
|
||||
} catch(err) { };
|
||||
});
|
||||
|
||||
|
||||
} else {
|
||||
event.reply(dbot.t("no-hits"));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if(comicId !== "") {
|
||||
comicId = comicId + "/";
|
||||
}
|
||||
|
||||
var link = "http://xkcd.com/"+comicId+"info.0.json";
|
||||
request(link, function(error, response, body) {
|
||||
try {
|
||||
if (response.statusCode == "200") {
|
||||
data = JSON.parse(body);
|
||||
event.reply(dbot.t("xkcd", data));
|
||||
} else {
|
||||
event.reply(dbot.t("no-hits"));
|
||||
}
|
||||
} catch(err) { };
|
||||
});
|
||||
if(comicId !== "") {
|
||||
comicId = comicId + "/";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
var link = "http://xkcd.com/"+comicId+"info.0.json";
|
||||
request(link, function(error, response, body) {
|
||||
try {
|
||||
if (response.statusCode == "200") {
|
||||
data = JSON.parse(body);
|
||||
event.reply(dbot.t("xkcd", data));
|
||||
} else {
|
||||
event.reply(dbot.t("no-hits"));
|
||||
}
|
||||
} catch(err) { };
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
'~ud': function(event) {
|
||||
var query = event.input[1];
|
||||
|
||||
@ -206,18 +119,27 @@ var link = function(dbot) {
|
||||
});
|
||||
}
|
||||
};
|
||||
commands['~ud'].regex = [/ud (.+)/, 2];
|
||||
commands['~ud'].regex = [/~ud (.+)/, 2];
|
||||
this.commands = commands;
|
||||
|
||||
this.listener = function(event) {
|
||||
var urlMatches = event.message.match(this.urlRegex);
|
||||
if(urlMatches !== null) {
|
||||
this.links[event.channel.name] = urlMatches[0];
|
||||
console.log('DEBUG: got a link');
|
||||
if(this.config.autoTitle == true) {
|
||||
this.api.parseLink(urlMatches[0], function(result) {
|
||||
event.reply(result);
|
||||
});
|
||||
if(dbot.config.link.autoTitle == true) {
|
||||
var handlerFound = false;
|
||||
for(var i=0;i<this.handlers.length;i++) {
|
||||
var matches = this.handlers[i].regex.exec(urlMatches[0]);
|
||||
if(matches) {
|
||||
this.handlers[i].callback(event, matches, this.handlers[i].name);
|
||||
handlerFound = true; break;
|
||||
}
|
||||
}
|
||||
if(!handlerFound) {
|
||||
this.api.getTitle(urlMatches[0], function(title) {
|
||||
event.reply(dbot.t('link', { 'link': title } ));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
|
@ -4,29 +4,19 @@
|
||||
"na'vi": "Oel ke tsun run 'upxare atxin.",
|
||||
"cy": "Ni chanfuwyd teitl y dudalen",
|
||||
"nl": "Er is geen paginatitel gevonden.",
|
||||
"de": "Kein Seitenname gefunden.",
|
||||
"fr": "Aucun titre de page trouvé.",
|
||||
"it": "Nessun titolo di pagina trovato."
|
||||
"de": "Kein Seitenname gefunden."
|
||||
},
|
||||
"xkcd": {
|
||||
"en": "xkcd {num}: {title} https://xkcd.com/{num}",
|
||||
"fr": "xkcd {num}: {title} https://xkcd.com/{num}",
|
||||
"it": "xkcd {num}: {title} https://xkcd.com/{num}",
|
||||
"de": "xkcd {num}: {title} https://xkcd.com/{num}"
|
||||
"en": "xkcd {num}: {title} https://xkcd.com/{num}"
|
||||
},
|
||||
"no-hits": {
|
||||
"en": "No hits.",
|
||||
"na'vi": "Oel ke tsun rivum ayuoti.",
|
||||
"cy": "Dim canlyniadau.",
|
||||
"nl": "Geen resultaten.",
|
||||
"de": "Keine Treffer.",
|
||||
"fr": "Aucun résultat.",
|
||||
"it": "Nessun risultato."
|
||||
"de": "Keine Treffer."
|
||||
},
|
||||
"link": {
|
||||
"en": "{link}",
|
||||
"fr": "{link}",
|
||||
"it": "{link}",
|
||||
"de": "{link}"
|
||||
"en": "{link}"
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user