changes for coupon codes and various fixes

pull/29/head
Matthew 2020-11-09 23:55:10 -05:00
parent 5555913586
commit add982a73e
No known key found for this signature in database
GPG Key ID: 210AF32ADE3B5C4B
6 changed files with 66 additions and 14 deletions

View File

@ -4,7 +4,24 @@ import pluris from 'pluris';
import mongoose from 'mongoose'; import mongoose from 'mongoose';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import { Collection, Command, LocalStorage, Queue, Util, ServerManagement, Event } from '.'; 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 import { Config } from '../../types'; // eslint-disable-line
pluris(eris); pluris(eris);
@ -26,7 +43,7 @@ export default class Client extends eris.Client {
public stripe: Stripe; public stripe: Stripe;
public db: { Customer: mongoose.Model<CustomerInterface>, CustomerPortal: mongoose.Model<CustomerPortalInterface>, File: mongoose.Model<FileInterface>, Member: mongoose.Model<MemberInterface>, Merchant: mongoose.Model<MerchantInterface>, Moderation: mongoose.Model<ModerationInterface>, NNTrainingData: mongoose.Model<NNTrainingDataInterface>, Note: mongoose.Model<NoteInterface>, PagerNumber: mongoose.Model<PagerNumberInterface>, Rank: mongoose.Model<RankInterface>, Redirect: mongoose.Model<RedirectInterface>, Score: mongoose.Model<ScoreInterface>, ScoreHistorical: mongoose.Model<ScoreHistoricalInterface>, Staff: mongoose.Model<StaffInterface>, Stat: mongoose.Model<StatInterface>, local: { muted: LocalStorage } }; public db: { Customer: mongoose.Model<CustomerInterface>, CustomerPortal: mongoose.Model<CustomerPortalInterface>, File: mongoose.Model<FileInterface>, Member: mongoose.Model<MemberInterface>, Merchant: mongoose.Model<MerchantInterface>, Moderation: mongoose.Model<ModerationInterface>, NNTrainingData: mongoose.Model<NNTrainingDataInterface>, Note: mongoose.Model<NoteInterface>, PagerNumber: mongoose.Model<PagerNumberInterface>, Promo: mongoose.Model<PromoInterface>, Rank: mongoose.Model<RankInterface>, Redirect: mongoose.Model<RedirectInterface>, Score: mongoose.Model<ScoreInterface>, ScoreHistorical: mongoose.Model<ScoreHistoricalInterface>, Staff: mongoose.Model<StaffInterface>, Stat: mongoose.Model<StatInterface>, local: { muted: LocalStorage } };
constructor(token: string, options?: eris.ClientOptions) { constructor(token: string, options?: eris.ClientOptions) {
super(token, options); super(token, options);
@ -34,7 +51,7 @@ export default class Client extends eris.Client {
this.events = new Collection<Event>(); this.events = new Collection<Event>();
this.intervals = new Collection<NodeJS.Timeout>(); this.intervals = new Collection<NodeJS.Timeout>();
this.queue = new Queue(this); 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') } };
} }

View File

@ -76,6 +76,11 @@ export default class Apply extends Command {
first_time_transaction: true, 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); 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.*`); 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; 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.*`); 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.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp(); embed.setTimestamp();
return message.channel.createMessage({ embed }); return message.channel.createMessage({ embed });

View File

@ -1,20 +1,23 @@
import axios from 'axios'; import axios from 'axios';
import { Message } from 'eris'; import { Message } from 'eris';
import type { Stripe } from 'stripe';
import { Client, Command } from '../class'; import { Client, Command } from '../class';
import type { PromoInterface } from '../models';
export default class Billing_T3 extends Command { export default class Billing_T3 extends Command {
constructor(client: Client) { constructor(client: Client) {
super(client); super(client);
this.name = 't3'; this.name = 't3';
this.description = 'Subscription to CS Tier 3.'; 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.permissions = 0;
this.guildOnly = false; this.guildOnly = false;
this.enabled = true; this.enabled = true;
} }
public async run(message: Message) { public async run(message: Message, args: string[]) {
try { try {
await message.delete();
const response = <{ const response = <{
found: boolean, found: boolean,
emailAddress?: string, 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 }); 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.`); 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({ let promoCode: PromoInterface;
customer: customer.cusID, if (args[0]) {
payment_behavior: 'allow_incomplete', promoCode = await this.client.db.Promo.findOne({ code: args[0].toUpperCase() });
items: [{ price: 'price_1H8e6ODatwI1hQ4WFVvX6Nda' }], }
days_until_due: 1,
collection_method: 'send_invoice', let subscription: Stripe.Response<Stripe.Subscription>;
default_tax_rates: ['txr_1HlAadDatwI1hQ4WRHu14S2I'], 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()); await this.client.stripe.invoices.finalizeInvoice(subscription.latest_invoice.toString());
const invoice = await this.client.stripe.invoices.retrieve(subscription.latest_invoice.toString()); const invoice = await this.client.stripe.invoices.retrieve(subscription.latest_invoice.toString());

View File

@ -44,7 +44,8 @@ export default class Score extends Command {
user = this.client.util.resolveMember(args[0], this.mainGuild)?.user; user = this.client.util.resolveMember(args[0], this.mainGuild)?.user;
if (!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])] }); 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 (!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.'); if (message.channel.type !== 0) return this.error(message.channel, 'Hard Inquiries must be initiated in a guild.');

13
src/models/Promo.ts Normal file
View File

@ -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<PromoInterface>('Promo', Promo);

View File

@ -7,6 +7,7 @@ export { default as Moderation, ModerationInterface } from './Moderation';
export { default as NNTrainingData, NNTrainingDataInterface } from './NNTrainingData'; export { default as NNTrainingData, NNTrainingDataInterface } from './NNTrainingData';
export { default as Note, NoteInterface } from './Note'; export { default as Note, NoteInterface } from './Note';
export { default as PagerNumber, PagerNumberInterface, PagerNumberRaw } from './PagerNumber'; 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 Rank, RankInterface } from './Rank';
export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect'; export { default as Redirect, RedirectInterface, RedirectRaw } from './Redirect';
export { default as Score, ScoreInterface, ScoreInterfaceRaw } from './Score'; export { default as Score, ScoreInterface, ScoreInterfaceRaw } from './Score';