diff --git a/.eslintrc.json b/.eslintrc.json index f1f15b9..af3e032 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -38,6 +38,7 @@ "object-curly-newline": "off", "import/prefer-default-export": "off", "no-useless-constructor": "off", - "@typescript-eslint/no-useless-constructor": 2 + "@typescript-eslint/no-useless-constructor": 2, + "import/extensions": "off" } } \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..683d018 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,19 @@ +stages: + - build + - test + +typescript_build: + stage: build + script: + - cp ../config.json ./src/config.json + - yarn install --ignore-engines + - tsc -p ./tsconfig.json + +lint: + stage: test + before_script: + - cp ../config.json ./src/config.json + - yarn install --ignore-engines + script: + - yarn run lint-find + diff --git a/package.json b/package.json index fd6125c..355e0cc 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "dist/Client.js", "scripts": { "lint": "eslint ./ --ext ts --fix", - "build": "tsc -p ./tsconfig.json" + "build": "tsc -p ./tsconfig.json", + "lint-find": "eslint ./ --ext ts" }, "author": "Library of Code sp-us Engineering Team", "license": "AGPL-3.0-only", diff --git a/src/Client.ts b/src/Client.ts index 8e1b637..97cfbb9 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -119,7 +119,11 @@ export default class Client extends Eris.Client { }); this.server = new Server(this, { port: this.config.port }); - require.cache = Object.create(null); + const corepath = '/var/CloudServices/dist'; + const cmdFiles = await fs.readdir('/var/CloudServices/dist/commands'); + cmdFiles.forEach((f) => delete require.cache[`${corepath}/${f}`]); + delete require.cache[`${corepath}/config.json`]; + delete require.cache[`${corepath}/class/Util`]; } } diff --git a/src/commands/help.ts b/src/commands/help.ts index 9db8143..c02d6ac 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -44,15 +44,16 @@ export default class Help extends Command { if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] }); return createPaginationEmbed(message, this.client, cmdPages); } - const { cmd } = await this.client.util.resolveCommand(args, message); - if (!cmd) return message.channel.createMessage(`${this.client.stores.emojis.error} **Command not found!**`); + const resolved = await this.client.util.resolveCommand(args, message); + if (!resolved) return message.channel.createMessage(`${this.client.stores.emojis.error} **Command not found!**`); + const { cmd } = resolved; const perms: string[] = []; let allowedRoles = cmd.permissions && cmd.permissions.roles && cmd.permissions.roles.map((r) => `<@&${r}>`).join(', '); if (allowedRoles) { allowedRoles = `**Roles:** ${allowedRoles}`; perms.push(allowedRoles); } let allowedUsers = cmd.permissions && cmd.permissions.users && cmd.permissions.users.map((u) => `<@${u}>`).join(', '); 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 aliases = cmd.aliases.length ? `\n**Aliases:** ${cmd.aliases.map((alias) => `${this.client.config.prefix}${cmd.parentName ? `${cmd.parentName} ` : ''}${alias}`).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); diff --git a/src/commands/load.ts b/src/commands/load.ts index b639c3b..8f55fe5 100644 --- a/src/commands/load.ts +++ b/src/commands/load.ts @@ -9,21 +9,24 @@ export default class Load extends Command { this.description = '(Re)loads command, config or util'; this.aliases = ['reload']; this.permissions = { users: ['253600545972027394', '278620217221971968'] }; - this.enabled = false; + this.enabled = true; } public async run(message: Message, args: string[]) { try { if (!args[0]) return this.client.commands.get('help').run(message, [this.name]); - const allowed = ['config', 'util', 'command', 'function']; + const allowed = ['config', 'util', 'command']; const type = args[0].toLowerCase(); if (!allowed.includes(type)) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid type to (re)load***`); const corepath = '/var/CloudServices/dist'; - if (type === 'config') this.client.config = require(`${corepath}/config.json`); - else if (type === 'util') { - const Util = require(`${corepath}/class/Util`); + if (type === 'config') { + this.client.config = require(`${corepath}/config.json`); + delete require.cache[`${corepath}/config.json`]; + } else if (type === 'util') { + const Util = require(`${corepath}/class/Util`).default; this.client.util = new Util(this.client); + delete require.cache[`${corepath}/class/Util.js`]; } else { try { const cmdIndex = require('../commands'); @@ -32,6 +35,8 @@ export default class Load extends Command { Cmd = require(`${corepath}/commands/${args[1]}`).default; this.client.commands.remove(args[1]); this.client.loadCommand(Cmd); + delete require.cache[`${corepath}/commands/index.js`]; + delete require.cache[`${corepath}/commands/${args[1]}.js`]; } catch (error) { if (error.message.includes('Cannot find module')) return message.channel.createMessage(`${this.client.stores.emojis} ***Cannot find file***`); throw error; diff --git a/src/commands/pull.ts b/src/commands/pull.ts index 6a861ca..6205880 100644 --- a/src/commands/pull.ts +++ b/src/commands/pull.ts @@ -16,7 +16,7 @@ export default class Pull extends Command { try { if (this.client.updating) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Update in progress***`); this.client.updating = true; - const updateMessage = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Fetching latest commit...***\n\`\`\`sh\ngit pull\n\`\`\``); + const updateMessage = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Fetching latest commit...***\n\`\`\`sh\n$ git pull\n\`\`\``); let pull: string; try { @@ -33,14 +33,14 @@ export default class Pull extends Command { this.client.updating = false; return updateMessage.edit(updatedMessage); } - if (!pull.includes('origin/master')) { + if (!pull.includes('origin/master') && !pull.includes(' changed, ')) { 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...***`) - .replace(/```$/, `${pull}\nyarn install\n\`\`\``); + .replace(/```$/, `${pull}\n$ yarn install\n\`\`\``); const passedPull = await updateMessage.edit(continueMessage); @@ -56,11 +56,11 @@ export default class Pull extends Command { let updatedPackages: Message; if (install.includes('Already up-to-date')) { const updatedMessage = passedPull.content.replace(`${this.client.stores.emojis.loading} ***Reinstalling dependencies...***`, `${this.client.stores.emojis.success} ***No dependency updates available***\n${this.client.stores.emojis.loading} ***Rebuilding files...***`) - .replace(/```$/, `${install}\nyarn run build\n\`\`\``); + .replace(/```$/, `${install}\n$ yarn run build\n\`\`\``); updatedPackages = await updateMessage.edit(updatedMessage); } else if (install.includes('success Saved lockfile.')) { const updatedMessage = passedPull.content.replace(`${this.client.stores.emojis.loading} ***Reinstalling dependencies...***`, `${this.client.stores.emojis.success} ***Updated dependencies***\n${this.client.stores.emojis.loading} ***Rebuilding files...***`) - .replace(/```$/, `${install}\nyarn run build\n\`\`\``); + .replace(/```$/, `${install}\n$ yarn run build\n\`\`\``); updatedPackages = await updateMessage.edit(updatedMessage); } else { const updatedMessage = passedPull.content.replace(`${this.client.stores.emojis.loading} ***Reinstalling dependencies...***`, `${this.client.stores.emojis.error} ***Unexpected yarn install output***`) diff --git a/src/commands/restart.ts b/src/commands/restart.ts index 80e3a33..b110322 100644 --- a/src/commands/restart.ts +++ b/src/commands/restart.ts @@ -14,7 +14,7 @@ export default class Restart extends Command { public async run(message: Message, args: string[]) { try { if (this.client.updating && args[0] !== '-f') return message.channel.createMessage(`${this.client.stores.emojis.error} ***Update in progress***`); - if (this.client.buildError) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Build error, resolve before restarting***`); + if (this.client.buildError) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Build error, resolve before restarting. See CI job on Gitlab***`); await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Restarting...***`); return process.exit(1); } catch (error) {