diff --git a/src/_application.yml b/src/_application.yml index 38cd486..74ba252 100644 --- a/src/_application.yml +++ b/src/_application.yml @@ -57,9 +57,11 @@ discord : math : true snipe : true # Category : INFORMATION + user : true stats : true guild : true avatar : true + github : true commits : true commands : true # Category : IMAGE @@ -73,6 +75,8 @@ discord : # Category : DEVELOPER eval : true echo : true + exec : true api : - lol: '<--snip-->' \ No newline at end of file + lol: '<--snip-->' + dbl: '<--snip-->' diff --git a/src/assets/config/colors.yml b/src/assets/config/colors.yml index 71584cb..4013786 100644 --- a/src/assets/config/colors.yml +++ b/src/assets/config/colors.yml @@ -1,5 +1,6 @@ error : 0xff0000 # Red cooldown: 0x7289DA # Blurple +votelock: 0xF7AE69 core : locale: 0x7289DA # Blurple @@ -31,5 +32,9 @@ image : developer : eval : + success: 0x00ff00 # Green + failure: 0xff0000 # Red + + exec : success: 0x00ff00 # Green failure: 0xff0000 # Red \ No newline at end of file diff --git a/src/assets/config/emotes.yml b/src/assets/config/emotes.yml index 28c1d49..f05cfa4 100644 --- a/src/assets/config/emotes.yml +++ b/src/assets/config/emotes.yml @@ -1,7 +1,11 @@ +votelock : + 0 : <:exclamation:542368036255039509> + 1 : <:send:544852981254848513> cooldown : <:stopwatch:542477522147868672> # On cooldown owner_only: <:exclamation:542368036255039509> # Only owners guild_only: <:exclamation:542368036255039509> # Only guilds + core : locale: 0 : <:wumpus_blob:541629681120837648> # Dupe locale (user) @@ -13,6 +17,7 @@ core : 6 : <:ok_hand:497396122416054287> # Updated (user) 7 : <:sad:500719642403405824> # Invalid locale 8 : <:sad:500719642403405824> # Missing permissions (guild) + prefix: 0 : <:wumpus_blob:541629681120837648> # Dupe prefix (user) 1 : <:wumpus_blob:541629681120837648> # Dupe prefix (guild) @@ -23,8 +28,9 @@ core : 6 : <:ok_hand:497396122416054287> # Updated (user) 7 : <:sad:500719642403405824> # Missing permissions (guild) -logs : - ready : '<:spacewump:542723940997529641>' +logs : + ready: '<:spacewump:542723940997529641>' + shard : ready : '<:create_webhook:542716503674454016>' resume : '<:update_webhook:542716504089690124>' @@ -36,68 +42,100 @@ util : 1 : <:thumbsup:501844577725054976> # Heartbeat 2 : <:blueberry:506201160382939141> # Round-trip 3 : <:WumpLove:506200781549076482> # Health + math : 0 : <:blueberry:506201160382939141> # Calculating 1 : # Evaluation 2 : # Invalid equation + snipe: <:snipe:508653323788877825> # No snipes found info: - guild : - 0 : <:search:542368817163010057> # Guild Name - 1 : <:wumpus_flag:495525134220787713> # Guild region - 2 : <:cloud:542368816911613963> # Guild creation - 3 : <:alert:542367222279176202> # Content filter - 4 : <:exclamation:542368036255039509> # Verification level - 5 : <:hashtag:542367004024242176> # Channels - 6 : <:owner:542365741844922368> # Owner tag - 7 : <:early:542366345795207178> # Owner creation - 8 : <:store:542366547180781588> # Owner avatar - 9 : <:bot:473670328334155805> # Total bots - 10 : <:member:542362747896201218> # Total users - 11 : <:online:362670805051768833> # Total online members - 12 : <:idle:362670805760475136> # Total idle members - 13 : <:dnd:362670805676720128> # Total DnD members - 14 : <:offline:362670805441708032> # Total offline members - 15 : <:exclamation:542368036255039509> # Invalid query - avatar : <:blueberry:506201160382939141> # User's avatar - commits : - 0 : <:wumplus:542809926414761995> # 10 most recent commits - 1 : <:early:542366345795207178> # Total commits - 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 : # OS uptime - 5 : # 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 + guild: + 0 : <:search:542368817163010057> # Guild Name + 1 : <:wumpus_flag:495525134220787713> # Guild region + 2 : <:cloud:542368816911613963> # Guild creation + 3 : <:alert:542367222279176202> # Content filter + 4 : <:exclamation:542368036255039509> # Verification level + 5 : <:hashtag:542367004024242176> # Channels + 6 : <:owner:542365741844922368> # Owner tag + 7 : <:early:542366345795207178> # Owner creation + 8 : <:store:542366547180781588> # Owner avatar + 9 : <:bot:473670328334155805> # Total bots + 10 : <:member:542362747896201218> # Total users + 11 : <:online:362670805051768833> # Total online members + 12 : <:idle:362670805760475136> # Total idle members + 13 : <:dnd:362670805676720128> # Total DnD members + 14 : <:offline:362670805441708032> # Total offline members + 15 : <:exclamation:542368036255039509> # Invalid query + + user: + 0 : <:hashtag:542367004024242176> # User tag + 1 : <:early:542366345795207178> # Creation date + 2 : <:streaming:362670805185724418> # User status + 3 : <:wumpus_blob:541629681120837648> # Nickname + 4 : <:join:546066271318441994> # Joined date + 5 : <:create_role:546066640417325066> # Roles + 6 : <:exclamation:542368036255039509> # Status (unknown) + 7 : <:online:362670805051768833> # Status (online) + 8 : <:idle:362670805760475136> # Status (away) + 9 : <:dnd:362670805676720128> # Status (DnD) + 10: <:offline:362670805441708032> # Status (offline) + 11: <:exclamation:542368036255039509> # Invalid user + + avatar: <:blueberry:506201160382939141> # User's avatar + + commits: + 0 : <:wumplus:542809926414761995> # 10 most recent commits + 1 : <:early:542366345795207178> # Total commits + + commands: + 0 : <:blueberry:506201160382939141> # Guild prefix + 1 : <:spirit:332131321759399937> # More info + 2 : <:WumpLove:506200781549076482> # Links + 3 : <:Starlinator:332182009680101376> # Name + 4 : <:beetle_tank:445274774579445771> # Syntax + 5 : <:chubi:447107570239537152> # Aliases + 6 : <:reptice:331951247445983235> # Cooldown + 7 : <:the_mole:445271536690003968> # Arguments + + statistics: + 0 : <:ok_hand:497396122416054287> # Fetching + 1 : <:blueberry:506201160382939141> # Operating System + 2 : <:happy:500719642231177220> # Process hash + 3 : <:WumpLove:506200781549076482> # Load average + 4 : # OS uptime + 5 : # 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 -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 : # Invalid message + eval : 0 : # Invalid snippet 1 : # Evaluating diff --git a/src/assets/i18n/en_us/strings.yml b/src/assets/i18n/en_us/strings.yml index 2133409..0aaf7ec 100644 --- a/src/assets/i18n/en_us/strings.yml +++ b/src/assets/i18n/en_us/strings.yml @@ -19,9 +19,13 @@ error : - 'Message = "$[err:message]"' - '```' cooldown: '$[emoji#0] $[author:mention] **>** This command is on cooldown for **$[cooldown:left]**' +votelock: + - '$[emoji#0] This command is **votelocked**, upvote [**`Wump`**](https://discordbots.org/bot/318057009188438016/vote) to unlock this command/parameters (It can take up to 10 minutes to register your vote)' + - '' + - '$[emoji#1] If you still have issues after that, you can either create an [**`issue`**](https://github.com/PassTheWessel/wump/issues) on [**`GitHub`**](https://github.com/PassTheWessel/wump) or join my [**`Discord`**](https://discord.gg/SV7DAE9) and posting it there' core : - prefix : + prefix : gchanged: '$[emoji#5] Successfully updated the guild''s prefix to `$[guild:prefix]`' changed : '$[emoji#6] Successfully updated your prefix to `$[user:prefix]`' gperms : '$[emoji#8] You''re missing permissions in order to execute this command (`MANAGE_GUILD`)' @@ -66,9 +70,11 @@ util : - '$[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: ' Method "$[math:function]" has been disabled for security reasons ' + snipe : fail : '$[emoji#0] No snipeable messages found' footer : 'Sniped by $[author:tag] ($[author:id])' @@ -76,27 +82,30 @@ util : info : stats : fetching: '$[emoji#0] Fetching statistics, this may take some time...' + avatar : '$[emoji#0] Here''s **$[user:full]** avatar' commits : - '$[emoji#1] **Total commits**: [`$[commits:total]`](https://github.com/PassTheWessel/wump/commits "Click here for a list of all commits")' - '$[emoji#0] **10 most recent commits done on [`PassTheWessel/wump`](https://github.com/PassTheWessel/wump/)**: $[commits:list]' + commands: multi : - '$[emoji#0] The prefix for **$[guild:name]** is `$[guild:prefix]`' - '$[emoji#1] Type `$[guild:prefix]command ` 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]' + - '$[emoji#3] **Name**: $[command:name]' + - '$[emoji#4] **Syntax**: $[command:syntax]' + - '$[emoji#5] **Aliases**: $[command:aliases]' + - '$[emoji#6] **Cooldown**: $[command:cooldown#formatted]' + - '$[emoji#7] **Arguments**: $[command:arguments]' fields: - 'Core' - 'Information' - 'Image' - 'Utility' - 'Developer' + guild: fields: guild: @@ -126,12 +135,29 @@ info : - '$[emoji#14] Offline **⤏** `$[guild:users#offline]`' invalid: '$[emoji#15] No guild found with your query' + user : + invalid : '$[emoji#11] No user found with your query' + fields : + self : + name : '❯ User Information' + value: + - '$[emoji#0] **Tag**: $[user:tag] (`$[user:id]`)' + - '$[emoji#1] **Creation**: $[user:created@precise] ago (`$[user:created@exact]`)' + - '$[emoji#2] **Status**: $[user:status@full]' + member: + name : '❯ Member Information' + value: + - '$[emoji#3] **Nickname**: $[member:nickname]' + - '$[emoji#4] **Joined**: $[member:created@precise] ago (`$[member:created@exact]`)' + - '$[emoji#5] **Roles**: $[member:roles]' + 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...' @@ -143,4 +169,17 @@ developer: - '$[emoji#3] **Result** (`$[result:type]`):' - '```js' - '$[result:message]' + - '```' + + exec : + args : '$[emoji#0] Invalid command to execute' + busy : '$[emoji#1] Executing, this may take some time...' + silent: '$[emoji#2] Silently executed your command' + types : + - 'succeed' + - 'failed' + result: + - '$[emoji#3] **Result** (`$[result:type]`):' + - '```sh' + - '$[result:message]' - '```' \ No newline at end of file diff --git a/src/assets/i18n/nl/strings.yml b/src/assets/i18n/nl/strings.yml index 9d53f1d..2295332 100644 --- a/src/assets/i18n/nl/strings.yml +++ b/src/assets/i18n/nl/strings.yml @@ -19,6 +19,10 @@ error : - 'Bericht = "$[err:message]"' - '```' cooldown: '$[emoji#0] $[author:mention] **>** Dit commando is op cooldown voor **$[cooldown:left]**' +votelock: + - '$[emoji#0] Dit commando is **votelocked**, stem voor [**`Wump`**](https://discordbots.org/bot/318057009188438016/vote) om dit commando/parameters te ontgrendelen (Het kan tot 10 minuten duren om uw stem te registreren)' + - '' + - '$[emoji#1] Als u nogsteeds problemen hebt ná dat, kunt u een [**`issue`**](https://github.com/PassTheWessel/wump/issues) maken op [**`GitHub`**](https://github.com/PassTheWessel/wump) of mijn [**`Discord`**](https://discord.gg/SV7DAE9) joinen en het daar te plaatsen' core : prefix : @@ -66,9 +70,11 @@ util : - '$[emoji#2] **Rondvaart**: $[roundtrip]ms' - '$[emoji#1] **Hartslag**: $[latency]ms' - '$[emoji#3] **Gezondheid**: $[health]' + math : busy : '$[emoji#0] Aam het berekenen, dit kan enige tijd duren...' blocked: ' De methode "$[math:function]" is om veiligheidsredenen uitgeschakeld ' + snipe : fail : '$[emoji#0] Geen snipebare berichten gevonden' footer : 'Sniped door $[author:tag] ($[author:id])' @@ -76,18 +82,20 @@ util : info : stats : fetching: '$[emoji#0] Statistieken aan het ophalen, dit kan enige tijd duren...' - avatar : '$[emoji#0] Hier is **$[user:full]** avatar' + + avatar : '$[emoji#0] Hier is **$[user:full]** avatar' + commands: multi : - '$[emoji#0] Het voorvoegsel voor **$[guild:name]** is `$[guild:prefix]`' - '$[emoji#1] typ `$[guild:prefix]command ` voor meer informatie' - '$[emoji#2] **Links**: [`Uitnodiging`]($[bot:invite]) **|** [`Ondersteuning`](https://discord.gg/SV7DAE9) **|** [`GitHub`](https://github.com/PassTheWessel/wump) **|** [`Patreon`](https://patreon.com/wessel)' single: - - '**Naam**: $[command:name]' - - '**Syntaxis**: $[command:syntax]' - - '**Aliassen**: $[command:aliases]' - - '**Cooldown**: $[command:cooldown#formatted]' - - '**Argumenten**: $[command:arguments]' + - '$[emoji#3] **Naam**: $[command:name]' + - '$[emoji#4] **Syntaxis**: $[command:syntax]' + - '$[emoji#5] **Aliassen**: $[command:aliases]' + - '$[emoji#6] **Cooldown**: $[command:cooldown#formatted]' + - '$[emoji#7] **Argumenten**: $[command:arguments]' fields: - 'Kern' - 'Informatie' @@ -123,12 +131,30 @@ info : - '$[emoji#14] Offline **⤏** `$[guild:users#offline]`' invalid: '$[emoji#15] Geen gilde gevonden met uw zoekopdracht' + user : + invalid : '$[emoji#11] Geen gebruiker gevonden met uw zoekopdracht' + fields : + self : + name : '❯ Gebruikers Informatie' + value: + - '$[emoji#0] **Label**: $[user:tag] (`$[user:id]`)' + - '$[emoji#1] **Creatie**: $[user:created@precise] ago (`$[user:created@exact]`)' + - '$[emoji#2] **Staat**: $[user:status@full]' + member: + name : '❯ Ledeninformatie' + value: + - '$[emoji#3] **Bijnaam**: $[member:nickname]' + - '$[emoji#4] **Aangesloten**: $[member:created@precise] ago (`$[member:created@exact]`)' + - '$[emoji#5] **Rollen**: $[member:roles]' + + image: fetching : '$[emoji#0] Een willekeurig plaatje aan het ophalen, dit kan enige tijd duren...' failed_cache: 'Klik hier als het plaatje niet is geladen' developer: echo : '$[emoji#0] Ongeldig bericht om te echoën' + eval : args : '$[emoji#0] Ongeldig codefragment om te evalueren' busy : '$[emoji#1] Aan het evalueren, Dit kan enige tijd duren...' @@ -140,4 +166,17 @@ developer: - '$[emoji#3] **Resultaat** (`$[result:type]`):' - '```js' - '$[result:message]' + - '```' + + exec : + args : '$[emoji#0] Ongeldig commando om uit te voeren' + busy : '$[emoji#1] Aan het uitvoeren, dit kan enige tijd duren...' + silent: '$[emoji#2] Commando stil uitgevoerd' + types : + - 'geslaagd' + - 'mislukt' + result: + - '$[emoji#3] **Resultaat** (`$[result:type]`):' + - '```sh' + - '$[result:message]' - '```' \ No newline at end of file diff --git a/src/assets/img/emoji/Audit logs/create_role.png b/src/assets/img/emoji/Audit logs/create_role.png new file mode 100644 index 0000000..82e6d59 Binary files /dev/null and b/src/assets/img/emoji/Audit logs/create_role.png differ diff --git a/src/assets/img/emoji/join.png b/src/assets/img/emoji/join.png new file mode 100644 index 0000000..b34f1cd Binary files /dev/null and b/src/assets/img/emoji/join.png differ diff --git a/src/assets/img/emoji/send.png b/src/assets/img/emoji/send.png new file mode 100644 index 0000000..a0ac895 Binary files /dev/null and b/src/assets/img/emoji/send.png differ diff --git a/src/assets/img/thumb/votelocked.png b/src/assets/img/thumb/votelocked.png new file mode 100644 index 0000000..7716186 Binary files /dev/null and b/src/assets/img/thumb/votelocked.png differ diff --git a/src/commands/Discord/Core/locale.js b/src/commands/Discord/Core/locale.js index b47bbd7..5d65c63 100644 --- a/src/commands/Discord/Core/locale.js +++ b/src/commands/Discord/Core/locale.js @@ -1,7 +1,5 @@ const { DiscordCommand } = require('../../../core'); -const larg = require('larg'); - module.exports = class Locale extends DiscordCommand { constructor(bot) { super(bot, { @@ -13,7 +11,7 @@ module.exports = class Locale extends DiscordCommand { hidden : false, enabled : true, - cooldown : 1000, + cooldown : 10000, category : 'Core', ownerOnly : false, guildOnly : false, @@ -26,11 +24,20 @@ module.exports = class Locale extends DiscordCommand { if (!guild || guild === null) guild = await this.bot.m.connection.collection('dGuilds').findOne({ guildId: msg.channel.guild.id }); if (args.join(' ').includes('-u') || args.join(' ').includes('--user')) { - for (let i = 0; i < args.length; i++) !this.bot.locales.has(args[i]) ? args.splice(i, -1) : undefined; - if (!this.bot.locales.has(args[0])) return msg.channel.createMessage(this.localize(msg.author.locale['core']['locale']['invalid'])); - if (user.locale === args[0]) return msg.channel.createMessage(this.localize(msg.author.locale['core']['locale']['dupe'], { uLocale: user.locale })); + for (let _ = 0; _ < args.length; _++) { + if (!this.bot.locales.has(args[_])) args.splice(_, -1); + }; + + if (!this.bot.locales.has(args[0])) { + return msg.channel.createMessage(this.localize(msg.author.locale['core']['locale']['invalid'])); + } + if (user.locale === args[0]) { + return msg.channel.createMessage(this.localize(msg.author.locale['core']['locale']['dupe'], { uLocale: user.locale || 'en_us' })); + } - this.bot.m.connection.collection('dUsers').findOneAndUpdate({ 'userId': user.userId }, { $set: { locale: args[0] } }, (err) => { if (err) throw err; }); + this.bot.m.connection.collection('dUsers').findOneAndUpdate({ 'userId': user.userId }, { $set: { locale: args[0] } }, (err) => { + if (err) throw err; + }); this.bot.cache.get('users').some((v, _) => { if (v['userId'] === msg.author.id) this.bot.cache.get('users').splice(_, 1); }); msg.channel.createMessage(this.localize(this.bot.locales.get(args[0])['core']['locale']['changed'], { uLocale: args[0] })); } else if (args.join(' ').includes('-g') || args.join(' ').includes('--guild')) { diff --git a/src/commands/Discord/Developer/echo.js b/src/commands/Discord/Developer/echo.js index 1b008bd..246094d 100644 --- a/src/commands/Discord/Developer/echo.js +++ b/src/commands/Discord/Developer/echo.js @@ -1,13 +1,13 @@ const { DiscordCommand } = require('../../../core'); -module.exports = class Eval extends DiscordCommand { +module.exports = class Echo extends DiscordCommand { constructor(bot) { super(bot, { name : 'echo', syntax : 'echo <...message:str>', aliases : [], argument : [ '<...message:str>' ], - description : 'Evaluate a snippet', + description : 'Repeat your input', hidden : false, enabled : true, @@ -26,7 +26,9 @@ module.exports = class Eval extends DiscordCommand { localize(msg) { // Empty - if (!msg) return ''; + if (!msg) { + return ''; + } // Main return msg.replace(/\$\[emoji#0]/g, this.bot.emote('developer', 'echo')); } diff --git a/src/commands/Discord/Developer/exec.js b/src/commands/Discord/Developer/exec.js new file mode 100644 index 0000000..5a4b346 --- /dev/null +++ b/src/commands/Discord/Developer/exec.js @@ -0,0 +1,87 @@ +const { DiscordCommand } = require('../../../core'); + +const { execSync } = require('child_process'); + +module.exports = class Exec extends DiscordCommand { + constructor(bot) { + super(bot, { + // Information + name : 'exec', + syntax : 'exec <...cmd:str>', + aliases : [], + argument : [ ], + description: 'Execute a command', + // Checks + hidden : false, + enabled : true, + cooldown : 0, + category : 'Developer', + ownerOnly : true, + guildOnly : false, + permissions: [ 'embedLinks' ] + }); + } + + async execute(msg, args, user, guild) { + let result = '$'; + + let raw = args.join(' ').trim().endsWith('--raw') ? args.pop() : false; + let silent = args.join(' ').trim().endsWith('--silent') || args.join(' ').trim().endsWith('-s') ? args.pop() : false; + let errored = false; + + if (args.length <= 0) return msg.channel.createMessage(this.localize(msg.author.locale['developer']['exec']['args'])); + + const message = await msg.channel.createMessage(this.localize(msg.author.locale['developer']['exec']['busy'])); + + try { result = execSync(args.join(' '), { timeout: 100000 }); } + catch (ex) { result = ex; errored = true; } + finally { + if (silent) return message.edit(this.localize(msg.author.locale['developer']['exec']['silent'])); + result = this.bot.util.escapeMarkdown(this.sanitize(String(result))); + + if (raw) return msg.channel.createMessage(`\`\`\`sh\n${result}\`\`\``); + message.edit({ + content: '', + embed: { + color : (errored ? this.bot.col['developer']['exec']['failure'] : this.bot.col['developer']['exec']['success']), + description: this.localize(msg.author.locale['developer']['exec']['result'].join('\n'), { resultType: errored ? msg.author.locale['developer']['exec']['types'][1] : msg.author.locale['developer']['exec']['types'][0], resultMessage: this.bot.util.shorten(result, 1850) || '$' }) + } + }); + }; + } + + sanitize(msg) { + // Return nothing if empty + if (!msg) return msg; + // API tokens + for (let _ in this.bot.conf['api']) { + msg = msg.replace(new RegExp(this.bot.conf['api'][_], 'gi'), '<--snip-->'); + } + // Webhook information + for (let _ in this.bot.conf.discord.webhook) { + msg = msg.replace(new RegExp(this.bot.conf.discord.webhook[_], 'gi'), '<--snip-->'); + } + // Bot tokens + return msg + .replace(new RegExp(this.bot.token, 'gi'), '<--snip-->') + .replace(new RegExp(this.bot.conf['discord']['token'], 'gi'), '<--snip-->'); + } + + localize(msg, extData) { + // Empty + if (!msg) return ''; + // extData + if (extData && extData.resultType) { + msg = msg.replace(/\$\[result:type]/g, extData.resultType); + } + if (extData && extData.resultMessage) { + msg = msg.replace(/\$\[result:message]/g, extData.resultMessage); + } + // Main + return msg + .replace(/\$\[emoji#0]/g, this.bot.emote('developer', 'exec', '0')) + .replace(/\$\[emoji#1]/g, this.bot.emote('developer', 'exec', '1')) + .replace(/\$\[emoji#2]/g, this.bot.emote('developer', 'exec', '2')) + .replace(/\$\[emoji#3]/g, this.bot.emote('developer', 'exec', '3')); + } +}; diff --git a/src/commands/Discord/Information/avatar.js b/src/commands/Discord/Information/avatar.js index c61fc94..cba0cce 100644 --- a/src/commands/Discord/Information/avatar.js +++ b/src/commands/Discord/Information/avatar.js @@ -1,9 +1,10 @@ const { DiscordCommand } = require('../../../core'); -const w = require('wumpfetch'); -const sizeOf = require('../../../util/sizeOf'); -const { extname } = require('path'); - +const w = require('wumpfetch'); +const sizeOf = require('../../../util/sizeOf'); +const { extname } = require('path'); +const { readFileSync } = require('fs'); +// Sharp is an optional dependency let s; try { s = require('sharp'); } catch (ex) { throw new Error('Sharp not found, not loading this command'); } @@ -12,9 +13,9 @@ module.exports = class Avatar extends DiscordCommand { constructor(bot) { super(bot, { name : 'avatar', - syntax : 'avatar [...user:string] [--large] [--(nearest|linear)]', + syntax : 'avatar [...user:string] [--large] [--(nearest|linear)] [--greyscale] [--jpeg] [--blur]', aliases : [ 'avt', 'pfp' ], - argument : [ '[...user:string]', '[--large]', '[--(nearest|linear)]' ], + argument : [ '[...user:string]', '[--large]', '[--(nearest|linear)]', '[--greyscale]', '[--jpeg]', '[--blur]' ], description: 'Get a user\'s avatar', hidden : false, @@ -25,56 +26,127 @@ module.exports = class Avatar extends DiscordCommand { guildOnly : false, permissions: [ 'embedLinks' ] }); + + this.mutable = { + reg: [ /--large/i, /--(nearest|linear)/i, /--greyscale/i, /--jpeg/i, /--blur/i ], + req: { + headers: { + 'User-Agent' : this.bot.ua, + 'Authorization': this.bot.conf.api.dbl + } + } + }; - this.regex = [/--large/i, /--(nearest|linear)/i, /--greyscale/i]; + try { this.mutable.thumb = readFileSync('./assets/img/thumb/votelocked.png'); } + catch(ex) { this.thumb = undefined; } } async execute(msg, args) { + // Resizing method, original args, extras and edited + const oArgs = args; + const edited = this.mutable.reg[0].test(oArgs) || this.mutable.reg[1].test(oArgs) || this.mutable.reg[2].test(oArgs) || this.mutable.reg[3].test(oArgs) || this.mutable.reg[4].test(oArgs); + const extras = `${this.mutable.reg[2].exec(oArgs) ? 'GREYSCALE' : ''} ${this.mutable.reg[3].exec(oArgs) ? 'JPEG' : ''} ${this.mutable.reg[4].exec(oArgs) ? 'BLUR' : ''}`; const resize = - this.regex[1].test(args) && this.regex[1].exec(args)[0].toLowerCase() === '--nearest' ? 'NEAREST' : - this.regex[1].test(args) && this.regex[1].exec(args)[0].toLowerCase() === '--linear' ? 'LINEAR_A' : 'LINEAR_B'; - - const oldArgs = args; - args = args.join(' ').trim().replace(this.regex[0], '').replace(this.regex[1], '').replace(this.regex[2], '').split(' ').filter((v) => { return v !== ''; }); - let user = this.bot.REST.getUser(args[0] ? args.join(' ') : msg.author.id); - if (!user) user = this.bot.users.get(msg.author.id); + this.mutable.reg[1].test(args) && this.mutable.reg[1].exec(args)[0].toLowerCase() === '--nearest' ? 'NEAREST' : + this.mutable.reg[1].test(args) && this.mutable.reg[1].exec(args)[0].toLowerCase() === '--linear' ? 'LINEAR_A' : 'LINEAR_B'; + // Strip args + args = args + .join(' ') + .trim() + .replace(this.mutable.reg[0], '') + .replace(this.mutable.reg[1], '') + .replace(this.mutable.reg[2], '') + .replace(this.mutable.reg[3], '') + .replace(this.mutable.reg[4], '') + .split(' ') + .filter((v) => { return v !== ''; }); + // Fetch user + let user = this.bot.REST.getUser(args[0] ? args.join(' ') : msg.author.id); + if (!user) user = this.bot.users.get(msg.author.id); + // Base avatar URL of `user` + let img; + const avatarURL = (user.avatar ? user.avatarURL : user.defaultAvatarURL).split('?')[0]; - let img, dim; - const avatarURL = (user.avatar ? user.avatarURL : user.defaultAvatarURL).split('?')[0]; + if (edited) { + // Image manipulation + const manipulate = async () => { + let tmp, dim; + // Fetching avatar of `user` + tmp = await w(avatarURL).send(); + tmp = tmp.body; + // Resizing + dim = sizeOf(tmp); + tmp = await s(tmp) + .resize(dim.width * 2, dim.height * 2, { kernel: resize === 'LINEAR_B' ? s.kernel.linearB : resize === 'LINEAR_A' ? s.kernel.linearA : resize === 'NEAREST' ? s.kernel.nearest : s.kernel.linearA }) // { fit: 'inside' } + .toBuffer(); + // Utility customization + if (this.mutable.reg[2].test(oArgs)) tmp = await s(tmp).greyscale().toBuffer(); + if (this.mutable.reg[3].test(oArgs)) tmp = await s(tmp).jpeg({ quality: 5 }).toBuffer(); + if (this.mutable.reg[4].test(oArgs)) tmp = await s(tmp).blur(4).toBuffer(); - if (this.regex[0].test(oldArgs.join(' '))) { - img = await w(avatarURL).send(); - img = img.body; - - dim = sizeOf(img); - img = await s(img) - .resize(dim.width * 2, dim.height * 2, { kernel: resize === 'LINEAR_B' ? s.kernel.linearB : resize === 'LINEAR_A' ? s.kernel.linearA : resize === 'NEAREST' ? s.kernel.nearest : s.kernel.linearA }) // { fit: 'inside' } - .toBuffer(); - if (this.regex[2].exec(args)) img = await s(img).greyscale().toBuffer(); + return tmp; + }; + // Vote lock + const voters = this.bot.cache.get('votes') ? this.bot.cache.get('votes') : this.bot.cache.set('votes', []) && this.bot.cache.get('votes'); + if (!this.bot.op(msg.author.id) && !voters.includes(msg.author.id)) { + // Fetch votes + const req = await w(`https://discordbots.org/api/bots/318057009188438016/check?userId=${msg.author.id}`, this.mutable.req).send(); + const res = req.json(); + // Succeed if code isn't `200` + if(req.statusCode !== 200) { + img = await manipulate(); + } else { + if (res.voted === 0) { + // User didn't vote + return msg.channel.createMessage({ + embed: { + color : this.bot.col['votelock'], + thumbnail : { url: 'attachment://thumb.png' }, + description: this.localize(msg.author.locale['votelock'].join('\n'), { votelocked: true }) + } + }, this.mutable.thumb ? { file: this.mutable.thumb, name: 'thumb.png' } : undefined); + } else if (res.voted === 1) { + // User voted + img = await manipulate(); + voters.push(msg.author.id); + } + } + } else { + img = await manipulate(); + } } else { + // Fetching avatar of `user` img = await w(avatarURL).send(); img = img.body; } - if (this.regex[2].test(oldArgs)) img = await s(img).greyscale().toBuffer(); - msg.channel.createMessage({ embed: { - image: { url: `attachment://thumb${extname(avatarURL)}` }, - color: this.bot.col['info']['avatar'], - description: `${this.localize(msg.author.locale['info']['avatar'], { user: user })} (\`${this.regex[0].test(oldArgs.join(' ')) ? 'LARGE' : 'DEFAULT'} ${resize} ${this.regex[2].exec(oldArgs) ? 'GREYSCALE' : ''}\`)` + image : { url: `attachment://thumb${edited ? '.jpg' : extname(avatarURL)}` }, + color : this.bot.col['info']['avatar'], + description: `${this.localize(msg.author.locale['info']['avatar'], { user: user })} (\`${this.mutable.reg[0].test(oArgs.join(' ')) ? 'LARGE' : 'DEFAULT'} ${resize} ${extras}\`)` } }, { file: img, - name: `thumb${extname(avatarURL)}` + name: `thumb${edited ? '.jpg' : extname(avatarURL)}` }); } localize(msg, extData) { if (!msg) return ''; + + if (extData) { + if (extData.user) { + msg = msg.replace(/\$\[user:full]/g, `${extData.user.username}'${!extData.user.username.toLowerCase().endsWith('s') ? 's' : ''}`); + } + if (extData.votelocked) { + return msg + .replace(/\$\[emoji#0]/g, this.bot.emote('votelock', '0')) + .replace(/\$\[emoji#1]/g, this.bot.emote('votelock', '1')); + } + } return msg - .replace(/\$\[user:full]/g, `${extData.user.username}'${!extData.user.username.toLowerCase().endsWith('s') ? 's' : ''}`) .replace(/\$\[emoji#0]/g, this.bot.emote('info', 'avatar')); } }; \ No newline at end of file diff --git a/src/commands/Discord/Information/commands.js b/src/commands/Discord/Information/commands.js index cb42fd0..210dd6b 100644 --- a/src/commands/Discord/Information/commands.js +++ b/src/commands/Discord/Information/commands.js @@ -93,6 +93,11 @@ module.exports = class Commands extends DiscordCommand { 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')); + .replace(/\$\[emoji#2]/g, this.bot.emote('info', 'commands', '2')) + .replace(/\$\[emoji#3]/g, this.bot.emote('info', 'commands', '3')) + .replace(/\$\[emoji#4]/g, this.bot.emote('info', 'commands', '4')) + .replace(/\$\[emoji#5]/g, this.bot.emote('info', 'commands', '5')) + .replace(/\$\[emoji#6]/g, this.bot.emote('info', 'commands', '6')) + .replace(/\$\[emoji#7]/g, this.bot.emote('info', 'commands', '7')); } }; \ No newline at end of file diff --git a/src/commands/Discord/Information/guild.js b/src/commands/Discord/Information/guild.js index 1b1ef60..747dec1 100644 --- a/src/commands/Discord/Information/guild.js +++ b/src/commands/Discord/Information/guild.js @@ -66,14 +66,16 @@ module.exports = class Guild extends DiscordCommand { o.cs = [ o.c.years >= 1 ? `${o.c.years} years` : undefined, o.c.months >= 1 ? `${o.c.months} months` : undefined, - o.c.days >= 1 ? `${o.c.days} days` : undefined + o.c.days >= 1 ? `${o.c.days} days` : undefined, + o.days <= 0 && o.months <= 0 && o.years <= 0 ? 'Less than a day' : undefined ].join(' '); extData.guild.c = moment.preciseDiff(new Date(), new Date(extData.guild.createdAt), true); extData.guild.cs = [ extData.guild.c.years >= 1 ? `${extData.guild.c.years} years` : undefined, extData.guild.c.months >= 1 ? `${extData.guild.c.months} months` : undefined, - extData.guild.c.days >= 1 ? `${extData.guild.c.days} days` : undefined + extData.guild.c.days >= 1 ? `${extData.guild.c.days} days` : undefined, + extData.guild.days <= 0 && extData.guild.months <= 0 && extData.guild.years <= 0 ? 'Less than a day' : undefined ].join(' '); msg = msg diff --git a/src/commands/Discord/Information/user.js b/src/commands/Discord/Information/user.js new file mode 100644 index 0000000..a2aab31 --- /dev/null +++ b/src/commands/Discord/Information/user.js @@ -0,0 +1,111 @@ +const { DiscordCommand } = require('../../../core'); + +const m = require('moment'); require('../../../util/moment/diff.js'); + +module.exports = class Guild extends DiscordCommand { + constructor(bot) { + super(bot, { + name : 'user', + syntax : 'user <...user:string>', + aliases : [ '<...user:string>' ], + argument : [], + description : 'Get a user\'s information', + + hidden : false, + enabled : true, + cooldown : 1000, + category : 'Information', + ownerOnly : false, + guildOnly : false, + permissions : [ 'embedLinks' ] + }); + + this.mutable.status = { + '_unknown': `${this.bot.emote('info', 'user', '6')}Unknown`, + 'online' : `${this.bot.emote('info', 'user', '7')}online`, + 'idle' : `${this.bot.emote('info', 'user', '8')}away`, + 'dnd' : `${this.bot.emote('info', 'user', '9')}do not disturb`, + 'offline' : `${this.bot.emote('info', 'user', '10')}offline` + }; + } + + async execute(msg, args) { + const u = this.bot.REST.getUser((args.length >= 1 ? args.join(' ') : msg.author.id)); + if (!u) return msg.channel.createMessage(this._localize(msg.author.locale['info']['user']['invalid'])); + + const mem = msg.channel.guild && msg.channel.guild.members.get(u.id) ? msg.channel.guild.members.get(u.id) : undefined; + + const structure = { + embed: { + color: this.bot.col['info']['guild'], + thumbnail: { + url: u.avatar ? u.avatarURL : u.defaultAvatarURL + }, + fields: [ + { + name: msg.author.locale['info']['user']['fields']['self']['name'], + value: this._localize(msg.author.locale['info']['user']['fields']['self']['value'].join('\n'), { user: u, member: mem }), + inline: true + } + ] + } + }; + + if (mem) { + structure.embed.fields.push({ + name: msg.author.locale['info']['user']['fields']['member']['name'], + value: this._localize(msg.author.locale['info']['user']['fields']['member']['value'].join('\n'), { user: u, member: mem, guildId: msg.channel.guild.id }), + inline: true + }); + } + + msg.channel.createMessage(structure); + } + + _localize(msg, extData) { + if (!msg) return ''; + if (extData) { + if (extData.user) { + const u = extData.user; + u.c = m.preciseDiff(new Date(), new Date(u.createdAt), true); + u.cs = [ + u.c.years >= 1 ? `${u.c.years} years` : undefined, + u.c.months >= 1 ? `${u.c.months} months` : undefined, + u.c.days >= 1 ? `${u.c.days} days` : undefined, + u.c.days <= 0 && u.c.months <= 0 && u.c.years <= 0 ? 'Less than a day' : undefined + ].join(' '); + + msg = msg + .replace(/\$\[user:id]/g , u.id) + .replace(/\$\[user:tag]/g , `${u.username}#${u.discriminator}`) + .replace(/\$\[user:created@exact]/g, m(u.createdAt).format('YYYY[/]MM[/]DD HH[:]mm')) + .replace(/\$\[user:created@precise]/g, u.cs) + .replace(/\$\[user:status@full]/g, extData.member && this.mutable.status[extData.member.status] ? this.mutable.status[extData.member.status] : this.mutable.status['_unknown']); + } + if (extData.member) { + const mem = extData.member; + mem.c = m.preciseDiff(new Date(), new Date(mem.joinedAt), true); + mem.cs = [ + mem.c.years >= 1 ? `${mem.c.years} years` : undefined, + mem.c.months >= 1 ? `${mem.c.months} months` : undefined, + mem.c.days >= 1 ? `${mem.c.days} days` : undefined, + mem.c.days <= 0 && mem.c.months <= 0 && mem.c.years <= 0 ? 'Less than a day' : undefined + ].join(' '); + msg = msg + .replace(/\$\[member:nickname]/g, mem && mem.nick ? this.bot.util.escapeMarkdown(mem.nick) : '*No nickname set*') + .replace(/\$\[member:roles]/g, mem.roles.length >= 1 ? mem.roles.map((v) => `<@&${v}>`).slice(0, 25).join(' **/** ') : 'n/a') + .replace(/\$\[member:created@exact]/g, m(mem.joinedAt).format('YYYY[/]MM[/]DD HH[:]mm')) + .replace(/\$\[member:created@precise]/g, mem.cs); + } + } + + return msg + .replace(/\$\[emoji#0]/g, this.bot.emote('info', 'user', '0')) + .replace(/\$\[emoji#1]/g, this.bot.emote('info', 'user', '1')) + .replace(/\$\[emoji#2]/g, this.bot.emote('info', 'user', '2')) + .replace(/\$\[emoji#3]/g, this.bot.emote('info', 'user', '3')) + .replace(/\$\[emoji#4]/g, this.bot.emote('info', 'user', '4')) + .replace(/\$\[emoji#5]/g, this.bot.emote('info', 'user', '5')) + .replace(/\$\[emoji#11]/g, this.bot.emote('info', 'user', '11')); + } +}; \ No newline at end of file diff --git a/src/core/internal/Discord/Command.js b/src/core/internal/Discord/Command.js index 5e0392e..776acd7 100644 --- a/src/core/internal/Discord/Command.js +++ b/src/core/internal/Discord/Command.js @@ -17,9 +17,13 @@ module.exports = class WumpCommand { guildOnly : false, // Guild only ( true / false ) permissions : [] // Bot permissions ( optional ) }, opts); + + this.static = {}; + this.mutable = {}; + Object.freeze(this.static); } async execute(msg, args, user, guild) {} - localize(msg) {} + _localize(msg) {} }; \ No newline at end of file diff --git a/src/core/internal/Discord/Event.js b/src/core/internal/Discord/Event.js index dafcd31..d3162c5 100644 --- a/src/core/internal/Discord/Event.js +++ b/src/core/internal/Discord/Event.js @@ -6,5 +6,5 @@ module.exports = class WumpEvent { emit(...args) {} - localize(msg) {} + _localize(msg) {} }; \ No newline at end of file diff --git a/src/core/internal/Discord/__baseCommand.js b/src/core/internal/Discord/__baseCommand.js index 63432bb..bb6bd96 100644 --- a/src/core/internal/Discord/__baseCommand.js +++ b/src/core/internal/Discord/__baseCommand.js @@ -21,5 +21,5 @@ module.exports = class name extends DiscordCommand { async execute(msg, args, user, guild) {} - localize(msg) {} + _localize(msg) {} }; \ No newline at end of file diff --git a/src/core/internal/Discord/rest.js b/src/core/internal/Discord/rest.js index 3a548dc..fd347d2 100644 --- a/src/core/internal/Discord/rest.js +++ b/src/core/internal/Discord/rest.js @@ -73,6 +73,7 @@ module.exports = class RESTclient { } getMember($, g, n = false) { + if (!$ || !g) return undefined; if (/^\d+$/.test($) && g.members.get($)) return g.members.get($); else if (/^<@!?(\d+)>$/.test($)) { const m = $.match(/^<@!?(\d+)>$/); diff --git a/src/core/registry/Discord/Commands.js b/src/core/registry/Discord/Commands.js index 7bb5114..82577e8 100644 --- a/src/core/registry/Discord/Commands.js +++ b/src/core/registry/Discord/Commands.js @@ -33,13 +33,13 @@ module.exports = class CommandRegistry { 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'); + if (err) process.handleError(err, 'LoadError', cyan('Discord')); 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'); } + } catch(ex) { process.handleError(err, 'LoadError', cyan('Discord')); } }); }); } @@ -167,7 +167,7 @@ module.exports = class CommandRegistry { 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'); + process.handleError(ex, 'CommandError', cyan('Discord')); msg.channel.createMessage({ embed: { color : this.bot.col['error'], diff --git a/src/core/registry/Discord/Events.js b/src/core/registry/Discord/Events.js index ccacd16..428555a 100644 --- a/src/core/registry/Discord/Events.js +++ b/src/core/registry/Discord/Events.js @@ -9,7 +9,7 @@ module.exports = class EventStore { execute(event) { const execAsync = async(...args) => { try { await event.emit(...args); } - catch (ex) { process.handleError(ex, cyan('Discord'), 'EventError'); } + catch (ex) { process.handleError(ex, 'EventError', cyan('Discord')); } }; this.bot.on(event.extData.name, execAsync); diff --git a/src/core/registry/Discord/Locales.js b/src/core/registry/Discord/Locales.js index e8876ca..0bbd183 100644 --- a/src/core/registry/Discord/Locales.js +++ b/src/core/registry/Discord/Locales.js @@ -24,7 +24,7 @@ module.exports = class LocaleRegistry { } } } catch (ex) { - process.handleError(ex, cyan('Discord'), 'LoadError'); + process.handleError(ex, 'LoadError', cyan('Discord')); return { success: false, err: ex }; } diff --git a/src/main.js b/src/main.js index 4df084b..9051ec0 100644 --- a/src/main.js +++ b/src/main.js @@ -38,8 +38,8 @@ 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('uncaughtException', (err) => process.handleError(err)); +process.on('unhandledRejection', (err) => process.handleError(err)); process.on('SIGINT', () => { if (Database) { try { @@ -67,7 +67,7 @@ process.on('SIGINT', () => { 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); + mongoose.connection.on('error', (err) => process.handleError(err)); print(2, `${yellow('Database')} >> ${green('Connected to database')}` ); })(); diff --git a/src/util/Util.js b/src/util/Util.js index 53582b1..1eba873 100644 --- a/src/util/Util.js +++ b/src/util/Util.js @@ -7,7 +7,7 @@ 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`; + 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; }); @@ -35,13 +35,18 @@ module.exports = class WumpUtil { } } - 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'); + 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(text, onlyCodeBlock = false, onlyInlineCode = false) { + if (onlyCodeBlock) return text.replace(/```/g, '`\u200b``'); + if (onlyInlineCode) return text.replace(/\\(`|\\)/g, '$1').replace(/(`|\\)/g, '\\$1'); + return text.replace(/\\(\*|_|`|~|\\)/g, '$1').replace(/(\*|_|`|~|\\)/g, '\\$1'); + } + }; \ No newline at end of file