From add982a73ed2e21c91f31feb02166967d561557b Mon Sep 17 00:00:00 2001 From: Matthew R Date: Mon, 9 Nov 2020 23:55:10 -0500 Subject: [PATCH] changes for coupon codes and various fixes --- src/class/Client.ts | 23 ++++++++++++++++++++--- src/commands/apply.ts | 6 ++++++ src/commands/billing_t3.ts | 34 ++++++++++++++++++++++++---------- src/commands/score.ts | 3 ++- src/models/Promo.ts | 13 +++++++++++++ src/models/index.ts | 1 + 6 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 src/models/Promo.ts diff --git a/src/class/Client.ts b/src/class/Client.ts index b268489..efa6b4c 100644 --- a/src/class/Client.ts +++ b/src/class/Client.ts @@ -4,7 +4,24 @@ import pluris from 'pluris'; import mongoose from 'mongoose'; import { promises as fs } from 'fs'; import { Collection, Command, LocalStorage, Queue, Util, ServerManagement, Event } from '.'; -import { Customer, CustomerInterface, CustomerPortal, CustomerPortalInterface, File, FileInterface, Member, MemberInterface, Merchant, MerchantInterface, Moderation, ModerationInterface, NNTrainingData, NNTrainingDataInterface, Note, NoteInterface, PagerNumber, PagerNumberInterface, Rank, RankInterface, Redirect, RedirectInterface, Score, ScoreInterface, ScoreHistorical, ScoreHistoricalInterface, Staff, StaffInterface, Stat, StatInterface } from '../models'; +import { + Customer, CustomerInterface, + CustomerPortal, CustomerPortalInterface, + File, FileInterface, + Member, MemberInterface, + Merchant, MerchantInterface, + Moderation, ModerationInterface, + NNTrainingData, NNTrainingDataInterface, + Note, NoteInterface, + PagerNumber, PagerNumberInterface, + Promo, PromoInterface, + Rank, RankInterface, + Redirect, RedirectInterface, + Score, ScoreInterface, + ScoreHistorical, ScoreHistoricalInterface, + Staff, StaffInterface, + Stat, StatInterface, +} from '../models'; import { Config } from '../../types'; // eslint-disable-line pluris(eris); @@ -26,7 +43,7 @@ export default class Client extends eris.Client { public stripe: Stripe; - public db: { Customer: mongoose.Model, CustomerPortal: mongoose.Model, File: mongoose.Model, Member: mongoose.Model, Merchant: mongoose.Model, Moderation: mongoose.Model, NNTrainingData: mongoose.Model, Note: mongoose.Model, PagerNumber: mongoose.Model, Rank: mongoose.Model, Redirect: mongoose.Model, Score: mongoose.Model, ScoreHistorical: mongoose.Model, Staff: mongoose.Model, Stat: mongoose.Model, local: { muted: LocalStorage } }; + public db: { Customer: mongoose.Model, CustomerPortal: mongoose.Model, File: mongoose.Model, Member: mongoose.Model, Merchant: mongoose.Model, Moderation: mongoose.Model, NNTrainingData: mongoose.Model, Note: mongoose.Model, PagerNumber: mongoose.Model, Promo: mongoose.Model, Rank: mongoose.Model, Redirect: mongoose.Model, Score: mongoose.Model, ScoreHistorical: mongoose.Model, Staff: mongoose.Model, Stat: mongoose.Model, local: { muted: LocalStorage } }; constructor(token: string, options?: eris.ClientOptions) { super(token, options); @@ -34,7 +51,7 @@ export default class Client extends eris.Client { this.events = new Collection(); this.intervals = new Collection(); this.queue = new Queue(this); - this.db = { Customer, CustomerPortal, File, Member, Merchant, Moderation, NNTrainingData, Note, PagerNumber, Rank, Redirect, Score, ScoreHistorical, Staff, Stat, local: { muted: new LocalStorage('muted') } }; + this.db = { Customer, CustomerPortal, File, Member, Merchant, Moderation, NNTrainingData, Note, PagerNumber, Promo, Rank, Redirect, Score, ScoreHistorical, Staff, Stat, local: { muted: new LocalStorage('muted') } }; } diff --git a/src/commands/apply.ts b/src/commands/apply.ts index 9def6ae..d8979df 100644 --- a/src/commands/apply.ts +++ b/src/commands/apply.ts @@ -76,6 +76,11 @@ export default class Apply extends Command { first_time_transaction: true, }, }); + const doc = new client.db.Promo({ + code: promo.code, + pID: promo.id, + }); + await doc.save(); const chan = await client.getDMChannel(customer.userID); chan.createMessage(`__**Tier 3 Coupon Code**__\n\`${promo.code}\`\n\n*Do not share this promotional code with anyone else. This promo code is good for your first purchase of Tier 2, 25% off applied. Will apply to your first invoice only, for more questions contact support.*`); }, @@ -113,6 +118,7 @@ export default class Apply extends Command { if (!test && args[0] !== 'full') continue; embed.addField(service[0], `**Description**: ${service[1].description}\n**Inquiry Type:** ${service[1].type}\n\n*Run \`${this.client.config.prefix}apply ${service[0]}\` to apply.*`); } + if (embed.fields?.length <= 0) embed.setDescription(`*We have no offers for you at this time. To see a full list of offers, please run \`${this.client.config.prefix}apply full\`.*`); embed.setFooter(this.client.user.username, this.client.user.avatarURL); embed.setTimestamp(); return message.channel.createMessage({ embed }); diff --git a/src/commands/billing_t3.ts b/src/commands/billing_t3.ts index 4fab16d..bdc4823 100644 --- a/src/commands/billing_t3.ts +++ b/src/commands/billing_t3.ts @@ -1,20 +1,23 @@ import axios from 'axios'; import { Message } from 'eris'; +import type { Stripe } from 'stripe'; import { Client, Command } from '../class'; +import type { PromoInterface } from '../models'; export default class Billing_T3 extends Command { constructor(client: Client) { super(client); this.name = 't3'; this.description = 'Subscription to CS Tier 3.'; - this.usage = `${this.client.config.prefix}billing t3`; + this.usage = `${this.client.config.prefix}billing t3 [promoCode]`; this.permissions = 0; this.guildOnly = false; this.enabled = true; } - public async run(message: Message) { + public async run(message: Message, args: string[]) { try { + await message.delete(); const response = <{ found: boolean, emailAddress?: string, @@ -26,14 +29,25 @@ export default class Billing_T3 extends Command { const customer = await this.client.db.Customer.findOne({ userID: message.author.id }); if (!customer) return this.error(message.channel, `You do not have a Customer Account. Please run \`${this.client.config.prefix}billing\`, once you visit the Billing Portal via the URL given to you, please try again.`); - const subscription = await this.client.stripe.subscriptions.create({ - customer: customer.cusID, - payment_behavior: 'allow_incomplete', - items: [{ price: 'price_1H8e6ODatwI1hQ4WFVvX6Nda' }], - days_until_due: 1, - collection_method: 'send_invoice', - default_tax_rates: ['txr_1HlAadDatwI1hQ4WRHu14S2I'], - }); + let promoCode: PromoInterface; + if (args[0]) { + promoCode = await this.client.db.Promo.findOne({ code: args[0].toUpperCase() }); + } + + let subscription: Stripe.Response; + try { + subscription = await this.client.stripe.subscriptions.create({ + customer: customer.cusID, + payment_behavior: 'allow_incomplete', + items: [{ price: 'price_1H8e6ODatwI1hQ4WFVvX6Nda' }], + days_until_due: 1, + collection_method: 'send_invoice', + default_tax_rates: ['txr_1HlAadDatwI1hQ4WRHu14S2I'], + promotion_code: promoCode ? promoCode.id : undefined, + }); + } catch (err) { + return this.error(message.channel, `Error creating subscription.\n\n${err}`); + } await this.client.stripe.invoices.finalizeInvoice(subscription.latest_invoice.toString()); const invoice = await this.client.stripe.invoices.retrieve(subscription.latest_invoice.toString()); diff --git a/src/commands/score.ts b/src/commands/score.ts index 10c0882..6b9b2cf 100644 --- a/src/commands/score.ts +++ b/src/commands/score.ts @@ -44,7 +44,8 @@ export default class Score extends Command { user = this.client.util.resolveMember(args[0], this.mainGuild)?.user; if (!user) { const sc = await this.client.db.Score.findOne({ pin: [Number(args[0].split('-')[0]), Number(args[0].split('-')[1]), Number(args[0].split('-')[2])] }); - user = this.client.util.resolveMember(sc.userID, this.mainGuild).user; + if (!sc) return this.error(message.channel, 'Member not found.'); + user = this.client.util.resolveMember(sc.userID, this.mainGuild)?.user; } if (!user) return this.error(message.channel, 'Member not found.'); if (message.channel.type !== 0) return this.error(message.channel, 'Hard Inquiries must be initiated in a guild.'); diff --git a/src/models/Promo.ts b/src/models/Promo.ts new file mode 100644 index 0000000..adbe2b0 --- /dev/null +++ b/src/models/Promo.ts @@ -0,0 +1,13 @@ +import { Document, Schema, model } from 'mongoose'; + +export interface PromoInterface extends Document { + code: string, + pID: string, +} + +const Promo: Schema = new Schema({ + code: String, + pID: String, +}); + +export default model('Promo', Promo); diff --git a/src/models/index.ts b/src/models/index.ts index a560036..d3cc016 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -7,6 +7,7 @@ export { default as Moderation, ModerationInterface } from './Moderation'; export { default as NNTrainingData, NNTrainingDataInterface } from './NNTrainingData'; export { default as Note, NoteInterface } from './Note'; export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber'; +export { default as Promo, PromoInterface } from './Promo'; export { default as Rank, RankInterface } from './Rank'; export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect'; export { default as Score, ScoreInterface, ScoreInterfaceRaw } from './Score';