// To ensure the command caller has, 1. an account and 2. has enough balance for the request // The pricing table needs to be in the DB so it can be updated via API const { DebugBuilder } = require("../utilities/debugBuilder"); const log = new DebugBuilder("server", "balanceAuthorizations"); const { UserStorage } = require("../libStorage"); const userStorage = new UserStorage(); /** * Check to see if the discord ID has an account associated with it * @param {*} _discordAccountId The discord account to look for * @param {*} callback The callback function to be called * @callback false|* */ function checkForAccount(_discordAccountId, callback){ userStorage.getRecordBy("discord_account_id", _discordAccountId, (err, results) => { if (err) return callback(err, undefined); if (!results) return callback(undefined, false); return callback(undefined, results); }) } /** * Create an account from a discord ID * @param {*} _discordAccountId * @param {*} callback */ function createAccount(_discordAccountId, callback){ if (!_discordAccountId) return callback(new Error("No discord account specified before creation")); userStorage.saveAccount(_discordAccountId, (err, results) => { if (err) return callback(err, undefined); if (!results) return callback(new Error("No results from creating account"), undefined); return callback(undefined, results); }) } function verifyBalance(_tokensToBeUsed, _accountId, callback){ userStorage.checkBalance(_tokensToBeUsed, _accountId, (err, results) => { if (err) return callback(err, undefined); if(!results) return callback(undefined, false); return callback(undefined, true); }) } function insufficientTokensResponse(interaction){ log.DEBUG("INSUFFICIENT TOKENS RESPONSE") return interaction.reply("Sorry, not enough tokens for this request."); } function welcomeResponse(interaction){ log.DEBUG("WELCOME RESPONSE") return interaction.reply("Hey there, you have an account now."); } exports.authorizeTokenUsage = async (interaction, command, next) => { log.DEBUG("Command requires tokens? ", command.isPrivileged) if(!command.requiresTokens) return next(true); if(!interaction.member && (!interaction.options.getNumber("tokens") || !command.defaultTokenUsage)) throw new Error("No member or tokens specified before attempting to authorize"); const memberId = interaction.member.id; const tokensToBeUsed = interaction.options.getNumber("tokens") ?? command.defaultTokenUsage log.DEBUG(`Authorizing ${memberId} for a purchase worth ${tokensToBeUsed} tokens`) log.DEBUG("Checking for account associated with discord ID: ", memberId); await checkForAccount(memberId, async (err, results) => { if (err) throw err; log.DEBUG("Results from checking for account: ", results); // First time user is attempting transaction if(!results){ log.DEBUG("No account for discord ID: ", memberId); await createAccount(memberId, (err, results) => { if (err) throw err; if (results) return welcomeResponse(interaction); }) } else{ // User has an account log.DEBUG(`Account ID: ${results.account_id} found for discord ID: ${memberId}`); await verifyBalance(tokensToBeUsed, results.account_id, async (err, isVerified) => { if (err) throw err; if(!isVerified) return insufficientTokensResponse(interaction); return next(isVerified); }) } }) }