mirror of
https://github.com/Wessel/yorushika.git
synced 2026-07-17 22:14:57 +02:00
Main code!
This commit is contained in:
75
.eslintrc
Normal file
75
.eslintrc
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"env": {
|
||||
"amd": false,
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"jest": false,
|
||||
"mongo": true,
|
||||
"mocha": false,
|
||||
"qunit": false,
|
||||
"worker": true,
|
||||
"meteor": false,
|
||||
"jquery": false,
|
||||
"browser": false,
|
||||
"jasmine": false,
|
||||
"shelljs": false,
|
||||
"nashorn": false,
|
||||
"commonjs": true,
|
||||
"atomtest": false,
|
||||
"embertest": false,
|
||||
"phantomjs": false,
|
||||
"protractor": false,
|
||||
"prototypejs": false,
|
||||
"applescript": false,
|
||||
"greasemonkey": false,
|
||||
"webextensions": false,
|
||||
"serviceworker": false,
|
||||
"shared-node-browser": false
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"restParams": true,
|
||||
"impliedStrict": true,
|
||||
"jsx": true,
|
||||
"arrowFunctions": true,
|
||||
"binaryLiterals": true,
|
||||
"blockBindings": true,
|
||||
"classes": true,
|
||||
"defaultParams": true,
|
||||
"destructuring": true,
|
||||
"forOf": true,
|
||||
"generators": true,
|
||||
"modules": true,
|
||||
"objectLiteralComputedProperties": true,
|
||||
"objectLiteralDuplicateProperties": true,
|
||||
"objectLiteralShorthandMethods": true,
|
||||
"objectLiteralShorthandProperties": true,
|
||||
"octalLiterals": true,
|
||||
"regexUFlag": true,
|
||||
"regexYFlag": true,
|
||||
"spread": true,
|
||||
"superInFunctions": true,
|
||||
"templateStrings": true,
|
||||
"unicodeCodePointEscapes": true,
|
||||
"globalReturn": true
|
||||
}
|
||||
},
|
||||
"plugins": [],
|
||||
"rules": {
|
||||
"strict": 0,
|
||||
"semi": "warn",
|
||||
"indent": [
|
||||
0,
|
||||
2
|
||||
],
|
||||
"no-undef": 1,
|
||||
"no-global-assign": 1,
|
||||
"comma-dangle": "warn"
|
||||
},
|
||||
"globals": {
|
||||
"_config": false,
|
||||
"console": false
|
||||
}
|
||||
}
|
||||
14
.github/CONTRIBUTING.md
vendored
Normal file
14
.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Contributing
|
||||
|
||||
**The issue tracker is only for bug reports and enhancement suggestions. If you have a question, please ask it in the [Discord](https://discord.gg/SV7DAE9) instead of opening an issue – you will get redirected there anyway.**
|
||||
|
||||
If you wish to contribute to Wump, feel free to fork the repository and submit a pull request.
|
||||
[ESLint](https://eslint.org/) is used to correct most typo's you make, so it would be helpful if you added [ESLint](https://eslint.org/) to your editor of choice)
|
||||
|
||||
## Setup
|
||||
To get ready to work on the codebase, please do the following:
|
||||
|
||||
1. Fork & clone the repository, and make sure you're on the **master** branch
|
||||
2. Run `yarn --dev` or `npm install --dev`
|
||||
4. Code your heart out and test using `yarn test` or `npm run test`!
|
||||
6. [Submit a pull request](https://github.com/PassTheWessel/wump/compare)
|
||||
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Bug Report
|
||||
description: Report incorrect or unexpected behaviour
|
||||
|
||||
---
|
||||
|
||||
**Please describe the problem you are having in as much detail as possible:**
|
||||
|
||||
|
||||
**Include a reproducible code sample here, if possible:**
|
||||
```js
|
||||
// Place your code here
|
||||
```
|
||||
|
||||
**Further details:**
|
||||
- Node.js version:
|
||||
- Operating system:
|
||||
|
||||
<!--
|
||||
If this applies to you, please check the respective checkbox: [ ] becomes [x].
|
||||
-->
|
||||
|
||||
- [ ] I have also tested the issue on latest master, commit hash:
|
||||
18
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
18
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Request a feature
|
||||
|
||||
---
|
||||
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the ideal solution**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
**Please describe the changes this PR makes and why it should be merged:**
|
||||
|
||||
|
||||
**Status**
|
||||
- [ ] Code changes have been tested and there aren't any typos in it
|
||||
|
||||
**Semantic versioning classification:**
|
||||
- [ ] This PR changes the library's interface (methods or parameters added)
|
||||
- [ ] This PR includes breaking changes (methods removed or renamed, parameters moved or removed)
|
||||
- [ ] This PR **only** includes non-code changes, like changes to documentation, README, etc.
|
||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
web/
|
||||
src/tmp
|
||||
node_modules/
|
||||
src/application.yml
|
||||
.vscode/
|
||||
17
LICENSE
17
LICENSE
@@ -1,7 +1,8 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -631,8 +632,8 @@ to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
{one line to give the program's name and a brief idea of what it does.}
|
||||
Copyright (C) {year} {name of author}
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -645,14 +646,14 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
Copyright (C) 2019-present Wessel Tip
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@@ -664,11 +665,11 @@ might be different; for a GUI interface, you would use an "about box".
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
15
README.md
Normal file
15
README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
<div align="center">
|
||||
<br />
|
||||
<p>
|
||||
<a href="https://github.com/PassTheWessel/wump">Wump</a>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<a href="https://discord.gg/SV7DAE9"><img src="https://discordapp.com/api/guilds/107131083958538240/embed.png" alt="Discord" /></a>
|
||||
<a href="https://www.patreon.com/wessel"><img src="https://img.shields.io/badge/donate-patreon-F96854.svg" alt="Patreon" /></a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
> A multi-platform bot written fully in Node.js
|
||||
|
||||
You may use this project, but only **if** you follow the [licensing](./LICENSE)
|
||||
29
package.json
Normal file
29
package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "wump",
|
||||
"version": "1.2.0",
|
||||
"displayName": "Wump",
|
||||
"description": "A multi-platform bot written in Node.js",
|
||||
"author": "Wessel \"wesselgame\" T <discord@go2it.eu>",
|
||||
"contributors": [],
|
||||
"maintainers": [
|
||||
"Wessel \"wesselgame\" T <discord@go2it.eu >"
|
||||
],
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"eris": "^0.9.0",
|
||||
"js-yaml": "^3.12.0",
|
||||
"larg": "^0.0.1",
|
||||
"mathjs": "^5.1.2",
|
||||
"moment": "^2.22.2",
|
||||
"mongoose": "^5.2.17",
|
||||
"nabbit": "^0.0.2",
|
||||
"table": "^5.1.0",
|
||||
"vm2": "^3.6.3",
|
||||
"wumpfetch": "^0.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^5.6.0"
|
||||
},
|
||||
"main": "src/main.js",
|
||||
"repository": "https://github.com/PassTheWessel/wump"
|
||||
}
|
||||
66
src/_application.yml
Normal file
66
src/_application.yml
Normal file
@@ -0,0 +1,66 @@
|
||||
#-----------------[ Wump config ]-----------------#
|
||||
# This is the configuration file of "Wump", all #
|
||||
# your sensitive information is stored inside of #
|
||||
# this file. Do **not** give this file or it's #
|
||||
# contents to **anyone**, they can do a lot of #
|
||||
# bad things with your tokens. Don't forget to #
|
||||
# follow the licensing. - Wessel #
|
||||
#-------------[ Configurable values ]-------------#
|
||||
# db - <String>: The db URI (Mongo) #
|
||||
# debug - <Number[0-3]>: The logging leven #
|
||||
# nightly - <Boolean>: Run inside of dev mode #
|
||||
# discord: #
|
||||
# enabled - <Boolean>: Enable/disable client #
|
||||
# op - <Array>: The bot's OwnerIDs #
|
||||
# token - <String>: The bot's tokens #
|
||||
# prefix - <String>: The command prefix #
|
||||
# events - Each<Boolean>: Enable/disable evts #
|
||||
# playing - Each<any>: The bot's status #
|
||||
# commands - Each<Boolean>: Enable/disable cmds #
|
||||
#-------------------------------------------------#
|
||||
|
||||
db : 'mongodb://localhost:27017/Wump'
|
||||
debug : 3
|
||||
nightly: true
|
||||
|
||||
discord :
|
||||
enabled: true
|
||||
token : '<--snip-->'
|
||||
prefix : '!'
|
||||
locale : 'en_us'
|
||||
|
||||
op :
|
||||
- '107130754189766656'
|
||||
playing :
|
||||
url : 'https://twitch.tv/wumpusapp'
|
||||
name : 'type !help'
|
||||
type : 1 # 0 - Playing / 1 - Streaming / 2 - Listening / 3 - Watching
|
||||
status: 'online' # online / idle / dnd / invisible
|
||||
|
||||
events :
|
||||
ready : true
|
||||
disconnect : true
|
||||
messagecreate: true
|
||||
messagedelete: true
|
||||
commands :
|
||||
# Category : UTILITY
|
||||
ping : true
|
||||
math : true
|
||||
snipe : true
|
||||
# Category : INFORMATION
|
||||
stats : true
|
||||
commands : true
|
||||
# Category : IMAGE
|
||||
cat : true
|
||||
dog : true
|
||||
fox : true
|
||||
duck : true
|
||||
birb : true
|
||||
lizard : true
|
||||
penguin : true
|
||||
# Category : DEVELOPER
|
||||
eval : true
|
||||
echo : true
|
||||
|
||||
api :
|
||||
lol: '<--snip-->'
|
||||
28
src/assets/config/colors.yml
Normal file
28
src/assets/config/colors.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
error : 0xff0000 # Red
|
||||
cooldown: 0x7289DA # Blurple
|
||||
|
||||
util :
|
||||
ping :
|
||||
0 : 0xffa500 # Orange
|
||||
1 : 0x00ff00 # Green
|
||||
2 : 0xffa500 # Orange
|
||||
3 : 0xff0000 # Red
|
||||
snipe: 0x23272A # Not quite black
|
||||
|
||||
info :
|
||||
stats : 0x02C2F33 # Dark but not black
|
||||
commands: 0x02C2F33 # Dark but not black
|
||||
|
||||
image :
|
||||
cat : 0x7289DA # Blurple
|
||||
dog : 0x7289DA # Blurple
|
||||
fox : 0x7289DA # Blurple
|
||||
birb : 0x7289DA # Blurple
|
||||
duck : 0x7289DA # Blurple
|
||||
lizard : 0x7289DA # Blurple
|
||||
penguin: 0x7289DA # Blurple
|
||||
|
||||
developer :
|
||||
eval :
|
||||
success: 0x00ff00 # Green
|
||||
failure: 0xff0000 # Red
|
||||
55
src/assets/config/emotes.yml
Normal file
55
src/assets/config/emotes.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
cooldown : <:sad:500719642403405824> # On cooldown
|
||||
owner_only: <:sad:500719642403405824> # Only owners
|
||||
guild_only: <:sad:500719642403405824> # Only guilds
|
||||
|
||||
util :
|
||||
ping:
|
||||
0 : <:bored:500719642164199425> # Pinging
|
||||
1 : <:thumbsup:501844577725054976> # Heartbeat
|
||||
2 : <:blueberry:506201160382939141> # Round-trip
|
||||
3 : <:WumpLove:506200781549076482> # Health
|
||||
math:
|
||||
0 : <:blueberry:506201160382939141> # Calculating
|
||||
1 : <a:ablobdevil:494927811451027458> # Evaluation
|
||||
2 : <a:agoogleoctopus:494927680911704067> # Invalid equation
|
||||
snipe : <:snipe:508653323788877825> # No snipes found
|
||||
|
||||
info:
|
||||
commands :
|
||||
0 : <:blueberry:506201160382939141> # Guild prefix
|
||||
1 : <:spirit:332131321759399937> # More info
|
||||
2 : <:WumpLove:506200781549076482> # Links
|
||||
statistics :
|
||||
0 : <:ok_hand:497396122416054287> # Fetching
|
||||
1 : <:blueberry:506201160382939141> # Operating System
|
||||
2 : <:happy:500719642231177220> # Process hash
|
||||
3 : <:WumpLove:506200781549076482> # Load average
|
||||
4 : <a:ablobangel:494926715592900608> # OS uptime
|
||||
5 : <a:agoogleoctopus:494927680911704067> # Uptime
|
||||
6 : <:monkey:369880931630317568> # Memory usage
|
||||
7 : <:spirit:332131321759399937> # User agent
|
||||
8 : <:dev_server:495573905092902942> # Shards
|
||||
9 : <:beetle_tank:445274774579445771> # Cache
|
||||
10 : <:srv_server:495680009197977617> # Channels
|
||||
11 : <:srv_tags:496035430052134912> # Guilds
|
||||
12 : <:srv_user:495917052784148480> # Users
|
||||
|
||||
image :
|
||||
cat :
|
||||
0 : <:blueberry:506201160382939141> # Fetching
|
||||
1 : <:spirit:332131321759399937> # Cat fact
|
||||
dog :
|
||||
0 : <:blueberry:506201160382939141> # Fetching
|
||||
1 : <:spirit:332131321759399937> # dog fact
|
||||
fox : <:blueberry:506201160382939141> # Fetching
|
||||
birb : <:blueberry:506201160382939141> # Fetching
|
||||
duck : <:blueberry:506201160382939141> # Fetching
|
||||
lizard : <:blueberry:506201160382939141> # Fetching
|
||||
penguin: <:blueberry:506201160382939141> # Fetching
|
||||
|
||||
developer:
|
||||
echo : <a:voting:501106582915121154> # Invalid message
|
||||
eval :
|
||||
0 : <a:voting:501106582915121154> # Invalid snippet
|
||||
1 : <a:agoogleoctopus:494927680911704067> # Evaluating
|
||||
2 : <a:voting:501106582915121154> # Result
|
||||
79
src/assets/i18n/en_us/strings.yml
Normal file
79
src/assets/i18n/en_us/strings.yml
Normal file
@@ -0,0 +1,79 @@
|
||||
translation :
|
||||
code : 'en_us' # Language code
|
||||
flag : '🇺🇸' # Language flag
|
||||
full : 'English (United States)' # Full language name in english
|
||||
orig : 'English (United States)' # Full language name in your language
|
||||
translator : # Your information (can leave fields empty)
|
||||
email : 'discord@go2it.eu'
|
||||
website : 'https://wessel.meek.moe'
|
||||
discord :
|
||||
name : 'Wesselgame'
|
||||
userid : '107130754189766656'
|
||||
discrim: '0498'
|
||||
|
||||
error :
|
||||
- '$[author:mention] **>** An error occured while executing this command'
|
||||
- 'If this problem keeps occurring, consider joining ***https://discord.gg/SV7DAE9*** and posting your problem there'
|
||||
- '```ini'
|
||||
- '[ Error Information ]'
|
||||
- 'Code = "$[err:code]"'
|
||||
- 'Message = "$[err:message]"'
|
||||
- '```'
|
||||
cooldown: '$[emoji#0] $[author:mention] **>** This command is on cooldown for **$[cooldown:left]**'
|
||||
|
||||
util :
|
||||
ping :
|
||||
busy : '$[emoji#0] Pinging...'
|
||||
health :
|
||||
- 'Unknown'
|
||||
- 'Good'
|
||||
- 'Okay'
|
||||
- 'Bad'
|
||||
result :
|
||||
- '$[emoji#2] **Round-Trip**: $[roundtrip]ms'
|
||||
- '$[emoji#1] **Heartbeat**: $[latency]ms'
|
||||
- '$[emoji#3] **Health**: $[health]'
|
||||
math :
|
||||
busy : '$[emoji#0] Calculating, this may take some time...'
|
||||
blocked: '<blocked> Method "$[math:function]" has been disabled for security reasons <blocked>'
|
||||
snipe :
|
||||
fail : '$[emoji#0] No snipeable messages found'
|
||||
footer : 'Sniped by $[author:tag] ($[author:id])'
|
||||
|
||||
info :
|
||||
stats :
|
||||
fetching: '$[emoji#0] Fetching statistics, this may take some time...'
|
||||
commands:
|
||||
multi :
|
||||
- '$[emoji#0] The prefix for **$[guild:name]** is `$[guild:prefix]`'
|
||||
- '$[emoji#1] Type `$[guild:prefix]command <command:str>` for more information'
|
||||
- '$[emoji#2] **Links**: [`Invite`]($[bot:invite]) **|** [`Support`](https://discord.gg/SV7DAE9) **|** [`GitHub`](https://github.com/PassTheWessel/wump) **|** [`Patreon`](https://patreon.com/wessel)'
|
||||
single:
|
||||
- '**Name**: $[command:name]'
|
||||
- '**Syntax**: $[command:syntax]'
|
||||
- '**Aliases**: $[command:aliases]'
|
||||
- '**Cooldown**: $[command:cooldown#formatted]'
|
||||
- '**Arguments**: $[command:arguments]'
|
||||
fields:
|
||||
- 'Information'
|
||||
- 'Image'
|
||||
- 'Utility'
|
||||
- 'Developer'
|
||||
|
||||
image:
|
||||
fetching : '$[emoji#0] Fetching a random image, this may take some time...'
|
||||
failed_cache: 'Click here if the image didn''t load properly'
|
||||
|
||||
developer:
|
||||
echo : '$[emoji#0] Invalid content to echo'
|
||||
eval :
|
||||
args : '$[emoji#0] Invalid snippet of code to evaluate'
|
||||
busy: '$[emoji#1] Evaluating, this may take some time...'
|
||||
types:
|
||||
- 'succeed'
|
||||
- 'failed'
|
||||
result:
|
||||
- '$[emoji#2] **Result** (`$[result:type]`):'
|
||||
- '```js'
|
||||
- '$[result:message]'
|
||||
- '```'
|
||||
BIN
src/assets/img/logo/dist.png
Normal file
BIN
src/assets/img/logo/dist.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/logo/nightly.jpg
Normal file
BIN
src/assets/img/logo/nightly.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
BIN
src/assets/img/thumb/commands.png
Normal file
BIN
src/assets/img/thumb/commands.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/img/thumb/stats.png
Normal file
BIN
src/assets/img/thumb/stats.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
32
src/commands/Discord/Developer/echo.js
Normal file
32
src/commands/Discord/Developer/echo.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
module.exports = class Eval extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'echo',
|
||||
syntax : 'echo <...message:str>',
|
||||
aliases : [],
|
||||
argument : [ '<...message:str>' ],
|
||||
description : 'Evaluate a snippet',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 0,
|
||||
category : 'Developer',
|
||||
ownerOnly : true,
|
||||
guildOnly : false,
|
||||
permissions : [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg, args) {
|
||||
if (args.length <= 0) return msg.channel.createMessage(this.localize(msg.author.locale['developer']['echo']));
|
||||
msg.channel.createMessage(args.join(' '));
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('developer', 'echo'));
|
||||
}
|
||||
};
|
||||
68
src/commands/Discord/Developer/eval.js
Normal file
68
src/commands/Discord/Developer/eval.js
Normal file
@@ -0,0 +1,68 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const { inspect } = require('util');
|
||||
|
||||
module.exports = class Eval extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'eval',
|
||||
syntax : 'eval <...code:str>',
|
||||
aliases : [],
|
||||
argument : [],
|
||||
description: 'Evaluate a snippet',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 0,
|
||||
category : 'Developer',
|
||||
ownerOnly : true,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg, args) {
|
||||
let result;
|
||||
let errored = false;
|
||||
|
||||
if (args.length <= 0) return msg.channel.createMessage(this.localize(msg.author.locale['developer']['eval']['args']));
|
||||
|
||||
const message = await msg.channel.createMessage(this.localize(msg.author.locale['developer']['eval']['busy']));
|
||||
|
||||
try { result = eval(args.join(' ')); }
|
||||
catch (ex) { result = ex; errored = true; }
|
||||
finally {
|
||||
result = this.sanitize(String(inspect(result)));
|
||||
|
||||
message.edit({
|
||||
content: '',
|
||||
embed: {
|
||||
color : errored ? this.bot.col['developer']['eval']['failure'] : this.bot.col['developer']['eval']['success'],
|
||||
description: this.localize(msg.author.locale['developer']['eval']['result'].join('\n'), { resultType: errored ? msg.author.locale['developer']['eval']['types'][1] : msg.author.locale['developer']['eval']['types'][0], resultMessage: this.bot.util.shorten(result, 1950) || '{}' })
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
sanitize(msg) {
|
||||
if (!msg) return undefined;
|
||||
|
||||
for(let _ in this.bot.conf['api']) msg = msg.replace(new RegExp(this.bot.conf['api'][_], 'gi'), '<--snip-->');
|
||||
|
||||
return msg
|
||||
.replace(new RegExp(this.bot.token, 'gi'), '<--snip-->')
|
||||
.replace(new RegExp(this.bot.conf['discord']['token'], 'gi'), '<--snip-->');
|
||||
}
|
||||
|
||||
localize(msg, extData) {
|
||||
if (!msg) return '';
|
||||
|
||||
if (extData && extData.resultType) msg = msg.replace(/\$\[result:type]/g, extData.resultType);
|
||||
if (extData && extData.resultMessage) msg = msg.replace(/\$\[result:message]/g, extData.resultMessage);
|
||||
|
||||
return msg
|
||||
.replace(/\$\[emoji#0]/g, this.bot.emote('developer', 'eval', '0'))
|
||||
.replace(/\$\[emoji#1]/g, this.bot.emote('developer', 'eval', '1'))
|
||||
.replace(/\$\[emoji#2]/g, this.bot.emote('developer', 'eval', '2'));
|
||||
}
|
||||
};
|
||||
45
src/commands/Discord/Image/birb.js
Normal file
45
src/commands/Discord/Image/birb.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const w = require('wumpfetch');
|
||||
|
||||
module.exports = class Birb extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'birb',
|
||||
syntax : 'birb',
|
||||
aliases : [ 'bird' ],
|
||||
argument : [],
|
||||
description: 'Get a random birb',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 2500,
|
||||
category : 'Image',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg) {
|
||||
const message = await msg.channel.createMessage(this.localize(msg.author.locale['image']['fetching']));
|
||||
|
||||
let img = await w('https://some-random-api.ml/birbimg', { headers: { 'User-Agent': this.bot.ua } }).send();
|
||||
img = img.json();
|
||||
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['image']['birb'],
|
||||
image : { url: img.link ? img.link : '' },
|
||||
description: `*[\`${msg.author.locale['image']['failed_cache']}\`](${img && img.link ? img.link : 'https://www.google.com/'})*`
|
||||
}
|
||||
});
|
||||
message.delete();
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('image', 'birb'));
|
||||
}
|
||||
};
|
||||
47
src/commands/Discord/Image/cat.js
Normal file
47
src/commands/Discord/Image/cat.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const w = require('wumpfetch');
|
||||
|
||||
module.exports = class Cat extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'cat',
|
||||
syntax : 'cat',
|
||||
aliases : [ 'kitten' ],
|
||||
argument : [],
|
||||
description: 'Get a random cat',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 2500,
|
||||
category : 'Image',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg) {
|
||||
const message = await msg.channel.createMessage(this.localize(msg.author.locale['image']['fetching']));
|
||||
|
||||
let img = await w('https://aws.random.cat/meow', { headers: { 'User-Agent': this.bot.ua } }).send();
|
||||
let res = await w('https://catfact.ninja/fact?max_length=1500', { headers: { 'User-Agent': this.bot.ua } }).send();
|
||||
img = img.json();
|
||||
res = res.json();
|
||||
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['image']['cat'],
|
||||
image : { url: img.file ? img.file : '' },
|
||||
description: `${this.bot.emote('image', 'cat', '1')} *Random Fact* **>** ${res.fact}\n\n*[\`${msg.author.locale['image']['failed_cache']}\`](${img && img.file ? img.file : 'https://www.google.com/'})*`
|
||||
}
|
||||
});
|
||||
message.delete();
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('image', 'cat', '0'));
|
||||
}
|
||||
};
|
||||
47
src/commands/Discord/Image/dog.js
Normal file
47
src/commands/Discord/Image/dog.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const w = require('wumpfetch');
|
||||
|
||||
module.exports = class Dog extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'dog',
|
||||
syntax : 'dog',
|
||||
aliases : [ 'doggo' ],
|
||||
argument : [],
|
||||
description: 'Get a random dog',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 5000,
|
||||
category : 'Image',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg) {
|
||||
const message = await msg.channel.createMessage(this.localize(msg.author.locale['image']['fetching']));
|
||||
|
||||
let img = await w('https://dog.ceo/api/breeds/image/random', { headers: { 'User-Agent': this.bot.ua } }).send();
|
||||
let res = await w('https://some-random-api.ml/dogfact', { headers: { 'User-Agent': this.bot.ua } }).send();
|
||||
img = img.json();
|
||||
res = res.json();
|
||||
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['image']['dog'],
|
||||
image : { url: img.message ? img.message : '' },
|
||||
description: `${this.bot.emote('image', 'dog', '1')} *Random Fact* **>** ${res.fact.slice(0, 1990)}\n\n*[\`${msg.author.locale['image']['failed_cache']}\`](${img && img.message ? img.message : 'https://www.google.com/'})*`
|
||||
}
|
||||
});
|
||||
message.delete();
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('image', 'dog', '0'));
|
||||
}
|
||||
};
|
||||
45
src/commands/Discord/Image/duck.js
Normal file
45
src/commands/Discord/Image/duck.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const w = require('wumpfetch');
|
||||
|
||||
module.exports = class Duck extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'duck',
|
||||
syntax : 'duck',
|
||||
aliases : [ 'quack' ],
|
||||
argument : [],
|
||||
description: 'Get a random duck',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 5000,
|
||||
category : 'Image',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg) {
|
||||
const message = await msg.channel.createMessage(this.localize(msg.author.locale['image']['fetching']));
|
||||
|
||||
let img = await w('https://random-d.uk/api/v1/random', { headers: { 'User-Agent': this.bot.ua } }).send();
|
||||
img = img.json();
|
||||
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['image']['duck'],
|
||||
image : { url: img.url ? img.url : '' },
|
||||
description: `*[\`${msg.author.locale['image']['failed_cache']}\`](${img && img.url ? img.url : 'https://www.google.com/'})*`
|
||||
}
|
||||
});
|
||||
message.delete();
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('image', 'duck'));
|
||||
}
|
||||
};
|
||||
44
src/commands/Discord/Image/fox.js
Normal file
44
src/commands/Discord/Image/fox.js
Normal file
@@ -0,0 +1,44 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const w = require('wumpfetch');
|
||||
|
||||
module.exports = class Cat extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'fox',
|
||||
syntax : 'fox',
|
||||
aliases : [ 'fox' ],
|
||||
argument : [],
|
||||
description: 'Get a random fox',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 2500,
|
||||
category : 'Image',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg) {
|
||||
const message = await msg.channel.createMessage(this.localize(msg.author.locale['image']['fetching']));
|
||||
|
||||
let img = await w('https://randomfox.ca/floof/', { headers: { 'User-Agent': this.bot.ua } }).send();
|
||||
img = img.json();
|
||||
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['image']['fox'],
|
||||
image : { url: img.image ? img.image : '' },
|
||||
description: `*[\`${msg.author.locale['image']['failed_cache']}\`](${img && img.image ? img.image : 'https://www.google.com/'})*`
|
||||
}
|
||||
});
|
||||
message.delete();
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('image', 'fox'));
|
||||
}
|
||||
};
|
||||
45
src/commands/Discord/Image/lizard.js
Normal file
45
src/commands/Discord/Image/lizard.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const w = require('wumpfetch');
|
||||
|
||||
module.exports = class Cat extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'lizard',
|
||||
syntax : 'lizard',
|
||||
aliases : [],
|
||||
argument : [],
|
||||
description: 'Get a random lizard',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 2500,
|
||||
category : 'Image',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg) {
|
||||
const message = await msg.channel.createMessage(this.localize(msg.author.locale['image']['fetching']));
|
||||
|
||||
let img = await w('https://nekos.life/api/v2/img/lizard', { headers: { 'User-Agent': this.bot.ua } }).send();
|
||||
img = img.json();
|
||||
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['image']['lizard'],
|
||||
image : { url: img.url ? img.url : '' },
|
||||
description: `*[\`${msg.author.locale['image']['failed_cache']}\`](${img && img.url ? img.url : 'https://www.google.com/'})*`
|
||||
}
|
||||
});
|
||||
message.delete();
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('image', 'lizard'));
|
||||
}
|
||||
};
|
||||
45
src/commands/Discord/Image/penguin.js
Normal file
45
src/commands/Discord/Image/penguin.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const w = require('wumpfetch');
|
||||
|
||||
module.exports = class Cat extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'penguin',
|
||||
syntax : 'penguin',
|
||||
aliases : [ 'pengu', 'waddle' ],
|
||||
argument : [],
|
||||
description: 'Get a random pengu',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 2500,
|
||||
category : 'Image',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg) {
|
||||
const message = await msg.channel.createMessage(this.localize(msg.author.locale['image']['fetching']));
|
||||
|
||||
let img = await w('https://animals.anidiots.guide/penguin', { headers: { 'User-Agent': this.bot.ua } }).send();
|
||||
img = img.json();
|
||||
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['image']['penguin'],
|
||||
image : { url: img.link ? img.link : '' },
|
||||
description: `*[\`${msg.author.locale['image']['failed_cache']}\`](${img && img.link ? img.link : 'https://www.google.com/'})*`
|
||||
}
|
||||
});
|
||||
message.delete();
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
return msg
|
||||
.replace(/\$\[emoji#0]/g, this.bot.emote('image', 'penguin'));
|
||||
}
|
||||
};
|
||||
93
src/commands/Discord/Information/commands.js
Normal file
93
src/commands/Discord/Information/commands.js
Normal file
@@ -0,0 +1,93 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const moment = require('moment'); require('../../../util/moment/format');
|
||||
const { readFileSync } = require('fs');
|
||||
|
||||
module.exports = class Commands extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'commands',
|
||||
syntax : 'commands [command:str]',
|
||||
aliases : [ 'command', 'cmds', 'cmd', 'help' ],
|
||||
argument : [ '[command:str]' ],
|
||||
description: 'Lists all commands',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 1000,
|
||||
category : 'Information',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
|
||||
try { this.thumb = readFileSync('./assets/img/thumb/commands.png'); }
|
||||
catch(ex) { this.thumb = undefined; }
|
||||
}
|
||||
|
||||
async execute(msg, args) {
|
||||
let cmd = this.bot.cmds.filter((v) => v.extData.name.toLowerCase() === args.join(' ').toLowerCase() || v.extData.aliases.includes(args.join(' ').toLowerCase()));
|
||||
|
||||
if (cmd.length >= 1) {
|
||||
cmd = cmd[0].extData;
|
||||
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
description: this.localize(msg.author.locale['info']['commands']['single'].join('\n'), { msg: msg, cmd: cmd })
|
||||
}
|
||||
});
|
||||
} else {
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['info']['commands'],
|
||||
thumbnail : { url: 'attachment://thumb.png' },
|
||||
description: this.localize(msg.author.locale['info']['commands']['multi'].join('\n'), { msg: msg }),
|
||||
fields : [
|
||||
{
|
||||
name : msg.author.locale['info']['commands']['fields'][0],
|
||||
value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'information' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'),
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name : msg.author.locale['info']['commands']['fields'][1],
|
||||
value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'image' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'),
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name : msg.author.locale['info']['commands']['fields'][2],
|
||||
value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'utility' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'),
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name : msg.author.locale['info']['commands']['fields'][3],
|
||||
value : this.bot.cmds.filter((v) => v.extData.category.toLowerCase() === 'developer' && !v.extData.hidden).map((v) => `**•** [\`${msg.prefix}${v.extData.name}\`](https://discordapp.com/channels/${msg.channel.guild.id}/${msg.channel.id}/${msg.id}) ${v.extData.description ? `**-** ${v.extData.description}` : ''}`).join('\n'),
|
||||
inline: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
this.thumb ? { file: this.thumb, name: 'thumb.png' } : undefined);
|
||||
}
|
||||
}
|
||||
|
||||
localize(msg, extData) {
|
||||
if (!msg) return '';
|
||||
|
||||
if (extData && extData.msg) msg = msg
|
||||
.replace(/\$\[guild:name]/g, extData.msg.channel.guild.name)
|
||||
.replace(/\$\[guild:prefix]/g, extData.msg.prefix)
|
||||
.replace(/\$\[bot:invite]/g, this.bot.gatherInvite(8));
|
||||
|
||||
if (extData && extData.cmd) msg = msg
|
||||
.replace(/\$\[command:name]/g, extData.cmd.name)
|
||||
.replace(/\$\[command:syntax]/g, `${extData.msg.prefix}${extData.cmd.syntax}`)
|
||||
.replace(/\$\[command:aliases]/g, extData.cmd.aliases.map((v) => `\`${v}\``).join(', ') || '`n/a`')
|
||||
.replace(/\$\[command:arguments]/g, extData.cmd.argument.map((v) => `\`${v}\``).join(', ') || '`n/a`')
|
||||
.replace(/\$\[command:cooldown#formatted]/g, moment.duration(extData.cmd.cooldown ? extData.cmd.cooldown : 0).format('YYYY[y] MM[M] DD[d] HH[h] mm[m] ss[s]'));
|
||||
|
||||
return msg
|
||||
.replace(/\$\[emoji#0]/g, this.bot.emote('info', 'commands', '0'))
|
||||
.replace(/\$\[emoji#1]/g, this.bot.emote('info', 'commands', '1'))
|
||||
.replace(/\$\[emoji#2]/g, this.bot.emote('info', 'commands', '2'));
|
||||
}
|
||||
};
|
||||
122
src/commands/Discord/Information/stats.js
Normal file
122
src/commands/Discord/Information/stats.js
Normal file
@@ -0,0 +1,122 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const os = require('os');
|
||||
const larg = require('larg');
|
||||
const moment = require('moment'); require('../../../util/moment/format');
|
||||
const { readFileSync } = require('fs');
|
||||
|
||||
module.exports = class Stats extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'stats',
|
||||
syntax : 'stats [--{no-deps|no-bot|no-sys|no-cpu|no-thumb}]',
|
||||
aliases : [ 'statistics' ],
|
||||
argument : [ '[--{no-deps|no-bot|no-sys|no-cpu|no-thumb}]' ],
|
||||
description: 'Some small statistics',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 5000,
|
||||
category : 'Information',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
|
||||
try { this.thumb = readFileSync('./assets/img/thumb/stats.png'); }
|
||||
catch(ex) { this.thumb = undefined; }
|
||||
}
|
||||
|
||||
async execute( msg, args ) {
|
||||
args = larg(args);
|
||||
const message = await msg.channel.createMessage(this.localize(msg.author.locale['info']['stats']['fetching']));
|
||||
|
||||
const cpus = os.cpus();
|
||||
let platform = {
|
||||
'arch' : os.arch() ? os.arch() : '??x',
|
||||
'release' : os.release() ? os.release() : '?.?.?',
|
||||
'platform': os.platform()
|
||||
};
|
||||
|
||||
switch (platform.platform) {
|
||||
case 'aix' : platform.platform = 'Linux'; break;
|
||||
case 'sunos' : platform.platform = 'Linux'; break;
|
||||
case 'win32' : platform.platform = 'Windows'; break;
|
||||
case 'linux' : platform.platform = 'Linux'; break;
|
||||
case 'darwin' : platform.platform = 'Macintosh'; break;
|
||||
case 'freebsd': platform.platform = 'Linux'; break;
|
||||
case 'openbsd': platform.platform = 'Linux'; break;
|
||||
case 'android': platform.platform = 'Android'; break;
|
||||
default : platform.platform = 'Unknown';
|
||||
}
|
||||
|
||||
const fields = [];
|
||||
|
||||
if (!args['no-bot']) {
|
||||
fields.push({
|
||||
name : '❯ Bot information',
|
||||
value :
|
||||
[
|
||||
`${this.bot.emote('info', 'statistics', '7')} **User Agent**: ${this.bot.ua ? this.bot.ua : 'Unknown'}`,
|
||||
`${this.bot.emote('info', 'statistics', '8')} **Shards \`[Current / Total]\`**: ${msg.channel.guild.shard.id} **/** ${this.bot.shards.size}`,
|
||||
`${this.bot.emote('info', 'statistics', '9')} **Cache \`[Users / Guilds]\`**: ${this.bot.cache.get('users').length || 0} **/** ${this.bot.cache.get('guilds').length || 0}`,
|
||||
`${this.bot.emote('info', 'statistics', '10')} **Channels**: ${Object.keys(this.bot.channelGuildMap).length}`,
|
||||
`${this.bot.emote('info', 'statistics', '11')} **Guilds**: ${this.bot.guilds.size}`,
|
||||
`${this.bot.emote('info', 'statistics', '12')} **Users**: ${this.bot.users.size}`
|
||||
].join('\n'),
|
||||
inline: true
|
||||
});
|
||||
}
|
||||
if (!args['no-sys']) {
|
||||
fields.push({
|
||||
name : '❯ System and process information',
|
||||
value :
|
||||
[
|
||||
`${this.bot.emote('info', 'statistics', '1')} **Operating System**: ${platform.platform} ${platform.release} **(**${platform.arch}**)**`,
|
||||
`${this.bot.emote('info', 'statistics', '2')} **Process Hash**: ${process.hash}`,
|
||||
`${this.bot.emote('info', 'statistics', '3')} **Load Average**: ${os.loadavg().join(' **/** ')}`,
|
||||
`${this.bot.emote('info', 'statistics', '4')} **OS Uptime**: ${moment.duration(os.uptime() * 1000).format('YYYY[y] MM[M] DD[d] HH[h] mm[m] ss[s]')}`,
|
||||
`${this.bot.emote('info', 'statistics', '5')} **Uptime**: ${moment.duration(this.bot.uptime).format('YYYY[y] MM[M] DD[d] HH[h] mm[m] ss[s]')}`,
|
||||
`${this.bot.emote('info', 'statistics', '6')} **Memory**: ${this.formatBytes(process.memoryUsage().heapUsed)} **/** ${this.formatBytes(os.totalmem())} **(**${((process.memoryUsage().heapUsed / os.totalmem()) * 100).toFixed(2)}%**)**`
|
||||
].join('\n'),
|
||||
inline: true
|
||||
});
|
||||
}
|
||||
if (!args['no-deps']) {
|
||||
fields.push({
|
||||
name : '❯ Runtime & Dependencies',
|
||||
value : `**Node.js**: ${process.version}\n\n${Array.list(Object.keys(this.bot.pkg.dependencies).map((v, _) => `\`${v}\``))}`,
|
||||
inline: true
|
||||
});
|
||||
}
|
||||
if (!args['no-cpu']) {
|
||||
fields.push({
|
||||
name : '❯ CPU information',
|
||||
value : `\`\`\`ini\navailable=${cpus.length}\nendianness="${os.endianness()}"\n; List of all (available) CPU's\n${cpus.map((v, _) => `[${_ + 1}] ${v.model}`).join('\n')}\`\`\``,
|
||||
inline: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
msg.channel.createMessage({
|
||||
content: '',
|
||||
embed: {
|
||||
color : this.bot.col['info']['stats'],
|
||||
fields : fields,
|
||||
thumbnail: { url: !args['no-thumb'] ? 'attachment://thumb.png' : '' }
|
||||
}
|
||||
},
|
||||
this.thumb && !args['no-thumb'] ? { file: this.thumb, name: 'thumb.png' } : '');
|
||||
message.delete();
|
||||
}
|
||||
|
||||
formatBytes(b) {
|
||||
if(b < 1073741824) return(b / 1048576).toFixed(2) + ' MB';
|
||||
else return(b / 1073741824).toFixed(2) + ' GB';
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('info', 'statistics', '0'));
|
||||
}
|
||||
};
|
||||
52
src/commands/Discord/Utility/math.js
Normal file
52
src/commands/Discord/Utility/math.js
Normal file
@@ -0,0 +1,52 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
const { NodeVM } = require('vm2');
|
||||
const { eval: mEval, config } = require('mathjs');
|
||||
|
||||
module.exports = class Math extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'math',
|
||||
syntax : 'math <...equation:str>',
|
||||
aliases : [],
|
||||
argument : [ '<...equation:str>' ],
|
||||
description : 'Evaluate an equation',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 5000,
|
||||
category : 'Utility',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions : []
|
||||
});
|
||||
|
||||
this.regex = /eval|import|parse|simplify|derivative|createUnit/gi;
|
||||
config({ number: 'BigNumber', precision: 64 });
|
||||
}
|
||||
|
||||
async execute(msg, args) {
|
||||
let sandbox = null;
|
||||
let message = null;
|
||||
let blocked = undefined;
|
||||
let origMsg = await msg.channel.createMessage(this.localize(msg.author.locale['util']['math']['busy']));
|
||||
let equation = 0;
|
||||
|
||||
try {
|
||||
equation = (args[0] ? args.join(' ') : '2+2-1');
|
||||
blocked = this.regex.exec(equation);
|
||||
if (blocked && blocked[0] && !this.bot.op(msg.author.id)) throw msg.author.locale['util']['math']['blocked'].replace(/\$\[math:function]/g, blocked[0]);
|
||||
|
||||
const vm = new NodeVM({ timeout: 10000, sandbox: { mEval: mEval }, require: { external: true } });
|
||||
sandbox = vm.run('module.exports = function(equation) { return mEval(`${equation}`) }');
|
||||
message = `${this.bot.util.shorten(`${this.bot.emote('util', 'math', '1' )} ${msg.author.mention} **>** \`${this.bot.util.escapeMarkdown(equation.replace(/ /gi, ''), false, true)}\` = \`${sandbox(equation) || 0}\``, 2000)}`;
|
||||
} catch (ex) {
|
||||
message = `${this.bot.util.shorten(`${this.bot.emote( 'util', 'math', '2' )} ${msg.author.mention} **>** \`${this.bot.util.escapeMarkdown(equation.replace(/ /gi, ''), false, true)}\` = \`${this.bot.util.escapeMarkdown(ex.message ? ex.message : ex, false, true)}\``, 2000)}`;
|
||||
} finally { origMsg.edit(message); }
|
||||
}
|
||||
|
||||
localize(msg) {
|
||||
if (!msg) return '';
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('util', 'math', '0'));
|
||||
}
|
||||
};
|
||||
60
src/commands/Discord/Utility/ping.js
Normal file
60
src/commands/Discord/Utility/ping.js
Normal file
@@ -0,0 +1,60 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
module.exports = class Ping extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'ping',
|
||||
syntax : 'ping',
|
||||
aliases : [ 'pong' ],
|
||||
argument : [],
|
||||
description: 'Lists latencies',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 1000,
|
||||
category : 'Utility',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg) {
|
||||
const now = Date.now();
|
||||
const latency = msg.channel.guild ? msg.channel.guild.shard.latency : undefined;
|
||||
|
||||
let health;
|
||||
if (isNaN(latency)) health = msg.author.locale['util']['ping']['health'][0];
|
||||
else if (latency < 200) health = `${msg.author.locale['util']['ping']['health'][1]} (**${this.bot.util.getPercentage(200, latency).toFixed()}%** \`[${'='.repeat(10 - Math.round(10* latency / 200))}${'-'.repeat(Math.round(10* latency / 200))}]\`)`;
|
||||
else if (latency < 400) health = `${msg.author.locale['util']['ping']['health'][2]} (**${this.bot.util.getPercentage(400, latency).toFixed()}%** \`[${'='.repeat(10 - Math.round(10* latency / 400))}${'-'.repeat(Math.round(10* latency / 400))}]\`)`;
|
||||
else if (latency > 400) health = `${msg.author.locale['util']['ping']['health'][3]} Bad (**0%** \`[----------]\`)`;
|
||||
|
||||
const message = await msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['util']['ping']['0'],
|
||||
description: this.localize(msg.author.locale['util']['ping']['busy'])
|
||||
}
|
||||
});
|
||||
|
||||
message.edit({
|
||||
embed: {
|
||||
color : latency < 200 ? this.bot.col['util']['ping']['1'] : latency > 200 && latency < 400 ? this.bot.col['util']['ping']['2'] : this.bot.col['util']['ping']['3'],
|
||||
description: this.localize(msg.author.locale['util']['ping']['result'].join('\n'), { latency: latency, now: now, health: health })
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
localize(msg, extData = {}) {
|
||||
if (!msg) return '';
|
||||
|
||||
if (extData && extData.now) msg = msg.replace(/\$\[roundtrip]/g, Date.now() - extData.now);
|
||||
if (extData && extData.health) msg = msg.replace(/\$\[health]/g, extData.health);
|
||||
if (extData && extData.latency) msg = msg.replace(/\$\[latency]/g, extData.latency);
|
||||
|
||||
return msg
|
||||
.replace(/\$\[emoji#0]/g, this.bot.emote('util', 'ping', '0'))
|
||||
.replace(/\$\[emoji#1]/g, this.bot.emote('util', 'ping', '1'))
|
||||
.replace(/\$\[emoji#2]/g, this.bot.emote('util', 'ping', '2'))
|
||||
.replace(/\$\[emoji#3]/g, this.bot.emote('util', 'ping', '3'));
|
||||
}
|
||||
};
|
||||
72
src/commands/Discord/Utility/snipe.js
Normal file
72
src/commands/Discord/Utility/snipe.js
Normal file
@@ -0,0 +1,72 @@
|
||||
const { DiscordCommand } = require('../../../core/');
|
||||
|
||||
module.exports = class Snipe extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : 'snipe',
|
||||
syntax : 'snipe',
|
||||
aliases : [],
|
||||
argument : [],
|
||||
description: 'Re-post a deleted message',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 1000,
|
||||
category : 'Utility',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions: [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
execute(msg) {
|
||||
const message = this.bot.cache.get(`${msg.channel.id}:SNIPE`);
|
||||
if (!message) return msg.channel.createMessage(this.localize(msg.author.locale['util']['snipe']['fail']));
|
||||
|
||||
let structure = {
|
||||
author : {
|
||||
name : `${message.author.username}#${message.author.discriminator} (${message.author.id})`,
|
||||
icon_url: message.author.avatar ? message.author.avatarURL : message.author.defaultAvatarURL
|
||||
},
|
||||
color : this.bot.col['util']['snipe'],
|
||||
footer : {
|
||||
text : this.localize(msg.author.locale['util']['snipe']['footer'], { msg: msg }),
|
||||
icon_url: msg.author.avatar ? msg.author.avatarURL : msg.author.defaultAvatarURL
|
||||
},
|
||||
timestamp: new Date(message.timestamp).toISOString()
|
||||
};
|
||||
|
||||
if (message.embeds.length > 0 && 'url' in message.embeds[0]) structure.url = message.embeds[0].url;
|
||||
if (message.embeds.length > 0 && 'type' in message.embeds[0]) structure.type = message.embeds[0].type;
|
||||
if (message.embeds.length > 0 && 'title' in message.embeds[0]) structure.title = message.embeds[0].title;
|
||||
if (message.embeds.length > 0 && 'image' in message.embeds[0]) structure.image = message.embeds[0].image;
|
||||
if (message.embeds.length > 0 && 'video' in message.embeds[0]) structure.video = message.embeds[0].video;
|
||||
if (message.embeds.length > 0 && 'fields' in message.embeds[0]) structure.fields = message.embeds[0].fields;
|
||||
if (message.embeds.length > 0 && 'provider' in message.embeds[0]) structure.provider = message.embeds[0].provider;
|
||||
if (message.embeds.length > 0 && 'thumbnail' in message.embeds[0]) structure.thumbnail = message.embeds[0].thumbnail;
|
||||
if (message.embeds.length > 0 && 'description' in message.embeds[0]) structure.description = (`${message.content ? message.content : ''}\n\n${message.embeds[0].description}`).slice(0, 2048);
|
||||
else if (message.content !== '' ) structure.description = message.content;
|
||||
if (!('image' in structure) && message.attachments.length > 0) {
|
||||
structure.image = {
|
||||
url : message.attachments[0].url,
|
||||
width : message.attachments[0].width,
|
||||
height : message.attachments[0].height,
|
||||
proxy_url: message.attachments[0].proxy_url
|
||||
};
|
||||
}
|
||||
|
||||
msg.channel.createMessage({ embed: structure });
|
||||
this.bot.cache.delete(`${msg.channel.id}:SNIPE`);
|
||||
}
|
||||
|
||||
localize(msg, extData) {
|
||||
if (!msg) return '';
|
||||
|
||||
if (extData && extData.msg) msg = msg
|
||||
.replace(/\$\[author:tag]/g, `${extData.msg.author.username}#${extData.msg.author.discriminator}`)
|
||||
.replace(/\$\[author:id]/g, extData.msg.author.id);
|
||||
|
||||
return msg
|
||||
.replace(/\$\[emoji#0]/g, this.bot.emote('util', 'snipe'));
|
||||
}
|
||||
};
|
||||
97
src/core/clients/Discord.js
Normal file
97
src/core/clients/Discord.js
Normal file
@@ -0,0 +1,97 @@
|
||||
// Main
|
||||
const Webhook = require('./DiscordWebhook');
|
||||
const { Client: Eris } = require('eris');
|
||||
// Registries
|
||||
const EventRegistry = require('../registry/Discord/Events');
|
||||
const LocaleRegistry = require('../registry/Discord/Locales');
|
||||
const CommandRegistry = require('../registry/Discord/Commands');
|
||||
// Utilities
|
||||
const Util = require('../../util/Util');
|
||||
const Schema = require('../internal/Discord/Schemas');
|
||||
const { cyan } = require('../../util/colors');
|
||||
const Collection = require('../../util/Collection');
|
||||
const PermissionUtil = require('../internal/Discord/Utils/PermissionUtil');
|
||||
|
||||
module.exports = class WumpDiscord extends Eris {
|
||||
constructor(token, options = {}) {
|
||||
if (!token) throw new Error('Invalid token');
|
||||
if (!options.db) throw new Error('Invalid database');
|
||||
|
||||
super(token, options.clientOptions);
|
||||
this.hook = options.webhook ? new Webhook({ token: options.webhook.token, channel: options.webhook.channel }) : new Webhook();
|
||||
|
||||
this.cmds = new Collection();
|
||||
this.cache = new Collection();
|
||||
this.events = new Collection();
|
||||
this.locales = new Collection();
|
||||
this.localeMap = [];
|
||||
this.localeDic = [];
|
||||
|
||||
this.m = options.db;
|
||||
this.eventRegistry = new EventRegistry(this);
|
||||
this.localeRegistry = new LocaleRegistry(this);
|
||||
this.commandRegistry = new CommandRegistry(this);
|
||||
|
||||
this.util = Util;
|
||||
this.print = Util.print;
|
||||
this.schema = Schema;
|
||||
this.Collection = Collection;
|
||||
|
||||
this.ua = options.ua ? options.ua : undefined;
|
||||
this.pkg = options.pkg ? options.pkg : undefined;
|
||||
this.col = options.colors ? options.colors : undefined;
|
||||
this.ico = options.emojis ? options.emojis : undefined;
|
||||
this.conf = options.config ? options.config : undefined;
|
||||
}
|
||||
|
||||
async launch(events, commands, locales) {
|
||||
this.eventRegistry.run(events);
|
||||
this.localeRegistry.run(locales);
|
||||
this.commandRegistry.run(commands);
|
||||
|
||||
this.connect()
|
||||
.then(() => this.print(1, `${cyan('Discord')} >> Connecting shards to websockets...`));
|
||||
}
|
||||
|
||||
op(id) { return this.conf['discord']['op'].includes(id); }
|
||||
|
||||
emote(a, b, c) {
|
||||
if (!a || !this.ico[a]) return '';
|
||||
if (c) {
|
||||
if (!this.ico[a][b]) return '';
|
||||
if (!this.ico[a][b][c]) return '';
|
||||
if (this.ico[a][b][c].length <= 0) return '';
|
||||
else return this.ico[a][b][c];
|
||||
} else if (b) {
|
||||
if (!this.ico[a][b]) return '';
|
||||
if (this.ico[a][b].length <= 0) return '';
|
||||
else return this.ico[a][b];
|
||||
} else {
|
||||
if (this.ico[a].length < 1) return '';
|
||||
else return this.ico[a];
|
||||
}
|
||||
}
|
||||
|
||||
gatherInvite(permission) {
|
||||
permission = PermissionUtil.resolve(permission);
|
||||
return `https://discordapp.com/oauth2/authorize?client_id=${this.user.id}&scope=bot&permissions=${permission}`;
|
||||
}
|
||||
|
||||
destroy(code = 0) {
|
||||
let trace = { success: false, code: code };
|
||||
try {
|
||||
this.disconnect({ reconnect: false });
|
||||
trace.success = true;
|
||||
} catch ( err ) {
|
||||
trace = {
|
||||
err: {
|
||||
code : err.code,
|
||||
stack : err.stack,
|
||||
message : err.message
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return trace;
|
||||
}
|
||||
};
|
||||
24
src/core/clients/DiscordWebhook.js
Normal file
24
src/core/clients/DiscordWebhook.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const fetch = require('wumpfetch');
|
||||
const { randomBytes } = require('crypto');
|
||||
|
||||
module.exports = class DiscordWebhook {
|
||||
constructor(extData = {}) {
|
||||
|
||||
this.hash = randomBytes(Math.floor(Math.random() * 10) + 5).toString('hex');
|
||||
this.baseURL = 'https://discordapp.com/api/webhooks';
|
||||
this.extData = extData;
|
||||
|
||||
(async() => {
|
||||
try {
|
||||
if (!this.extData.token || !this.extData.channel) return this.hook = undefined;
|
||||
this.hook = await fetch(`${this.baseURL}/${this.extData.channel}/${this.extData.token}`, { method: 'GET' }).send();
|
||||
if (this.hook.statusCode !== 200) throw new SyntaxError( 'Failed to fetch webhook' );
|
||||
} catch (ex) { throw ex; }
|
||||
})();
|
||||
}
|
||||
|
||||
async send(data = {}) {
|
||||
if (!this.hook) return true;
|
||||
return await fetch(`${this.baseURL}/${this.extData.channel}/${this.extData.token}`, { method: 'POST', data: data }).send();
|
||||
}
|
||||
};
|
||||
6
src/core/index.js
Normal file
6
src/core/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
DiscordEvent : require('./internal/Discord/Event'),
|
||||
DiscordClient : require('./clients/Discord'),
|
||||
DiscordCommand: require('./internal/Discord/Command'),
|
||||
DiscordContext: require('./internal/Discord/Context')
|
||||
};
|
||||
24
src/core/internal/Discord/Command.js
Normal file
24
src/core/internal/Discord/Command.js
Normal file
@@ -0,0 +1,24 @@
|
||||
module.exports = class WumpCommand {
|
||||
constructor(bot, opts = {}) {
|
||||
this.bot = bot;
|
||||
this.extData = Object.assign({
|
||||
name : null, // Command name ( required )
|
||||
syntax : null, // Command syntax ( optional )
|
||||
aliases : [], // Command aliases ( optional )
|
||||
argument : [], // Command arguments ( optional )
|
||||
description : null, // Command description ( optional )
|
||||
|
||||
hidden : false, // Hidden from view ( true / false )
|
||||
enabled : true, // Enabled or disabled ( true / false )
|
||||
cooldown : 1000, // Command cooldown ( optional )
|
||||
category : 'General', // Command category ( required )
|
||||
ownerOnly : false, // Owner only ( true / false )
|
||||
guildOnly : false, // Guild only ( true / false )
|
||||
permissions : [] // Bot permissions ( optional )
|
||||
}, opts);
|
||||
}
|
||||
|
||||
async execute(msg, args, user, guild) {}
|
||||
|
||||
localize(msg) {}
|
||||
};
|
||||
18
src/core/internal/Discord/Context.js
Normal file
18
src/core/internal/Discord/Context.js
Normal file
@@ -0,0 +1,18 @@
|
||||
module.exports = class WumpContext {
|
||||
constructor(bot, msg) {
|
||||
Object.assign(this, msg);
|
||||
this.bot = bot;
|
||||
this.orig = msg;
|
||||
this.locale = null;
|
||||
this.prefix = null;
|
||||
}
|
||||
|
||||
get guild() { return this.channel.guild; }
|
||||
|
||||
getPrefix() { return this.prefix; }
|
||||
getLocale() { return this.locale; }
|
||||
getMember() { return this.member; }
|
||||
|
||||
setPrefix(prefix) { this.prefix = prefix; }
|
||||
setLocale(locale) { this.locale = locale; }
|
||||
};
|
||||
10
src/core/internal/Discord/Event.js
Normal file
10
src/core/internal/Discord/Event.js
Normal file
@@ -0,0 +1,10 @@
|
||||
module.exports = class WumpEvent {
|
||||
constructor(bot, opts = {}) {
|
||||
this.bot = bot;
|
||||
this.extData = Object.assign({ name: null }, opts);
|
||||
}
|
||||
|
||||
emit(...args) {}
|
||||
|
||||
localize(msg) {}
|
||||
};
|
||||
37
src/core/internal/Discord/RESTclient.js
Normal file
37
src/core/internal/Discord/RESTclient.js
Normal file
@@ -0,0 +1,37 @@
|
||||
module.exports = class RESTclient {
|
||||
constructor(bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
resolveGuild(q) {
|
||||
if (q) return undefined;
|
||||
|
||||
const g = this.bot.guilds.get(q);
|
||||
if (/^\d+$/.test(q)) return g;
|
||||
else {
|
||||
const gs = this.bot.guilds.filter((v) => v.name.toLowerCase().includes(q.toLowerCase()));
|
||||
if (gs.length > 1) return gs[0];
|
||||
else return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
resolveUser(q) {
|
||||
if (!q) return undefined;
|
||||
|
||||
if (/^\d+$/.test(q)) {
|
||||
const u = this.bot.users.get(q);
|
||||
if (u) return u;
|
||||
} else if (/^<@!?(\d+)>$/.test(q)) {
|
||||
const u = this.bot.users.get(q.match(/^<@!?(\d+)>$/)[1]);
|
||||
if (u) return u;
|
||||
} else if (/^(.+)#(\d{4})$/.test(q)) {
|
||||
const m = q.match(/^(.+)#(\d{4})$/);
|
||||
const u = this.bot.users.filter((v) => v.username === m[1] && Number(v.discriminator) === Number(m[2]));
|
||||
if (u.length >= 1) return u[0];
|
||||
} else {
|
||||
const u = this.bot.users.filter((v) => v.username.toLowerCase().includes(q.toLowerCase()));
|
||||
if (u.length >= 1) return u[0];
|
||||
else return undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
20
src/core/internal/Discord/Schemas.js
Normal file
20
src/core/internal/Discord/Schemas.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const mongoose = require('mongoose');
|
||||
const { safeLoad } = require('js-yaml');
|
||||
const { readFileSync } = require('fs');
|
||||
|
||||
const conf = safeLoad(readFileSync('application.yml', { encoding: 'utf8' }));
|
||||
|
||||
const guild = new mongoose.Schema({
|
||||
guildId: { type: String, default: undefined },
|
||||
prefix : { type: String, default: conf['discord']['prefix'] }
|
||||
});
|
||||
|
||||
const user = new mongoose.Schema({
|
||||
userId: { type: String, default: undefined },
|
||||
locale: { type: String, default: conf['discord']['locale'] }
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
user : mongoose.model('dUsers', user, 'dUsers'),
|
||||
guild: mongoose.model('dGuilds', guild, 'dGuilds')
|
||||
};
|
||||
10
src/core/internal/Discord/Utils/PermissionUtil.js
Normal file
10
src/core/internal/Discord/Utils/PermissionUtil.js
Normal file
@@ -0,0 +1,10 @@
|
||||
const { Constants } = require('eris');
|
||||
|
||||
module.exports = class PermissionUtil {
|
||||
static resolve(permission) {
|
||||
if (typeof permission === 'number' && permission >= 0) return permission;
|
||||
if (typeof permission === 'string') return Constants.permission[permission];
|
||||
if (permission instanceof Array) return permission.map((v) => this.resolve(v)).reduce((prev, p) => prev | p, 0);
|
||||
throw new RangeError('Invalid permission');
|
||||
}
|
||||
};
|
||||
25
src/core/internal/Discord/__baseCommand.js
Normal file
25
src/core/internal/Discord/__baseCommand.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const { DiscordCommand } = require('../../../core');
|
||||
|
||||
module.exports = class name extends DiscordCommand {
|
||||
constructor(bot) {
|
||||
super(bot, {
|
||||
name : '',
|
||||
syntax : '',
|
||||
aliases : [],
|
||||
argument : [],
|
||||
description : '',
|
||||
|
||||
hidden : false,
|
||||
enabled : true,
|
||||
cooldown : 1000,
|
||||
category : 'Utility',
|
||||
ownerOnly : false,
|
||||
guildOnly : false,
|
||||
permissions : [ 'embedLinks' ]
|
||||
});
|
||||
}
|
||||
|
||||
async execute(msg, args, user, guild) {}
|
||||
|
||||
localize(msg) {}
|
||||
};
|
||||
183
src/core/registry/Discord/Commands.js
Normal file
183
src/core/registry/Discord/Commands.js
Normal file
@@ -0,0 +1,183 @@
|
||||
const moment = require('moment'); require('../../../util/moment/format');
|
||||
const { safeLoad } = require('js-yaml');
|
||||
const { Collection } = require('eris');
|
||||
const { red, green, yellow, cyan } = require('../../../util/colors');
|
||||
const { readdir, readdirSync, readFileSync } = require('fs');
|
||||
|
||||
const Context = require('../../internal/Discord/Context');
|
||||
const startTimestamp = Date.now();
|
||||
|
||||
module.exports = class CommandRegistry {
|
||||
constructor(bot) {
|
||||
this.bot = bot;
|
||||
this.ratelimits = new Collection();
|
||||
}
|
||||
|
||||
start(directory, category, file) {
|
||||
try {
|
||||
const cmd = new(require(`${directory}/${category}/${file}`))(this.bot);
|
||||
cmd.extData.location = `${directory}/${category}/${file}`;
|
||||
|
||||
if (!cmd.extData.enabled) return;
|
||||
if (!this.bot.conf['discord']['commands'][cmd.extData.name]) return;
|
||||
if (this.bot.cmds.has(cmd.extData.name)) return this.bot.print(1, `${cyan('Discord')} -- Duplicate command found - ${red(`${directory}/${category}/${file}`)}` );
|
||||
|
||||
this.bot.cmds.set(cmd.extData.name, cmd);
|
||||
this.bot.print(2, `${cyan('Discord')} ++ Loaded command ${green(cmd.extData.name)} in ${yellow(`${(Date.now() - startTimestamp)}ms`)}`);
|
||||
} catch (ex) { this.bot.print(1, `${cyan('Discord')} >> ${yellow(`${directory}/${category}/${file}`)} ${red(`is not a valid command: ${ex.message}`)}`); }
|
||||
}
|
||||
|
||||
async run(directory) {
|
||||
const categories = await readdirSync(directory);
|
||||
|
||||
for (let i = 0; i < categories.length; i++) {
|
||||
if (categories[i].endsWith('md')) return;
|
||||
readdir(`${directory}/${categories[i]}`, (err, cmds) => {
|
||||
if (err) process.handleError(err, cyan('Discord'), 'LoadError');
|
||||
this.bot.print(1, `${cyan('Discord')} >> Loading ${green(cmds.length)} commands from category ${yellow(categories[i])}` );
|
||||
|
||||
cmds.forEach((cmd) => {
|
||||
try {
|
||||
this.start(directory, categories[i], cmd);
|
||||
} catch(ex) { process.handleError(err, cyan('Discord'), 'LoadError'); }
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
reload(command = 'ping') {
|
||||
const cmd = this.bot.cmds.get(command);
|
||||
const dir = cmd ? cmd.extData.location : undefined;
|
||||
|
||||
if (!cmd || !dir) return false;
|
||||
|
||||
delete require.gCache[require.resolve(dir)];
|
||||
this.bot.cmds.delete(command);
|
||||
this.start(dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
async handleCommand(msg) {
|
||||
let perm;
|
||||
let prefix;
|
||||
let guild, user;
|
||||
let gCache, uCache;
|
||||
|
||||
if (msg.author.bot || !this.bot.ready) return;
|
||||
if (msg.channel.guild) {
|
||||
perm = msg.channel.permissionsOf(this.bot.user.id);
|
||||
gCache = this.bot.cache.has('guilds') ? this.bot.cache.get('guilds') : this.bot.cache.set('guilds', []) && this.bot.cache.get('guilds');
|
||||
uCache = this.bot.cache.has('users') ? this.bot.cache.get('users') : this.bot.cache.set('users', []) && this.bot.cache.get('users');
|
||||
if (!this.checkArray('guildId', msg.channel.guild.id, gCache)) {
|
||||
guild = await this.bot.m.connection.collection('dGuilds').findOne({ guildId: msg.channel.guild.id });
|
||||
if (!guild) {
|
||||
guild = new this.bot.schema.guild({ guildId: msg.channel.guild.id });
|
||||
await guild.save((err) => { if (err) process.handleError(err); });
|
||||
} else gCache.push({ 'guildId': msg.channel.guild.id, 'prefix': guild.prefix, 'entryAge': Date.now() });
|
||||
} else guild = gCache.filter((v) => v['guildId'] === msg.channel.guild.id );
|
||||
|
||||
if (!this.checkArray('userId', msg.author.id, uCache)) {
|
||||
user = await this.bot.m.connection.collection('dUsers').findOne({ userId: msg.author.id });
|
||||
if (!user) {
|
||||
user = new this.bot.schema.user({ userId: msg.author.id });
|
||||
await user.save((err) => { if (err) process.handleError(err); });
|
||||
} else uCache.push({ 'userId': msg.author.id, locale: user.locale ? user.locale : this.bot.conf['discord']['locale'], 'entryAge': Date.now() });
|
||||
} else user = gCache.filter((v) => v['userId'] === msg.author.id );
|
||||
msg.author.locale = this.bot.locales.get(user['locale'] ? user['locale'] : 'en_us');
|
||||
|
||||
prefix = new RegExp([
|
||||
`^<@!?${this.bot.user.id}> `,
|
||||
`^${this.bot.conf['discord']['prefix'].replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}`,
|
||||
`^${guild && guild['prefix'] ? guild['prefix'].replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') : this.bot.conf['discord']['prefix'].replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}`
|
||||
].join('|')).exec(msg.content.toLowerCase());
|
||||
} else {
|
||||
guild = undefined;
|
||||
prefix = /(?:)/.exec(msg['content'].toLowerCase());
|
||||
}
|
||||
|
||||
if (!prefix) return;
|
||||
|
||||
const ctx = new Context(this.bot, msg);
|
||||
ctx.setPrefix(prefix);
|
||||
|
||||
const args = msg.content.slice(prefix[0].length).trim().split(/ +/g);
|
||||
let cmd = args.shift().toLowerCase();
|
||||
cmd = this.bot.cmds.filter((v) => v.extData.name.toLowerCase() === cmd || v.extData.aliases.includes(cmd));
|
||||
|
||||
if (cmd.length > 0) {
|
||||
user['entryAge'] = Date.now();
|
||||
guild['entryAge'] = Date.now();
|
||||
cmd = cmd[0];
|
||||
|
||||
if (cmd.extData.ownerOnly && !this.bot.op(msg.author.id))
|
||||
return msg.channel.createMessage(`${this.bot.emote('owner_only')} ${msg.author.mention} **>** You don't have enough permissions to execute this command (\`BOT_OP\`)`);
|
||||
|
||||
if (cmd.extData.guildOnly && msg.channel.type === 1)
|
||||
return msg.channel.createMessage( `${this.bot.emote('guild_only')} ${msg.author.mention} **>** This command can only be used in guilds` );
|
||||
|
||||
if (msg.channel.guild && (cmd.extData.permissions && cmd.extData.permissions.some((v) => !perm.has(v))) ||
|
||||
msg.channel.guild && !perm.has('sendMessages')) return;
|
||||
|
||||
if (!this.ratelimits.has(cmd.extData.name)) this.ratelimits.set(cmd.extData.name, []);
|
||||
|
||||
const now = Date.now();
|
||||
const timestamps = this.ratelimits.get(cmd.extData.name);
|
||||
const cooldownUser = timestamps.find((v) => v.authorId === msg.author.id);
|
||||
const cooldownAmount = !this.bot.op(msg.author.id) ? (cmd.extData.cooldown) : 0;
|
||||
|
||||
if (!cooldownUser) {
|
||||
timestamps.push({ authorId: msg.author.id, date: now });
|
||||
setTimeout(() => {
|
||||
const _ = timestamps.findIndex((v) => v.authorId === msg.author.id);
|
||||
if (_ > -1) timestamps.splice(_, 1);
|
||||
else return false;
|
||||
}, cooldownAmount);
|
||||
} else {
|
||||
const expirationTime = cooldownUser.date + cooldownAmount;
|
||||
|
||||
if (now <= expirationTime) {
|
||||
const timeLeft = (expirationTime - now);
|
||||
|
||||
return msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['cooldown'],
|
||||
description: this.localize(msg.author.locale['cooldown'], { left: moment.duration(timeLeft).format('YYYY[y] M[M] DD[d] H[h] m[m] s[S] SS[ms]'), author: msg.author })
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await cmd.execute(ctx, args, user, guild);
|
||||
this.bot.print(3, `${cyan('Discord')} >> event "${yellow('COMMAND_EXECUTE')}" fired`);
|
||||
this.bot.print(3, `${cyan(`DShard #${msg.channel.guild ? msg.channel.guild.shard.id : 0}`)} >> Command '${cmd.extData.name}' executed by ${yellow(msg.author.id)}`);
|
||||
} catch (ex) {
|
||||
process.handleError(ex, cyan('Discord'), 'CommandError');
|
||||
msg.channel.createMessage({
|
||||
embed: {
|
||||
color : this.bot.col['error'],
|
||||
description: this.localize(msg.author.locale['error'].join('\n'), { author: msg.author, err: ex })
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkArray(field, value, array) {
|
||||
if (array instanceof Array) {
|
||||
return array.some((v) => { return v[field] === value; });
|
||||
} else return false;
|
||||
}
|
||||
|
||||
localize(msg, extData) {
|
||||
if (!msg) return '';
|
||||
|
||||
if (extData.err) msg = msg
|
||||
.replace(/\$\[err:code]/g, extData.err.code)
|
||||
.replace(/\$\[err:message]/g, extData.err.message.replace(/"/gi, '\\"'));
|
||||
if (extData.left) msg = msg.replace(/\$\[cooldown:left]/g, extData.left);
|
||||
if (extData.author) msg = msg.replace(/\$\[author:mention]/g, extData.author.mention);
|
||||
|
||||
return msg.replace(/\$\[emoji#0]/g, this.bot.emote('cooldown'));
|
||||
}
|
||||
};
|
||||
40
src/core/registry/Discord/Events.js
Normal file
40
src/core/registry/Discord/Events.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const { readdirSync } = require('fs');
|
||||
const { red, green, yellow, cyan } = require('../../../util/colors');
|
||||
|
||||
module.exports = class EventStore {
|
||||
constructor(bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
execute(event) {
|
||||
const execAsync = async(...args) => {
|
||||
try { await event.emit(...args); }
|
||||
catch (ex) { process.handleError(ex, cyan('Discord'), 'EventError'); }
|
||||
};
|
||||
|
||||
this.bot.on(event.extData.name, execAsync);
|
||||
}
|
||||
|
||||
async run(directory) {
|
||||
const startTimestamp = Date.now();
|
||||
|
||||
const events = await readdirSync(directory);
|
||||
|
||||
this.bot.print(1, `${cyan('Discord')} >> Loading ${green(events.length)} events...`);
|
||||
events.forEach((e) => {
|
||||
if (!e.endsWith('.js' )) return;
|
||||
const event = new(require(`${directory}/${e}`))(this.bot);
|
||||
|
||||
if (!this.bot.conf['discord']['events'][event.extData.name.toLowerCase()]) return false;
|
||||
if (this.bot.events.has(event.extData.name)) return this.bot.print(1, `[${cyan('Discord')}] -- Duplicate event found - ${red(`${directory}/${event.extData.name}`)}`);
|
||||
|
||||
this.bot.events.set(event.extData.name, event);
|
||||
this.bot.print(2, `${cyan('Discord')} ++ Loaded event ${green(event.extData.name)} in ${yellow(`${(Date.now() - startTimestamp)}ms`)}`);
|
||||
|
||||
this.execute(event);
|
||||
});
|
||||
|
||||
this.bot.print(2, `${cyan('Discord')} >> Successfully loaded ${green(this.bot.events.size)} events`);
|
||||
return { success: true, directory: directory, events: this.bot.events };
|
||||
}
|
||||
};
|
||||
34
src/core/registry/Discord/Locales.js
Normal file
34
src/core/registry/Discord/Locales.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const { safeLoad } = require('js-yaml');
|
||||
const { cyan, red } = require('../../../util/colors');
|
||||
const { readdirSync, readFileSync } = require('fs');
|
||||
|
||||
module.exports = class LocaleRegistry {
|
||||
constructor(bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
async run(directory) {
|
||||
const locales = await readdirSync(directory);
|
||||
|
||||
for (let i = 0; i < locales.length; i++) {
|
||||
const files = await readdirSync(`${directory}/${locales[i]}`);
|
||||
files.forEach((f) => {
|
||||
try {
|
||||
if (f.endsWith('.yml') || f.endsWith('.yaml') ) {
|
||||
const l = safeLoad(readFileSync(`${directory}/${locales[i]}/${f}`));
|
||||
|
||||
if (f.startsWith('strings')) {
|
||||
this.bot.locales.set(l['translation']['code'].toLowerCase(), l);
|
||||
this.bot.localeDic.push(l['translation']['code']);
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
process.handleError(ex, cyan('Discord'), 'LoadError');
|
||||
return { success: false, err: ex };
|
||||
}
|
||||
|
||||
return { success: true, dictionary: this.bot.localeDic, map: this.bot.localeMap };
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
13
src/events/Discord/disconnected.js
Normal file
13
src/events/Discord/disconnected.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const { DiscordEvent } = require('../../core');
|
||||
|
||||
const { green, cyan } = require('../../util/colors');
|
||||
|
||||
module.exports = class Disconnect extends DiscordEvent {
|
||||
constructor(bot) {
|
||||
super(bot, { name: 'disconnect' });
|
||||
}
|
||||
|
||||
emit() {
|
||||
this.bot.print(1, `${cyan('Discord')} >> All websockets disconnected from ${green(`${this.bot.user.username}#${this.bot.user.discriminator}`)}`);
|
||||
}
|
||||
};
|
||||
11
src/events/Discord/messageCreate.js
Normal file
11
src/events/Discord/messageCreate.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const { DiscordEvent } = require('../../core');
|
||||
|
||||
module.exports = class MessageCreate extends DiscordEvent {
|
||||
constructor(bot) {
|
||||
super(bot, { name: 'messageCreate' });
|
||||
}
|
||||
|
||||
async emit(msg) {
|
||||
this.bot.commandRegistry.handleCommand(msg);
|
||||
}
|
||||
};
|
||||
12
src/events/Discord/messageDelete.js
Normal file
12
src/events/Discord/messageDelete.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const { DiscordEvent } = require('../../core');
|
||||
|
||||
module.exports = class MessageDelete extends DiscordEvent {
|
||||
constructor(bot) {
|
||||
super(bot, { name: 'messageDelete' });
|
||||
}
|
||||
|
||||
emit(msg) {
|
||||
if (!msg.channel.guild || !msg.author || !this.bot.ready) return;
|
||||
this.bot.cache.set(`${msg.channel.id}:SNIPE`, msg);
|
||||
}
|
||||
};
|
||||
32
src/events/Discord/ready.js
Normal file
32
src/events/Discord/ready.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const { DiscordEvent } = require('../../core');
|
||||
|
||||
const { green, cyan } = require('../../util/colors');
|
||||
|
||||
module.exports = class Ready extends DiscordEvent {
|
||||
constructor(bot) {
|
||||
super(bot, { name: 'ready' });
|
||||
}
|
||||
|
||||
emit() {
|
||||
this.bot.print(1, `${cyan( 'Discord' )} >> All websockets connected to ${green(`${this.bot.user.username}#${this.bot.user.discriminator}`)}`);
|
||||
|
||||
if (this.bot.conf['discord']['playing']) {
|
||||
this.bot.editStatus({
|
||||
url : this.bot.conf['discord']['playing']['url'] || null,
|
||||
type : this.bot.conf['discord']['playing']['type'] || 3,
|
||||
name : this.bot.conf['discord']['playing']['name'] || 'Wump',
|
||||
status : this.bot.conf['discord']['playing']['status'] || 'online'
|
||||
});
|
||||
}
|
||||
|
||||
// Cache flushing if entry isn't used within `flushTime` minutes
|
||||
const flushTime = 1800000;
|
||||
setInterval(() => {
|
||||
const uCache = this.bot.cache.get('users') || [];
|
||||
const gCache = this.bot.cache.get('guilds') || [];
|
||||
|
||||
uCache.forEach((v, _) => (new Date(v.entryAge) <= new Date(new Date() - flushTime)) ? uCache.splice(_, 1) : undefined);
|
||||
gCache.forEach((v, _) => (new Date(v.entryAge) <= new Date(new Date() - flushTime)) ? gCache.splice(_, 1) : undefined);
|
||||
}, flushTime);
|
||||
}
|
||||
};
|
||||
94
src/main.js
Normal file
94
src/main.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @name Wunp
|
||||
* @author Wessel "wesselgame" T < discord@go2it.eu >
|
||||
* @license GPL-3.0
|
||||
* @version 0.1.1
|
||||
* @description A multi-functional bot written in Node.js
|
||||
*/
|
||||
|
||||
console.clear();
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
const { DiscordClient } = require('./core');
|
||||
|
||||
const { print } = require('./util/Util');
|
||||
const { safeLoad } = require('js-yaml');
|
||||
const { globalize } = require('nabbit');
|
||||
const { join: pJoin } = require('path');
|
||||
const { readFileSync } = require('fs');
|
||||
const { magenta, green, cyan, yellow, red } = require('./util/colors');
|
||||
|
||||
globalize();
|
||||
let Discord, Database;
|
||||
|
||||
process.argv = require('larg')(process.argv.slice(2));
|
||||
process.hash = String.string(Math.floor(Math.random() * 5) + 3);
|
||||
|
||||
process.handleError = (err, name, type, exit = false, custom = false) => {
|
||||
if (!custom) print(0, `${type ? type : green('Master')} !! ${name ? name : err.name ? err.name : 'Error'} -\n${red(`${err.message && err.stack ? `${err.message}\n${err.stack}` : err}`)}`);
|
||||
else print(0, custom);
|
||||
|
||||
if (exit) process.exit(process.type(exit) === 8 ? exit : 1);
|
||||
};
|
||||
|
||||
print(3, `${magenta('Debug')} >> Loading configuration files...`);
|
||||
const pkg = require('../package.json');
|
||||
const ico = safeLoad(readFileSync( 'assets/config/emotes.yml'));
|
||||
const col = safeLoad(readFileSync( 'assets/config/colors.yml'));
|
||||
const conf = safeLoad(readFileSync('application.yml'));
|
||||
print(3, `${magenta('Debug')} >> Configuration files loaded`);
|
||||
|
||||
process.on('uncaughtException', process.handleError);
|
||||
process.on('unhandledRejection', process.handleError);
|
||||
process.on('SIGINT', () => {
|
||||
if (Database) {
|
||||
try {
|
||||
print(2, `${yellow('Database')} >> Closing connection from database...`);
|
||||
mongoose.connection.close();
|
||||
} catch (ex) {
|
||||
print(2, `${yellow('Database')} >> Failed to close connection from database - ${red(`${ex.message}\n${ex.stack}`)}`);
|
||||
process.exit(1);
|
||||
} finally { print(2, `${yellow('Database')} >> ${green('Connection from database closed')}`); }
|
||||
}
|
||||
|
||||
if (Discord) {
|
||||
try {
|
||||
print(2, `${cyan('Discord')} >> Disconnecting websockets...`);
|
||||
Discord.destroy(0);
|
||||
} catch (ex) {
|
||||
print(2, `${cyan('Discord' )} >> Failed to disconnect websockets - ${red(`${ex.message}\n${ex.stack}`)}`);
|
||||
process.exit(1);
|
||||
} finally { print(2, `${cyan('Discord')} >> ${green('Connection from websockets closed')}`); }
|
||||
}
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
(async() => {
|
||||
if (!conf['db']) process.handleError(undefined, undefined, undefined, 1, red('!! Failed to start: No database found !!'));
|
||||
print(2, `${yellow('Database' )} >> Connecting to database...`);
|
||||
Database = mongoose.connect(conf['db'], { useNewUrlParser: true });
|
||||
mongoose.connection.on('error', process.handleError);
|
||||
print(2, `${yellow('Database')} >> ${green('Connected to database')}` );
|
||||
})();
|
||||
|
||||
|
||||
if (conf['discord']['enabled']) {
|
||||
print(2, `${cyan('Discord')} >> Creating client...`);
|
||||
Discord = new DiscordClient(conf['discord']['token'], {
|
||||
clientOptions : {
|
||||
maxShards : 'auto',
|
||||
getAllUsers : false,
|
||||
autoreconnect: true
|
||||
},
|
||||
|
||||
ua : `${pkg.displayName}/${pkg.version}/${conf['nightly'] ? 'nightly' : 'distribution'}`,
|
||||
db : mongoose,
|
||||
pkg : pkg,
|
||||
colors: col,
|
||||
emojis: ico,
|
||||
config: conf
|
||||
});
|
||||
|
||||
print(2, `${cyan('Discord')} >> Client created, launching client...`);
|
||||
Discord.launch(pJoin(__dirname, 'events', 'Discord'), pJoin(__dirname, 'commands', 'Discord'), pJoin(__dirname, 'assets', 'i18n'), pJoin(__dirname, 'schedulers', 'Discord'));
|
||||
}
|
||||
23
src/util/Collection.js
Normal file
23
src/util/Collection.js
Normal file
@@ -0,0 +1,23 @@
|
||||
module.exports = class WumpCollection extends Map {
|
||||
constructor() { super(); }
|
||||
|
||||
filter(callback) {
|
||||
const all = Array.from(this.values());
|
||||
let result = [];
|
||||
for (let i = 0; i < all.length; i++) {
|
||||
if (callback(all[i])) result.push(all[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
map(callback) {
|
||||
let result = [];
|
||||
const values = Array.from(this.values());
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
result.push(callback(values[i]));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
47
src/util/Util.js
Normal file
47
src/util/Util.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const fs = require('fs');
|
||||
const yaml = require('js-yaml');
|
||||
const moment = require('moment');
|
||||
const { strip } = require('../util/colors');
|
||||
|
||||
const conf = yaml.safeLoad(fs.readFileSync('application.yml', { encoding: 'utf8' }));
|
||||
|
||||
module.exports = class WumpUtil {
|
||||
static print(lvl = 0, msg = '') {
|
||||
const log = `tmp\\log\\${moment(new Date).format('DD[-]MM[-]YYYY')}.log`;
|
||||
|
||||
fs.mkdir('tmp', 777, (err) => { if (err && err.code !== 'EEXIST') throw err; });
|
||||
fs.mkdir('tmp\\log', 777, (err) => { if (err && err.code !== 'EEXIST') throw err; });
|
||||
|
||||
switch (lvl) {
|
||||
case 1 && conf['debug'] && conf['debug'] >= 1:
|
||||
console.log(`[${moment(new Date).format( 'HH[:]mm[:]ss' )} / ${process.hash}] ${msg}`);
|
||||
fs.appendFileSync(log, `[${moment(new Date).format('HH[:]mm[:]ss')} / ${process.hash}] ${strip(msg)}\r\n`);
|
||||
break;
|
||||
case 2 && conf['debug'] && conf['debug'] >= 2:
|
||||
console.log(`[${moment(new Date).format( 'HH[:]mm[:]ss' )} / ${process.hash}] ${msg}`);
|
||||
fs.appendFileSync(log, `[${moment(new Date).format('HH[:]mm[:]ss')} / ${process.hash}] ${strip(msg)}\r\n`);
|
||||
break;
|
||||
case 3 && conf['debug'] && conf['debug'] >= 3:
|
||||
console.log(`[${moment(new Date).format( 'HH[:]mm[:]ss' )} / ${process.hash}] ${msg}`);
|
||||
fs.appendFileSync(log, `[${moment(new Date).format('HH[:]mm[:]ss')} / ${process.hash}] ${strip(msg)}\r\n`);
|
||||
break;
|
||||
case 4 && conf['debug'] && conf['debug'] >= 4:
|
||||
console.log(`[${moment(new Date).format( 'HH[:]mm[:]ss' )} / ${process.hash}] ${msg}`);
|
||||
fs.appendFileSync(log, `[${moment(new Date).format('HH[:]mm[:]ss')} / ${process.hash}] ${strip(msg)}\r\n`);
|
||||
break;
|
||||
default:
|
||||
console.log(`[${moment(new Date).format( 'HH[:]mm[:]ss' )} / ${process.hash}] ${msg}`);
|
||||
fs.appendFileSync(log, `[${moment(new Date).format('HH[:]mm[:]ss')} / ${process.hash}] ${strip(msg)}\r\n`);
|
||||
}
|
||||
}
|
||||
|
||||
static getPercentage(o, n) { return ( ( o - n ) / o ) * 100; }
|
||||
|
||||
static shorten(t = '', m = 2000) { return t.length > m ? `${t.substr( 0, m - 3 )}...` : t; }
|
||||
|
||||
static escapeMarkdown(t = '', oc = false, oi = false) {
|
||||
if (oc) return t.replace(/```/g, '\u200b`\u200b`\u200b`');
|
||||
if (oi) return t.replace(/\\([`\\])/g, '$1').replace(/([`\\])/g, '\u200b$1');
|
||||
return t.replace(/([*_`~\\])/g , '\u200b$1').replace(/\\([*_`~\\])/g, '$1');
|
||||
}
|
||||
};
|
||||
4
src/util/colors/index.js
Normal file
4
src/util/colors/index.js
Normal file
@@ -0,0 +1,4 @@
|
||||
var colors = require('./lib/colors');
|
||||
module['exports'] = colors;
|
||||
|
||||
require('./lib/extendStringPrototype')();
|
||||
201
src/util/colors/lib/colors.js
Normal file
201
src/util/colors/lib/colors.js
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Original Library
|
||||
- Copyright (c) Marak Squires
|
||||
|
||||
Additional functionality
|
||||
- Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var colors = {};
|
||||
module['exports'] = colors;
|
||||
|
||||
colors.themes = {};
|
||||
|
||||
var util = require('util');
|
||||
var ansiStyles = colors.styles = require('./styles');
|
||||
var defineProps = Object.defineProperties;
|
||||
var newLineRegex = new RegExp(/[\r\n]+/g);
|
||||
|
||||
colors.supportsColor = require('./system/supports-colors').supportsColor;
|
||||
|
||||
if (typeof colors.enabled === 'undefined') {
|
||||
colors.enabled = colors.supportsColor() !== false;
|
||||
}
|
||||
|
||||
colors.enable = function() {
|
||||
colors.enabled = true;
|
||||
};
|
||||
|
||||
colors.disable = function() {
|
||||
colors.enabled = false;
|
||||
};
|
||||
|
||||
colors.stripColors = colors.strip = function(str) {
|
||||
return ('' + str).replace(/\x1B\[\d+m/g, '');
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
var stylize = colors.stylize = function stylize(str, style) {
|
||||
if (!colors.enabled) {
|
||||
return str+'';
|
||||
}
|
||||
|
||||
return ansiStyles[style].open + str + ansiStyles[style].close;
|
||||
};
|
||||
|
||||
var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
|
||||
var escapeStringRegexp = function(str) {
|
||||
if (typeof str !== 'string') {
|
||||
throw new TypeError('Expected a string');
|
||||
}
|
||||
return str.replace(matchOperatorsRe, '\\$&');
|
||||
};
|
||||
|
||||
function build(_styles) {
|
||||
var builder = function builder() {
|
||||
return applyStyle.apply(builder, arguments);
|
||||
};
|
||||
builder._styles = _styles;
|
||||
// __proto__ is used because we must return a function, but there is
|
||||
// no way to create a function with a different prototype.
|
||||
builder.__proto__ = proto;
|
||||
return builder;
|
||||
}
|
||||
|
||||
var styles = (function() {
|
||||
var ret = {};
|
||||
ansiStyles.grey = ansiStyles.gray;
|
||||
Object.keys(ansiStyles).forEach(function(key) {
|
||||
ansiStyles[key].closeRe =
|
||||
new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
|
||||
ret[key] = {
|
||||
get: function() {
|
||||
return build(this._styles.concat(key));
|
||||
}
|
||||
};
|
||||
});
|
||||
return ret;
|
||||
})();
|
||||
|
||||
var proto = defineProps(function colors() {}, styles);
|
||||
|
||||
function applyStyle() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
|
||||
var str = args.map(function(arg) {
|
||||
if (arg !== undefined && arg.constructor === String) {
|
||||
return arg;
|
||||
} else {
|
||||
return util.inspect(arg);
|
||||
}
|
||||
}).join(' ');
|
||||
|
||||
if (!colors.enabled || !str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
var newLinesPresent = str.indexOf('\n') != -1;
|
||||
|
||||
var nestedStyles = this._styles;
|
||||
|
||||
var i = nestedStyles.length;
|
||||
while (i--) {
|
||||
var code = ansiStyles[nestedStyles[i]];
|
||||
str = code.open + str.replace(code.closeRe, code.open) + code.close;
|
||||
if (newLinesPresent) {
|
||||
str = str.replace(newLineRegex, function(match) {
|
||||
return code.close + match + code.open;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
colors.setTheme = function(theme) {
|
||||
if (typeof theme === 'string') {
|
||||
console.log('colors.setTheme now only accepts an object, not a string. ' +
|
||||
'If you are trying to set a theme from a file, it is now your (the ' +
|
||||
'caller\'s) responsibility to require the file. The old syntax ' +
|
||||
'looked like colors.setTheme(__dirname + ' +
|
||||
'\'/../themes/generic-logging.js\'); The new syntax looks like '+
|
||||
'colors.setTheme(require(__dirname + ' +
|
||||
'\'/../themes/generic-logging.js\'));');
|
||||
return;
|
||||
}
|
||||
for (var style in theme) {
|
||||
(function(style) {
|
||||
colors[style] = function(str) {
|
||||
if (typeof theme[style] === 'object') {
|
||||
var out = str;
|
||||
for (var i in theme[style]) {
|
||||
out = colors[theme[style][i]](out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
return colors[theme[style]](str);
|
||||
};
|
||||
})(style);
|
||||
}
|
||||
};
|
||||
|
||||
function init() {
|
||||
var ret = {};
|
||||
Object.keys(styles).forEach(function(name) {
|
||||
ret[name] = {
|
||||
get: function() {
|
||||
return build([name]);
|
||||
}
|
||||
};
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
var sequencer = function sequencer(map, str) {
|
||||
var exploded = str.split('');
|
||||
exploded = exploded.map(map);
|
||||
return exploded.join('');
|
||||
};
|
||||
|
||||
// custom formatter methods
|
||||
colors.trap = require('./custom/trap');
|
||||
colors.zalgo = require('./custom/zalgo');
|
||||
|
||||
// maps
|
||||
colors.maps = {};
|
||||
colors.maps.america = require('./maps/america')(colors);
|
||||
colors.maps.zebra = require('./maps/zebra')(colors);
|
||||
colors.maps.rainbow = require('./maps/rainbow')(colors);
|
||||
colors.maps.random = require('./maps/random')(colors);
|
||||
|
||||
for (var map in colors.maps) {
|
||||
(function(map) {
|
||||
colors[map] = function(str) {
|
||||
return sequencer(colors.maps[map], str);
|
||||
};
|
||||
})(map);
|
||||
}
|
||||
|
||||
defineProps(colors, init());
|
||||
46
src/util/colors/lib/custom/trap.js
Normal file
46
src/util/colors/lib/custom/trap.js
Normal file
@@ -0,0 +1,46 @@
|
||||
module['exports'] = function runTheTrap(text, options) {
|
||||
var result = '';
|
||||
text = text || 'Run the trap, drop the bass';
|
||||
text = text.split('');
|
||||
var trap = {
|
||||
a: ['\u0040', '\u0104', '\u023a', '\u0245', '\u0394', '\u039b', '\u0414'],
|
||||
b: ['\u00df', '\u0181', '\u0243', '\u026e', '\u03b2', '\u0e3f'],
|
||||
c: ['\u00a9', '\u023b', '\u03fe'],
|
||||
d: ['\u00d0', '\u018a', '\u0500', '\u0501', '\u0502', '\u0503'],
|
||||
e: ['\u00cb', '\u0115', '\u018e', '\u0258', '\u03a3', '\u03be', '\u04bc',
|
||||
'\u0a6c'],
|
||||
f: ['\u04fa'],
|
||||
g: ['\u0262'],
|
||||
h: ['\u0126', '\u0195', '\u04a2', '\u04ba', '\u04c7', '\u050a'],
|
||||
i: ['\u0f0f'],
|
||||
j: ['\u0134'],
|
||||
k: ['\u0138', '\u04a0', '\u04c3', '\u051e'],
|
||||
l: ['\u0139'],
|
||||
m: ['\u028d', '\u04cd', '\u04ce', '\u0520', '\u0521', '\u0d69'],
|
||||
n: ['\u00d1', '\u014b', '\u019d', '\u0376', '\u03a0', '\u048a'],
|
||||
o: ['\u00d8', '\u00f5', '\u00f8', '\u01fe', '\u0298', '\u047a', '\u05dd',
|
||||
'\u06dd', '\u0e4f'],
|
||||
p: ['\u01f7', '\u048e'],
|
||||
q: ['\u09cd'],
|
||||
r: ['\u00ae', '\u01a6', '\u0210', '\u024c', '\u0280', '\u042f'],
|
||||
s: ['\u00a7', '\u03de', '\u03df', '\u03e8'],
|
||||
t: ['\u0141', '\u0166', '\u0373'],
|
||||
u: ['\u01b1', '\u054d'],
|
||||
v: ['\u05d8'],
|
||||
w: ['\u0428', '\u0460', '\u047c', '\u0d70'],
|
||||
x: ['\u04b2', '\u04fe', '\u04fc', '\u04fd'],
|
||||
y: ['\u00a5', '\u04b0', '\u04cb'],
|
||||
z: ['\u01b5', '\u0240'],
|
||||
};
|
||||
text.forEach(function(c) {
|
||||
c = c.toLowerCase();
|
||||
var chars = trap[c] || [' '];
|
||||
var rand = Math.floor(Math.random() * chars.length);
|
||||
if (typeof trap[c] !== 'undefined') {
|
||||
result += trap[c][rand];
|
||||
} else {
|
||||
result += c;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
110
src/util/colors/lib/custom/zalgo.js
Normal file
110
src/util/colors/lib/custom/zalgo.js
Normal file
@@ -0,0 +1,110 @@
|
||||
// please no
|
||||
module['exports'] = function zalgo(text, options) {
|
||||
text = text || ' he is here ';
|
||||
var soul = {
|
||||
'up': [
|
||||
'̍', '̎', '̄', '̅',
|
||||
'̿', '̑', '̆', '̐',
|
||||
'͒', '͗', '͑', '̇',
|
||||
'̈', '̊', '͂', '̓',
|
||||
'̈', '͊', '͋', '͌',
|
||||
'̃', '̂', '̌', '͐',
|
||||
'̀', '́', '̋', '̏',
|
||||
'̒', '̓', '̔', '̽',
|
||||
'̉', 'ͣ', 'ͤ', 'ͥ',
|
||||
'ͦ', 'ͧ', 'ͨ', 'ͩ',
|
||||
'ͪ', 'ͫ', 'ͬ', 'ͭ',
|
||||
'ͮ', 'ͯ', '̾', '͛',
|
||||
'͆', '̚',
|
||||
],
|
||||
'down': [
|
||||
'̖', '̗', '̘', '̙',
|
||||
'̜', '̝', '̞', '̟',
|
||||
'̠', '̤', '̥', '̦',
|
||||
'̩', '̪', '̫', '̬',
|
||||
'̭', '̮', '̯', '̰',
|
||||
'̱', '̲', '̳', '̹',
|
||||
'̺', '̻', '̼', 'ͅ',
|
||||
'͇', '͈', '͉', '͍',
|
||||
'͎', '͓', '͔', '͕',
|
||||
'͖', '͙', '͚', '̣',
|
||||
],
|
||||
'mid': [
|
||||
'̕', '̛', '̀', '́',
|
||||
'͘', '̡', '̢', '̧',
|
||||
'̨', '̴', '̵', '̶',
|
||||
'͜', '͝', '͞',
|
||||
'͟', '͠', '͢', '̸',
|
||||
'̷', '͡', ' ҉',
|
||||
],
|
||||
};
|
||||
var all = [].concat(soul.up, soul.down, soul.mid);
|
||||
|
||||
function randomNumber(range) {
|
||||
var r = Math.floor(Math.random() * range);
|
||||
return r;
|
||||
}
|
||||
|
||||
function isChar(character) {
|
||||
var bool = false;
|
||||
all.filter(function(i) {
|
||||
bool = (i === character);
|
||||
});
|
||||
return bool;
|
||||
}
|
||||
|
||||
|
||||
function heComes(text, options) {
|
||||
var result = '';
|
||||
var counts;
|
||||
var l;
|
||||
options = options || {};
|
||||
options['up'] =
|
||||
typeof options['up'] !== 'undefined' ? options['up'] : true;
|
||||
options['mid'] =
|
||||
typeof options['mid'] !== 'undefined' ? options['mid'] : true;
|
||||
options['down'] =
|
||||
typeof options['down'] !== 'undefined' ? options['down'] : true;
|
||||
options['size'] =
|
||||
typeof options['size'] !== 'undefined' ? options['size'] : 'maxi';
|
||||
text = text.split('');
|
||||
for (l in text) {
|
||||
if (isChar(l)) {
|
||||
continue;
|
||||
}
|
||||
result = result + text[l];
|
||||
counts = {'up': 0, 'down': 0, 'mid': 0};
|
||||
switch (options.size) {
|
||||
case 'mini':
|
||||
counts.up = randomNumber(8);
|
||||
counts.mid = randomNumber(2);
|
||||
counts.down = randomNumber(8);
|
||||
break;
|
||||
case 'maxi':
|
||||
counts.up = randomNumber(16) + 3;
|
||||
counts.mid = randomNumber(4) + 1;
|
||||
counts.down = randomNumber(64) + 3;
|
||||
break;
|
||||
default:
|
||||
counts.up = randomNumber(8) + 1;
|
||||
counts.mid = randomNumber(6) / 2;
|
||||
counts.down = randomNumber(8) + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
var arr = ['up', 'mid', 'down'];
|
||||
for (var d in arr) {
|
||||
var index = arr[d];
|
||||
for (var i = 0; i <= counts[index]; i++) {
|
||||
if (options[index]) {
|
||||
result = result + soul[index][randomNumber(soul[index].length)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// don't summon him
|
||||
return heComes(text, options);
|
||||
};
|
||||
|
||||
104
src/util/colors/lib/extendStringPrototype.js
Normal file
104
src/util/colors/lib/extendStringPrototype.js
Normal file
@@ -0,0 +1,104 @@
|
||||
var colors = require('./colors');
|
||||
|
||||
module['exports'] = function() {
|
||||
//
|
||||
// Extends prototype of native string object to allow for "foo".red syntax
|
||||
//
|
||||
var addProperty = function(color, func) {
|
||||
String.prototype.__defineGetter__(color, func);
|
||||
};
|
||||
|
||||
addProperty('strip', function() {
|
||||
return colors.strip(this);
|
||||
});
|
||||
|
||||
addProperty('stripColors', function() {
|
||||
return colors.strip(this);
|
||||
});
|
||||
|
||||
addProperty('trap', function() {
|
||||
return colors.trap(this);
|
||||
});
|
||||
|
||||
addProperty('zalgo', function() {
|
||||
return colors.zalgo(this);
|
||||
});
|
||||
|
||||
addProperty('zebra', function() {
|
||||
return colors.zebra(this);
|
||||
});
|
||||
|
||||
addProperty('rainbow', function() {
|
||||
return colors.rainbow(this);
|
||||
});
|
||||
|
||||
addProperty('random', function() {
|
||||
return colors.random(this);
|
||||
});
|
||||
|
||||
addProperty('america', function() {
|
||||
return colors.america(this);
|
||||
});
|
||||
|
||||
//
|
||||
// Iterate through all default styles and colors
|
||||
//
|
||||
var x = Object.keys(colors.styles);
|
||||
x.forEach(function(style) {
|
||||
addProperty(style, function() {
|
||||
return colors.stylize(this, style);
|
||||
});
|
||||
});
|
||||
|
||||
function applyTheme(theme) {
|
||||
//
|
||||
// Remark: This is a list of methods that exist
|
||||
// on String that you should not overwrite.
|
||||
//
|
||||
var stringPrototypeBlacklist = [
|
||||
'__defineGetter__', '__defineSetter__', '__lookupGetter__',
|
||||
'__lookupSetter__', 'charAt', 'constructor', 'hasOwnProperty',
|
||||
'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString',
|
||||
'valueOf', 'charCodeAt', 'indexOf', 'lastIndexOf', 'length',
|
||||
'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice',
|
||||
'split', 'substring', 'toLocaleLowerCase', 'toLocaleUpperCase',
|
||||
'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight',
|
||||
];
|
||||
|
||||
Object.keys(theme).forEach(function(prop) {
|
||||
if (stringPrototypeBlacklist.indexOf(prop) !== -1) {
|
||||
console.log('warn: '.red + ('String.prototype' + prop).magenta +
|
||||
' is probably something you don\'t want to override. ' +
|
||||
'Ignoring style name');
|
||||
} else {
|
||||
if (typeof(theme[prop]) === 'string') {
|
||||
colors[prop] = colors[theme[prop]];
|
||||
} else {
|
||||
var tmp = colors[theme[prop][0]];
|
||||
for (var t = 1; t < theme[prop].length; t++) {
|
||||
tmp = tmp[theme[prop][t]];
|
||||
}
|
||||
colors[prop] = tmp;
|
||||
}
|
||||
addProperty(prop, function() {
|
||||
return colors[prop](this);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
colors.setTheme = function(theme) {
|
||||
if (typeof theme === 'string') {
|
||||
console.log('colors.setTheme now only accepts an object, not a string. ' +
|
||||
'If you are trying to set a theme from a file, it is now your (the ' +
|
||||
'caller\'s) responsibility to require the file. The old syntax ' +
|
||||
'looked like colors.setTheme(__dirname + ' +
|
||||
'\'/../themes/generic-logging.js\'); The new syntax looks like '+
|
||||
'colors.setTheme(require(__dirname + ' +
|
||||
'\'/../themes/generic-logging.js\'));');
|
||||
return;
|
||||
} else {
|
||||
applyTheme(theme);
|
||||
}
|
||||
};
|
||||
};
|
||||
10
src/util/colors/lib/maps/america.js
Normal file
10
src/util/colors/lib/maps/america.js
Normal file
@@ -0,0 +1,10 @@
|
||||
module['exports'] = function(colors) {
|
||||
return function(letter, i, exploded) {
|
||||
if (letter === ' ') return letter;
|
||||
switch (i%3) {
|
||||
case 0: return colors.red(letter);
|
||||
case 1: return colors.white(letter);
|
||||
case 2: return colors.blue(letter);
|
||||
}
|
||||
};
|
||||
};
|
||||
12
src/util/colors/lib/maps/rainbow.js
Normal file
12
src/util/colors/lib/maps/rainbow.js
Normal file
@@ -0,0 +1,12 @@
|
||||
module['exports'] = function(colors) {
|
||||
// RoY G BiV
|
||||
var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta'];
|
||||
return function(letter, i, exploded) {
|
||||
if (letter === ' ') {
|
||||
return letter;
|
||||
} else {
|
||||
return colors[rainbowColors[i++ % rainbowColors.length]](letter);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
10
src/util/colors/lib/maps/random.js
Normal file
10
src/util/colors/lib/maps/random.js
Normal file
@@ -0,0 +1,10 @@
|
||||
module['exports'] = function(colors) {
|
||||
var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green',
|
||||
'blue', 'white', 'cyan', 'magenta'];
|
||||
return function(letter, i, exploded) {
|
||||
return letter === ' ' ? letter :
|
||||
colors[
|
||||
available[Math.round(Math.random() * (available.length - 2))]
|
||||
](letter);
|
||||
};
|
||||
};
|
||||
5
src/util/colors/lib/maps/zebra.js
Normal file
5
src/util/colors/lib/maps/zebra.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module['exports'] = function(colors) {
|
||||
return function(letter, i, exploded) {
|
||||
return i % 2 === 0 ? letter : colors.inverse(letter);
|
||||
};
|
||||
};
|
||||
77
src/util/colors/lib/styles.js
Normal file
77
src/util/colors/lib/styles.js
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
var styles = {};
|
||||
module['exports'] = styles;
|
||||
|
||||
var codes = {
|
||||
reset: [0, 0],
|
||||
|
||||
bold: [1, 22],
|
||||
dim: [2, 22],
|
||||
italic: [3, 23],
|
||||
underline: [4, 24],
|
||||
inverse: [7, 27],
|
||||
hidden: [8, 28],
|
||||
strikethrough: [9, 29],
|
||||
|
||||
black: [30, 39],
|
||||
red: [31, 39],
|
||||
green: [32, 39],
|
||||
yellow: [33, 39],
|
||||
blue: [34, 39],
|
||||
magenta: [35, 39],
|
||||
cyan: [36, 39],
|
||||
white: [37, 39],
|
||||
gray: [90, 39],
|
||||
grey: [90, 39],
|
||||
|
||||
bgBlack: [40, 49],
|
||||
bgRed: [41, 49],
|
||||
bgGreen: [42, 49],
|
||||
bgYellow: [43, 49],
|
||||
bgBlue: [44, 49],
|
||||
bgMagenta: [45, 49],
|
||||
bgCyan: [46, 49],
|
||||
bgWhite: [47, 49],
|
||||
|
||||
// legacy styles for colors pre v1.0.0
|
||||
blackBG: [40, 49],
|
||||
redBG: [41, 49],
|
||||
greenBG: [42, 49],
|
||||
yellowBG: [43, 49],
|
||||
blueBG: [44, 49],
|
||||
magentaBG: [45, 49],
|
||||
cyanBG: [46, 49],
|
||||
whiteBG: [47, 49],
|
||||
|
||||
};
|
||||
|
||||
Object.keys(codes).forEach(function(key) {
|
||||
var val = codes[key];
|
||||
var style = styles[key] = [];
|
||||
style.open = '\u001b[' + val[0] + 'm';
|
||||
style.close = '\u001b[' + val[1] + 'm';
|
||||
});
|
||||
35
src/util/colors/lib/system/has-flag.js
Normal file
35
src/util/colors/lib/system/has-flag.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function(flag, argv) {
|
||||
argv = argv || process.argv;
|
||||
|
||||
var terminatorPos = argv.indexOf('--');
|
||||
var prefix = /^-{1,2}/.test(flag) ? '' : '--';
|
||||
var pos = argv.indexOf(prefix + flag);
|
||||
|
||||
return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
|
||||
};
|
||||
151
src/util/colors/lib/system/supports-colors.js
Normal file
151
src/util/colors/lib/system/supports-colors.js
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var os = require('os');
|
||||
var hasFlag = require('./has-flag.js');
|
||||
|
||||
var env = process.env;
|
||||
|
||||
var forceColor = void 0;
|
||||
if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) {
|
||||
forceColor = false;
|
||||
} else if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true')
|
||||
|| hasFlag('color=always')) {
|
||||
forceColor = true;
|
||||
}
|
||||
if ('FORCE_COLOR' in env) {
|
||||
forceColor = env.FORCE_COLOR.length === 0
|
||||
|| parseInt(env.FORCE_COLOR, 10) !== 0;
|
||||
}
|
||||
|
||||
function translateLevel(level) {
|
||||
if (level === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return {
|
||||
level: level,
|
||||
hasBasic: true,
|
||||
has256: level >= 2,
|
||||
has16m: level >= 3,
|
||||
};
|
||||
}
|
||||
|
||||
function supportsColor(stream) {
|
||||
if (forceColor === false) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hasFlag('color=16m') || hasFlag('color=full')
|
||||
|| hasFlag('color=truecolor')) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (hasFlag('color=256')) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (stream && !stream.isTTY && forceColor !== true) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var min = forceColor ? 1 : 0;
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
// Node.js 7.5.0 is the first version of Node.js to include a patch to
|
||||
// libuv that enables 256 color output on Windows. Anything earlier and it
|
||||
// won't work. However, here we target Node.js 8 at minimum as it is an LTS
|
||||
// release, and Node.js 7 is not. Windows 10 build 10586 is the first
|
||||
// Windows release that supports 256 colors. Windows 10 build 14931 is the
|
||||
// first release that supports 16m/TrueColor.
|
||||
var osRelease = os.release().split('.');
|
||||
if (Number(process.versions.node.split('.')[0]) >= 8
|
||||
&& Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
||||
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ('CI' in env) {
|
||||
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(function(sign) {
|
||||
return sign in env;
|
||||
}) || env.CI_NAME === 'codeship') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
if ('TEAMCITY_VERSION' in env) {
|
||||
return (/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0
|
||||
);
|
||||
}
|
||||
|
||||
if ('TERM_PROGRAM' in env) {
|
||||
var version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
|
||||
|
||||
switch (env.TERM_PROGRAM) {
|
||||
case 'iTerm.app':
|
||||
return version >= 3 ? 3 : 2;
|
||||
case 'Hyper':
|
||||
return 3;
|
||||
case 'Apple_Terminal':
|
||||
return 2;
|
||||
// No default
|
||||
}
|
||||
}
|
||||
|
||||
if (/-256(color)?$/i.test(env.TERM)) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ('COLORTERM' in env) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (env.TERM === 'dumb') {
|
||||
return min;
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
function getSupportLevel(stream) {
|
||||
var level = supportsColor(stream);
|
||||
return translateLevel(level);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
supportsColor: getSupportLevel,
|
||||
stdout: getSupportLevel(process.stdout),
|
||||
stderr: getSupportLevel(process.stderr),
|
||||
};
|
||||
1662
src/util/moment/format.js
Normal file
1662
src/util/moment/format.js
Normal file
File diff suppressed because it is too large
Load Diff
129
src/util/moment/shorten.js
Normal file
129
src/util/moment/shorten.js
Normal file
@@ -0,0 +1,129 @@
|
||||
if (typeof moment === "undefined" && typeof require === 'function') {
|
||||
var moment = require('moment');
|
||||
}
|
||||
|
||||
(function(moment) {
|
||||
var STRINGS = {
|
||||
nodiff: '',
|
||||
year: 'year',
|
||||
years: 'years',
|
||||
month: 'month',
|
||||
months: 'months',
|
||||
day: 'day',
|
||||
days: 'days',
|
||||
hour: 'hour',
|
||||
hours: 'hours',
|
||||
minute: 'minute',
|
||||
minutes: 'minutes',
|
||||
second: 'second',
|
||||
seconds: 'seconds',
|
||||
delimiter: ' '
|
||||
};
|
||||
|
||||
function pluralize(num, word) {
|
||||
return num + ' ' + STRINGS[word + (num === 1 ? '' : 's')];
|
||||
}
|
||||
|
||||
function buildStringFromValues(yDiff, mDiff, dDiff, hourDiff, minDiff, secDiff){
|
||||
var result = [];
|
||||
|
||||
if (yDiff) {
|
||||
result.push(pluralize(yDiff, 'year'));
|
||||
}
|
||||
if (mDiff) {
|
||||
result.push(pluralize(mDiff, 'month'));
|
||||
}
|
||||
if (dDiff) {
|
||||
result.push(pluralize(dDiff, 'day'));
|
||||
}
|
||||
if (hourDiff) {
|
||||
result.push(pluralize(hourDiff, 'hour'));
|
||||
}
|
||||
if (minDiff) {
|
||||
result.push(pluralize(minDiff, 'minute'));
|
||||
}
|
||||
if (secDiff) {
|
||||
result.push(pluralize(secDiff, 'second'));
|
||||
}
|
||||
|
||||
return result.join(STRINGS.delimiter);
|
||||
}
|
||||
|
||||
function buildValueObject(yDiff, mDiff, dDiff, hourDiff, minDiff, secDiff, firstDateWasLater) {
|
||||
return {
|
||||
"years" : yDiff,
|
||||
"months" : mDiff,
|
||||
"days" : dDiff,
|
||||
"hours" : hourDiff,
|
||||
"minutes" : minDiff,
|
||||
"seconds" : secDiff,
|
||||
"firstDateWasLater" : firstDateWasLater
|
||||
};
|
||||
}
|
||||
moment.fn.preciseDiff = function(d2, returnValueObject) {
|
||||
return moment.preciseDiff(this, d2, returnValueObject);
|
||||
};
|
||||
|
||||
moment.preciseDiff = function(d1, d2, returnValueObject) {
|
||||
var m1 = moment(d1), m2 = moment(d2), firstDateWasLater;
|
||||
|
||||
m1.add(m2.utcOffset() - m1.utcOffset(), 'minutes'); // shift timezone of m1 to m2
|
||||
|
||||
if (m1.isSame(m2)) {
|
||||
if (returnValueObject) {
|
||||
return buildValueObject(0, 0, 0, 0, 0, 0, false);
|
||||
} else {
|
||||
return STRINGS.nodiff;
|
||||
}
|
||||
}
|
||||
if (m1.isAfter(m2)) {
|
||||
var tmp = m1;
|
||||
m1 = m2;
|
||||
m2 = tmp;
|
||||
firstDateWasLater = true;
|
||||
} else {
|
||||
firstDateWasLater = false;
|
||||
}
|
||||
|
||||
var yDiff = m2.year() - m1.year();
|
||||
var mDiff = m2.month() - m1.month();
|
||||
var dDiff = m2.date() - m1.date();
|
||||
var hourDiff = m2.hour() - m1.hour();
|
||||
var minDiff = m2.minute() - m1.minute();
|
||||
var secDiff = m2.second() - m1.second();
|
||||
|
||||
if (secDiff < 0) {
|
||||
secDiff = 60 + secDiff;
|
||||
minDiff--;
|
||||
}
|
||||
if (minDiff < 0) {
|
||||
minDiff = 60 + minDiff;
|
||||
hourDiff--;
|
||||
}
|
||||
if (hourDiff < 0) {
|
||||
hourDiff = 24 + hourDiff;
|
||||
dDiff--;
|
||||
}
|
||||
if (dDiff < 0) {
|
||||
var daysInLastFullMonth = moment(m2.year() + '-' + (m2.month() + 1), "YYYY-MM").subtract(1, 'M').daysInMonth();
|
||||
if (daysInLastFullMonth < m1.date()) { // 31/01 -> 2/03
|
||||
dDiff = daysInLastFullMonth + dDiff + (m1.date() - daysInLastFullMonth);
|
||||
} else {
|
||||
dDiff = daysInLastFullMonth + dDiff;
|
||||
}
|
||||
mDiff--;
|
||||
}
|
||||
if (mDiff < 0) {
|
||||
mDiff = 12 + mDiff;
|
||||
yDiff--;
|
||||
}
|
||||
|
||||
if (returnValueObject) {
|
||||
return buildValueObject(yDiff, mDiff, dDiff, hourDiff, minDiff, secDiff, firstDateWasLater);
|
||||
} else {
|
||||
return buildStringFromValues(yDiff, mDiff, dDiff, hourDiff, minDiff, secDiff);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}(moment));
|
||||
94
src/util/normalize.js
Normal file
94
src/util/normalize.js
Normal file
@@ -0,0 +1,94 @@
|
||||
let changes;
|
||||
const defaultDiacriticsRemovalMap = [
|
||||
{ 'base': 'A', 'letters': /[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g},
|
||||
{ 'base': 'AA', 'letters': /[\uA732]/g},
|
||||
{ 'base': 'AE', 'letters': /[\u00C6\u01FC\u01E2]/g},
|
||||
{ 'base': 'AO', 'letters': /[\uA734]/g},
|
||||
{ 'base': 'AU', 'letters': /[\uA736]/g},
|
||||
{ 'base': 'AV', 'letters': /[\uA738\uA73A]/g},
|
||||
{ 'base': 'AY', 'letters': /[\uA73C]/g},
|
||||
{ 'base': 'B', 'letters': /[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},
|
||||
{ 'base': 'C', 'letters': /[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g},
|
||||
{ 'base': 'D', 'letters': /[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g},
|
||||
{ 'base': 'DZ', 'letters': /[\u01F1\u01C4]/g},
|
||||
{ 'base': 'Dz', 'letters': /[\u01F2\u01C5]/g},
|
||||
{ 'base': 'E', 'letters': /[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g},
|
||||
{ 'base': 'F', 'letters': /[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},
|
||||
{ 'base': 'G', 'letters': /[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g},
|
||||
{ 'base': 'H', 'letters': /[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g},
|
||||
{ 'base': 'I', 'letters': /[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g},
|
||||
{ 'base': 'J', 'letters': /[\u004A\u24BF\uFF2A\u0134\u0248]/g},
|
||||
{ 'base': 'K', 'letters': /[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g},
|
||||
{ 'base': 'L', 'letters': /[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g},
|
||||
{ 'base': 'LJ', 'letters': /[\u01C7]/g},
|
||||
{ 'base': 'Lj', 'letters': /[\u01C8]/g},
|
||||
{ 'base': 'M', 'letters': /[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},
|
||||
{ 'base': 'N', 'letters': /[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g},
|
||||
{ 'base': 'NJ', 'letters': /[\u01CA]/g},
|
||||
{ 'base': 'Nj', 'letters': /[\u01CB]/g},
|
||||
{ 'base': 'O', 'letters': /[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g},
|
||||
{ 'base': 'OI', 'letters': /[\u01A2]/g},
|
||||
{ 'base': 'OO', 'letters': /[\uA74E]/g},
|
||||
{ 'base': 'OU', 'letters': /[\u0222]/g},
|
||||
{ 'base': 'P', 'letters': /[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},
|
||||
{ 'base': 'Q', 'letters': /[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},
|
||||
{ 'base': 'R', 'letters': /[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g},
|
||||
{ 'base': 'S', 'letters': /[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g},
|
||||
{ 'base': 'T', 'letters': /[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g},
|
||||
{ 'base': 'TZ', 'letters': /[\uA728]/g},
|
||||
{ 'base': 'U', 'letters': /[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g},
|
||||
{ 'base': 'V', 'letters': /[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},
|
||||
{ 'base': 'VY', 'letters': /[\uA760]/g},
|
||||
{ 'base': 'W', 'letters': /[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g},
|
||||
{ 'base': 'X', 'letters': /[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},
|
||||
{ 'base': 'Y', 'letters': /[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g},
|
||||
{ 'base': 'Z', 'letters': /[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g},
|
||||
{ 'base': 'a', 'letters': /[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g},
|
||||
{ 'base': 'aa', 'letters': /[\uA733]/g},
|
||||
{ 'base': 'ae', 'letters': /[\u00E6\u01FD\u01E3]/g},
|
||||
{ 'base': 'ao', 'letters': /[\uA735]/g},
|
||||
{ 'base': 'au', 'letters': /[\uA737]/g},
|
||||
{ 'base': 'av', 'letters': /[\uA739\uA73B]/g},
|
||||
{ 'base': 'ay', 'letters': /[\uA73D]/g},
|
||||
{ 'base': 'b', 'letters': /[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g},
|
||||
{ 'base': 'c', 'letters': /[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g},
|
||||
{ 'base': 'd', 'letters': /[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g},
|
||||
{ 'base': 'dz', 'letters': /[\u01F3\u01C6]/g},
|
||||
{ 'base': 'e', 'letters': /[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g},
|
||||
{ 'base': 'f', 'letters': /[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g},
|
||||
{ 'base': 'g', 'letters': /[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g},
|
||||
{ 'base': 'h', 'letters': /[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g},
|
||||
{ 'base': 'hv', 'letters': /[\u0195]/g},
|
||||
{ 'base': 'i', 'letters': /[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g},
|
||||
{ 'base': 'j', 'letters': /[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g},
|
||||
{ 'base': 'k', 'letters': /[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g},
|
||||
{ 'base': 'l', 'letters': /[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g},
|
||||
{ 'base': 'lj', 'letters': /[\u01C9]/g},
|
||||
{ 'base': 'm', 'letters': /[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g},
|
||||
{ 'base': 'n', 'letters': /[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g},
|
||||
{ 'base': 'nj', 'letters': /[\u01CC]/g},
|
||||
{ 'base': 'o', 'letters': /[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g},
|
||||
{ 'base': 'oi', 'letters': /[\u01A3]/g},
|
||||
{ 'base': 'ou', 'letters': /[\u0223]/g},
|
||||
{ 'base': 'oo', 'letters': /[\uA74F]/g},
|
||||
{ 'base': 'p', 'letters': /[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g},
|
||||
{ 'base': 'q', 'letters': /[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g},
|
||||
{ 'base': 'r', 'letters': /[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g},
|
||||
{ 'base': 's', 'letters': /[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g},
|
||||
{ 'base': 't', 'letters': /[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g},
|
||||
{ 'base': 'tz', 'letters': /[\uA729]/g},
|
||||
{ 'base': 'u', 'letters': /[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g},
|
||||
{ 'base': 'v', 'letters': /[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g},
|
||||
{ 'base': 'vy', 'letters': /[\uA761]/g},
|
||||
{ 'base': 'w', 'letters': /[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g},
|
||||
{ 'base': 'x', 'letters': /[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g},
|
||||
{ 'base': 'y', 'letters': /[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g},
|
||||
{ 'base': 'z', 'letters': /[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g}
|
||||
];
|
||||
|
||||
module.exports = (str) => {
|
||||
if ( !changes ) changes = defaultDiacriticsRemovalMap;
|
||||
|
||||
for ( let i = 0; i < changes.length; i++ ) { str = str.replace( changes[i].letters, changes[i].base ); }
|
||||
return str;
|
||||
};
|
||||
22
src/util/raspi.js
Normal file
22
src/util/raspi.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const { readFileSync } = require('fs');
|
||||
|
||||
const MODELS = [ 'BCM2708', 'BCM2709', 'BCM2710', 'BCM2835', 'BCM2837B0' ];
|
||||
const isPi = ( model ) => { return MODELS.indexOf(model) > -1; };
|
||||
|
||||
module.exports = () => {
|
||||
let cpuInfo;
|
||||
|
||||
try { cpuInfo = readFileSync('/proc/cpuinfo', { encoding: 'utf8' }); }
|
||||
catch (ex) { return false; }
|
||||
|
||||
const model = cpuInfo
|
||||
.split('\n')
|
||||
.map((v) => v.replace(/\t/g, ''))
|
||||
.filter((v) => v.length > 0)
|
||||
.map((v) => v.split( ':' ) )
|
||||
.map((v) => v.map((e) => e.trim()))
|
||||
.filter((v) => v[0] === 'Hardware');
|
||||
|
||||
if (!model || model.length <= 0) return false;
|
||||
return isPi(model[0][1]);
|
||||
};
|
||||
Reference in New Issue
Block a user