import { Message } from 'discord.js'; import { rename } from 'fs/promises'; import { Client, Command } from '../class'; import { LINUX_USERNAME_REGEX } from '../class/AccountUtil'; export default class Usermod extends Command { constructor(client: Client) { super(client); this.name = 'usermod'; this.description = 'Modifies properties of a user\'s cloud account'; this.usage = `${this.client.config.prefix}usermod [account] [property: username | email] [value]`; this.permissions = { roles: ['662163685439045632', '701454780828221450'] }; this.enabled = true; } public async run(message: Message, args: string[]) { if (!args.length) return this.client.commands.get('help').run(message, [this.name]); const [, property, value] = args; const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0] }] }); if (!account) return this.error(message.channel, 'Cannot find user.'); switch (property) { case 'email': { if (value === account.emailAddress) return this.error(message.channel, 'The new email address cannot be the same as the old one.'); if (await this.client.db.Account.exists({ emailAddress: value })) return this.error(message.channel, 'An account with this email address already exists.'); if (!this.client.util.isValidEmail(value)) return this.error(message.channel, 'The supplied email address is invalid.'); const modifyingPropertyResponse = await this.loading(message.channel, `Modifying \`${property}\` of \`${account.username}\`'s account...`); await this.client.commands.get('notify') .run(message, [account.username, ...`Your email address has been changed from ${account.emailAddress} to ${value}.`.split(' ')]); await account.updateOne({ emailAddress: value }); modifyingPropertyResponse.delete(); this.success(message.channel, `Successfully updated \`${account.username}\`'s email address.`); break; } case 'username': { if (value === account.username) return this.error(message.channel, 'The username cannot be the same as the old one.'); if (await this.client.db.Account.exists({ username: value })) return this.error(message.channel, 'An account with this username already exists.'); if (!LINUX_USERNAME_REGEX.test(value)) return this.error(message.channel, 'Please supply a valid username.'); if (value === 'root') return this.error(message.channel, 'This username is unavailable.'); const modifyingPropertyResponse = await this.loading(message.channel, `Modifying \`${property}\` of \`${account.username}\`'s account...`); try { await this.client.commands.get('notify') .run(message, [account.username, ...`Changing your username from \`${account.username}\` to \`${value}\`.`.split(' ')]); if (!account.locked) { await account.updateOne({ locked: true }); await this.client.util.exec(`lock ${account.username}`); } await this.client.util.exec(`usermod -l ${value} ${account.username}`); await rename(account.homepath, `/home/${value}`); await this.client.util.exec(`usermod -d /home/${value} ${value}`); await this.client.util.exec(`groupmod -n ${value} ${account.username}`); await account.updateOne({ username: value, homepath: `/home/${value}`, }); await this.client.db.Moderation.updateMany( { username: account.username, date: { $gt: account.createdAt }, }, { username: value }, ); await this.client.commands.get('notify') .run(message, [value, ...`Your username has been successfully changed. Remember to use \`ssh ${value}@cloud.libraryofcode.org\` when logging in.`.split(' ')]); } catch (error) { await this.client.commands.get('notify') .run(message, [account.username, ...'Your username change was unsuccessful. Please contact a Technician for more details.'.split(' ')]); await this.client.util.handleError(error); return this.error(message.channel, 'Failed to modify username. Please check <#595788220764127272> for more information.'); } finally { if (!account.locked) { await this.client.util.exec(`unlock ${account.username}`); await account.updateOne({ locked: false }); } } modifyingPropertyResponse.delete(); this.success(message.channel, 'Successfully modified username.'); break; } default: this.error(message.channel, 'Please specify a valid option.'); break; } } }