From d5fb18b73b43cd2a8d325079108dee96171f3cd2 Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 13:26:15 +0000 Subject: [PATCH 01/13] Change 1 for auth update --- src/commands/securesign_init.ts | 2 +- src/models/Account.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/securesign_init.ts b/src/commands/securesign_init.ts index e9d8417..1ccccfa 100644 --- a/src/commands/securesign_init.ts +++ b/src/commands/securesign_init.ts @@ -47,7 +47,7 @@ export default class SecureSign_Init extends Command { } const init = await this.client.util.exec(`sudo -H -u ${account.username} bash -c 'securesign-canary init -a ${args[0]}'`); if (!init.replace(/^\s+|\s+$/g, '').endsWith('Initialization sequence completed.')) throw new Error(`Account initialization did not complete successfully:\n${init}`); - await this.client.db.Account.updateOne({ userID: message.author.id }, { $set: { hash: args[0] } }); + await this.client.db.Account.updateOne({ userID: message.author.id }, { $set: { hash: true } }); return msg.edit(`${this.client.stores.emojis.success} ***Account initialized***`); } catch (error) { return this.client.util.handleError(error, message, this); diff --git a/src/models/Account.ts b/src/models/Account.ts index 0f99acb..cadec7a 100644 --- a/src/models/Account.ts +++ b/src/models/Account.ts @@ -15,7 +15,7 @@ export interface AccountInterface extends Document { engineer: boolean }, root: boolean, - hash: string, + hash: boolean, salt: string, authTag: Buffer } @@ -35,7 +35,7 @@ const Account: Schema = new Schema({ engineer: Boolean, }, root: Boolean, - hash: String, + hash: Boolean, salt: String, authTag: Buffer, }); From b04cfbd0a67270f23f4e5447483b0d9294088144 Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 13:32:33 +0000 Subject: [PATCH 02/13] Don't restart when updating --- src/commands/pull.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/commands/pull.ts b/src/commands/pull.ts index 569f940..4ad34da 100644 --- a/src/commands/pull.ts +++ b/src/commands/pull.ts @@ -14,6 +14,7 @@ export default class Pull extends Command { public async run(message: Message) { try { + this.client.updating = true; const updateMessage = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Fetching latest commit...***\n\`\`\`sh\ngit pull\n\`\`\``); let pull: string; @@ -22,16 +23,19 @@ export default class Pull extends Command { } catch (error) { const updatedMessage = updateMessage.content.replace(`${this.client.stores.emojis.loading} ***Fetching latest commit...***`, `${this.client.stores.emojis.error} ***Could not fetch latest commit***`) .replace(/```$/, `${error.message}\n\`\`\``); + this.client.updating = false; return updateMessage.edit(updatedMessage); } if (pull.includes('Already up to date')) { const updatedMessage = updateMessage.content.replace(`${this.client.stores.emojis.loading} ***Fetching latest commit...***`, `${this.client.stores.emojis.success} ***No updates available***`) .replace(/```$/, `${pull}\n\`\`\``); + this.client.updating = false; return updateMessage.edit(updatedMessage); } if (!pull.includes('origin/master')) { const updatedMessage = updateMessage.content.replace(`${this.client.stores.emojis.loading} ***Fetching latest commit...***`, `${this.client.stores.emojis.error} ***Unexpected git output***`) .replace(/```$/, `${pull}\n\`\`\``); + this.client.updating = false; return updateMessage.edit(updatedMessage); } const continueMessage = updateMessage.content.replace(`${this.client.stores.emojis.loading} ***Fetching latest commit...***`, `${this.client.stores.emojis.success} ***Pulled latest commit***\n${this.client.stores.emojis.loading} ***Reinstalling dependencies...***`) @@ -43,6 +47,7 @@ export default class Pull extends Command { try { install = await this.client.util.exec('yarn install'); } catch (error) { + this.client.updating = false; const updatedMessage = passedPull.content.replace(`${this.client.stores.emojis.loading} ***Reinstalling dependencies...***`, `${this.client.stores.emojis.error} ***Failed to reinstall dependencies***`) .replace(/```$/, `${error.message}\n\`\`\``); return updateMessage.edit(updatedMessage); @@ -59,6 +64,7 @@ export default class Pull extends Command { } else { const updatedMessage = passedPull.content.replace(`${this.client.stores.emojis.loading} ***Reinstalling dependencies...***`, `${this.client.stores.emojis.error} ***Unexpected yarn install output***`) .replace(/```$/, `${pull}\n\`\`\``); + this.client.updating = false; return updateMessage.edit(updatedMessage); } @@ -68,13 +74,15 @@ export default class Pull extends Command { } catch (error) { const updatedMessage = updatedPackages.content.replace(`${this.client.stores.emojis.loading} ***Rebuilding files...***`, `${this.client.stores.emojis.error} ***Failed to rebuild files***`) .replace(/```$/, `${error.message}\n\`\`\``); + this.client.updating = false; return updateMessage.edit(updatedMessage); } const finalMessage = updatedPackages.content.replace(`${this.client.stores.emojis.loading} ***Rebuilding files...***`, `${this.client.stores.emojis.success} ***Files rebuilt***`) .replace(/```$/, `${build}\n\`\`\``); - + this.client.updating = false; return updateMessage.edit(finalMessage); } catch (error) { + this.client.updating = false; return this.client.util.handleError(error, message, this); } } From 405d9345dd7dfb5958401570c71836bd9e2327db Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 13:41:07 +0000 Subject: [PATCH 03/13] Matt fuckin look at the errors --- src/class/Route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/Route.ts b/src/class/Route.ts index 33db377..d15f936 100644 --- a/src/class/Route.ts +++ b/src/class/Route.ts @@ -7,7 +7,7 @@ export default class Route { public router: router; - public conf: { path: string, deprecated?: boolean }; + public conf: { path: string, deprecated?: boolean, maintenance?: boolean }; constructor(server: Server, conf: { path: string, deprecated?: boolean, maintenance?: boolean }) { this.server = server; From a7415ce3813b1dbffc903b39407de54d9c778413 Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 14:00:50 +0000 Subject: [PATCH 04/13] Use securesign cli hash --- src/class/Util.ts | 13 +++++++++++++ src/functions/checkSS.ts | 5 +++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/class/Util.ts b/src/class/Util.ts index 2197a92..0459d73 100644 --- a/src/class/Util.ts +++ b/src/class/Util.ts @@ -5,6 +5,7 @@ import nodemailer from 'nodemailer'; import { Message, PrivateChannel, Member, User } from 'eris'; import uuid from 'uuid/v4'; import moment from 'moment'; +import fs from 'fs'; import { Client } from '..'; import { Command, RichEmbed } from '.'; import { ModerationInterface, AccountInterface } from '../models'; @@ -195,9 +196,13 @@ export default class Util { /** * @param type `0` - Create + * * `1` - Warn + * * `2` - Lock + * * `3` - Unlock + * * `4` - Delete */ public async createModerationLog(user: string, moderator: Member|User, type: number, reason?: string, duration?: number): Promise { @@ -251,4 +256,12 @@ export default class Util { return Promise.resolve(log); } + + public getAcctHash(username: string) { + try { + return fs.readFileSync(`/home/${username}/.securesign/auth`).toString(); + } catch (error) { + return null; + } + } } diff --git a/src/functions/checkSS.ts b/src/functions/checkSS.ts index 45868b6..29e7b55 100644 --- a/src/functions/checkSS.ts +++ b/src/functions/checkSS.ts @@ -7,8 +7,9 @@ export default function checkSS(client: Client) { try { const accounts = await client.db.Account.find(); const hashes = accounts.filter((h) => h.hash); - for (const { hash, userID } of hashes) { + for (const { userID, username } of hashes) { try { + const hash = client.util.getAcctHash(username); await axios({ method: 'get', url: 'https://api.securesign.org/account/details', @@ -17,7 +18,7 @@ export default function checkSS(client: Client) { } catch (error) { const { status } = error.response; if (status === 400 || status === 401 || status === 403 || status === 404) { - await client.db.Account.updateOne({ hash }, { $set: { hash: null } }); + await client.db.Account.updateOne({ userID }, { $set: { hash: false } }); client.getDMChannel(userID).then((channel) => channel.createMessage('Your SecureSign password has been reset - please reinitialize your SecureSign account')).catch(); } } From 2152c988bfcca2743a72bef7efb77e0b10a55297 Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 14:06:44 +0000 Subject: [PATCH 05/13] Use new hash getter to authenticate --- src/commands/securesign_activatekey.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/commands/securesign_activatekey.ts b/src/commands/securesign_activatekey.ts index 24c78e1..7c7d74a 100644 --- a/src/commands/securesign_activatekey.ts +++ b/src/commands/securesign_activatekey.ts @@ -19,17 +19,18 @@ export default class SecureSign_ActivateKey extends Command { if (!account) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Account not found***`); if (!account.hash) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Account not initialized***`); const msg = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Activating key...***`); + const hash = this.client.util.getAcctHash(account.username); try { await axios({ method: 'POST', url: 'https://api.securesign.org/account/keys/activation', - headers: { Authorization: account.hash, 'Content-Type': 'application/json' }, + headers: { Authorization: hash, 'Content-Type': 'application/json' }, data: JSON.stringify({ key: args[0] }), }); } catch (error) { const { code } = error.response.data; if (code === 1001) { - await this.client.db.Account.updateOne({ hash: account.hash }, { $set: { hash: null } }); + await this.client.db.Account.updateOne({ userID: account.userID }, { $set: { hash: false } }); this.client.getDMChannel(account.userID).then((channel) => channel.createMessage('Your SecureSign password has been reset - please reinitialize your SecureSign account')).catch(); return msg.edit(`${this.client.stores.emojis.error} ***Authentication failed***`); } From af136b1b6e0db686b0e0155bd0839c6cd26b42fb Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 15:45:22 +0000 Subject: [PATCH 06/13] Added createcrt command --- src/commands/securesign.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/commands/securesign.ts b/src/commands/securesign.ts index 275b6fe..4f184a5 100644 --- a/src/commands/securesign.ts +++ b/src/commands/securesign.ts @@ -5,6 +5,7 @@ import Build from './securesign_build'; import Init from './securesign_init'; import Account from './securesign_account'; import ActivateKey from './securesign_activatekey'; +import CreateCrt from './securesign_createcrt'; export default class SecureSign extends Command { constructor(client: Client) { @@ -13,7 +14,7 @@ export default class SecureSign extends Command { this.description = 'Runs SecureSign CLI commands'; this.usage = `Run ${this.client.config.prefix}${this.name} [subcommand] for usage information`; this.aliases = ['ss']; - this.subcmds = [Build, Init, Account, ActivateKey]; + this.subcmds = [Build, Init, Account, ActivateKey, CreateCrt]; this.enabled = true; } From 28f8ec58ec27d9a9da8a764d86b7f0289249f6e6 Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 15:47:37 +0000 Subject: [PATCH 07/13] Include the damn fuckin file --- src/commands/securesign_createcrt.ts | 63 ++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/commands/securesign_createcrt.ts diff --git a/src/commands/securesign_createcrt.ts b/src/commands/securesign_createcrt.ts new file mode 100644 index 0000000..30e1238 --- /dev/null +++ b/src/commands/securesign_createcrt.ts @@ -0,0 +1,63 @@ +import { Message, PrivateChannel, TextChannel } from 'eris'; +import axios from 'axios'; +import { Client } from '..'; +import { Command } from '../class'; + +export default class SecureSign_Init extends Command { + constructor(client: Client) { + super(client); + this.name = 'createcrt'; + this.description = 'Creates a new certificate'; + this.usage = `${this.client.config.prefix}securesign createcrt [-s sign] [-c class] [-m digest]\n\`sign\`: Sign type (ecc/rsa)\n\`class\`: Certificate Class (1/2/3)\n\`digest\`: SHA Digest (256/384/512)`; + this.enabled = true; + this.guildOnly = false; + } + + public async run(message: Message, args: string[]) { + try { + const account = await this.client.db.Account.findOne({ userID: message.author.id }); + if (!account) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Account not found***`); + if (!account.hash) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Account not initialized***`); + + // @ts-ignore + const options: { s?: string, c?: string, m?: string } = args.length ? Object.fromEntries(` ${args.join(' ')}`.split(' -').filter((a) => a).map((a) => a.split(' '))) : {}; // eslint-disable-line + if (options.s && options.s.toLowerCase() !== 'ecc' && options.s.toLowerCase() !== 'rsa') return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid signing type, choose between \`ecc\` or \`rsa\``); + if (options.c && (!Number(options.c) || Number(options.c) < 1 || Number(options.c) > 3)) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid class selected, choose between Class **1**, **2** or **3**`); + if (options.m && (!Number(options.m) || (options.m !== '256' && options.m !== '384' && options.m !== '512'))) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid SHA Digest selected, choose between **256**, **384** or **512**`); + + const msg = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Creating certificate...***`); + const hash = this.client.util.getAcctHash(account.username); + + // Check if they can generate certificate + try { + const { data } = await axios({ + method: 'GET', + url: 'https://api.securesign.org/account/details', + headers: { Authorization: hash, 'Content-Type': 'application/json' }, + }); + + const { total, allowed } = data.message; + if (total >= allowed) return msg.edit(`${this.client.stores.emojis.error} ***Not enough certificate allowances - please ask a member of staff to increase this limit from ${total}***`); + if (Number(options.c) > data.message.class) return msg.edit(`${this.client.stores.emojis.error} ***Class too low, you are on a class ${data.message.class} account***`); + } catch (error) { + const { code } = error.response.data; + if (code === 1001) { + await this.client.db.Account.updateOne({ userID: account.userID }, { $set: { hash: false } }); + this.client.getDMChannel(account.userID).then((channel) => channel.createMessage('Your SecureSign password has been reset - please reinitialize your SecureSign account')).catch(); + return msg.edit(`${this.client.stores.emojis.error} ***Authentication failed***`); + } + throw error; + } + + const execoptions = `${options.s ? ` -s ${options.s}` : ''}${options.c ? ` -c ${options.c}` : ''}${options.m ? ` -m ${options.m}` : ''}`; + const cmd = `sudo -H -u ${account.username} bash -c 'securesign-canary createcrt${execoptions}'`; + + const exec = await this.client.util.exec(cmd); + if (!exec.replace(/^\s+|\s+$/g, '').endsWith('Successfully wrote certificate.')) throw new Error(`Certificate generation did not complete successfully:\n${cmd}`); + + return msg.edit(`${this.client.stores.emojis.success} ***Successfully created certificate***`); + } catch (error) { + return this.client.util.handleError(error, message, this); + } + } +} From 6106fb067c5deede158a8bc5627701e277df4afd Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 15:53:55 +0000 Subject: [PATCH 08/13] Fix markdown --- src/commands/securesign_createcrt.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/securesign_createcrt.ts b/src/commands/securesign_createcrt.ts index 30e1238..df8f26f 100644 --- a/src/commands/securesign_createcrt.ts +++ b/src/commands/securesign_createcrt.ts @@ -22,8 +22,8 @@ export default class SecureSign_Init extends Command { // @ts-ignore const options: { s?: string, c?: string, m?: string } = args.length ? Object.fromEntries(` ${args.join(' ')}`.split(' -').filter((a) => a).map((a) => a.split(' '))) : {}; // eslint-disable-line if (options.s && options.s.toLowerCase() !== 'ecc' && options.s.toLowerCase() !== 'rsa') return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid signing type, choose between \`ecc\` or \`rsa\``); - if (options.c && (!Number(options.c) || Number(options.c) < 1 || Number(options.c) > 3)) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid class selected, choose between Class **1**, **2** or **3**`); - if (options.m && (!Number(options.m) || (options.m !== '256' && options.m !== '384' && options.m !== '512'))) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid SHA Digest selected, choose between **256**, **384** or **512**`); + if (options.c && (!Number(options.c) || Number(options.c) < 1 || Number(options.c) > 3)) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid class selected, choose between Class \`1\`, \`2\` or \`3\``); + if (options.m && (!Number(options.m) || (options.m !== '256' && options.m !== '384' && options.m !== '512'))) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid SHA Digest selected, choose between \`256\`, \`384\` or \`512\``); const msg = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Creating certificate...***`); const hash = this.client.util.getAcctHash(account.username); From 6651e3cc86239aa77f0728a784de40c6b6945585 Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 15:57:28 +0000 Subject: [PATCH 09/13] Stop erroring in DMs --- src/commands/securesign_account.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/securesign_account.ts b/src/commands/securesign_account.ts index 10d63e2..64b4ed6 100644 --- a/src/commands/securesign_account.ts +++ b/src/commands/securesign_account.ts @@ -36,7 +36,7 @@ export default class SecureSign_Account extends Command { embed.setTitle(title); embed.setDescription(description); embed.setAuthor(this.client.user.username, this.client.user.avatarURL); - embed.setFooter(`Requested by ${message.member.username}#${message.member.discriminator}`, message.member.avatarURL); + embed.setFooter(`Requested by ${message.author.username}#${message.author.discriminator}`, message.author.avatarURL); // @ts-ignore return msg.edit({ content, embed }); From bb179d28547bfcf7d5a1e4f0d87af13ec10d99c7 Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 20:20:33 +0000 Subject: [PATCH 10/13] I think this adds the subcommand properly to the subcommand list --- src/class/Util.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/class/Util.ts b/src/class/Util.ts index 0459d73..61accda 100644 --- a/src/class/Util.ts +++ b/src/class/Util.ts @@ -64,11 +64,12 @@ export default class Util { } else if (resolvedCommand.subcommands.has(args[0])) { parentLabel += `${resolvedCommand.name} `; resolvedCommand = resolvedCommand.subcommands.get(args[0]); args.shift(); + parentLabel += `${resolvedCommand.name} `; } else { const subcommandArray = resolvedCommand.subcommands.toArray(); for (const subCmd of subcommandArray) { if (subCmd.aliases.includes(args[0])) { - parentLabel += `${resolvedCommand.name} `; resolvedCommand = subCmd; args.shift(); break; + parentLabel += `${resolvedCommand.name} `; resolvedCommand = subCmd; parentLabel += `${resolvedCommand.name} `; args.shift(); break; } if (subcommandArray.findIndex((v) => v === subCmd) === subcommandArray.length - 1) { hasSubCommands = false; break; From e550c68fbe5f45c911ae2f292f9c10a4edf48bce Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 20:26:08 +0000 Subject: [PATCH 11/13] Let's try this method --- src/class/Util.ts | 3 +-- src/commands/help.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/class/Util.ts b/src/class/Util.ts index 61accda..0459d73 100644 --- a/src/class/Util.ts +++ b/src/class/Util.ts @@ -64,12 +64,11 @@ export default class Util { } else if (resolvedCommand.subcommands.has(args[0])) { parentLabel += `${resolvedCommand.name} `; resolvedCommand = resolvedCommand.subcommands.get(args[0]); args.shift(); - parentLabel += `${resolvedCommand.name} `; } else { const subcommandArray = resolvedCommand.subcommands.toArray(); for (const subCmd of subcommandArray) { if (subCmd.aliases.includes(args[0])) { - parentLabel += `${resolvedCommand.name} `; resolvedCommand = subCmd; parentLabel += `${resolvedCommand.name} `; args.shift(); break; + parentLabel += `${resolvedCommand.name} `; resolvedCommand = subCmd; args.shift(); break; } if (subcommandArray.findIndex((v) => v === subCmd) === subcommandArray.length - 1) { hasSubCommands = false; break; diff --git a/src/commands/help.ts b/src/commands/help.ts index 99804fb..7d42cb1 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -53,10 +53,10 @@ export default class Help extends Command { if (allowedUsers) { allowedUsers = `**Users:** ${allowedUsers}`; perms.push(allowedUsers); } const displayedPerms = perms.length ? `\n**Permissions:**\n${perms.join('\n')}` : ''; const aliases = cmd.aliases.length ? `\n**Aliases:** ${cmd.aliases.map((alias) => `${this.client.config.prefix}${cmd.parentName}${alias}`).join(', ')}` : ''; - const subcommands = cmd.subcommands.size ? `\n**Subcommands:** ${cmd.subcommands.map((s) => s.parentName || `${cmd.name} ${s.name}`).join(', ')}` : ''; + const subcommands = cmd.subcommands.size ? `\n**Subcommands:** ${cmd.subcommands.map((s) => `${cmd.name} ${s.name}`).join(', ')}` : ''; const embed = new RichEmbed(); embed.setTimestamp(); embed.setFooter(`Requested by ${message.author.username}#${message.author.discriminator}`, message.author.avatarURL); - embed.setTitle(`${this.client.config.prefix}${cmd.parentName}${cmd.name}`); embed.setAuthor(`${this.client.user.username}#${this.client.user.discriminator}`, this.client.user.avatarURL); + embed.setTitle(`${this.client.config.prefix}${cmd.parentName || cmd.name}`); embed.setAuthor(`${this.client.user.username}#${this.client.user.discriminator}`, this.client.user.avatarURL); const description = `**Description**: ${cmd.description}\n**Usage:** ${cmd.usage}${aliases}${displayedPerms}${subcommands}`; embed.setDescription(description); // @ts-ignore From f97b43426b8bd4246909b9289fbc609f2a823f90 Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 20:30:08 +0000 Subject: [PATCH 12/13] title not showing subcommand --- src/commands/help.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/help.ts b/src/commands/help.ts index 7d42cb1..3a02809 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -56,7 +56,7 @@ export default class Help extends Command { const subcommands = cmd.subcommands.size ? `\n**Subcommands:** ${cmd.subcommands.map((s) => `${cmd.name} ${s.name}`).join(', ')}` : ''; const embed = new RichEmbed(); embed.setTimestamp(); embed.setFooter(`Requested by ${message.author.username}#${message.author.discriminator}`, message.author.avatarURL); - embed.setTitle(`${this.client.config.prefix}${cmd.parentName || cmd.name}`); embed.setAuthor(`${this.client.user.username}#${this.client.user.discriminator}`, this.client.user.avatarURL); + embed.setTitle(`${this.client.config.prefix}${cmd.parentName ? `${cmd.parentName} ${cmd.name}` : cmd.name}`); embed.setAuthor(`${this.client.user.username}#${this.client.user.discriminator}`, this.client.user.avatarURL); const description = `**Description**: ${cmd.description}\n**Usage:** ${cmd.usage}${aliases}${displayedPerms}${subcommands}`; embed.setDescription(description); // @ts-ignore From 7d212bde3ff26c7fc0fa396664231a8e5be794cd Mon Sep 17 00:00:00 2001 From: Bsian Date: Tue, 19 Nov 2019 20:34:24 +0000 Subject: [PATCH 13/13] I don't like extra spaces --- src/commands/help.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/help.ts b/src/commands/help.ts index 3a02809..d597f3f 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -56,7 +56,7 @@ export default class Help extends Command { const subcommands = cmd.subcommands.size ? `\n**Subcommands:** ${cmd.subcommands.map((s) => `${cmd.name} ${s.name}`).join(', ')}` : ''; const embed = new RichEmbed(); embed.setTimestamp(); embed.setFooter(`Requested by ${message.author.username}#${message.author.discriminator}`, message.author.avatarURL); - embed.setTitle(`${this.client.config.prefix}${cmd.parentName ? `${cmd.parentName} ${cmd.name}` : cmd.name}`); embed.setAuthor(`${this.client.user.username}#${this.client.user.discriminator}`, this.client.user.avatarURL); + embed.setTitle(`${this.client.config.prefix}${cmd.parentName ? `${cmd.parentName}${cmd.name}` : cmd.name}`); embed.setAuthor(`${this.client.user.username}#${this.client.user.discriminator}`, this.client.user.avatarURL); const description = `**Description**: ${cmd.description}\n**Usage:** ${cmd.usage}${aliases}${displayedPerms}${subcommands}`; embed.setDescription(description); // @ts-ignore