├── emoji
├── loader.gif
├── signal0.png
├── signal1.png
├── signal2.png
├── signal3.png
├── signal4.png
├── exception.png
└── userexception.png
├── plugins
├── images
│ ├── fog.png
│ ├── cloudy.png
│ ├── moony.png
│ ├── rain.png
│ ├── snow.png
│ ├── sunny.png
│ ├── sunset.png
│ ├── wind.png
│ ├── compass.png
│ ├── humidity.png
│ ├── pressure.png
│ ├── question.png
│ ├── rainsnow.png
│ ├── sunrise.png
│ ├── thunder.png
│ ├── unavail.png
│ ├── dayclearw.png
│ ├── daycloudw.png
│ ├── nightclearw.png
│ ├── nightcloudw.png
│ ├── precipitation.png
│ ├── question.svg
│ ├── thunder.svg
│ ├── precipitation.svg
│ ├── fog.svg
│ ├── sunrise.svg
│ ├── sunset.svg
│ ├── cloudy.svg
│ ├── moony.svg
│ ├── pressure.svg
│ ├── unavail.svg
│ ├── compass.svg
│ ├── sunny.svg
│ ├── wind.svg
│ ├── snow.svg
│ ├── rainsnow.svg
│ ├── rain.svg
│ └── humidity.svg
├── monitor.js
├── suggestions.js
├── eval.js
├── settings.js
├── spam.js
├── warning.js
├── misc.js
└── chatModeration.js
├── icons
├── astralmod-2018.png
└── astralmod-2019.png
├── jsconfig.json
├── .gitignore
├── AstralMod.tslprj
├── translations
├── ur_PK
│ └── translation.json
├── zh_Hans
│ └── translation.json
├── uk
│ ├── help.json
│ └── translation.json
├── pt_BR
│ └── translation.json
├── de
│ └── translation.json
├── vi
│ └── help.json
├── en
│ └── help.json
└── nl
│ └── translation.json
├── webserver.html
├── package.json
├── .vscode
└── launch.json
└── README.md
/emoji/loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/emoji/loader.gif
--------------------------------------------------------------------------------
/emoji/signal0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/emoji/signal0.png
--------------------------------------------------------------------------------
/emoji/signal1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/emoji/signal1.png
--------------------------------------------------------------------------------
/emoji/signal2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/emoji/signal2.png
--------------------------------------------------------------------------------
/emoji/signal3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/emoji/signal3.png
--------------------------------------------------------------------------------
/emoji/signal4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/emoji/signal4.png
--------------------------------------------------------------------------------
/emoji/exception.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/emoji/exception.png
--------------------------------------------------------------------------------
/plugins/images/fog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/fog.png
--------------------------------------------------------------------------------
/emoji/userexception.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/emoji/userexception.png
--------------------------------------------------------------------------------
/icons/astralmod-2018.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/icons/astralmod-2018.png
--------------------------------------------------------------------------------
/icons/astralmod-2019.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/icons/astralmod-2019.png
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "exclude": [
3 | "node_modules",
4 | "plugins"
5 | ]
6 | }
--------------------------------------------------------------------------------
/plugins/images/cloudy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/cloudy.png
--------------------------------------------------------------------------------
/plugins/images/moony.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/moony.png
--------------------------------------------------------------------------------
/plugins/images/rain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/rain.png
--------------------------------------------------------------------------------
/plugins/images/snow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/snow.png
--------------------------------------------------------------------------------
/plugins/images/sunny.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/sunny.png
--------------------------------------------------------------------------------
/plugins/images/sunset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/sunset.png
--------------------------------------------------------------------------------
/plugins/images/wind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/wind.png
--------------------------------------------------------------------------------
/plugins/images/compass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/compass.png
--------------------------------------------------------------------------------
/plugins/images/humidity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/humidity.png
--------------------------------------------------------------------------------
/plugins/images/pressure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/pressure.png
--------------------------------------------------------------------------------
/plugins/images/question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/question.png
--------------------------------------------------------------------------------
/plugins/images/rainsnow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/rainsnow.png
--------------------------------------------------------------------------------
/plugins/images/sunrise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/sunrise.png
--------------------------------------------------------------------------------
/plugins/images/thunder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/thunder.png
--------------------------------------------------------------------------------
/plugins/images/unavail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/unavail.png
--------------------------------------------------------------------------------
/plugins/images/dayclearw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/dayclearw.png
--------------------------------------------------------------------------------
/plugins/images/daycloudw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/daycloudw.png
--------------------------------------------------------------------------------
/plugins/images/nightclearw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/nightclearw.png
--------------------------------------------------------------------------------
/plugins/images/nightcloudw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/nightcloudw.png
--------------------------------------------------------------------------------
/plugins/images/precipitation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vicr123/AstralMod/HEAD/plugins/images/precipitation.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .vs/
3 | .idea/
4 |
5 | td.js
6 | consts.js
7 | keys.js
8 |
9 | settings.json
10 | .settings-beforeEncrypt.json
11 |
12 |
13 | iv.txt
14 | log.log
15 |
16 |
17 | iv
18 | gce
19 |
20 | .kdev4/AstralMod.kdev4
21 | .DS_Store
22 | .settings-backup.json
23 |
--------------------------------------------------------------------------------
/AstralMod.tslprj:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0",
3 | "debuggerType": "nodejs",
4 | "runTypes": [
5 | {
6 | "name": "Start",
7 | "program": "./bot.js --nowelcome",
8 | "debug": true
9 | },
10 | {
11 | "name": "Start with Debug messages",
12 | "program": "./bot.js --nowelcome --debug",
13 | "debug": true
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/translations/ur_PK/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "SETLOC_LANGUAGE": "ٹھیک ہے، تمہاری زبان اب اردو (پاکستان) ہے.",
3 | "UINFO_NICKNAME": "**عرفی نام:** {{nickname}}",
4 | "UINFO_NAMES": "نام",
5 | "UINFO_USER_INFORMATION": "صارف کی معلومات",
6 | "UINFO_USER_ID": "صارف کا نمبر: {{id}}",
7 | "SPECIAL_STIME": "{{time, stime}}",
8 | "UINFO_TIMESTAMPS": "تاریخ",
9 | "WEATHER_TODAY": "آج",
10 | "THIS_LOCALE": "Urdu (Pakistan)",
11 | "TIME_RESPONSE": "{{clockEmote}} **{{request}}** ({{offset}}) {{time, dddd[,] MMMM D}}, at {{time, stime}}"
12 | }
13 |
--------------------------------------------------------------------------------
/translations/zh_Hans/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "SPECIAL_STIME": "{{time, stime}}",
3 | "UINFO_USER_INFORMATION": "",
4 | "UINFO_CREATEDAT": "**做了在:**{{createdat, datetime}}",
5 | "UINFO_JOINEDAT": "**来了在:** {{joinedat, datetime}}",
6 | "UINFO_TIMESTAMPS": "",
7 | "UINFO_NONICKNAME": "没有混名",
8 | "UINFO_NICKNAME": "**混名:**{{nickname}}",
9 | "UINFO_NAMES": "名",
10 | "SETLOC_LANGUAGE": "好,你的现场是中文。",
11 | "SINFO_SERVER_CREATED": "**做了在:**{{creatdat, datetime}}",
12 | "SINFO_PEOPLE": "人",
13 | "WEATHER_TITLE": "天气",
14 | "WEATHER_CURRENT_WEATHER": "现在的天气",
15 | "WEATHER_TODAY": "今天",
16 | "WEATHER_PLEASE_PRINT": "你可以打印这个",
17 | "WEATHER_PREPARING": "在准备天气。。。",
18 | "UINFO_DISPLAYNAME": "**显示:** {{displayname}}",
19 | "WEATHER_ERROR_CITY_NOT_FOUND": "找不到这个城市"
20 | }
21 |
--------------------------------------------------------------------------------
/webserver.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | AstralMod Console
4 |
5 |
6 | AstralMod Console
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
23 |
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "astralmod",
3 | "version": "1.0.0",
4 | "description": "Discord Moderation Bot for AstralPhaser Central, ShiftOS, theShell and other servers",
5 | "main": "bot.js",
6 | "scripts": {
7 | "start": "node bot.js"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/vicr123/AstralMod.git"
12 | },
13 | "author": "vicr123",
14 | "license": "GPL-3.0",
15 | "bugs": {
16 | "url": "https://github.com/vicr123/AstralMod/issues"
17 | },
18 | "dependencies": {
19 | "blessed": "^0.1.81",
20 | "canvas": "^1.6.10",
21 | "discord.js": "^11.4.2",
22 | "erlpack": "github:discordapp/erlpack",
23 | "hawk": "^7.0.10",
24 | "i18next": "^12.1.0",
25 | "i18next-node-fs-backend": "^2.1.0",
26 | "libsodium-wrappers": "^0.7.3",
27 | "localize": "^0.4.7",
28 | "moment": "^2.21.0",
29 | "moment-duration-format": "^2.2.2",
30 | "openweathermap-js": "^1.0.1",
31 | "opusscript": "0.0.3",
32 | "yandex-translate": "^2.1.2",
33 | "yql": "^1.0.2"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible Node.js debug attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "node",
9 | "request": "launch",
10 | "name": "Launch Program",
11 | "program": "${workspaceFolder}/bot.js",
12 | "console": "integratedTerminal",
13 | "args": [
14 | "--blueprint",
15 | ]
16 | },
17 | {
18 | "type": "node",
19 | "request": "launch",
20 | "name": "Launch Program with debug messages",
21 | "program": "${workspaceFolder}/bot.js",
22 | "console": "integratedTerminal",
23 | "args": [
24 | "--debug",
25 | "--blueprint"
26 | ]
27 | },
28 | {
29 | "type": "node",
30 | "request": "attach",
31 | "name": "Attach to Port",
32 | "address": "localhost",
33 | "port": 23364
34 | }
35 | ]
36 | }
--------------------------------------------------------------------------------
/plugins/images/question.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
77 |
--------------------------------------------------------------------------------
/plugins/monitor.js:
--------------------------------------------------------------------------------
1 | /****************************************
2 | *
3 | * Monitor: Plugin for AstralMod that gives monitoring information about AstralMod
4 | * Copyright (C) 2019 Victor Tran, John Tur
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | * *************************************/
20 |
21 | var client;
22 | var consts;
23 | const moment = require('moment');
24 | const fs = require('fs')
25 |
26 | var pingMessage = null;
27 | var pingDate = null;
28 |
29 | function processCommand(message, isMod, command, options) {
30 | let $ = _[options.locale];
31 | if (command == "uptime") {
32 | message.reply($("UPTIME", {emoji: ":clock4:", time: { duration: moment.duration(client.uptime, "milliseconds"), settings: {trim: false} }}));
33 | } else if (command == "settingssize") {
34 |
35 | let stats = fs.statSync("settings.json");
36 |
37 | log("no")
38 | log(stats == undefined);
39 |
40 | message.reply($("SETTINGSSIZE", {bytes: stats["size"] == undefined ? JSON.stringify(settings).length * 2 : stats["size"]}));
41 | }
42 | }
43 |
44 | module.exports = {
45 | name: "Monitor",
46 | translatableName: "TITLE_MONITOR",
47 | constructor: function(discordClient, commandEmitter, constants) {
48 | client = discordClient;
49 | consts = constants;
50 |
51 | //commandEmitter.on('startup', startup);
52 | commandEmitter.on('processCommand', processCommand);
53 | },
54 | destructor: function(commandEmitter) {
55 | //commandEmitter.removeListener('startup', startup);
56 | commandEmitter.removeListener('processCommand', processCommand);
57 | },
58 | availableCommands: {
59 | general: {
60 | commands: [
61 | "uptime",
62 | "settingssize"
63 | ]
64 | }
65 | },
66 | acquireHelp: function(helpCmd, message, h$) {
67 | var help = {};
68 |
69 | switch (helpCmd) {
70 | case "uptime":
71 | help.title = prefix(message.guild.id) + "uptime";
72 | help.helpText = h$("UPTIME_HELPTEXT");
73 | break;
74 | case "settingssize":
75 | help.title = prefix(message.guild.id) + "settingssize";
76 | help.helpText = h$("SETTINGSSIZE_HELPTEXT");
77 | break;
78 | }
79 |
80 | return help;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/plugins/images/thunder.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
76 |
--------------------------------------------------------------------------------
/translations/uk/help.json:
--------------------------------------------------------------------------------
1 | {
2 | "CONFIG_HELPTEXT": "",
3 | "SHOO_HELPTEXT": "",
4 | "OKNICK_HELPTEXT": "",
5 | "PING_HELPTEXT": "",
6 | "VERSION_HELPTEXT": "",
7 | "NICK_HELPTEXT": "",
8 | "NICK_PARAM1": "",
9 | "SETLOCALE_HELPTEXT": "",
10 | "HELP_HELPTEXT": "",
11 | "HELP_PARAM1": "",
12 | "ABOUT_HELPTEXT": "",
13 | "SUDO_HELPTEXT": "",
14 | "TITLE_CHAT_MODERATION": "",
15 | "TITLE_EVAL": "",
16 | "TITLE_FLAG": "",
17 | "TITLE_MISC": "",
18 | "TITLE_MONITOR": "",
19 | "TITLE_SETTINGS": "",
20 | "TITLE_SPAM": "",
21 | "TITLE_SUGGESTIONS": "",
22 | "TITLE_TIME": "",
23 | "TITLE_USER": "",
24 | "TITLE_WARN": "",
25 | "TITLE_WEATHER": "",
26 | "RM_HELPTEXT": "",
27 | "RM_PARAM1": "",
28 | "RM_PARAM2": "",
29 | "CHNK_HELPTEXT": "",
30 | "CHNK_PARAM1": "",
31 | "BLOCK_HELPTEXT": "",
32 | "BLOCK_PARAM1": "",
33 | "BLOCK_REMARKS": "",
34 | "BLOCK_AVAILABLEOPTIONS": "",
35 | "UNBLOCK_HELPTEXT": "",
36 | "UNBLOCK_PARAM1": "",
37 | "UNBLOCK_REMARKS": "",
38 | "UNBLOCK_AVAILABLEOPTIONS": "",
39 | "EVAL_HELPTEXT": "",
40 | "EVAL_REMARKS": "",
41 | "PIN_HELPTEXT": "",
42 | "PIN_PARAM1": "",
43 | "PIN_AVAILABLEOPTIONS": "",
44 | "PIN_REMARKS": "",
45 | "PINS_HELPTEXT": "",
46 | "PINS_PARAM1": "",
47 | "UNPIN_HELPTEXT": "",
48 | "UNPIN_PARAM1": "",
49 | "PIC_HELPTEXT": "",
50 | "PIC_PARAM1": "",
51 | "SETUNIT_HELPTEXT": "",
52 | "SETUNIT_PARAM1": "",
53 | "SETUNIT_REMARKS": "",
54 | "SINFO_HELPTEXT": "",
55 | "CALC_HELPTEXT": "",
56 | "CALC_REMARKS": "",
57 | "TR_HELPTEXT": "",
58 | "TR_PARAM1": "",
59 | "TR_PARAM2": "",
60 | "TR_PARAM3": "",
61 | "UPTIME_HELPTEXT": "",
62 | "SETTINGSSIZE_HELPTEXT": "",
63 | "RETRSETTINGS_HELPTEXT": "",
64 | "RESETSETTINGS_HELPTEXT": "",
65 | "RESETSETTINGS_REMARKS": "",
66 | "SPAMCTL_HELPTEXT": "",
67 | "SPAMCTL_PARAM1": "",
68 | "SPAMDATA_HELPTEXT": "",
69 | "SUGGEST_HELPTEXT": "",
70 | "TIME_HELPTEXT": "",
71 | "TIME_PARAM1": "",
72 | "SETTZ_HELPTEXT": "",
73 | "SETTZ_PARAM1": "",
74 | "SETTZ_REMARKS": "",
75 | "TIMER_HELPTEXT": "",
76 | "TIMER_PARAM1": "",
77 | "TIMER_PARAM2": "",
78 | "TIMERS_HELPTEXT": "",
79 | "RMTIMER_HELPTEXT": "",
80 | "RMTIMER_PARAM1": "",
81 | "UINFO_HELPTEXT": "",
82 | "UINFO_OPTION1": "",
83 | "UINFO_PARAM1": "",
84 | "FETCHUSER_HELPTEXT": "",
85 | "FETCHUSER_PARAM1": "",
86 | "FETCHUSER_REMARKS": "",
87 | "FIND_HELPTEXT": "",
88 | "FIND_PARAM1": "",
89 | "FIND_REMARKS": "",
90 | "DEAL_HELPTEXT": "",
91 | "DEAL_PARAM1": "",
92 | "WARN_HELPTEXT": "",
93 | "WARN_PARAM1": "",
94 | "LSWARN_HELPTEXT": "",
95 | "LSWARN_PARAM1": "",
96 | "RMWARN_HELPTEXT": "",
97 | "RMWARN_PARAM1": "",
98 | "RMWARN_PARAM2": "",
99 | "WEATHER_HELPTEXT": "",
100 | "WEATHER_PARAM1": "",
101 | "WEATHER_AVAILABLEOPTIONS": "",
102 | "WEATHER_REMARKS": "",
103 | "SETLOC_HELPTEXT": "",
104 | "SETLOC_PARAM1": "",
105 | "SETLOC_REMARKS": ""
106 | }
107 |
--------------------------------------------------------------------------------
/plugins/images/precipitation.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
101 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AstralMod
2 | Discord Moderation Bot for bits & Bytes, theShell and many other servers
3 |
4 | #### [Invite AstralMod to your server](https://discordapp.com/oauth2/authorize?client_id=282048599574052864&scope=bot&permissions=461843558)
5 |
6 | ## Commands
7 | For a full list of commands, use `am:help` in a channel. Use `am:help [command]` to look up help for a specific command. To get help with terminal commands, type `help` into the terminal.
8 |
9 | ## Running AstralMod yourself
10 | 1. Make sure you have [Node.js](https://nodejs.org/en/) installed. If it's recent enough it should work.
11 | 2. Clone this repository into your folder of choice.
12 | 3. Run `npm install` in this directory to install all of AstralMod's dependencies.
13 | 4. Create a new file in the root directory of AstralMod called `consts.js`. Fill it with this (and specify your own information where necessary):
14 |
15 | ```js
16 | module.exports = {
17 | keys: {
18 | token: "", // This is where the token for your bot account goes
19 | settingsKey: "", // This is the encryption key for the settings file. What you input here really doesn't matter - it should be about 32 characters (if you go any longer it will be truncated). Don't change it or else you won't be able to use your settings file again.
20 | yandexKey: "" // This is the token used for the Yandex.Translate API. You can leave this blank, but 'am:tr' will be disabled. If you want to use 'am:tr' though, you can get a token at https://tech.yandex.com/translate/ and insert it here.
21 | },
22 | config: {
23 | prefix: "am:", // This is the default prefix used by AstralMod.
24 | bprefix: "am#", // This is the default prefix used by AstralMod when it is running as AstralMod Blueprint.
25 | pinToPinEmoji: "📌", // This is used as the emoji for the Portable Pins and the Pin to Pin feature. You can generally leave this as the default, but if you have other bots that interpret the 📌 emoji as something else, you might want to change it.
26 | calcProcess: "/usr/bin/thecalculator", // This is a path to the compiled binary for theCalculator, used for calculating expressions in 'am:calc'. You can leave this blank, but 'am:calc' will be disabled. You can grab a copy of theCalculator at https://github.com/vicr123/thecalculator/releases.
27 | emojiServer: "" // This is the server ID of a server that has all of the AstralMod-specific emoji. More information about setting up the emoji can be found below. You can leave this blank, but all custom emoji will be replaced by ➡.
28 | },
29 | colors: { // These are the colors used for embeds.
30 | done: "#FFC000",
31 | info: "#1E3C8C",
32 | fail: "#FF5000",
33 | none: "#36393F"
34 | }
35 | }
36 | ```
37 |
38 | 3. Run the bot by running `node bot.js` with your preferred options.
39 |
40 | ### AstralMod Emoji?
41 | Set up a server and upload the the emoji in the `/emoji` folder to it. You can change the actual emoji picture to whatever you want, but make sure to keep the names the same. Then, invite your bot into it, and set the `emojiServer` value in the `consts.js` file to the server ID of that server.
42 |
43 | ### Command line options
44 | - `--blueprint` Runs AstralMod as AstralMod Blueprint. The version number is replaced with "Blueprint" and the prefix is changed.
45 | - `--debug` Enables debugging output in the console
46 | - `--nowelcome` Disables the welcome message that AstralMod sends when it joins a new server
47 | - `--novacuum` Disables the periodic cleanup of the settings file
48 |
49 | ### Developing AstralMod
50 | If you wish to add a command, look at the `plugins` directory. Make your own plugin to include commands.
51 | If you wish to modify the actual program, look at `bot.js`, or the AstralMod source code.
52 |
--------------------------------------------------------------------------------
/plugins/images/fog.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
97 |
--------------------------------------------------------------------------------
/plugins/images/sunrise.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
105 |
--------------------------------------------------------------------------------
/plugins/images/sunset.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
105 |
--------------------------------------------------------------------------------
/plugins/images/cloudy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
76 |
--------------------------------------------------------------------------------
/plugins/images/moony.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
101 |
--------------------------------------------------------------------------------
/plugins/suggestions.js:
--------------------------------------------------------------------------------
1 | /****************************************
2 | *
3 | * Suggestions: Plugin for AstralMod that lets users make server suggestions
4 | * Copyright (C) 2019 John Tur
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | * *************************************/
20 |
21 | var client;
22 | var consts;
23 | const Discord = require('discord.js');
24 |
25 | function processCommand(message, isMod, command, options) {
26 | let $ = _[options.locale];
27 | let $$ = _[options.glocale];
28 | if(!command.startsWith("suggest")) return;
29 |
30 | if (settings.guilds[message.guild.id].suggestions == null) {
31 | message.reply($("SUGGEST_NOT_ENABLED"));
32 | return;
33 | }
34 |
35 | message.reply($("SUGGEST_FURTHER_INSTRUCTIONS", {emoji: ":arrow_right:"}));
36 | message.author.send($("SUGGEST_INSTRUCTIONS")).then(_ => {
37 | let collector = message.author.dmChannel.createMessageCollector(f => f.author.id == message.author.id);
38 | collector.on('collect', coll => {
39 | collector.stop();
40 | awaitUserConfirmation({
41 | title: $("SUGGEST_CONFIRMATION_TITLE"),
42 | msg: $("SUGGEST_CONFIRMATION_MESSAGE", {guild: message.guild.name}),
43 | msgOnSuccess: $("SUGGEST_CONFIRMATION_SUCCESS"),
44 | msgOnFail: $("SUGGEST_CONFIRMATION_CANCEL", {prefix: prefix(message.guild.id)}),
45 | channel: message.author.dmChannel,
46 | author: message.author,
47 | time: 10,
48 | locale: options.locale,
49 | doNotClear: true,
50 | extraFields: [
51 | [$("SUGGEST_CONFIRMATION_SUGGESTION_TITLE"), coll.content]
52 | ]
53 | }).then(() => {
54 | let embed = new Discord.RichEmbed();
55 | embed.setAuthor($$("SUGGEST_SUGGESTION_TITLE", {user: message.author.username}), message.author.avatarURL);
56 | embed.setColor(consts.colors.info);
57 | embed.setDescription(coll.content);
58 | embed.setTimestamp();
59 | message.guild.channels.get(settings.guilds[message.guild.id].suggestions).send(embed);
60 | }).catch((err) => {
61 | if (!err) return; //User cancelled
62 |
63 | //Exception of some sort?
64 | log(err, logType.warning);
65 | message.author.dmChannel.send($("SUGGEST_SUGGESTION_ERROR", {emoji: ":no_entry_sign:"}));
66 | });
67 | });
68 | }).catch(err => log(err, logType.critical));
69 | }
70 |
71 | module.exports = {
72 | name: "Suggestions",
73 | translatableName: "TITLE_SUGGESTIONS",
74 | constructor: function(discordClient, commandEmitter, constants) {
75 | client = discordClient;
76 | consts = constants;
77 |
78 | commandEmitter.on('processCommand', processCommand);
79 | },
80 | destructor: function(commandEmitter) {
81 | commandEmitter.removeListener('processCommand', processCommand);
82 | },
83 | availableCommands: {
84 | general: {
85 | commands: [
86 | "suggest"
87 | ],
88 | modCommands: [
89 |
90 | ],
91 | hiddenCommands: [
92 |
93 | ]
94 | }
95 | },
96 | acquireHelp: function(helpCmd, message, h$) {
97 | var help = {};
98 |
99 | switch (helpCmd) {
100 | case "suggest":
101 | help.title = prefix(message.guild.id) + "suggest";
102 | help.helpText = h$("SUGGEST_HELPTEXT");
103 | break;
104 | }
105 |
106 | return help;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/plugins/images/pressure.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
118 |
--------------------------------------------------------------------------------
/plugins/images/unavail.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
71 |
--------------------------------------------------------------------------------
/plugins/images/compass.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
111 |
--------------------------------------------------------------------------------
/translations/uk/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "SPECIAL_STIME": "{{time, stime}}",
3 | "SPECIAL_DATETIME": "",
4 | "THIS_LOCALE": "Українська",
5 | "SETLOC_TITLE": "Локалізація AstralMod",
6 | "UINFO_RETRIEVING": "Підготовка інформації користувача...",
7 | "UINFO_USER_ID": "Ідентифікатор користувача: {{id}}",
8 | "UINFO_USER_INFORMATION": "Інформація про користувача",
9 | "UINFO_CREATEDAT": "**Створено:** {{createdat, datetime}}",
10 | "UINFO_JOINEDAT": "**Приєднався:** {{joinedat, datetime}}",
11 | "UINFO_TIMESTAMPS": "Мітки часу",
12 | "UINFO_DISPLAYNAME": "**Відображуване ім’я:** {{displayname}}",
13 | "UINFO_USERNAME": "**Ім'я користувача:** {{username}}",
14 | "UINFO_NONICKNAME": "Немає",
15 | "UINFO_NICKNAME": "**Нікнейм:** {{nickname}}",
16 | "UINFO_NAMES": "Імена",
17 | "UINFO_DISCRIMINATOR": "**Дискримінатор:** {{discriminator}}",
18 | "UINFO_ALERTS": "Сповіщення",
19 | "UINFO_BOT_ACCOUNT_WARNING": "Цей користувач є ботом.",
20 | "RM_ITS_A_CATASTROPHE": "Катастрофічна Невдача",
21 | "RM_NAN": "Це не число.",
22 | "SETLOC_LANGUAGE": "Гаразд, ваша мова тепер {{locale}}.",
23 | "SETLOC_YOUR_LOCALE": "Поточна Мова",
24 | "SETLOC_AVAILABLE_LOCALES": "Доступні Мови",
25 | "SINFO_RETRIEVING_SERVER": "Підготовка інформації про сервер...",
26 | "SINFO_GUILDID": "Ідентифікатор сервера: {{id}}",
27 | "SINFO_SERVER_INFORMATION": "Інформація про сервер",
28 | "SINFO_SERVER_CREATED": "**Створено:** {{createdat, datetime}}",
29 | "SINFO_AM_JOINED": "**AstralMod Приєднався:** {{joinedat, datetime}}",
30 | "SINFO_TIMESTAMPS": "Мітки часу",
31 | "SINFO_MEMBER_COUNT": "**Користувачів:** {{count}}",
32 | "SINFO_SERVER_OWNER": "**Власник сервера:** {{owner}}",
33 | "SINFO_PEOPLE": "Люди",
34 | "SINFO_ROLES": "Ролі",
35 | "SINFO_ALERTS": "Сповіщення",
36 | "ERROR_DETAILS": "Деталі",
37 | "ERROR_INTERNAL": "Внутрішня помилка",
38 | "ERROR_USER_INPUT": "Помилка введення користувача",
39 | "TIME_PREPARING": "Підготовка часу...",
40 | "TIME_ERROR_DETAILS": "Деталі",
41 | "TIME_ERROR": "{{emoji}} Помилка часу",
42 | "TIME_UTC": "UTC {{number}}",
43 | "TIMER_SET_REASON": "Причина",
44 | "TIMER_SET_ALERT": "Сповіщення",
45 | "TIMER_ELAPSED_REASON_TITLE": "Причина",
46 | "TIMERS_REASON": "**Причина:** {{reason}}",
47 | "TIMERS_CHANNEL": "**Канал:** {{channel}}",
48 | "TIMERS_HEADER": "Таймер № {{index}}",
49 | "WEATHER_PREPARING": "Підготовка прогнозу погоди...",
50 | "WEATHER_TITLE": "Погода",
51 | "WEATHER_CURRENT_WEATHER": "Поточна Погода",
52 | "WEATHER_TODAY": "Сьогодні",
53 | "WEATHER_PLEASE_PRINT": "Ви можете роздрукувати це",
54 | "WEATHER_TEAR_PERFORATED_LINE": "Розірвіть по перфорованій лінії",
55 | "WEATHER_SO_MANY_DEGREES": "Так гаряче зовні...",
56 | "WEATHER_LONGER_DAYS": "Чи довше тривають дні?",
57 | "WEATHER_ERROR": "{{emoji}} Помилка погоди",
58 | "WEATHER_ERROR_DETAILS": "Деталі",
59 | "WEATHER_ERROR_TRY_THIS": "Спробуйте це",
60 | "WEATHERSTRING_TORNADO": "Торнадо",
61 | "WEATHERSTRING_TROPICALSTORM": "Тропічний шторм",
62 | "WEATHERSTRING_HURRICANE": "Ураган",
63 | "WEATHERSTRING_SEVERETHUNDERSTORMS": "Сильні грози",
64 | "WEATHERSTRING_THUNDERSTORMS": "Грози",
65 | "WEATHERSTRINGS_RAINANDSNOW": "Дощ і сніг",
66 | "WEATHERSTRINGS_RAINANDSLEET": "Дощ і мокрий сніг",
67 | "WEATHERSTRINGS_SNOWANDSLEET": "Сніг і мокрий сніг",
68 | "WEATHERSTRINGS_DRIZZLE": "Мрячити",
69 | "WEATHERSTRINGS_FREEZINGRAIN": "Крижаний дощ",
70 | "WEATHERSTRINGS_SHOWERS": "Дощі",
71 | "WEATHERSTRINGS_SNOW": "Сніг",
72 | "WEATHERSTRINGS_HAIL": "Град",
73 | "WEATHERSTRINGS_SLEET": "Сльота",
74 | "WEATHERSTRINGS_DUST": "Пильний",
75 | "WEATHERSTRINGS_FOG": "Туманний",
76 | "WEATHERSTRINGS_HAZE": "Імлистий",
77 | "WEATHERSTRINGS_SMOCK": "Димчастий",
78 | "WEATHERSTRINGS_BLUSTER": "Бурхливий",
79 | "WEATHERSTRINGS_WIND": "Вітряний",
80 | "WEATHERSTRINGS_COLD": "Холодна",
81 | "WEATHERSTRINGS_CLOUDY": "Хмарно",
82 | "WEATHERSTRINGS_MOSTLYCLOUDY": "Переважно хмарно",
83 | "WEATHERSTRINGS_PARTLYCLOUDY": "Мінлива хмарність",
84 | "WEATHERSTRING_CLEAR": "Чисте небо",
85 | "WEATHERSTRING_SUNNY": "Сонячний",
86 | "WEATHERSTRING_FAIR": "Хороша погода",
87 | "WEATHERSTRING_RAINANDHAIL": "Дощ і град",
88 | "WEATHERSTRING_HOT": "Гаряча",
89 | "WEATHERSTRING_ISOLATEDTHUNDERSTORMS": "Ізольовані грози",
90 | "WEATHERSTRING_SCATTEREDTHUNDERSTORMS": "",
91 | "WEATHERSTRING_HEAVYSNOW": "Сильний сніг",
92 | "WEATHERSTRING_THUNDERSHOWERS": "Зливи з грозою",
93 | "WEATHERSTRING_NOTAVAILABLE": "Недоступний",
94 | "AWAITUSERCONFIRMATION_FULFILLED": "Виконаний запит",
95 | "AWAITUSERCONFIRMATION_CANCELLED": "Скасовано запит"
96 | }
97 |
--------------------------------------------------------------------------------
/plugins/images/sunny.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
112 |
--------------------------------------------------------------------------------
/translations/pt_BR/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "SPECIAL_STIME": "{{time, stime}}",
3 | "UINFO_RETRIEVING": "Buscando informações do usuário…",
4 | "UINFO_USER_ID": "ID do Usuário: {{id}}",
5 | "UINFO_USER_INFORMATION": "Informações do Usuário",
6 | "UINFO_CREATEDAT": "**Criado Em:** {{createdat, datetime}}",
7 | "UINFO_JOINEDAT": "**Entrou Aqui Em:** {{joinedat, datetime}}",
8 | "UINFO_TIMESTAMPS": "Timestamps",
9 | "UINFO_DISPLAYNAME": "**Nome de Exibição:** {{displayname}}",
10 | "UINFO_USERNAME": "**Nome do Usuário:** {{username}}",
11 | "UINFO_NONICKNAME": "Sem Apelido",
12 | "UINFO_NICKNAME": "**Apelido:** {{nickname}}",
13 | "UINFO_NAMES": "Nomes",
14 | "UINFO_INVALID_JOIN": "-∞… e além! O Discord aparenta estar dando as informações incorretas… :(",
15 | "UINFO_NOT_PART_OF_SERVER": "Esse usuário não faz parte desse servidor.",
16 | "UINFO_NOT_ALLOWED_SERVER_SPECIFIC": "Você não é permitido ver informações específicas do usuário nesse servidor.",
17 | "SETLOC_TITLE": "Localização AstralMod",
18 | "SETLOC_LANGUAGE": "Tudo bem, sua localidade agora é português (Brasil).",
19 | "SETLOC_DISCLAIMER": "Localização AstralMod está em desenvolvido. Muitos itens não estão traduzidos.",
20 | "SETLOC_UNAVAILABLE": "Infelizmente, não temos esta localidade no AstralMod.",
21 | "UINFO_BANNED_FROM": "Esse usuário foi banido de {{count}} servidor conhecido ao AstralMod",
22 | "UINFO_BANNED_FROM_plural": "Esse usuário foi banido de {{count}} servidores conhecidos ao AstralMod",
23 | "UINFO_ALERTS": "Alertas",
24 | "UINFO_BOT_ACCOUNT_WARNING": "Esse usuário é uma conta de bot.",
25 | "SINFO_RETRIEVING_SERVER": "Buscando informações do servidor…",
26 | "SINFO_GUILDID": "ID da Guild: {{id}}",
27 | "SINFO_SERVER_INFORMATION": "Informações do Servidor",
28 | "SINFO_SERVER_CREATED": "**Criado Em:** {{createdat, datetime}}",
29 | "SINFO_AM_JOINED": "**AstralMod Adicionado:** {{joinedat, datetime}}",
30 | "SINFO_INVALID_JOIN_DATE": "-∞… e além! O Discord aparenta estar dando as informações incorretas… :(",
31 | "SINFO_TIMESTAMPS": "Timestamps",
32 | "SINFO_MEMBER_COUNT": "**Total de Membros:** {{count}}",
33 | "SINFO_BOT_COUNT": "({{count}} bot)",
34 | "SINFO_BOT_COUNT_plural": "({{count}} bots)",
35 | "SINFO_SERVER_OWNER": "**Dono do Servidor:** {{owner}}",
36 | "SINFO_PEOPLE": "Pessoas",
37 | "SINFO_SURPLUS_ROLES": "{{count}} cargo a mais",
38 | "SINFO_SURPLUS_ROLES_plural": "{{count}} cargos a mais",
39 | "SINFO_ROLES": "Cargos",
40 | "SINFO_ALERTS": "Alertas",
41 | "ERROR_DETAILS": "Detalhes",
42 | "TIME_TIMEZONE_NOT_SET": "{{user}} não ajustou seu fuso horário ainda. Fale para ele(a) para usar `{{prefix}}setz` agora!",
43 | "TIME_TIMEZONE_NOT_VALID": "{{tz}} não é um fuso válido.",
44 | "TIME_RESPONSE": "{{clockEmote}} **{{request}}** ({{offset}}) {{time, dddd[,] MMMM D}}, as {{time, stime}}",
45 | "ERROR_INTERNAL": "Erro Interno",
46 | "ERROR_USER_INPUT": "Erro na Entrada do Usuário",
47 | "ERROR_NOT_UNDERSTAND": "AstralMod não entendeu o que você quis dizer.",
48 | "ERROR_LOGGED": "Esse erro foi reportado, vamos procurar sobre ele.",
49 | "ERROR_INTERNAL_DESCRIPTION": "AstralMod teve um problema tentando processar esse comando.",
50 | "WEATHER_PREPARING": "Preparando o tempo…",
51 | "WEATHER_TITLE": "Tempo",
52 | "WEATHER_CURRENT_WEATHER": "Tempo Atual",
53 | "WEATHER_DATE_UPDATED": "A partir de {{updated, datetime}}",
54 | "WEATHER_TODAY": "Hoje",
55 | "WEATHER_PLEASE_PRINT": "Sinta-se a à vontade para imprimir isso",
56 | "WEATHER_TEAR_PERFORATED_LINE": "Por favor rasgue na linha perfurada",
57 | "WEATHER_SO_MANY_DEGREES": "Tantos graus…",
58 | "WEATHER_LONGER_DAYS": "Os dias estão ficando mais longos?",
59 | "WEATHER_ERROR": "{{emoji}} Erro do Tempo",
60 | "WEATHER_ERROR_NOT_RETRIEVED": "AstralMod não pode adquirir as informações do tempo.",
61 | "WEATHER_ERROR_DETAILS": "Detalhes",
62 | "WEATHER_ERROR_CITY_NOT_FOUND": "Essa cidade não pode ser achada",
63 | "WEATHER_ERROR_TRY_THIS": "Tente isso",
64 | "WEATHER_ERROR_TRY_THIS_DESCRIPTION": "Por favor, seja mais especifico ou tente outra ortografia para o lugar do qual você quer ver o tempo. Se você está tentado ver o tempo no seu local, tente restabelecer sua localização com `{{prefix}}setloc`.",
65 | "WEATHER_ERROR_UNSET_LOCATION": "{{user}} não nos falou sua localização ainda. Fale para ele(a) para usar `{{prefix}}setloc` agora!",
66 | "AWAITUSERCONFIRMATION_CANCEL_PROMPT": "Use {{emoji}} dentro de {{tempo}} segundos para cancelar",
67 | "AWAITUSERCONFIRMATION_FULFILLED": "Solicitação Cumprida",
68 | "AWAITUSERCONFIRMATION_CANCELLED": "Solicitação Cancelada",
69 | "NICK_NOT_ACCEPTED": "Mudanças de apelido não são aceitas nesse server pelo AstralMod.",
70 | "PING_PINGING": "{{emoji}} Estou aqui!",
71 | "PING_DONE": "{{emoji}} Estou aqui! Levou {{time}} milissegundos para responder.",
72 | "PING_DONE_420": "{{emoji}} Estou aqui! Levou ou 419 milissegundos ou 421 milissegundos para responder."
73 | }
74 |
--------------------------------------------------------------------------------
/plugins/images/wind.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
123 |
--------------------------------------------------------------------------------
/plugins/images/snow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
101 |
--------------------------------------------------------------------------------
/plugins/images/rainsnow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
104 |
--------------------------------------------------------------------------------
/plugins/images/rain.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
107 |
--------------------------------------------------------------------------------
/plugins/eval.js:
--------------------------------------------------------------------------------
1 | /****************************************
2 | *
3 | * Miscellaneous: Plugin for AstralMod that contains miscellaneous commands
4 | * Copyright (C) 2019 Victor Tran, John Tur
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | * *************************************/
20 |
21 | var client;
22 | var consts;
23 |
24 | var currentGuild = 0;
25 |
26 | var exec = require('child_process').exec;
27 |
28 | function exit(channel) {
29 | releaseInput(currentGuild);
30 | currentGuild = 0;
31 | channel.send("Exited Arbitrary Code Execution mode.")
32 | }
33 |
34 | function serialise(object) {
35 | let m = "";
36 |
37 | switch (typeof(object)) {
38 | case "object":
39 | if (Promise.resolve(object) == object) {
40 | m = "[unresolved promise]";
41 | break;
42 | } else {
43 | for (key in object) {
44 | m += "`" + key + "`: " + typeof(object[key]) + "\n";
45 | }
46 | }
47 | break;
48 | case "array":
49 | m += "[\n";
50 | for (key in array) {
51 | m += " `" + typeof(ojb [key]) + "`\n";
52 | }
53 | m += "]"
54 | break;
55 | case "function":
56 | m = "```js\n" + String(object) + "```";
57 | break;
58 | default:
59 | m = String(object);
60 | }
61 | return m;
62 | }
63 |
64 | async function processEval(message) {
65 | try {
66 | let forceOutput = false;
67 | let command = message.content;
68 | if (command.startsWith("$")) {
69 | command = command.substr(1);
70 | forceOutput = true;
71 | }
72 |
73 | let asyncFuncConstructor = Object.getPrototypeOf(async function(){}).constructor;
74 | let func = asyncFuncConstructor('message', 'client', 'exit', command);
75 | let ret = await func(message, client, () => exit(message.channel));
76 | let type = typeof(ret);
77 | let m = serialise(ret);
78 |
79 | if (currentGuild === 0)
80 | return;
81 |
82 | if (m == "undefined") {
83 | m = "[generated function had no return value]";
84 | }
85 |
86 | if ((m.length > 500 || m.split("\n").length > 5) && !forceOutput) {
87 | m = "[" + type + " output suppressed]";
88 | }
89 |
90 | let splitOptions = {};
91 | if (m.startsWith("```js")) {
92 | splitOptions.append = "```";
93 | splitOptions.prepend = "```js\n";
94 | }
95 |
96 | let mess = await message.channel.send(m, {
97 | split: splitOptions
98 | })
99 |
100 | } catch (err) {
101 | await message.channel.send(":large_orange_diamond: " + err.message.replace(client.token, "[client token redacted]"));
102 | }
103 | }
104 |
105 | function processCommand(message, isMod, command) {
106 | if (command == "exec") {
107 | if (message.author.id == global.botOwner.id) {
108 | captureInput(processEval, message.guild.id, message.author.id);
109 |
110 | if (currentGuild != 0) {
111 | exit();
112 | }
113 |
114 | currentGuild = message.guild.id;
115 | message.reply("Welcome to Arbitrary Code Execution mode. Any messages from here on will be interpreted as code. To exit, use the `exit()` command.");
116 | } else {
117 | message.reply("Arbitrary code execution mode is reserved.");
118 | }
119 | }
120 | }
121 |
122 | module.exports = {
123 | name: "Evaluation",
124 | translatableName: "TITLE_EVAL",
125 | constructor: function(discordClient, commandEmitter, constants) {
126 | client = discordClient;
127 | consts = constants;
128 |
129 | commandEmitter.on('processCommand', processCommand);
130 | },
131 | destructor: function(commandEmitter) {
132 | commandEmitter.removeListener('processCommand', processCommand);
133 | },
134 | availableCommands: {
135 | general: {
136 | commands: [
137 |
138 | ],
139 | modCommands: [
140 |
141 | ],
142 | hiddenCommands: [
143 | "exec"
144 | ]
145 | }
146 | },
147 | acquireHelp: function(helpCmd, message, h$) {
148 | var help = {};
149 |
150 | switch (helpCmd) {
151 | case "eval":
152 | help.title = prefix(message.guild.id) + "eval";
153 | help.usageText = prefix(message.guild.id) + "pic user";
154 | help.helpText = h$("EVAL_HELPTEXT");
155 | help.remarks = h$("EVAL_REMARKS");
156 | }
157 |
158 | return help;
159 | }
160 | }
--------------------------------------------------------------------------------
/plugins/settings.js:
--------------------------------------------------------------------------------
1 | /****************************************
2 | *
3 | * Settings: Plugin for AstralMod that does things with AstralMod settings
4 | * Copyright (C) 2019 Victor Tran, John Tur
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | * *************************************/
20 |
21 | var client;
22 | var consts;
23 | const zlib = require('zlib');
24 |
25 | function processCommand(message, isMod, command, options) {
26 | let $ = _[options.locale];
27 | if (command.startsWith("retrsettings")) {
28 | if (message.author.id === global.botOwner.id && command.indexOf("--user") == -1) {
29 | sendPreloader($("RETRSETTINGS_COMPRESSING_SETTINGS"), message.channel).then(function(messageToEdit) {
30 | //Compress the settings with gzip to save space
31 | zlib.gzip(JSON.stringify(settings), function(error, result) {
32 | if (error) {
33 | messageToEdit.edit($("RETRSETTINGS_PROBLEM_COMPRESSING"));
34 | } else {
35 | message.author.send($("RETRSETTINGS_COMPRESSING_SUCCESS"), {
36 | files: [
37 | {
38 | attachment: result,
39 | name: "settings.json.gz"
40 | }
41 | ]
42 | });
43 | messageToEdit.edit($("RETRSETTINGS_CHECK_FOR_COMPRESSIONS", {emoji: ":arrow_left:"}));
44 | }
45 | });
46 | });
47 | } else {
48 | if (settings.users[message.author.id] == undefined) {
49 | message.reply($("RETRSETTINGS_NO_SETTINGS"));
50 | return;
51 | }
52 |
53 | sendPreloader($("RETRSETTINGS_PREPARING_SETTINGS"), message.channel).then(function(messageToEdit) {
54 | message.author.send($("RETRSETTINGS_SETTINGS_RETRIEVED"), {
55 | files: [
56 | {
57 | attachment: Buffer.from(JSON.stringify(settings.users[message.author.id], null, 4), "utf8"),
58 | name: "settings.json"
59 | }
60 | ]
61 | });
62 | messageToEdit.edit($("RETRSETTINGS_CHECK_FOR_SETTINGS", {emoji: ":arrow_left:"}));
63 | });
64 | }
65 | } else if (command.startsWith("resetsettings")) {
66 | awaitUserConfirmation({
67 | title: $("RESETSETTINGS_CONFIRMATION_TITLE"),
68 | msg: $("RESETSETTINGS_CONFIRMATION_MESSAGE"),
69 | extraFields: [
70 | [$("RESETSETTINGS_REMOVED_SETTINGS_TITLE"), $("RESETSETTINGS_REMOVED_SETTINGS")],
71 | [$("RESETSETTINGS_NOT_REMOVED_SETTINGS_TITLE"), $("RESETSETTINGS_NOT_REMOVED_SETTINGS")],
72 | [$("RESETSETTINGS_NOT_UNDONE_TITLE"), $("RESETSETTINGS_NOT_UNDONE")]
73 | ],
74 | msgOnSuccess: $("RESETSETTINGS_CONFIRMATION_SUCCESS"),
75 | msgOnFail: $("RESETSETTINGS_CONFIRMATION_CANCELLED", {prefix: prefix(message.guild.id)}),
76 | channel: message.channel,
77 | author: message.author,
78 | time: 60,
79 | locale: options.locale
80 | }).then(() => {
81 | message.author.send($("RETRSETTINGS_SETTINGS_RETRIEVED"), {
82 | files: [
83 | {
84 | attachment: Buffer.from(JSON.stringify(settings.users[message.author.id], null, 4), "utf8"),
85 | name: "settings.json"
86 | }
87 | ]
88 | }).then(() => {
89 | delete settings.users[message.author.id];
90 | });
91 | }).catch(err => {
92 | //Do nothing
93 | });
94 | }
95 | }
96 |
97 | module.exports = {
98 | name: "AstralMod Settings",
99 | translatableName: "TITLE_SETTINGS",
100 | constructor: function(discordClient, commandEmitter, constants) {
101 | client = discordClient;
102 | consts = constants;
103 |
104 | commandEmitter.on('processCommand', processCommand);
105 | },
106 | destructor: function(commandEmitter) {
107 | commandEmitter.removeListener('processCommand', processCommand);
108 | },
109 | availableCommands: {
110 | general: {
111 | commands: [
112 | "retrsettings",
113 | "resetsettings"
114 | ],
115 | modCommands: [
116 |
117 | ],
118 | hiddenCommands: [
119 | ]
120 | }
121 | },
122 | acquireHelp: function(helpCmd, message, h$) {
123 | var help = {};
124 |
125 | switch (helpCmd) {
126 | case "retrsettings":
127 | help.title = prefix(message.guild.id) + "retrsettings";
128 | help.helpText = $("RETRSETTINGS_HELPTEXT");
129 | break;
130 | case "resetsettings":
131 | help.title = prefix(message.guild.id) + "resetsettings";
132 | help.helpText = h$("RESETSETTINGS_HELPTEXT");
133 | let $ = _[settings.users[message.author.id].locale]
134 | help.remarks = h$("RESETSETTINGS_REMARKS", {removed: $("RESETSETTINGS_REMOVED_SETTINGS"), notremoved: $("RESETSETTINGS_NOT_REMOVED_SETTINGS")})
135 | break;
136 | }
137 |
138 | return help;
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/translations/de/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "SPECIAL_STIME": "{{time, stime}}",
3 | "THIS_LOCALE": "Deutsch",
4 | "UINFO_RETRIEVING": "Erhalte Benutzer Informationen...",
5 | "UINFO_USER_ID": "Benutzer ID: {{id}}",
6 | "UINFO_USER_INFORMATION": "Benutzer Informationen",
7 | "UINFO_CREATEDAT": "**Erstellt am:** {{createdat, datetime}}",
8 | "UINFO_JOINEDAT": "**Trat bei am:** {{joinedat, datetime}}",
9 | "UINFO_TIMESTAMPS": "Zeitstempel",
10 | "UINFO_DISPLAYNAME": "**Display Name:** {{displayname}}",
11 | "UINFO_USERNAME": "**Benutzername:** {{username}}",
12 | "UINFO_NONICKNAME": "Kein Spitzname",
13 | "UINFO_NICKNAME": "**Spitzname:** {{nickname}}",
14 | "UINFO_NAMES": "Namen",
15 | "UINFO_INVALID_JOIN": "Bis in die Unendlichkeit, und noch viel weiter! Discord gibt mir inkorrekte Infos... :(",
16 | "UINFO_NOT_PART_OF_SERVER": "Dieser Benutzer ist nicht auf diesem Server.",
17 | "UINFO_NOT_ALLOWED_SERVER_SPECIFIC": "Dir ist es nicht erlaubt, Serverspezifische Informationen auf diesem Server zu sehen.",
18 | "SETLOC_TITLE": "AstralMod Lokalisierung",
19 | "SETLOC_LANGUAGE": "OK, deine Sprache ist nun {{locale}}.",
20 | "SETLOC_DISCLAIMER": "AstralMod Lokalisierung ist noch im Test. Viele Sachen sind noch nicht Übersetzt.",
21 | "SETLOC_UNAVAILABLE": "Leider haben wir diese Sprache nicht in AstralMod.",
22 | "SETLOC_YOUR_LOCALE": "Jetzige Sprache",
23 | "SETLOC_AVAILABLE_LOCALES": "Verfügbare Sprachen",
24 | "UINFO_BANNED_FROM": "Dieser Benutzer wurde von {{count}} AstralMod bekannten Server gebannt",
25 | "UINFO_BANNED_FROM_plural": "Dieser Benutzer wurde von {{count}} AstralMod bekannten Servern gebannt",
26 | "UINFO_ALERTS": "Warnungen",
27 | "UINFO_BOT_ACCOUNT_WARNING": "Dieser Benutzer ist ein Bot Account.",
28 | "SINFO_RETRIEVING_SERVER": "Erhalte Server Informationen...",
29 | "SINFO_GUILDID": "Guild ID: {{id}}",
30 | "SINFO_SERVER_INFORMATION": "Server Information",
31 | "SINFO_SERVER_CREATED": "**Erstellt am:** {{createdat, datetime}}",
32 | "SINFO_AM_JOINED": "**AstralMod beigetreten:** {{joinedat, datetime}}",
33 | "SINFO_INVALID_JOIN_DATE": "Bis in die Unendlichkeit und noch viel weiter! Discord gibt keine richtigen Informationen... :(",
34 | "SINFO_TIMESTAMPS": "Zeitstempel",
35 | "SINFO_MEMBER_COUNT": "**Nutzer insgesamt:** {{count}}",
36 | "SINFO_BOT_COUNT": "({{count}} Bot)",
37 | "SINFO_BOT_COUNT_plural": "({{count}} Bots)",
38 | "SINFO_SERVER_OWNER": "**Server Besitzer:** {{owner}}",
39 | "SINFO_PEOPLE": "Leute",
40 | "SINFO_SURPLUS_ROLES": "{{count}} Rolle mehr",
41 | "SINFO_SURPLUS_ROLES_plural": "{{count}} Rollen mehr",
42 | "SINFO_ROLES": "Rollen",
43 | "SINFO_ALERTS": "Warnungen",
44 | "ERROR_DETAILS": "Details",
45 | "TIME_ERROR_DETAILS": "Details",
46 | "TIME_ERROR": "{{emoji}} Zeit Error",
47 | "TIME_ERROR_NOT_RETRIEVED": "AstralMod konnte die Zeit nicht bekommen.",
48 | "TIME_LOCATION_NOT_FOUND": "Dieser Ort wurde nicht gefunden. Seien Sie bitte genauer oder versuchen Sie es mit einer anderen Schreibweise für den Ort, an dem Sie versuchen, die Uhrzeit zu ermitteln.",
49 | "TIME_TIMEZONE_NOT_SET": "{{user}} hat seine Zeitzone noch nicht eingestellt. Geh und nerf ihn ‘{{prefix}}settz‘ einzugeben. Schnell!",
50 | "TIME_RESPONSE": "{{clockEmote}} **{{request}}** ({{offset}}) {{time, dddd[,] MMMM D}}, um {{time, stime}}",
51 | "ERROR_INTERNAL": "Interner Error",
52 | "ERROR_USER_INPUT": "Benutzer Input Error",
53 | "ERROR_NOT_UNDERSTAND": "AstralMod hat nicht verstanden, was du meinst.",
54 | "ERROR_LOGGED": "Dieser Error wurde protokolliert, und wir werden ihn uns ansehen.",
55 | "ERROR_INTERNAL_DESCRIPTION": "AstralMod hatte ein Problem diesen Command auszuführen.",
56 | "WEATHER_PREPARING": "Bereite das Wetter vor...",
57 | "WEATHER_TITLE": "Wetter",
58 | "WEATHER_CURRENT_WEATHER": "Momentanes Wetter",
59 | "WEATHER_DATE_UPDATED": "Am {{updated, datetime}}",
60 | "WEATHER_TODAY": "Heute",
61 | "WEATHER_PLEASE_PRINT": "Druck das ruhig aus",
62 | "WEATHER_TEAR_PERFORATED_LINE": "Bitte reißen Sie die perforierte Linie ein",
63 | "WEATHER_SO_MANY_DEGREES": "So viel Grad...",
64 | "WEATHER_LONGER_DAYS": "Werden die Tage länger?",
65 | "WEATHER_ERROR": "{{emoji}} Wetter Error",
66 | "WEATHER_ERROR_NOT_RETRIEVED": "AstralMod konnte das Wetter nicht bekommen.",
67 | "WEATHER_ERROR_DETAILS": "Details",
68 | "WEATHER_ERROR_CITY_NOT_FOUND": "Diese Stadt wurde nicht gefunden",
69 | "WEATHER_ERROR_TRY_THIS": "Versuch das",
70 | "WEATHER_ERROR_TRY_THIS_DESCRIPTION": "Seien Sie bitte genauer oder versuchen Sie es mit einer anderen Schreibweise für den Ort, an dem Sie das Wetter abrufen möchten. Wenn Sie versuchen, Ihr eigenes Wetter zu erhalten, versuchen Sie, Ihren Standort mit `{{prefix}}setloc` zurückzusetzen.",
71 | "WEATHER_ERROR_UNSET_LOCATION": "{{user}} hat seinen Standort noch nicht eingestellt. Nerf ihn ‘{{prefix}}setloc‘ einzugeben. Schnell!",
72 | "AWAITUSERCONFIRMATION_CANCEL_PROMPT": "Benutze {{emoji}} in {{time}} Sekunden um abzubrechen",
73 | "AWAITUSERCONFIRMATION_FULFILLED": "Anfrage gesendet",
74 | "AWAITUSERCONFIRMATION_CANCELLED": "Anfrage abgebrochen",
75 | "NICK_NOT_ACCEPTED": "Spitznamen Änderungen sind auf diesem Server über AstralMod deaktiviert.",
76 | "PING_PINGING": "{{emoji}} Ich bin da!",
77 | "PING_DONE": "{{emoji}} Ich bin da! Es hat {{time}}ms gebraucht um zu antworten.",
78 | "PING_DONE_420": "{{emoji}} Ich bin da! Es hat entweder 419ms oder 421ms gedauert zu antworten.",
79 | "GUILD_BAN_ADD_TITLE": "{{emoji}} Benutzer gebannt",
80 | "GUILD_BAN_ADD_DESCRIPTION": "Ein Benutzer wurde vom Server gebannt.",
81 | "GUILD_BAN_ADD_USER": "Benutzer",
82 | "GUILD_BAN_ADD_USER_ID": "Benutzer ID",
83 | "GUILD_BAN_ADD_INVITES": "Erstellte Einladungen",
84 | "GUILD_BAN_ADD_BANNED_BY": "Gebannt von",
85 | "GUILD_BAN_ADD_BAN_REASON": "Grund",
86 | "SPAM_WARNING": "Du weißt das wir es nicht mögen, wenn du Spammst. (#{{warningNo}})",
87 | "SPAM_GUILD_WARNING": "{{emoji}} {{author}} hat in {{channel}} gespammt.",
88 | "SPAM_ENOUGH": "Ich hab's dir zu oft gesagt. Das Serverteam wurde verständigt. (#{{warningNo}})",
89 | "HELP_CONTENTS": "AstralMod Hilfeinhalte",
90 | "HELP_CONTENTS_INTRODUCTION": "Hier sind Sachen, sie du Ausprobieren kannst. Für mehr Informationen gibt ‘{{prefix}}help [command]‘ ein",
91 | "HELP_CORE_COMMANDS": "AstralMod Kern Commands",
92 | "HELP_FOOTER": "AstralMod {{amversion}}. Moderator Commands sind mit fetten Text gekennzeichnet.",
93 | "HELP_UNAVAILABLE": "Konnte keine Hilfe für den Command finden.",
94 | "HELP_COMMAND_TITLE": "Commander Hilfe",
95 | "HELP_COMMAND_FOR": "für {{title}}",
96 | "HELP_COMMAND_USAGE": "Benutzung",
97 | "HELP_COMMAND_DESCRIPTION": "Beschreibung",
98 | "HELP_COMMAND_OPTIONS": "Optionen",
99 | "HELP_COMMAND_AVAILABLE_OPTIONS": "Verfügbare Optionen",
100 | "HELP_COMMAND_PARAM": "Parameter {{param}}",
101 | "HELP_COMMAND_REMARKS": "Bemerkungen"
102 | }
103 |
--------------------------------------------------------------------------------
/plugins/images/humidity.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
170 |
--------------------------------------------------------------------------------
/translations/vi/help.json:
--------------------------------------------------------------------------------
1 | {
2 | "CONFIG_HELPTEXT": "Cấu hình AstralMod cho máy chủ này",
3 | "SHOO_HELPTEXT": "Thoát khỏi máy chủ, thanh trừng tất cả cấu hình",
4 | "OKNICK_HELPTEXT": "Chấp nhận tên nick",
5 | "PING_HELPTEXT": "Xin AstralMod trả lời bằng tin nhắn",
6 | "VERSION_HELPTEXT": "Truy vấn phiên bản AstralMod",
7 | "NICK_HELPTEXT": "Đặt tên nick sau khi người quản lý chấp nhận",
8 | "NICK_PARAM1": "Tên nick bạn muốn được gọi",
9 | "SETLOCALE_HELPTEXT": "Đạt ngôn ngữ AstralMod sử dụng khi xử lý lệnh của bạn",
10 | "HELP_HELPTEXT": "Thu trợ giúp với AstralMod và lệnh nào có sẵn",
11 | "HELP_PARAM1": "*Tham số không bắt buộc*\nLệnh để thu trợ giúp\nNếu tham số này mất, chúng tôi sẽ danh sách lệnh đã sẵn.",
12 | "ABOUT_HELPTEXT": "Thu thông tin với AstralMod",
13 | "SUDO_HELPTEXT": "Yêu cầu phép quản lý cho 5 phút",
14 | "TITLE_CHAT_MODERATION": "Quản lý trò chuyện",
15 | "TITLE_EVAL": "Chạy mã nguồn",
16 | "TITLE_FLAG": "Ghim di động",
17 | "TITLE_MISC": "Linh tinh",
18 | "TITLE_MONITOR": "Giám sát",
19 | "TITLE_SETTINGS": "Cài đặt AstralMod",
20 | "TITLE_SPAM": "Tin nhắn rác",
21 | "TITLE_SUGGESTIONS": "Gợi ý",
22 | "TITLE_TIME": "Thời gian",
23 | "TITLE_USER": "Người dùng",
24 | "TITLE_WARN": "Cảnh báo phạt",
25 | "TITLE_WEATHER": "Thời tiết",
26 | "RM_HELPTEXT": "Xóa một số tin nhắn",
27 | "RM_PARAM1": "Số tin nhắn để xóa, hoặc `all` để xóa tới 100 tin nhắn trong ngày hôm qua",
28 | "RM_PARAM2": "*Tham số không bắt buộc*\nTin nhắn của người dùng để xóa",
29 | "CHNK_HELPTEXT": "Đặt tên nick ngẫu nhiên cho người dùng",
30 | "CHNK_PARAM1": "- ID người dùng để đặt tên nick\n- Đề cập người dùng để đặt tên nick",
31 | "BLOCK_HELPTEXT": "Chặn người dùng sử dụng tính năng trong kênh hiện tại",
32 | "BLOCK_PARAM1": "*Tham số không bắt buộc*\nTính năng để chặn, hoặc `all` cho tất cả lệnh. Nếu tham số này mất, tất cả *lệnh* sẽ bị chặn.",
33 | "BLOCK_REMARKS": "Tính năng có hiệu lực là `spam`, `log` và lệnh nào, trừ `block`và `unblock`.\n`spam`sẽ tắt kiểm soát tin nhắn rác trong kênh, và `log` sẽ tắt thu thập đăng nhập trong kênh. Cũng không thể đặt trên toàn máy chủ, và `log` không thể chặn trong kênh cấu hình lưu trú đăng nhập.",
34 | "BLOCK_AVAILABLEOPTIONS": "`--serverwide` Thay đổi cài đặt chặn cho toàn máy chủ",
35 | "UNBLOCK_HELPTEXT": "Gỡ chặn cho người dùng sử dụng tính năng trong kênh hiện tại",
36 | "UNBLOCK_PARAM1": "*Tham số không bắt buộc*\nTính năng để gỡ chặn, Nếu tính năng mất, tất cả tính năng sẽ gỡ chặn.",
37 | "UNBLOCK_REMARKS": "Để xem tính năng đã sẵn, dùng `{{prefix}}features`",
38 | "UNBLOCK_AVAILABLEOPTIONS": "`--serverwide` Thay đổi cài đặt chặn cho toàn máy chủ",
39 | "EVAL_HELPTEXT": "Chạy tin nhắn gửi thành mã",
40 | "EVAL_REMARKS": "Lệnh này chỉ được bị chạy bởi chủ sở rô-bốt",
41 | "PIN_HELPTEXT": "Ghim tin nhắn di động để tham khảo",
42 | "PIN_PARAM1": "Tin nhắn để ghim; 1 cho tin nhắn đã gửi cuối cùng, 2 cho tin nhắn đã gửi cuối cùng thứ hai, v.v.\nBạn cũng có thể cho ID tin nhắn để ghim.",
43 | "PIN_AVAILABLEOPTIONS": "`--view [id]` Cho bạn xem ghim đó. Cũng có thể xem tệp đính kèm với tin nhắn đó",
44 | "PIN_REMARKS": "AstralMod ghim tin nhắn bởi lưu ID tin nhắn và ID kênh. Nếu tin nhắn hoặc kênh bị xóa, tin nhắn sẽ không được nhận được.",
45 | "PINS_HELPTEXT": "Hiển thị tin nhắn đã ghim di động",
46 | "PINS_PARAM1": "*Tham số không bắt buộc*\nSố trang bạn muốn xem",
47 | "UNPIN_HELPTEXT": "Gỡ ghim trên tin nhắn",
48 | "UNPIN_PARAM1": "Số ghim bạn muốn gỡ. Để xem số ghim, dùng `{{prefix}}pins`",
49 | "PIC_HELPTEXT": "Nhận ảnh đại diện cho người dùng",
50 | "PIC_PARAM1": "*Tham số không bắt buộc*\nNgười dùng bạn muốn thấy ảnh đại diện. Nếu không người dùng chỉ định, ảnh đại diện của bạn sẽ bị nhận",
51 | "SETUNIT_HELPTEXT": "Đật đơn vị bạn muốn AstralMod dùng",
52 | "SETUNIT_PARAM1": "Hoặc `metric`, `imperial`, `24(hr)`, hoặc `12(hr)`",
53 | "SETUNIT_REMARKS": "Nếu bạn muốn đặt ngôn ngữ bạn muốn AstralMod sử dụng, dùng {{prefix}}setlocale.",
54 | "SINFO_HELPTEXT": "Nhận thông tin linh tinh bởi máy chủ này",
55 | "CALC_HELPTEXT": "Gọi theCalculator để tính biểu thức toán",
56 | "CALC_REMARKS": "Nhiều biểu thức sẽ tính được bởi tách chúng bởi dấu hai chấm.",
57 | "TR_HELPTEXT": "Dịch cụm từ sang qua ngộn ngữ khác",
58 | "TR_PARAM1": "Ngôn ngữ để dịch từ. Nếu không có, ngôn ngữ sẽ bị phát hiện tự động.",
59 | "TR_PARAM2": "Ngôn ngữ để dịch đến. Nếu không có, mặc định là tiếng anh.",
60 | "TR_PARAM3": "Cụm từ để dịch.",
61 | "UPTIME_HELPTEXT": "Nhận giờ AstralMod đã kết nối với Discord",
62 | "SETTINGSSIZE_HELPTEXT": "Nhận kích thước tệp cài đặt của AstralMod trong byte",
63 | "RETRSETTINGS_HELPTEXT": "Nhận thông tin AstralMod đã lưu về bạn",
64 | "RESETSETTINGS_HELPTEXT": "Xóa thông tin AstralMod đã lưu về bạn",
65 | "RESETSETTINGS_REMARKS": "Hành động này không hoàn tác được. Điều sẽ bị xóa là: {{removed}}\n Tuy nhiên, điều này sẽ không bị xóa: {{notremoved}}\n Bản cài đặt sẽ bị gửi đến bạn trước khi nó bị xóa.",
66 | "SPAMCTL_HELPTEXT": "Chuyển đổi tùy chọn lọc tin nhắn rác cho máy chủ này",
67 | "SPAMCTL_PARAM1": "`on` hoặc `off`.",
68 | "SPAMDATA_HELPTEXT": "Truy vấn AstralMod để biết thông tin về thói quen tin nhắn rác của bạn",
69 | "SUGGEST_HELPTEXT": "Gửi gợi ý đến máy chủ",
70 | "TIME_HELPTEXT": "Nhận thời gian tại vị trí",
71 | "TIME_PARAM1": "- Bù UTC nào\n- Mã múi giờ AstralMod đã biết\n- Người dùng AstralMod biết và được cài đặt múi giờ\n- Vị trí AstralMod biết",
72 | "SETTZ_HELPTEXT": "Đặt múi giờ của bạn",
73 | "SETTZ_PARAM1": "- Bù UTC nào\n- Mã múi giờ AstralMod đã biết\n- Người dùng AstralMod biết và được cài đặt múi giờ\n- Vị trí AstralMod biết",
74 | "SETTZ_REMARKS": "Khi bạn sử dụng lệnh này, ai hỏi AstralMod sẽ được truy cập múi giờ của bạn.",
75 | "TIMER_HELPTEXT": "Đặt bộ hẹn giờ",
76 | "TIMER_PARAM1": "- Số phút\n- Số tiếp theo bởi `s`, `m`, `h`.",
77 | "TIMER_PARAM2": "*Tham số không bắt buộc*\nVăn bản để gửi khi bộ hẹn giờ hết hạn.",
78 | "TIMERS_HELPTEXT": "Danh sách bộ hẹn giờ bạn đang chạy",
79 | "RMTIMER_HELPTEXT": "Xóa bỏ hẹn giờ",
80 | "RMTIMER_PARAM1": "Số bộ hẹn giờ bạn muốn xóa. Bạn sẽ nhận số này được với `{{prefix}}timers`.",
81 | "UINFO_HELPTEXT": "Nhận thông tin với người dùng",
82 | "UINFO_OPTION1": "`--index [num]` Số dựa trên không của người dùng để truy vấn",
83 | "UINFO_PARAM1": "Người dùng bạn muốn nhận thông tin.",
84 | "FETCHUSER_HELPTEXT": "Thêm người dùng vào bộ nhớ AstralMod",
85 | "FETCHUSER_PARAM1": "ID người dùng bạn muốn bỏ thêm vào bộ nhớ AstralMod.",
86 | "FETCHUSER_REMARKS": "AstralMod chỉ nhận thức người dùng nó trong máy chủ với. Bạn sử dụng lệnh này để cho AstralMod biết người dùng từ máy chủ khác để dùng lệnh như `uinfo` hoặc `pic`.",
87 | "FIND_HELPTEXT": "Tìm kiếm người dùng trong bộ nhớ AstralMod",
88 | "FIND_PARAM1": "Người dùng bạn muốn tìm.",
89 | "FIND_REMARKS": "AstralMod sẽ tìm kiếm trận đấu gần nhất truy vấn. Mặc định, AstralMod sẽ bao gồm người dùng trong máy chủ lẫn nhau. Bạn có thể dùng lệnh `fetchuser` để bỏ thêm vào bộ nhớ.",
90 | "DEAL_HELPTEXT": "Cho ban quản lý người dùng",
91 | "DEAL_PARAM1": "Người dùng bạn muốn quản lý.",
92 | "WARN_HELPTEXT": "Đặt thêm cảnh báo phạt trên người dùng",
93 | "WARN_PARAM1": "Người dùng để đặt cảnh báo phạt lên.",
94 | "LSWARN_HELPTEXT": "Danh sách tất cả cảnh báo phạt cho người dùng",
95 | "LSWARN_PARAM1": "*Tham số không bắt buộc*\nNgười dùng đẻ danh sách cảnh báo phát. Nếu không có thì mặc định bạn.",
96 | "RMWARN_HELPTEXT": "Xóa cảnh báo phạt trên người dùng",
97 | "RMWARN_PARAM1": "ID cảnh báo phạt bạn muốn xóa.",
98 | "RMWARN_PARAM2": "Người dùng bạn muốn xóa cảnh báo phạt trên.",
99 | "WEATHER_HELPTEXT": "Nhận thời tiết tại vị trí",
100 | "WEATHER_PARAM1": "- Người dùng AstralMod biết đã đặt vị trí.\n- Vị trí AstralMod biết.",
101 | "WEATHER_AVAILABLEOPTIONS": "`--user [người dùng]` Cho bạn nhan thoi tiet tai người dùng.",
102 | "SETLOC_HELPTEXT": "Cài đặt vị trí của bạn",
103 | "SETLOC_PARAM1": "Vị trí AstralMod biết.",
104 | "SETLOC_REMARKS": "Khi bạn sử dụng lệnh này, ai hỏi AstralMod sẽ được truy cập vị trí của bạn. Để giảm bớt những lo ngại về quyền riêng tư, bạn nên đánh tên thành phố lớn gần bạn hoặc thành phố hơi lệch so với vị trí của bạn."
105 | }
106 |
--------------------------------------------------------------------------------
/translations/en/help.json:
--------------------------------------------------------------------------------
1 | {
2 | "CONFIG_HELPTEXT": "Configures AstralMod for this server",
3 | "SHOO_HELPTEXT": "Leave the server, purging all configuration",
4 | "OKNICK_HELPTEXT": "Accepts a nickname",
5 | "PING_HELPTEXT": "Asks AstralMod to reply with a message",
6 | "VERSION_HELPTEXT": "Queries the current AstralMod version",
7 | "NICK_HELPTEXT": "Sets your nickname after staff have a chance to review it",
8 | "NICK_PARAM1": "The nickname you wish to be known as",
9 | "SETLOCALE_HELPTEXT": "Sets the language AstralMod will use when processing your commands",
10 | "HELP_HELPTEXT": "Acquire information about how to use AstralMod and any available commands",
11 | "HELP_PARAM1": "*Optional Parameter*\nThe command to acquire information about.\nIf this parameter is not present, we'll list the available commands.",
12 | "ABOUT_HELPTEXT": "Acquire information about AstralMod",
13 | "SUDO_HELPTEXT": "Requests permission to use moderator commands for 5 minutes",
14 |
15 | "TITLE_CHAT_MODERATION": "Chat Moderation",
16 | "TITLE_EVAL": "Evaluation",
17 | "TITLE_FLAG": "Portable Pins",
18 | "TITLE_MISC": "Miscellaneous",
19 | "TITLE_MONITOR": "Monitor",
20 | "TITLE_SETTINGS": "AstralMod Settings",
21 | "TITLE_SPAM": "Spam",
22 | "TITLE_SUGGESTIONS": "Suggestions",
23 | "TITLE_TIME": "Time",
24 | "TITLE_USER": "Users",
25 | "TITLE_WARN": "Warning",
26 | "TITLE_WEATHER": "Weather",
27 |
28 | "RM_HELPTEXT": "Removes a number of messages",
29 | "RM_PARAM1": "The number of messages to remove, or `all` to remove up to 100 messages within the past day",
30 | "RM_PARAM2": "*Optional Parameter*\nThe user to delete messages from",
31 | "CHNK_HELPTEXT": "Sets a random nickname to user",
32 | "CHNK_PARAM1": "- The User ID of the user to apply a new nickname to\n- Mention of the user to apply a new nickname to",
33 | "BLOCK_HELPTEXT": "Blocks users from using a feature in the current channel",
34 | "BLOCK_PARAM1": "*Optional Parameter*\nThe feature to block, or `all` for all commands. If no feature is specified, all *commands* will be blocked.",
35 | "BLOCK_REMARKS": "Valid features are `spam`, `log` and any command, except for `block` and `unblock`.\n`spam` will disable spam control in the channel, and `log` will disable log collection from the channel. Neither can be applied server-wide, and `log` cannot be blocked or unblocked in channels configured for storing logs.",
36 | "BLOCK_AVAILABLEOPTIONS": "`--serverwide` Change serverwide blocking settings",
37 | "UNBLOCK_HELPTEXT": "Unblocks users from using a feature in the current channel",
38 | "UNBLOCK_PARAM1": "*Optional Parameter*\nThe feature to unblock. If no feature is specified, all features will be unblocked.",
39 | "UNBLOCK_REMARKS": "To see available features, use `{{prefix}}features`",
40 | "UNBLOCK_AVAILABLEOPTIONS": "`--serverwide` Change serverwide blocking settings",
41 |
42 | "EVAL_HELPTEXT": "Executes messages sent as code",
43 | "EVAL_REMARKS": "This can only be executed by the bot's owner",
44 |
45 | "PIN_HELPTEXT": "Portably pin a message for reference",
46 | "PIN_PARAM1": "The message to pin; 1 for the last message sent in this channel, 2 for the second last message, etc.\nYou can also provide a message ID to pin.",
47 | "PIN_AVAILABLEOPTIONS": "`--view [id]` Lets you view that specific pin. Will also let you view any attachments in the pin",
48 | "PIN_REMARKS": "AstralMod pins messages by taking the message ID and channel ID. If the message is deleted or if the channel is deleted, the message will not be retrievable.",
49 | "PINS_HELPTEXT": "Show your portably pinned messages",
50 | "PINS_PARAM1": "*Optional Parameter*\nThe page number you wish to view",
51 | "UNPIN_HELPTEXT": "Removes a message from your portable pins",
52 | "UNPIN_PARAM1": "The number of the pin that you want to unpin. To get pin numbers, use `{{prefix}}pins`",
53 |
54 | "PIC_HELPTEXT": "Gets someone's profile picture",
55 | "PIC_PARAM1": "*Optional Parameter*\nThe user that you want to get the profile picture of. If no user is specified, your profile picture will be returned",
56 | "SETUNIT_HELPTEXT": "Sets the units that you prefer AstralMod to use",
57 | "SETUNIT_PARAM1": "Either `metric`, `imperial`, `24(hr)`, or `12(hr)`",
58 | "SETUNIT_REMARKS": "If you want to set the language that you prefer AstralMod to use, use {{prefix}}setlocale.",
59 | "SINFO_HELPTEXT": "Retrieves miscellaneous information about the current server",
60 | "CALC_HELPTEXT": "Invokes theCalculator and calculates mathematical expressions",
61 | "CALC_REMARKS": "Multiple expressions can be evaluated consecutively by separating them with a colon.",
62 | "TR_HELPTEXT": "Translates a phrase between languages",
63 | "TR_PARAM1": "The language to translate from. If omitted, the language is automatically detected.",
64 | "TR_PARAM2": "The language to translate to. If omitted, defaults to English.",
65 | "TR_PARAM3": "The phrase to translate.",
66 |
67 | "UPTIME_HELPTEXT": "Gets the amount of time AstralMod has been connected to discord",
68 | "SETTINGSSIZE_HELPTEXT": "Gets the approximate size of the AstralMod settings file in bytes",
69 |
70 | "RETRSETTINGS_HELPTEXT": "Retrieves the information AstralMod has stored about you",
71 | "RESETSETTINGS_HELPTEXT": "Deletes the information AstralMod has stored about you",
72 | "RESETSETTINGS_REMARKS": "This action is permanent and cannot be reversed. Stuff that will be removed includes: {{removed}}\n However, this won't be removed: {{notremoved}}\n A copy of your settings will be sent to you before they are deleted.",
73 |
74 | "SPAMCTL_HELPTEXT": "Toggles whether AstralMod will control spam for this server",
75 | "SPAMCTL_PARAM1": "Either `on` or `off`.",
76 | "SPAMDATA_HELPTEXT": "Queries AstralMod for information about your spam habits",
77 |
78 | "SUGGEST_HELPTEXT": "Sends a suggestion to the server",
79 |
80 | "TIME_HELPTEXT": "Gets the time at a specific place",
81 | "TIME_PARAM1": "- Any UTC offset\n- A timezone code known to AstralMod\n- A user known to AstralMod that has set their time zone\n- Any location known to AstralMod",
82 | "SETTZ_HELPTEXT": "Sets your time zone",
83 | "SETTZ_PARAM1": "- Any UTC offset\n- A timezone code known to AstralMod\n- A user known to AstralMod that has set their time zone\n- Any location known to AstralMod",
84 | "SETTZ_REMARKS": "By using this command, your timezone will be available to anyone who asks AstralMod.",
85 | "TIMER_HELPTEXT": "Sets a timer for the amount of time specified in time",
86 | "TIMER_PARAM1": "- A number, in minutes\n-A number followed by either `s`, `m`, `h`.",
87 | "TIMER_PARAM2": "*Optional Parameter*\nThe text to be sent when timer expires.",
88 | "TIMERS_HELPTEXT": "Lists the timers you have running",
89 | "RMTIMER_HELPTEXT": "Removes the specified timer",
90 | "RMTIMER_PARAM1": "The index of the timer you wish to remove. This can be obtained with `{{prefix}}timers`.",
91 |
92 | "UINFO_HELPTEXT": "Gets information about a user",
93 | "UINFO_OPTION1": "`--index [num]` Zero based index of user to query",
94 | "UINFO_PARAM1": "The user that you want to get the information of.",
95 |
96 | "FETCHUSER_HELPTEXT": "Adds a user to AstralMod's user store",
97 | "FETCHUSER_PARAM1": "The user ID you want to add to AstralMod's store.",
98 | "FETCHUSER_REMARKS": "AstralMod is only aware of users it's in servers with. You can use this commands to let AstralMod know about users from other servers so you can use commands like `uinfo` or `pic` on them.",
99 | "FIND_HELPTEXT": "Lets you search through all users in AstralMod's store",
100 | "FIND_PARAM1": "The user you want to find.",
101 | "FIND_REMARKS": "AstralMod will try and find the closest match to your query. By default, it will include users in servers AstralMod's with. You can use `fetchuser` to add to the user store.",
102 | "DEAL_HELPTEXT": "Lets you manage a user",
103 | "DEAL_PARAM1": "The user you want to manage.",
104 |
105 | "WARN_HELPTEXT": "Adds a warning to a user",
106 | "WARN_PARAM1": "The user to warn.",
107 | "LSWARN_HELPTEXT": "Lists all the warnings for a user",
108 | "LSWARN_PARAM1": "*Optional Parameter*\n The user to list the warnings of. If no user is supplied, it defaults to you.",
109 | "RMWARN_HELPTEXT": "Removes a warning from a user",
110 | "RMWARN_PARAM1": "The ID of the warning you want to remove.",
111 | "RMWARN_PARAM2": "The user that you want to remove the warning from.",
112 |
113 | "WEATHER_HELPTEXT": "Gets the weather at a location",
114 | "WEATHER_PARAM1": "- A user whose location is known to AstralMod.\n- A location known to AstralMod.",
115 | "WEATHER_AVAILABLEOPTIONS": "`--user [user]` Lets you get the weather of a user rather than a location.",
116 | "WEATHER_REMARKS": "You can set your preferred units using `{{prefix}}setunit`.",
117 | "SETLOC_HELPTEXT": "Sets your location",
118 | "SETLOC_PARAM1": "Any location known to AstralMod.",
119 | "SETLOC_REMARKS": "By using this command, your location will be available to anyone who asks AstralMod. To reduce privacy concerns, it's a good idea to enter the name of a large city near you or a city slightly offset from your actual location."
120 | }
--------------------------------------------------------------------------------
/plugins/spam.js:
--------------------------------------------------------------------------------
1 | /****************************************
2 | *
3 | * Spam: Plugin for AstralMod that filters spam
4 | * Copyright (C) 2019 Victor Tran, John Tur
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | * *************************************/
20 |
21 | const Discord = require("discord.js");
22 |
23 | var client;
24 | var consts;
25 |
26 | var spamObject = {
27 | lastMessages: {},
28 | spamCounting: {},
29 | nonSpamCounting: {}
30 | };
31 |
32 | function startup() {
33 |
34 | }
35 |
36 | function newMessage(message, options) {
37 | var checkSpam = true;
38 | let $ = _[options.locale];
39 | let $$ = _[options.glocale];
40 |
41 | if (settings.guilds[message.guild.id] == null || typeof settings.guilds[message.guild.id] == "undefined") {
42 | checkSpam = false;
43 | } else {
44 | if (settings.guilds[message.guild.id].spamCtl != null) {
45 | if (settings.guilds[message.guild.id].spamCtl == false) {
46 | checkSpam = false;
47 | }
48 | }
49 |
50 | if (settings.guilds[message.guild.id].requiresConfig == true) {
51 | checkSpam = false;
52 | }
53 |
54 | if (message.author.bot) {
55 | checkSpam = false;
56 | }
57 |
58 | if (message.content.startsWith("jx:") || message.content.startsWith("jxr:")) {
59 | checkSpam = false;
60 | }
61 |
62 | if (settings.guilds[message.guild.id].blocked[message.channel.id].indexOf("spam") != -1 || settings.guilds[message.guild.id].blocked.guild.indexOf("spam") != -1) {
63 | checkSpam = false;
64 | }
65 | }
66 |
67 | if (checkSpam) {
68 | //Spam filtering enabled for this server
69 |
70 | /** @type{Array} */
71 | var lastMessagesOfUser = spamObject.lastMessages[message.author.id];
72 | if (lastMessagesOfUser == null) {
73 | lastMessagesOfUser = [];
74 | }
75 |
76 | /** @type{Number} */
77 | var spamCountingUser = spamObject.spamCounting[message.author.id];
78 | if (spamCountingUser == null) {
79 | spamCountingUser = 0;
80 | }
81 |
82 | /** @type{Number} */
83 | var nonSpamCountingUser = spamObject.nonSpamCounting[message.author.id];
84 | if (nonSpamCountingUser == null) {
85 | nonSpamCountingUser = 0;
86 | }
87 |
88 | /** @type{String} */
89 | var messageText = message.content.toLowerCase();
90 | var regex = messageText.match(//g);
91 |
92 | if (messageText.length > 4 & regex != null && messageText.replace(regex[0], "").length > 4) { // Ignore custom emoji and short messages
93 | if (lastMessagesOfUser.includes(messageText)) {
94 | spamCountingUser++;
95 |
96 | if (nonSpamCountingUser > 0) {
97 | nonSpamCountingUser--;
98 | }
99 |
100 | if (spamCountingUser >= 4) {
101 | if (spamCountingUser == 10) {
102 | if (client.channels.has(settings.guilds[message.guild.id].botWarnings)) {
103 | client.channels.get(settings.guilds[message.guild.id].botWarnings).send($$("SPAM_GUILD_WARNING", {emoji: ":red_circle:", author: "<@" + message.author.id + ">", channel: message.channel.name, interpolation: {escapeValue: false}}));
104 | } else {
105 | log("Bot Warnings channel " + settings.guilds[message.guild.id].botWarnings + " not found", logType.critical);
106 | }
107 | message.reply($("SPAM_ENOUGH", {warningNo: spamCountingUser.toString()}));
108 | } else if (spamCountingUser > 10) {
109 |
110 | } else {
111 | message.reply($("SPAM_WARNING", {warningNo: spamCountingUser.toString()}));
112 | }
113 | message.delete().catch(function() {
114 | logPromiseRejection(message, "messageDelete");
115 | });
116 | }
117 | } else {
118 | //Add last message to array
119 | lastMessagesOfUser.push(messageText);
120 |
121 | //Remove 11th message if there is one
122 | if (lastMessagesOfUser.length > 10) {
123 | lastMessagesOfUser.splice(0, 1);
124 | }
125 |
126 | nonSpamCountingUser++;
127 | }
128 |
129 | if (nonSpamCountingUser == 10) {
130 | spamCountingUser = 0;
131 | nonSpamCountingUser = 0;
132 | }
133 | }
134 |
135 | //Set Variables
136 | spamObject.lastMessages[message.author.id] = lastMessagesOfUser;
137 | spamObject.spamCounting[message.author.id] = spamCountingUser;
138 | spamObject.nonSpamCounting[message.author.id] = nonSpamCountingUser;
139 | }
140 | }
141 |
142 | function processCommand(message, isMod, command, options) {
143 | let $ = _[options.locale];
144 | if (isMod) {
145 | if (command.startsWith("spamctl ")) {
146 | var isOn = command.substr(8);
147 | if (isOn.toLowerCase() == $("SPAMCTL_ON_TEXT").toLowerCase()) {
148 | settings.guilds[message.guild.id].spamCtl = true;
149 | message.reply($("SPAMCTL_ON"));
150 | if (isOn.toLowerCase() == $("SPAMCTL_OFF_TEXT").toLowerCase()) {
151 | settings.guilds[message.guild.id].spamCtl = false;
152 | message.reply($("SPAMCTL_OFF"));
153 | } else {
154 | message.reply($("SPAMCTL_ABOUT"));
155 | }
156 | } else if (command == "spamctl") {
157 | let replyStr;
158 | if (settings.guilds[message.guild.id].spamCtl) {
159 | replyStr = $("SPAMCTL_CURRENTLY_ON");
160 | } else {
161 | replyStr = $("SPAMCTL_CURRENTLY_OFF");
162 | }
163 | replyStr += "\n" + $("SPAMCTL_ABOUT", {prefix: prefix(message.guild.id)});
164 | message.reply(replyStr);
165 | }
166 | }
167 |
168 | if (command == "spamdata") {
169 | /** @type{Array} */
170 | var lastMessagesOfUser = spamObject.lastMessages[message.author.id];
171 | if (lastMessagesOfUser == null) {
172 | lastMessagesOfUser = [];
173 | }
174 |
175 | /** @type{Number} */
176 | var spamCountingUser = spamObject.spamCounting[message.author.id];
177 | if (spamCountingUser == null) {
178 | spamCountingUser = 0;
179 | }
180 |
181 | /** @type{Number} */
182 | var nonSpamCountingUser = spamObject.nonSpamCounting[message.author.id];
183 | if (nonSpamCountingUser == null) {
184 | nonSpamCountingUser = 0;
185 | }
186 |
187 | var embed = new Discord.RichEmbed;
188 | embed.setAuthor(message.member.displayName, message.author.displayAvatarURL);
189 | embed.addField($("SPAMDATA_DATA_TITLE"), `${$("SPAMDATA_DETECTED")} ${spamCountingUser}\n${$("SPAMDATA_FORGIVENESS")} ${nonSpamCountingUser}`, true);
190 | embed.setColor(consts.colors.info);
191 |
192 | message.reply($("SPAMDATA_TITLE"), {embed: embed});
193 | }
194 | }
195 | }
196 |
197 | module.exports = {
198 | name: "Spam",
199 | translatableName: "TITLE_SPAM",
200 | constructor: function(discordClient, commandEmitter, constants) {
201 | client = discordClient;
202 | consts = constants;
203 |
204 | commandEmitter.on('startup', startup);
205 | commandEmitter.on('newMessage', newMessage);
206 | commandEmitter.on('processCommand', processCommand);
207 | },
208 | destructor: function(commandEmitter) {
209 | commandEmitter.removeListener('startup', startup);
210 | commandEmitter.removeListener('newMessage', newMessage);
211 | commandEmitter.removeListener('processCommand', processCommand);
212 | },
213 | availableCommands: {
214 | general: {
215 | modCommands: [
216 | "spamctl"
217 | ],
218 | commands: [
219 | "spamdata"
220 | ]
221 | }
222 | },
223 | acquireHelp: function(helpCmd, message, h$) {
224 | var help = {};
225 | let $ = _[settings.users[message.author.id].locale];
226 |
227 | switch (helpCmd) {
228 | case "spamctl":
229 | help.title = prefix(message.guild.id) + "spamctl";
230 | help.usageText = prefix(message.guild.id) + `spamctl ${$("SPAMCTL_ON_TEXT")}|${$("SPAMCTL_OFF_TEXT")}`;
231 | help.helpText = h$("SPAMCTL_HELPTEXT");
232 | help.param1 = h$("SPAMCTL_PARAM1");
233 | break;
234 | case "spamdata":
235 | help.title = prefix(message.guild.id) + "spamdata";
236 | help.helpText = h$("SPAMDATA_HELPTEXT");
237 | break;
238 | }
239 |
240 | return help;
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/translations/nl/translation.json:
--------------------------------------------------------------------------------
1 | {
2 | "SPECIAL_STIME": "{{time, stime}}",
3 | "THIS_LOCALE": "Nederlands",
4 | "UINFO_RETRIEVING": "Gebruikersinformatie ophalen...",
5 | "UINFO_USER_ID": "Gebruikers-id: {{id}}",
6 | "UINFO_USER_INFORMATION": "Gebruikersinformatie",
7 | "UINFO_CREATEDAT": "**Gemaakt op:** {{createdat, datetime}}",
8 | "UINFO_JOINEDAT": "**Gejoind op:** {{joinedat, datetime}}",
9 | "UINFO_TIMESTAMPS": "Tijdstempel",
10 | "UINFO_DISPLAYNAME": "**Weergavenaam:**{{displayname}}",
11 | "UINFO_USERNAME": "**Gebruikersnaam:** {{username}}",
12 | "UINFO_NONICKNAME": "Geen bijnaam",
13 | "UINFO_NICKNAME": "**Bijnaam:** {{nickname}}",
14 | "UINFO_NAMES": "Namen",
15 | "UINFO_INVALID_JOIN": "Naar de sterren.... een daar voorbij! Discord geeft mij verkeerde informatie... :(",
16 | "UINFO_NOT_PART_OF_SERVER": "Deze gebruiker is niet in deze server.",
17 | "UINFO_NOT_ALLOWED_SERVER_SPECIFIC": "Niet alle informatie wordt hier weergegeven; je hebt geen toestemming om serverspecifieke informatie te zien in deze server.",
18 | "UINFO_BANNED_FROM": "Deze gebruiker is van {{count}} bij AstralMod bekende server geband",
19 | "UINFO_BANNED_FROM_plural": "Deze gebruiker is van {{count}} bij AstralMod bekende servers geband",
20 | "UINFO_ALERTS": "Waarschuwingen",
21 | "UINFO_BOT_ACCOUNT_WARNING": "Dit is een bot.",
22 | "SETLOC_TITLE": "AstralMod-lokalisatie",
23 | "SETLOC_LANGUAGE": "OK, je taal is nu {{locale}}.",
24 | "SETLOC_DISCLAIMER": "AstralMod-localisatie is nog in de testfase. Veel dingen zijn nog niet vertaald.",
25 | "SETLOC_UNAVAILABLE": "Helaas hebben we die taal niet in AstralMod.",
26 | "SETLOC_YOUR_LOCALE": "Huidige taal",
27 | "SETLOC_AVAILABLE_LOCALES": "Beschikbare talen",
28 | "SINFO_RETRIEVING_SERVER": "Serverinformatie aan het ophalen...",
29 | "SINFO_SERVER_INFORMATION": "Serverinformatie",
30 | "SINFO_SERVER_CREATED": "**Gemaakt op:** {{createdat, datetime}}",
31 | "SINFO_AM_JOINED": "**AstralMod joined:** {{joinedat, datetime}}",
32 | "SINFO_INVALID_JOIN_DATE": "Naar de sterren en daar voorbij! Discord geeft geen goede informatie... :(",
33 | "SINFO_TIMESTAMPS": "Tijdstempel",
34 | "SINFO_MEMBER_COUNT": "**Totaal aantal leden:** {{count}}",
35 | "SINFO_SERVER_OWNER": "**Serverbezitter:** {{owner}}",
36 | "SINFO_SURPLUS_ROLES": "{{count}} rol meer",
37 | "SINFO_SURPLUS_ROLES_plural": "{{count}} rollen meer",
38 | "SINFO_ROLES": "Rollen",
39 | "SINFO_ALERTS": "Waarschuwingen",
40 | "ERROR_DETAILS": "Details",
41 | "TIME_PREPARING": "De tijd aan het voorbereiden...",
42 | "TIME_ERROR_DETAILS": "Details",
43 | "TIME_ERROR": "{{emoji}} Tijderror",
44 | "TIME_ERROR_NOT_RETRIEVED": "AstralMod kon de tijd niet ophalen.",
45 | "TIME_LOCATION_NOT_FOUND": "Die locatie werd niet gevonden. Probeer preciezer te zijn, of probeer een andere spelling voor de plaats waarvan je de tijd wil hebben.",
46 | "TIME_TIMEZONE_NOT_SET": "{{user}} heeft zijn tijdzone nog niet ingesteld. Ga hem irriteren om snel `{{prefix}}settz`!",
47 | "TIME_RESPONSE": "{{clockEmote}} **{{request}}** ({{time, Z}}) {{time, dddd[,] MMMM D}} op {{time, stime}}",
48 | "ERROR_INTERNAL": "Interne fout",
49 | "ERROR_USER_INPUT": "Gebruikersinvoerfout",
50 | "ERROR_NOT_UNDERSTAND": "AstralMod begreep niet wat je probeerde te zeggen.",
51 | "ERROR_LOGGED": "Deze fout is vastgelegd, en we zullen ernaar kijken.",
52 | "SPECIAL_DATETIME": "{{time, dddd[,] MMMM D YYYY}} op {{time, stime}} ({{time, Z}})",
53 | "BLOCK_ALL_BLOCKED_SERVER": "Ok, alle commando's zullen worden genegeerd in deze server.",
54 | "BLOCK_ALL_BLOCKED_CHANNEL": "Oké, alle commando's zullen worden genegeerd in dit kanaal.",
55 | "BLOCK_ABOUT": "Functies bestaan uit één woord. Voer alsjeblieft een geldige functie in. Voor meer informatie, typ `{{prefix}} help block` in",
56 | "BLOCK_CANT_BLOCK_THIS": "Ik kan het `block` commando niet blokkeren.",
57 | "BLOCK_CANT_BLOCK_UNBLOCK": "Ik kan het `unblock` commando niet blokkeren.",
58 | "BLOCK_LOG_ALREADY_BLOCKED_IN_LOG_CHANNELS": "Logkanalen hebben de verzameling van logs van hunzelf al uitgeschakeld.",
59 | "BLOCK_CANT_BLOCK_SPAMCTL_SERVERWIDE": "Om spamcontrole in deze eserver uit te schakelen, typ `{{prefix}}spamctl off` in.",
60 | "BLOCK_CANT_BLOCK_LOGS_SERVERWIDE": "Om logverzameling in deze server uit te schakelen, gebruik het `{{prefix}} config` commando om de logkanalen te verwijderen.",
61 | "BLOCK_SPAMCTL_ALREADY_DISABLED_CHANNEL": "Je hebt spamcontrole in dit kanaal al uitgeschakeld.",
62 | "BLOCK_LOG_ALREADY_DISABLED_CHANNEL": "Je hebt logverzameling in dit kanaal al uitgeschakeld.",
63 | "BLOCK_COMMAND_ALREADY_DISABLED_CHANNEL": "Je hebt {{command}} al uitgeschakeld in dit kanaal.",
64 | "BLOCK_COMMAND_ALREADY_DISABLED_SERVER": "Je hebt {{command}} al uitgeschakeld in deze server.",
65 | "BLOCK_COMMAND_BLOCKED_SERVER": "Oké, ik heb het onmogelijk gemaakt voor mensen om {{command}} in deze server uit te voeren.",
66 | "BLOCK_COMMAND_BLOCKED_CHANNEL": "Oké, ik heb het onmogelijk gemaakt voor mensen om {{command}} in dit kanaal uit te voeren.",
67 | "BLOCK_SPAMCTL_BLOCKED_CHANNEL": "Oké, ik heb spamcontrole in dit kanaal uitgeschakeld.",
68 | "BLOCK_LOG_BLOCKED_CHANNEL": "Oké, ik heb logverzameling voor dit kanaal uitgeschakeld.",
69 | "UINFO_DISCRIMINATOR": "**Discriminator:** {{discriminator}}",
70 | "RM_ITS_A_CATASTROPHE": "Er is iets misgegaan.",
71 | "RM_DELETED_NONE": "{{emoji}} Er zijn geen berichten van die gebruiker gevonden.",
72 | "RM_DELETED_FEWER": "{{emoji}} Er is alleen {{count}} bericht verwijderd.",
73 | "RM_DELETED_FEWER_plural": "{{emoji}} Er zijn alleen {{count}} berichten verwijderd.",
74 | "RM_DELETED": "{{emoji}} {{count}} berichten zijn verwijderd.",
75 | "RM_DELETED_plural": "{{emoji}} {{count}} berichten zijn verwijderd.",
76 | "RM_TOO_HIGH": "Slechts 99 berichten kunnen tegelijkertijd verwijderd worden.",
77 | "RM_NO_USER": "Ik kon geen gebruiker met die naam vinden.",
78 | "RM_NAN": "Dat is geen getal.",
79 | "RM_ALL_ABOUT": "De \"alles\"-optie kan alleen worden gebruikt als er bij het tweede argument naar een gebruiker wordt verwezen.",
80 | "RM_ALL_DOWNLOADING": "Geef ons even tijd om {{count}} bericht van {{user}} te vinden...",
81 | "RM_ALL_DOWNLOADING_plural": "Geef ons even tijd om {{count}} berichten van {{user}} te vinden...",
82 | "RM_ALL_DOWNLOADING_ALL": "Geef ons even tijd om alle berichten van {{user}} van de afgelopen dag te vinden...",
83 | "SINFO_GUILDID": "Guild-ID: {{id}}",
84 | "SINFO_BOT_COUNT": "({{count}} bot)",
85 | "SINFO_BOT_COUNT_plural": "({{count}} bots)",
86 | "SINFO_PEOPLE": "Mensen",
87 | "ERROR_COULDNT_COMPLETE": "AstralMod kon dat commando niet afmaken.",
88 | "ERROR_INTERNAL_DESCRIPTION": "AstralMod kan dit commando door een probleem niet uitvoeren.",
89 | "WEATHER_PREPARING": "Bezig met het weer voorbereiden...",
90 | "WEATHER_TITLE": "Weer",
91 | "WEATHER_CURRENT_WEATHER": "Het weer op dit moment",
92 | "WEATHER_DATE_UPDATED": "Op {{updated, dddd[,] MMMM D}}, om {{updated, stime}}",
93 | "WEATHER_TODAY": "Vandaag",
94 | "WEATHER_PLEASE_PRINT": "Print dit gerust uit",
95 | "WEATHER_TEAR_PERFORATED_LINE": "Scheur alsjeblieft op de stippellijn",
96 | "WEATHER_SO_MANY_DEGREES": "Het is zo heet buiten...",
97 | "WEATHER_LONGER_DAYS": "Worden de dagen langer?",
98 | "WEATHER_ERROR": "{{emoji}} Fout bij het weer",
99 | "WEATHER_ERROR_NOT_RETRIEVED": "AstralMod kon het weer niet vinden.",
100 | "WEATHER_ERROR_DETAILS": "Details",
101 | "WEATHER_ERROR_CITY_NOT_FOUND": "Die stad was niet gevonden.",
102 | "WEATHER_ERROR_TRY_THIS": "Probeer dit",
103 | "WEATHER_ERROR_TRY_THIS_DESCRIPTION": "Wees alsjeblieft specifieker, of probeer een andere spelling van de plaats waar je het weer van wil weten. Als je je eigen weer wil krijgen, probeer je locatie te resetten met `{{prefix}}setloc`.",
104 | "WEATHER_ERROR_UNSET_LOCATION": "{{user}} heeft zijn locatie nog niet ingevoerd. Laat hem snel `{{prefix}}setloc` doen!",
105 | "WEATHERSTRING_TORNADO": "Tornado",
106 | "WEATHERSTRING_TROPICALSTORM": "Tropische storm",
107 | "WEATHERSTRING_HURRICANE": "Orkaan",
108 | "WEATHERSTRING_SEVERETHUNDERSTORMS": "Hevig onweer",
109 | "WEATHERSTRING_THUNDERSTORMS": "Onweer",
110 | "WEATHERSTRINGS_RAINANDSNOW": "Regen en sneeuw",
111 | "WEATHERSTRINGS_RAINANDSLEET": "Regen en ijzel",
112 | "WEATHERSTRINGS_SNOWANDSLEET": "Sneeuw en ijzel",
113 | "WEATHERSTRINGS_FREEZINGDRIZZLE": "Ijzel",
114 | "WEATHERSTRINGS_DRIZZLE": "Motregen",
115 | "WEATHERSTRINGS_FREEZINGRAIN": "Hagel",
116 | "WEATHERSTRINGS_SHOWERS": "Regenbuien",
117 | "WEATHERSTRINGS_SNOWFLURRIES": "Sneeuwvlagen",
118 | "WEATHERSTRINGS_LIGHTSNOWSHOWERS": "Lichte sneeuwbuien",
119 | "WEATHERSTRINGS_BLOWINGSNOW": "Sneeuw",
120 | "WEATHERSTRINGS_SNOW": "Sneeuw",
121 | "WEATHERSTRINGS_HAIL": "Hagel",
122 | "WEATHERSTRINGS_SLEET": "Ijzel",
123 | "WEATHERSTRINGS_DUST": "Stoffig",
124 | "WEATHERSTRINGS_FOG": "Mistig",
125 | "WEATHERSTRINGS_HAZE": "Wazig",
126 | "WEATHERSTRINGS_SMOCK": "Rokerig",
127 | "WEATHERSTRINGS_BLUSTER": "Stormachtig",
128 | "WEATHERSTRINGS_WIND": "Winderig",
129 | "WEATHERSTRINGS_COLD": "Koud",
130 | "WEATHERSTRINGS_CLOUDY": "Bewolkt",
131 | "WEATHERSTRINGS_MOSTLYCLOUDY": "Veel bewolkt",
132 | "WEATHERSTRINGS_PARTLYCLOUDY": "Weinig bewolkt",
133 | "WEATHERSTRING_CLEAR": "Geen bewolking",
134 | "WEATHERSTRING_SUNNY": "Zonnig",
135 | "WEATHERSTRING_FAIR": "Mooi",
136 | "WEATHERSTRING_RAINANDHAIL": "Regen en hagel",
137 | "WEATHERSTRING_HOT": "Heet",
138 | "WEATHERSTRING_ISOLATEDTHUNDERSTORMS": "Geïsoleerde onweersbuien",
139 | "WEATHERSTRING_SCATTEREDTHUNDERSTORMS": "Verspreide onweersbuien",
140 | "WEATHERSTRING_SCATTEREDSHOWERS": "Verspreide regenbuien",
141 | "WEATHERSTRING_HEAVYSNOW": "Hevige sneeuw",
142 | "WEATHERSTRING_SCATTEREDSNOWSHOWERS": "Verspreide sneeuwbuien",
143 | "WEATHERSTRING_THUNDERSHOWERS": "Onweersbuien",
144 | "WEATHERSTRING_SNOWSHOWERS": "Sneeuwbuien",
145 | "WEATHERSTRING_ISOLATEDTHUNDERSHOWERS": "Geïsoleerde onweersbuien",
146 | "WEATHERSTRING_NOTAVAILABLE": "Niet beschikbaar",
147 | "AWAITUSERCONFIRMATION_CANCEL_PROMPT": "Gebruik"
148 | }
149 |
--------------------------------------------------------------------------------
/plugins/warning.js:
--------------------------------------------------------------------------------
1 | /****************************************
2 | *
3 | * Warnings: Plugin for AstralMod that manages warnings
4 | * Copyright (C) 2019 Victor Tran, John Tur
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | * *************************************/
20 |
21 | const Discord = require('discord.js');
22 | const moment = require('moment');
23 | var client;
24 | var consts;
25 |
26 | var currentWarnings = {};
27 |
28 | function processResponse(message) {
29 | releaseInput(message.guild.id);
30 |
31 | var tracker = currentWarnings[message.guild.id];
32 | currentWarnings[message.guild.id] = null;
33 | let $ = _[settings.users[tracker.warner.id].locale]
34 |
35 | if (message.content.toLowerCase() == "cancel") {
36 | message.channel.send($("WARN_CANCEL", {emoji: ":gear:"}));
37 | } else {
38 | var warnings = settings.guilds[message.guild.id].warnings;
39 | if (warnings == null) {
40 | warnings = {}
41 | }
42 |
43 | var userWarnings = warnings[tracker.user.id];
44 | if (userWarnings == null) {
45 | userWarnings = [];
46 | }
47 |
48 | var warningObject = {
49 | reason: message.content,
50 | warner: tracker.warner.id,
51 | timestamp: moment.utc()
52 | }
53 | userWarnings.push(warningObject);
54 |
55 | warnings[tracker.user.id] = userWarnings;
56 | settings.guilds[message.guild.id].warnings = warnings;
57 | message.channel.send(_[settings.users[tracker.user.id].locale]("WARN_WARNED", {warnee: `<@${tracker.user.id}>`, warner: getUserString(tracker.warner), warning: message.content, count: userWarnings.length}))
58 | }
59 | message.delete();
60 | }
61 |
62 | function processCommand(message, isMod, command, options) {
63 | let $ = _[options.locale];
64 | if (isMod) {
65 | if (command.startsWith("warn ")) {
66 | var user = command.substr(5);
67 |
68 | if (currentWarnings[message.guild.id] == null) {
69 | var users = parseUser(user, message.guild);
70 | if (users.length > 0) {
71 | var user = null;
72 |
73 | //Filter out members
74 | for (var i = 0; i < users.length; i++) {
75 | if (message.guild.members.has(users[i].id)) {
76 | user = users[i].id;
77 | i = users.length;
78 | }
79 | }
80 |
81 | if (user == null) {
82 | throw new CommandError($("WARN_NO_USER_FOUND"));
83 | } else {
84 | var member = message.guild.member(user);
85 | captureInput(processResponse, message.guild.id, message.author.id);
86 |
87 | var tracker = {
88 | user: member,
89 | warner: message.member
90 | }
91 | currentWarnings[message.guild.id] = tracker;
92 |
93 | message.channel.send($("WARN_ENTER_REASON", {user: getUserString(client.users.get(user)), emoji: ":gear:"}));
94 | }
95 | } else {
96 | throw new CommandError($("WARN_NO_USER_FOUND"));
97 | }
98 | } else {
99 |
100 | throw new CommandError($("WARN_ALREADY_WARNING", {user: getUserString(currentWarnings[message.guild.id].warner)}));
101 | }
102 | } else if (command.startsWith("lswarn ")) {
103 | var user = command.substr(7);
104 | var users = parseUser(user, message.guild);
105 | if (users.length > 0) {
106 | var user = null;
107 |
108 | //Filter out members
109 | for (var i = 0; i < users.length; i++) {
110 | if (message.guild.members.has(users[i].id)) {
111 | user = users[i].id;
112 | i = users.length;
113 | }
114 | }
115 |
116 | if (user == null) {
117 | throw new CommandError($("LSWARN_COULDNT_FIND_USER"));
118 | } else {
119 | var warnings = settings.guilds[message.guild.id].warnings;
120 | if (warnings == null) {
121 | warnings = {}
122 | }
123 |
124 | var userWarnings = warnings[user];
125 | if (userWarnings == null) {
126 | userWarnings = [];
127 | }
128 |
129 | if (userWarnings.length == 0) {
130 | message.reply($("LSWARN_NO_WARNINGS", {user: getUserString(message.guild.member(user))}));
131 | return;
132 | }
133 |
134 | var embed = new Discord.RichEmbed();
135 | embed.setColor(consts.colors.info);
136 | embed.setTitle($("LSWARN_TITLE"));
137 | embed.setDescription($("LSWARN_DESCRIPTION"))
138 | for (index in userWarnings) {
139 | var warning = userWarnings[index];
140 |
141 | var warner = warning.warner;
142 | if (message.guild.members.has(warning.warner)) {
143 | warner = message.guild.member(warning.warner);
144 | }
145 |
146 | embed.addField($("LSWARN_WARNING_TITLE", {index: (parseInt(index) + 1)}), $("LSWARN_WARNING_INFO", {warning: warning.reason, timestamp: {date: moment(warning.timestamp), h24: options.h24, offset: options.offset}, warner: warner, interpolation: {escapeValue: false}}), true);
147 | }
148 |
149 | message.channel.send("", {embed: embed});
150 | }
151 | } else {
152 | throw new CommandError($("LSWARN_COULDNT_FIND_USER"));
153 | }
154 | } else if (command.startsWith("rmwarn ")) {
155 | var args = command.substr(7);
156 | var split = args.indexOf(" ");
157 | var id = args.substr(0, split);
158 | var user = args.substr(split + 1);
159 |
160 | id = parseInt(id) - 1;
161 |
162 | if (isNaN(id)) {
163 | message.reply($("RMWARN_ABOUT", {prefix: prefix(message.guild.id)}));
164 | return;
165 | }
166 |
167 | var users = parseUser(user, message.guild);
168 | if (users.length > 0) {
169 | var user = null;
170 |
171 | //Filter out members
172 | for (var i = 0; i < users.length; i++) {
173 | if (message.guild.members.has(users[i].id)) {
174 | user = users[i].id;
175 | i = users.length;
176 | }
177 | }
178 |
179 | if (user == null) {
180 | throw new CommandError($("RMWARN_NO_USER_FOUND"));
181 | } else {
182 | var warnings = settings.guilds[message.guild.id].warnings;
183 | if (warnings == null) {
184 | warnings = {}
185 | }
186 |
187 | var userWarnings = warnings[user];
188 | if (userWarnings == null) {
189 | userWarnings = [];
190 | }
191 |
192 | if (userWarnings.length == 0) {
193 | throw new UserInputError($("RMWARN_NO_WARNINGS", {user: getUserString(message.guild.member(user))}));
194 | }
195 |
196 | if (userWarnings.length <= id) {
197 | throw new UserInputError($("RMWARN_INVALID_INDEX", {user: getUserString(message.guild.member(user))}));
198 | }
199 |
200 | if (id < 0) {
201 | throw new UserInputError($("RMWARN_INVALID_INDEX", {user: getUserString(message.guild.member(user))}));
202 | }
203 |
204 | userWarnings.splice(id, 1);
205 | message.channel.send($("RMWARN_SUCCESS", {emoji: ":gear:", prefix: prefix(message.guild.id)}));
206 |
207 | warnings[user] = userWarnings;
208 | settings.guilds[message.guild.id].warnings = warnings;
209 | }
210 | } else {
211 | throw new CommandError($("RMWARN_NO_USER_FOUND"));
212 | }
213 | }
214 | }
215 |
216 | if (command == "lswarn") {
217 | var user = message.author.id;
218 | var warnings = settings.guilds[message.guild.id].warnings;
219 | if (warnings == null) {
220 | warnings = {}
221 | }
222 |
223 | var userWarnings = warnings[user];
224 | if (userWarnings == null) {
225 | userWarnings = [];
226 | }
227 |
228 | if (userWarnings.length == 0) {
229 | message.reply($("LSWARN_NO_WARNINGS", {user: getUserString(message.guild.member(user))}));
230 | return;
231 | }
232 |
233 | var embed = new Discord.RichEmbed();
234 | embed.setColor(consts.colors.info);
235 | embed.setTitle($("LSWARN_TITLE"));
236 | embed.setDescription($("LSWARN_DESCRIPTION"));
237 | for (index in userWarnings) {
238 | var warning = userWarnings[index];
239 |
240 | var warner = warning.warner;
241 | if (message.guild.members.has(warning.warner)) {
242 | warner = message.guild.member(warning.warner);
243 | }
244 |
245 | embed.addField("Warning #" + (parseInt(index) + 1), $("LSWARN_WARNING_INFO", {warning: warning.reason, timestamp: {date: moment(warning.timestamp), h24: options.h24, offset: options.offset}, warner: warner, interpolation: {escapeValue: false}}), true);
246 | }
247 |
248 | message.channel.send("", {embed: embed});
249 | }
250 | }
251 |
252 | module.exports = {
253 | name: "Warning",
254 | translatableName: "TITLE_WARN",
255 | constructor: function(discordClient, commandEmitter, constants) {
256 | client = discordClient;
257 | consts = constants;
258 |
259 | commandEmitter.on('processCommand', processCommand);
260 | },
261 | destructor: function(commandEmitter) {
262 | commandEmitter.removeListener('processCommand', processCommand);
263 | },
264 | availableCommands: {
265 | general: {
266 | commands: [
267 | "lswarn"
268 | ],
269 | modCommands: [
270 | "warn",
271 | "rmwarn"
272 | ]
273 | }
274 | },
275 | acquireHelp: function(helpCmd, message, h$) {
276 | var help = {};
277 |
278 | switch (helpCmd) {
279 | case "warn":
280 | help.title = prefix(message.guild.id) + "warn";
281 | help.usageText = prefix(message.guild.id) + "warn [user]";
282 | help.helpText = h$("WARN_HELPTEXT");
283 | help.param1 = h$("WARN_PARAM1");
284 | break;
285 | case "lswarn":
286 | help.title = prefix(message.guild.id) + "lswarn";
287 | help.usageText = prefix(message.guild.id) + "lswarn [user]";
288 | help.helpText = h$("LSWARN_HELPTEXT");
289 | help.param1 = h$("LSWARN_PARAM1");
290 | break;
291 | case "rmwarn":
292 | help.title = prefix(message.guild.id) + "rmwarn";
293 | help.usageText = prefix(message.guild.id) + "rmwarn [#id] [user]";
294 | help.helpText = h$("RMWARN_HELPTEXT");
295 | help.param1 = h$("RMWARN_PARAM1");
296 | help.param2 = h$("RMWARN_PARAM2");
297 | break;
298 | }
299 |
300 | return help;
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/plugins/misc.js:
--------------------------------------------------------------------------------
1 | /****************************************
2 | *
3 | * Miscellaneous: Plugin for AstralMod that contains miscellaneous commands
4 | * Copyright (C) 2019 Victor Tran, John Tur
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | * *************************************/
20 |
21 | var client;
22 | var consts;
23 | const Discord = require('discord.js');
24 | let translate;
25 |
26 | function obtainPic(user, channel, $) {
27 | let embed = new Discord.RichEmbed();
28 |
29 | embed.setAuthor(user.tag, user.displayAvatarURL);
30 | embed.setTitle($("PIC_PROFILE_PICTURE"));
31 | embed.setImage(user.displayAvatarURL);
32 | embed.setColor(consts.colors.done);
33 | channel.send(embed);
34 | }
35 |
36 | function processCommand(message, isMod, command, options) {
37 | let $ = _[options.locale];
38 |
39 | if (command == "pic") {
40 | obtainPic(message.author, message.channel, $);
41 | } else if (command.startsWith("pic ")) {
42 | var user = command.substr(4);
43 | var users = parseUser(user, message.guild);
44 |
45 | if (users.length == 0) {
46 | message.reply($("PIC_NO_RESULTS"));
47 | } else {
48 | obtainPic(users[0], message.channel, $);
49 | }
50 | } else if (command.startsWith("setunit ")) {
51 | let units = command.substr(8);
52 |
53 | if (settings.users[message.author.id] == null) {
54 | settings.users[message.author.id] = {};
55 | }
56 |
57 | if (units.toLowerCase() === "metric") {
58 | settings.users[message.author.id].units = "metric";
59 | message.reply($("SETUNIT_METRIC"));
60 | } else if (units.toLowerCase() === "imperial") {
61 | settings.users[message.author.id].units = "imperial";
62 | message.reply($("SETUNIT_IMPERIAL"));
63 | } else if (units.toLowerCase() === "12" || units.toLowerCase() === "12h" || units.toLowerCase() === "12hr") {
64 | settings.users[message.author.id].timeunit = "12h";
65 | message.reply($("SETUNIT_12"));
66 | } else if (units.toLowerCase() === "24" || units.toLowerCase() === "24h" || units.toLowerCase() === "24hr") {
67 | settings.users[message.author.id].timeunit = "24h";
68 | message.reply($("SETUNIT_24"));
69 | } else {
70 | throw new UserInputError($("SETUNIT_INVALID_UNIT"));
71 | }
72 | } else if (command == "sinfo") {
73 | let g = message.guild;
74 | let messageToEdit;
75 | sendPreloader($("SINFO_RETRIEVING_SERVER"), message.channel).then(function(message) {
76 | messageToEdit = message;
77 | return g.fetchMembers();
78 | }).then(function() {
79 | var embed = new Discord.RichEmbed("uinfo");
80 | embed.setAuthor(g.name, g.iconURL);
81 | embed.setColor(consts.colors.info);
82 | embed.setFooter($("SINFO_GUILDID", {id:g.id}));
83 | embed.setDescription($("SINFO_SERVER_INFORMATION"));
84 | {
85 | //let msg = "**" + tr("Server Created") + "** " + translator.localDate(g.createdAt, "default", true) + "\n";
86 | let msg = $("SINFO_SERVER_CREATED", {createdat:{date:g.createdAt, h24: options.h24, offset: options.offset }}) + "\n";
87 |
88 | if (g.joinedAt.getTime() == 0) {
89 | msg += $("SINFO_AM_JOINED", {joinedat: $("SINFO_INVALID_JOIN_DATE")});
90 | } else {
91 | msg += $("SINFO_AM_JOINED", {joinedat: {date:g.joinedAt, h24: options.h24, offset: options.offset}});
92 | }
93 |
94 | embed.addField($("SINFO_TIMESTAMPS"), msg);
95 | }
96 |
97 | {
98 | let botCount = g.members.filter(function(member) {
99 | return member.user.bot;
100 | }).size;
101 | let msg;
102 | msg = $("SINFO_MEMBER_COUNT", {count: g.memberCount.toString()}); //Don't pluralise this; it'll look weird
103 | if (botCount > 0) {
104 | msg += " " + $("SINFO_BOT_COUNT", {count:botCount});
105 | }
106 | msg += "\n";
107 | msg += $("SINFO_SERVER_OWNER", {owner:g.owner.user.tag}) + "\n";
108 |
109 | embed.addField($("SINFO_PEOPLE"), msg);
110 | }
111 |
112 | {
113 | let msg = "";
114 | let numCharacters = 0;
115 | let numSurplus = 0;
116 | for (let [id, role] of g.roles) {
117 | if (numCharacters > 100) {
118 | numSurplus++;
119 | } else {
120 | msg += role + " ";
121 | numCharacters += role.name.length;
122 | }
123 | }
124 |
125 | if (numSurplus > 0)
126 | msg += "\n + " + $("SINFO_SURPLUS_ROLES", {count: numSurplus});
127 |
128 | embed.addField($("SINFO_ROLES"), msg);
129 | }
130 |
131 | {
132 | let msg;
133 | switch (g.explicitContentFilter) {
134 | case 0:
135 | msg = $("SINFO_NSFW_ALLOWED");
136 | break;
137 | case 1:
138 | msg = $("SINFO_NSFW_ROLE_CHANNEL");
139 | break;
140 | case 2:
141 | msg = $("SINFO_NSFW_CHANNEL");
142 | }
143 |
144 | if (!g.me.hasPermission("ADMINISTRATOR")) {
145 | msg += $("SINFO_LACKPERM_ADMINISTRATOR");
146 | }
147 | if (!g.me.hasPermission("MANAGE_MESSAGES")) {
148 | msg += $("SINFO_LACKPERM_MANAGE_MESSAGES");
149 | }
150 | if (!g.me.hasPermission("KICK_MEMBERS")) {
151 | msg += $("SINFO_LACKPERM_KICK");
152 | }
153 | if (!g.me.hasPermission("BAN_MEMBERS")) {
154 | msg += $("SINFO_LACKPERM_BAN");
155 | }
156 | if (!g.me.hasPermission("MANAGE_NICKNAMES")) {
157 | msg += $("SINFO_LACKPERM_MANAGE_NICKNAME");
158 | }
159 |
160 | embed.addField($("SINFO_ALERTS"), msg);
161 | }
162 |
163 | messageToEdit.edit(embed);
164 | });
165 | } else if (command.startsWith("calc ")) {
166 | let expr = command.substr(5);
167 |
168 | let calcProcess;
169 | if (consts.config.calcProcess == null) {
170 | calcProcess = "/usr/bin/thecalculator";
171 | } else {
172 | calcProcess = consts.config.calcProcess;
173 | }
174 |
175 | require('child_process').execFile(calcProcess, [
176 | "-e",
177 | expr
178 | ], {
179 | env: {
180 | "LANG": options.locale,
181 | "LANGUAGE": options.locale
182 | }
183 | }, function(err, stdout, stderr) {
184 | let out = stdout.split("\n").filter(function(element) {
185 | if (element == "") {
186 | return false;
187 | } else {
188 | return true;
189 | }
190 | });
191 |
192 | if (err) {
193 | if (out.length == 1) {
194 | message.reply(":large_orange_diamond: " + stdout);
195 | } else {
196 | let embed = new Discord.RichEmbed("calculation");
197 | embed.setAuthor("theCalculator", "https://raw.githubusercontent.com/vicr123/contemporary-icons/master/apps/16/accessories-calculator.svg");
198 | embed.setColor(consts.colors.done);
199 | //embed.setFooter(tr("Guild ID:") + " " + g.id);
200 | embed.setDescription($("CALC_DESC"));
201 |
202 | for (let key in out) {
203 | let parts = out[key].split(":");
204 |
205 | if (key == out.length - 1) {
206 | embed.addField(parts[0].trim(), ":large_orange_diamond: " + parts[1].trim(), true);
207 | } else {
208 | embed.addField(parts[0].trim(), parts[1].trim(), true);
209 | }
210 | }
211 |
212 | message.reply($("CALC_RESULTS"), {embed: embed});
213 | }
214 | } else {
215 | if (out.length == 1) {
216 | message.reply($("CALC_ANSWER_IS") + " " + stdout);
217 | } else {
218 | let embed = new Discord.RichEmbed("calculation");
219 | embed.setAuthor("theCalculator", "https://vicr123.com/images/thecalculator.svg");
220 | embed.setColor(consts.colors.done);
221 | //embed.setFooter(tr("Guild ID:") + " " + g.id);
222 | embed.setDescription($("CALC_DESC"));
223 |
224 | for (let key in out) {
225 | let parts = out[key].split(":");
226 | embed.addField(parts[0].trim(), parts[1].trim(), true);
227 | }
228 |
229 | message.reply($("CALC_RESULTS"), {embed: embed});
230 | }
231 | }
232 | });
233 | } else if (command == "tr") {
234 | let embed = new Discord.RichEmbed();
235 | embed.setColor(consts.colors.done);
236 | let str = ""
237 |
238 | translate.getLanguages({ui: options.locale.substring(0, 2)}, (err, res) => {
239 | let counter = 0;
240 | for (let [locale, lang] of Object.entries(res.langs).sort((f, s) => f[1].localeCompare(s[1]))){
241 | str += `\`${locale}\` — ${lang}\n`
242 | counter++;
243 | if (counter == 31) {
244 | embed.addField("", str, true)
245 | counter = 0;
246 | str = "";
247 | }
248 | }
249 |
250 | embed.fields[embed.fields.length - 1].value += str;
251 |
252 | embed.fields[0].name = $("TRANSLATE_AVAILABLE_LANGUAGES")
253 | message.channel.send(embed);
254 | })
255 |
256 | } else if (command.startsWith("tr ")) {
257 | sendPreloader($("TRANSLATE_TRANSLATING"), message.channel).then(function(message) {
258 | let words = command.substr(3);
259 | let args = words.split(" ");
260 |
261 | let toLang = options.locale.substring(0, 2);
262 | let fromLang = "";
263 | for (let i = 0; i < args.length; i++) {
264 | let arg = args[i];
265 | if (arg.startsWith("--from=")) {
266 | fromLang = arg.substr(7);
267 | args.splice(i, 1);
268 | i--;
269 | } else if (arg.startsWith("--to=")) {
270 | toLang = arg.substr(5);
271 | args.splice(i, 1);
272 | i--;
273 | }
274 | }
275 |
276 | let sourceText = args.join(" ").trim();
277 | let doTranslate = function(fromLang, toLang) {
278 | let options = {};
279 | if (fromLang != "") options.from = fromLang;
280 | options.to = toLang;
281 |
282 | translate.translate(sourceText, options, function(err, res) {
283 | try {
284 | let embed = new Discord.RichEmbed();
285 | if (res.code != 200) {
286 | embed.setColor(consts.colors.fail);
287 | embed.setTitle($("TRANSLATE_ERROR_TITLE"));
288 | embed.setDescription($("TRANSLATE_ERROR_DESCRIPTION")),
289 | embed.addField($("TRANSLATE_ERROR_DETAILS"), res.message);
290 |
291 | message.edit(embed);
292 | return;
293 | }
294 |
295 | embed.setAuthor($("TRANSLATE_TITLE"));
296 | embed.setColor(consts.colors.done);
297 | //embed.setFooter(tr("Guild ID:") + " " + g.id);
298 | embed.setTitle($("TRANSLATE_POWERED_BY"));
299 | embed.setURL("http://translate.yandex.com/");
300 |
301 | embed.addField($("TRANSLATE_SOURCE", {fromLang: fromLang}), sourceText + "");
302 | embed.addField($("TRANSLATE_TRANSLATED", {toLang: toLang}), res.text + "");
303 |
304 | message.edit(embed);
305 | } catch (err) {
306 | let embed = new Discord.RichEmbed();
307 | embed.setColor(consts.colors.fail);
308 | embed.setTitle($("TRANSLATE_ERROR_TITLE"));
309 | embed.setDescription($("TRANSLATE_ERROR_DESCRIPTION")),
310 | embed.addField($("TRANSLATE_ERROR_DETAILS"), err.message);
311 |
312 | message.edit(embed);
313 | }
314 | });
315 | }
316 |
317 | if (fromLang == "") {
318 | //Detect the language
319 | translate.detect(sourceText, function(err, res) {
320 | doTranslate(res.lang, toLang);
321 | });
322 | } else {
323 | doTranslate(fromLang, toLang);
324 | }
325 | });
326 | }
327 | }
328 |
329 | module.exports = {
330 | name: "Miscellaneous",
331 | translatableName: "TITLE_MISC",
332 | constructor: function(discordClient, commandEmitter, constants) {
333 | client = discordClient;
334 | consts = constants;
335 | translate = require('yandex-translate')(consts.keys.yandexKey);
336 |
337 | commandEmitter.on('processCommand', processCommand);
338 | },
339 | destructor: function(commandEmitter) {
340 | commandEmitter.removeListener('processCommand', processCommand);
341 | },
342 | availableCommands: {
343 | general: {
344 | commands: [
345 | "pic",
346 | "setunit",
347 | "sinfo",
348 | "calc",
349 | "tr"
350 | ],
351 | modCommands: [
352 |
353 | ]
354 | }
355 | },
356 | acquireHelp: function(helpCmd, message, h$) {
357 | var help = {};
358 |
359 | switch (helpCmd) {
360 | case "pic":
361 | help.title = prefix(message.guild.id) + "pic";
362 | help.usageText = prefix(message.guild.id) + "pic user";
363 | help.helpText = h$("PIC_HELPTEXT");
364 | help.param1 = h$("PIC_PARAM1");
365 | break;
366 | case "setunit":
367 | help.title = prefix(message.guild.id) + "setunit";
368 | help.usageText = prefix(message.guild.id) + "setunit units";
369 | help.helpText = h$("SETUNIT_HELPTEXT");
370 | help.param1 = h$("SETUNIT_PARAM1");
371 | help.remarks = h$("SETUNIT_REMARKS", {prefix: prefix(message.guild.id)});
372 | break;
373 | case "sinfo":
374 | help.title = prefix(message.guild.id) + "sinfo";
375 | help.usageText = prefix(message.guild.id) + "sinfo";
376 | help.helpText = h$("SINFO_HELPTEXT");
377 | break;
378 | case "calc":
379 | help.title = prefix(message.guild.id) + "calc";
380 | help.usageText = prefix(message.guild.id) + "calc expression";
381 | help.helpText = h$("CALC_HELPTEXT");
382 | help.remarks = h$("CALC_REMARKS");
383 | break;
384 | case "tr":
385 | help.title = prefix(message.guild.id) + "tr";
386 | help.usageText = prefix(message.guild.id) + "tr [--from=language] [--to=language] phrase";
387 | help.helpText = h$("TR_HELPTEXT");
388 | help.param1 = h$("TR_PARAM1");
389 | help.param2 = h$("TR_PARAM2");
390 | help.param3 = h$("TR_PARAM3");
391 | break;
392 | }
393 | return help;
394 | }
395 | }
--------------------------------------------------------------------------------
/plugins/chatModeration.js:
--------------------------------------------------------------------------------
1 | /****************************************
2 | *
3 | * Chat Moderation: Plugin for AstralMod that moderates chat
4 | * Copyright (C) 2019 Victor Tran, John Tur
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | *
19 | * *************************************/
20 |
21 | var client;
22 | var consts;
23 | const Discord = require('discord.js');
24 | const moment = require('moment')
25 |
26 | function processCommand(message, isMod, command, options) {
27 | let $ = _[options.locale];
28 | if (isMod) {
29 | let blockId = message.channel.id;
30 | if (command.indexOf("--serverwide") != -1) {
31 | command = command.replace("--serverwide", "").trim();
32 | blockId = "guild";
33 | }
34 |
35 | if (command.startsWith("rm ")) {
36 | var num;
37 | var numString;
38 | var user = "";
39 | var args = command.substr(3);
40 | var split = args.indexOf(" ");
41 |
42 | var messagesToDelete = [];
43 |
44 | var successfulDelete = function(messages, m) {
45 | var messagesDeleted = messages.size;
46 |
47 | if (messagesToDelete.length > 1) {
48 | var messagesDeleted = messagesToDelete.length;
49 | }
50 |
51 |
52 | if (messagesDeleted != num && num != -1) {
53 | if (messagesDeleted == 1) {
54 | throw new CommandError($("RM_ITS_A_CATASTROPHE"));
55 | } else {
56 | if (m)
57 | m.edit($("RM_DELETED_FEWER", {count: messagesDeleted - 1, emoji: ":large_orange_diamond:"}));
58 | else
59 | message.channel.send($("RM_DELETED_FEWER", {count: messagesDeleted - 1, emoji: ":large_orange_diamond:"}));
60 | }
61 | } else {
62 | if (m)
63 | m.edit($("RM_DELETED", {count: messagesDeleted - 1, emoji:":white_check_mark:"}));
64 | else
65 | message.channel.send($("RM_DELETED", {count: messagesDeleted - 1, emoji:":white_check_mark:"}));
66 | }
67 | }
68 |
69 | var failedDelete = err => {
70 | let embed = new Discord.RichEmbed;
71 | embed.setColor(consts.colors.fail);
72 |
73 | if (num >= 99) {
74 | embed.addField($("ERROR_DETAILS"), $("RM_TOO_HIGH"));
75 | embed.setTitle(getEmoji("userexception") + " " + $("ERROR_USER_INPUT"));
76 | embed.setDescription($("ERROR_NOT_UNDERSTAND"));
77 | } else {
78 | embed.setTitle(getEmoji("exception") + " " + $("ERROR_INTERNAL"));
79 | embed.setDescription($("ERROR_INTERNAL_DESCRIPTION"));
80 | embed.addField($("ERROR_DETAILS"), err.message);
81 | log(err, logType.critical);
82 | }
83 |
84 | message.channel.send(embed);
85 | }
86 |
87 | if (split == -1) {
88 | numString = args;
89 |
90 | if (numString == "all") {
91 | num = -1;
92 | } else {
93 | num = parseInt(numString);
94 | }
95 | } else {
96 | numString = args.substr(0, split);
97 | if (numString == "all") {
98 | num = -1;
99 | } else {
100 | num = parseInt(numString);
101 | }
102 |
103 | var userString = args.substr(split + 1);
104 |
105 | var users = parseUser(userString, message.guild);
106 | if (users.length > 0) {
107 | user = users[0]
108 | } else {
109 | throw new CommandError($("RM_NO_USER"));
110 | }
111 | }
112 |
113 | if (num != numString && num != -1) {
114 | throw new UserInputError($("RM_NAN"));
115 | } else if (!(user instanceof Discord.User)) {
116 | if (num == -1) {
117 | throw new UserInputError($("RM_ALL_ABOUT"));
118 | } else {
119 | num = num + 1; //Also remove the mod:rm command
120 | message.channel.bulkDelete(num, true).then(successfulDelete).catch(failedDelete);
121 | }
122 | } else {
123 | if (num != -1) {
124 | num = num + 1; //Also remove the mod:rm command
125 | }
126 |
127 | messagesToDelete = [
128 | message
129 | ]
130 |
131 | var userMember = user;
132 |
133 | //Search for the previous num messages from user
134 | var messagesFound = 0;
135 | var forceStop = false;
136 |
137 | function nextBatch(allMessages, preloader) {
138 | for (let [id, message] of allMessages) {
139 | if (message.author.id == user.id) {
140 | messagesToDelete.push(message);
141 | messagesFound++;
142 |
143 | if (messagesFound == num - 1) {
144 | break;
145 | }
146 | if (messagesFound == 99) {
147 | forceStop = true;
148 | break;
149 | }
150 | }
151 | lastMessage = id;
152 |
153 | log("processed batch");
154 |
155 | if (moment(message.createdAt) <= moment().subtract(1, 'day')) {
156 | forceStop = true;
157 | break;
158 | }
159 | }
160 |
161 | if (messagesFound == num - 1 || forceStop || allMessages.size == 0) {
162 | if (messagesFound.length == 0) {
163 | message.channel.send($("RM_DELETED_NONE", {emoji: ":no_entry_sign:"}));
164 | } else {
165 | message.channel.bulkDelete(messagesToDelete, true).then(r => successfulDelete(r, preloader)).catch(failedDelete);
166 | }
167 | } else {
168 | message.channel.fetchMessages({limit: 50, before: lastMessage}).then(r => nextBatch(r, preloader)).catch(function() {
169 | message.channel.bulkDelete(messagesToDelete, true).then(r => successfulDelete(r, preloader)).catch(failedDelete);
170 | });
171 | }
172 | }
173 |
174 | if (num != -1) {
175 | sendPreloader($("RM_ALL_DOWNLOADING", {count: num - 1, user: getUserString(userMember)}), message.channel).then(m => {
176 | message.channel.fetchMessages({limit: 50, before: message.id}).then(r => nextBatch(r, m)).catch(failedDelete);
177 | })
178 | } else {
179 | sendPreloader($("RM_ALL_DOWNLOADING_ALL", {user: getUserString(userMember)}), message.channel).then(m => {
180 | message.channel.fetchMessages({limit: 50, before: message.id}).then(r => nextBatch(r, m)).catch(failedDelete);
181 | })
182 | }
183 |
184 | }
185 | } else if (command == "chnk") {
186 | message.channel.send($("CHNK_ABOUT", {prefix: prefix(message.guild.id)}));
187 | } else if (command.startsWith("chnk ")) {
188 | //message.reply("This command is not ready yet.");
189 | let userStr = command.substr(5);
190 | let users = parseUser(userStr);
191 |
192 | if (users.length == 0) {
193 | throw new UserInputError($("CHNK_USER_NOT_FOUND"));
194 | }
195 |
196 | //Filter out members
197 | let user = null;
198 | for (var i = 0; i < users.length; i++) {
199 | if (message.guild.members.has(users[i].id)) {
200 | user = message.guild.members.get(users[i].id);
201 | i = users.length;
202 | }
203 | }
204 |
205 | if (user == null) {
206 | throw new UserInputError($("CHNK_USER_NOT_FOUND"));
207 | }
208 |
209 | if (user.highestRole.comparePositionTo(message.member.highestRole) >= 0) {
210 | throw new CommandError($("CHNK_MISSING_USER_PERMISSION"));
211 | }
212 |
213 | let nick = "";
214 | let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+[]{};':\",./<>?`~";
215 |
216 | for (var i = 0; i < Math.floor(Math.random() * 31) + 1; i++) {
217 | nick += possible.charAt(Math.floor(Math.random() * possible.length));
218 | }
219 |
220 | user.setNickname(nick).then(() => {
221 | message.delete();
222 | message.channel.send($("CHNK_SUCCESS", {emoji: ":abcd:", user: getUserString(user), name: nick.replace("`", "\`")}));
223 | }).catch(() => message.reply($("CHNK_MISSING_BOT_PERMISSION", {user: getUserString(user)})));
224 |
225 | } else if (command == "block") {
226 | settings.guilds[message.guild.id].blocked[blockId].push("all");
227 |
228 | if (blockId == "guild") {
229 | message.channel.send($("BLOCK_ALL_BLOCKED_SERVER"));
230 | } else {
231 | message.channel.send($("BLOCK_ALL_BLOCKED_CHANNEL"));
232 | }
233 | } else if (command.startsWith("block ")) {
234 | let c = command.substr(6).trim().toLowerCase();
235 |
236 | if (c.indexOf(" ") != -1) {
237 | message.reply($("BLOCK_ABOUT"));
238 | return;
239 | }
240 |
241 | if (c == "block") {
242 | message.reply($("BLOCK_CANT_BLOCK_THIS"));
243 | return;
244 | }
245 |
246 | if (c == "unblock") {
247 | message.reply($("BLOCK_CANT_BLOCK_UNBLOCK"));
248 | return;
249 | }
250 |
251 | if (c == "log" && [settings.guilds[message.guild.id].chatLogs,
252 | settings.guilds[message.guild.id].botWarnings,
253 | settings.guilds[message.guild.id].memberAlerts].includes(message.channel.id)) {
254 | message.reply($("BLOCK_LOG_ALREADY_BLOCKED_IN_LOG_CHANNELS"));
255 | return;
256 | }
257 |
258 | if (blockId == "guild" && c == "spam") {
259 | message.reply($("BLOCK_CANT_BLOCK_SPAMCTL_SERVERWIDE", {prefix: prefix(message.guild.id)}));
260 | return;
261 | }
262 |
263 | if (blockId == "guild" && c == "log") {
264 | message.reply($("BLOCK_CANT_BLOCK_LOGS_SERVERWIDE", {prefix: prefix(message.guild.id)}));
265 | return;
266 | }
267 |
268 | if (settings.guilds[message.guild.id].blocked[blockId].includes(c)) {
269 | if (blockId == "guild") {
270 | message.reply($("BLOCK_COMMAND_ALREADY_DISABLED_SERVER", {command: `\`${c}\``}));
271 | }
272 | if (c == "spam") {
273 | message.reply($("BLOCK_SPAMCTL_ALREADY_DISABLED_CHANNEL"));
274 | } else if (c == "log") {
275 | message.reply($("BLOCK_LOG_ALREADY_DISABLED_CHANNEL"));
276 | } else {
277 | message.reply($("BLOCK_COMMAND_ALREADY_DISABLED_CHANNEL", {command: `\`${c}\``}));
278 | }
279 |
280 | return;
281 | }
282 |
283 | settings.guilds[message.guild.id].blocked[blockId].push(c);
284 |
285 | if (blockId == "guild") {
286 | message.reply($("BLOCK_COMMAND_BLOCKED_SERVER", {command: `\`${c}\``}));
287 | } else {
288 | if (c == "spam") {
289 | message.reply($("BLOCK_SPAMCTL_BLOCKED_CHANNEL"));
290 | } else if (c == "log") {
291 | message.reply($("BLOCK_LOG_BLOCKED_CHANNEL"));
292 | } else {
293 | message.reply($("BLOCK_COMMAND_BLOCKED_CHANNEL", {command: `\`${c}\``}));
294 | }
295 | }
296 | } else if (command == "unblock") {
297 | settings.guilds[message.guild.id].blocked[blockId] = [];
298 | if (blockId == "guild")
299 | message.reply($("UNBLOCK_ALL_UNBLOCKED_SERVER"));
300 | else
301 | message.reply($("UNBLOCK_ALL_UNBLOCKED_CHANNEL"));
302 | } else if (command.startsWith("unblock ")) {
303 | let c = command.substr(8).trim().toLowerCase();
304 |
305 | if (c.indexOf(" ") != -1) {
306 | message.reply($("UNBLOCK_ABOUT"));
307 | return;
308 | }
309 |
310 | if (c == "log" && [settings.guilds[message.guild.id].chatLogs,
311 | settings.guilds[message.guild.id].botWarnings,
312 | settings.guilds[message.guild.id].memberAlerts].includes(message.channel.id)) {
313 | message.reply($("UNBLOCK_CANT_UNBLOCK_LOG_IN_LOG_CHANNELS"));
314 | return;
315 | }
316 |
317 | if (blockId == "guild" && c == "spam") {
318 | message.reply($("UNBLOCK_CANT_UNBLOCK_SPAMCTL_SERVERWIDE", {prefix: prefix(message.guild.id)}));
319 | return;
320 | }
321 |
322 | if (blockId == "guild" && c == "log") {
323 | message.reply($("UNBLOCK_CANT_UNBLOCK_LOGS_SERVERWIDE", {prefix: prefix(message.guild.id)}));
324 | return;
325 | }
326 |
327 | if (settings.guilds[message.guild.id].blocked[blockId].indexOf(c) == -1) {
328 | if (c == "spam") {
329 | message.reply($("UNBLOCK_SPAMCTL_ALREADY_ENABLED_CHANNEL"));
330 | } else if (c == "log") {
331 | message.reply($("UNBLOCK_LOG_ALREADY_ENABLED_CHANNEL"));
332 | } else {
333 | message.reply($("UNBLOCK_COMMAND_ALREADY_ENABLED_CHANNEL", {command: `\`${c}\``}));
334 | }
335 | return;
336 | }
337 |
338 | settings.guilds[message.guild.id].blocked[blockId].splice(settings.guilds[message.guild.id].blocked[blockId].indexOf(c), 1);
339 |
340 | if (blockId == "guild") {
341 | message.reply($("UNBLOCK_COMMAND_UNBLOCKED_SERVER", {command: `\`${c}\``}));
342 | } else {
343 | if (c == "spam") {
344 | message.reply($("UNBLOCK_SPAMCTL_UNBLOCKED_CHANNEL"));
345 | } else if (c == "log") {
346 | message.reply($("UNBLOCK_LOG_UNBLOCKED_CHANNEL"));
347 | } else {
348 | message.reply($("UNBLOCK_COMMAND_UNBLOCKED_CHANNEL", {command: `\`${c}\``}));
349 | }
350 | }
351 | }
352 | }
353 | }
354 |
355 | module.exports = {
356 | name: "Chat Moderation",
357 | translatableName: "TITLE_CHAT_MODERATION",
358 | constructor: function(discordClient, commandEmitter, constants) {
359 | client = discordClient;
360 | consts = constants;
361 |
362 | commandEmitter.on('processCommand', processCommand);
363 | },
364 | destructor: function(commandEmitter) {
365 | commandEmitter.removeListener('processCommand', processCommand);
366 | },
367 | availableCommands: {
368 | general: {
369 | modCommands: [
370 | "rm",
371 | "chnk",
372 | "block",
373 | "unblock"
374 | ],
375 | }
376 | },
377 | acquireHelp: function(helpCmd, message, h$) {
378 | var help = {};
379 |
380 | switch (helpCmd) {
381 | case "rm":
382 | help.title = prefix(message.guild.id) + "rm";
383 | help.usageText = prefix(message.guild.id) + "rm number [user]";
384 | help.helpText = h$("RM_HELPTEXT");
385 | help.param1 = h$("RM_PARAM1");
386 | help.param2 = h$("RM_PARAM2");
387 | break;
388 | case "chnk":
389 | help.title = prefix(message.guild.id) + "chnk";
390 | help.usageText = prefix(message.guild.id) + "chnk user";
391 | help.helpText = h$("CHNK_HELPTEXT");
392 | help.param1 = h$("CHNK_PARAM1");
393 | break;
394 | case "block":
395 | help.title = prefix(message.guild.id) + "block";
396 | help.usageText = prefix(message.guild.id) + "block [feature]";
397 | help.helpText = h$("BLOCK_HELPTEXT");
398 | help.param1 = h$("BLOCK_PARAM1");
399 | help.remarks = h$("BLOCK_REMARKS");
400 | help.availableOptions = h$("BLOCK_AVAILABLEOPTIONS");
401 | break;
402 | case "unblock":
403 | help.title = prefix(message.guild.id) + "unblock";
404 | help.usageText = prefix(message.guild.id) + "unblock [feature]";
405 | help.helpText = h$("UNBLOCK_HELPTEXT");
406 | help.param1 = h$("UNBLOCK_PARAM1");
407 | help.remarks = h$("UNBLOCK_REMARKS", {prefix: prefix(message.guild.id)});
408 | help.availableOptions = h$("UNBLOCK_AVAILABLEOPTIONS");
409 | break;
410 | }
411 |
412 | return help;
413 | }
414 | }
--------------------------------------------------------------------------------