From e47721801f264e54877756fad0903a7ab24726ad Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 25 Jun 2022 12:02:22 -0400 Subject: [PATCH 01/12] Added better email sending --- package-lock.json | 30 +---------------------------- package.json | 2 +- src/mailer.js | 22 ++++++++++++++++++++++ src/util.js | 48 +++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 66 insertions(+), 36 deletions(-) create mode 100644 src/mailer.js diff --git a/package-lock.json b/package-lock.json index 17e0fea..681e34c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,13 +18,13 @@ "express-handlebars": "^5.3.1", "express-locale": "^2.0.0", "fs-extra": "^9.1.0", - "gmail-send": "^1.8.14", "got": "^11.8.2", "gray-matter": "^4.0.3", "kaitai-struct": "^0.9.0", "marked": "^4.0.10", "mongoose": "^6.4.0", "morgan": "^1.10.0", + "nodemailer": "^6.7.5", "stripe": "^9.9.0", "trello": "^0.11.0", "uuid": "^8.3.2" @@ -1954,15 +1954,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gmail-send": { - "version": "1.8.14", - "resolved": "https://registry.npmjs.org/gmail-send/-/gmail-send-1.8.14.tgz", - "integrity": "sha512-hc+4Ej7ZJtw0G5sync10pmWkpPXIabkQ+p/a92lPPTXni3ChEU9sR2wxOvK6Hx+5Ou+2m9h1cVffWEgtR6Gzkw==", - "dependencies": { - "lodash": "^4.17.21", - "nodemailer": "^6.6.5" - } - }, "node_modules/got": { "version": "11.8.2", "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", @@ -2700,11 +2691,6 @@ "node": ">= 0.8.0" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -6006,15 +5992,6 @@ "type-fest": "^0.20.2" } }, - "gmail-send": { - "version": "1.8.14", - "resolved": "https://registry.npmjs.org/gmail-send/-/gmail-send-1.8.14.tgz", - "integrity": "sha512-hc+4Ej7ZJtw0G5sync10pmWkpPXIabkQ+p/a92lPPTXni3ChEU9sR2wxOvK6Hx+5Ou+2m9h1cVffWEgtR6Gzkw==", - "requires": { - "lodash": "^4.17.21", - "nodemailer": "^6.6.5" - } - }, "got": { "version": "11.8.2", "resolved": "https://registry.npmjs.org/got/-/got-11.8.2.tgz", @@ -6538,11 +6515,6 @@ "type-check": "~0.4.0" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", diff --git a/package.json b/package.json index c9531ae..590c825 100644 --- a/package.json +++ b/package.json @@ -26,13 +26,13 @@ "express-handlebars": "^5.3.1", "express-locale": "^2.0.0", "fs-extra": "^9.1.0", - "gmail-send": "^1.8.14", "got": "^11.8.2", "gray-matter": "^4.0.3", "kaitai-struct": "^0.9.0", "marked": "^4.0.10", "mongoose": "^6.4.0", "morgan": "^1.10.0", + "nodemailer": "^6.7.5", "stripe": "^9.9.0", "trello": "^0.11.0", "uuid": "^8.3.2" diff --git a/src/mailer.js b/src/mailer.js new file mode 100644 index 0000000..51b5ebd --- /dev/null +++ b/src/mailer.js @@ -0,0 +1,22 @@ +const nodemailer = require('nodemailer'); +const config = require('../config.json'); + +const transporter = nodemailer.createTransport({ + host: 'smtp.gmail.com', + port: 587, + secure: false, + auth: { + user: config.gmail.user, + pass: config.gmail.pass + } +}); + +async function sendMail(options) { + options.from = config.gmail.from; + + return await transporter.sendMail(options); +} + +module.exports = { + sendMail +}; \ No newline at end of file diff --git a/src/util.js b/src/util.js index c5b10a9..da2edae 100644 --- a/src/util.js +++ b/src/util.js @@ -1,14 +1,13 @@ const fs = require('fs-extra'); const got = require('got'); const crypto = require('crypto'); -const gmail = require('gmail-send'); const Stripe = require('stripe'); +const mailer = require('./mailer'); const database = require('./database'); const logger = require('./logger'); const config = require('../config.json'); const stripe = new Stripe(config.stripe.secret_key); -const sendGmail = gmail(config.gmail); function fullUrl(request) { return `${request.protocol}://${request.hostname}${request.originalUrl}`; @@ -93,9 +92,9 @@ async function handleStripeEvent(event) { }); try { - await sendGmail({ + await mailer.sendMail({ to: customer.email, - subject: 'Pretendo Subscription Failed - No Linked PNID', + subject: 'Pretendo Network Subscription Failed - No Linked PNID', text: `Your recent subscription to Pretendo Network has failed.\nThis is due to no PNID PID being linked to the Stripe customer account used. The subscription has been canceled and refunded. Please contact Jon immediately.\nStripe Customer ID: ${customer.id}` }); } catch (error) { @@ -128,9 +127,9 @@ async function handleStripeEvent(event) { }); try { - await sendGmail({ + await mailer.sendMail({ to: customer.email, - subject: 'Pretendo Subscription Failed - PNID Not Found', + subject: 'Pretendo Network Subscription Failed - PNID Not Found', text: `Your recent subscription to Pretendo Network has failed.\nThis is due to the provided PNID not being found. The subscription has been canceled and refunded. Please contact Jon immediately.\nStripe Customer ID: ${customer.id}\nPNID PID: ${pid}` }); } catch (error) { @@ -171,6 +170,43 @@ async function handleStripeEvent(event) { await database.PNID.updateOne({ pid }, { $set: updateData }, { upsert: true }).exec(); } + + if (subscription.status === 'active') { + try { + await mailer.sendMail({ + to: customer.email, + subject: 'Pretendo Network Subscription - Active', + text: `Thank you for purchasing the ${product.name} tier! We greatly value your support, thank you for helping keep Pretendo Network alive!\nIt may take a moment for your account dashboard to reflect these changes. Please wait a moment and refresh the dashboard to see them!` + }); + } catch (error) { + logger.error(`Error sending email | ${customer.id}, ${customer.email}, ${pid} | - ${error.message}`); + } + } + + if (subscription.status === 'canceled') { + try { + await mailer.sendMail({ + to: customer.email, + subject: 'Pretendo Network Subscription - Canceled', + text: `Your subscription for the ${product.name} tier has been canceled. We thank for your previous support, and hope you still enjoy the network! ` + }); + } catch (error) { + logger.error(`Error sending email | ${customer.id}, ${customer.email}, ${pid} | - ${error.message}`); + } + } + + if (subscription.status === 'unpaid') { + try { + await mailer.sendMail({ + to: customer.email, + subject: 'Pretendo Network Subscription - Unpaid', + text: `Your subscription for the ${product.name} tier has been canceled due to non payment. We thank for your previous support, and hope you still enjoy the network! ` + }); + } catch (error) { + logger.error(`Error sending email | ${customer.id}, ${customer.email}, ${pid} | - ${error.message}`); + } + } + } } From d97ed180f53bd80816b32f3014b350ffdec53237 Mon Sep 17 00:00:00 2001 From: Jonathan Barrow Date: Sat, 25 Jun 2022 19:55:39 -0400 Subject: [PATCH 02/12] Change tier --- public/assets/css/account.css | 8 ++++-- src/routers/account.js | 48 +++++++++++++++++++++++++++----- views/account/account.handlebars | 17 +++++++---- views/account/upgrade.handlebars | 24 ++++++++-------- 4 files changed, 70 insertions(+), 27 deletions(-) diff --git a/public/assets/css/account.css b/public/assets/css/account.css index dbb4739..42a8dbe 100644 --- a/public/assets/css/account.css +++ b/public/assets/css/account.css @@ -31,7 +31,8 @@ border-radius: 100%; background: var(--btn-secondary); } -.account-sidebar .user #download-cemu-files { +.account-sidebar .user #download-cemu-files, +.account-sidebar .user #account-upgrade { display: flex; flex-flow: column; align-items: center; @@ -40,7 +41,8 @@ margin: 24px 0 0; text-decoration: none; } -.account-sidebar .user #download-cemu-files p.download-caption { +.account-sidebar .user #download-cemu-files p.caption, +.account-sidebar .user #account-upgrade p.caption { margin: 15px 0 0; } .account-sidebar .user p.cemu-warning { @@ -152,7 +154,7 @@ fieldset:disabled form label { color: var(--text); } -.setting-card #remove-discord-connection { +.setting-card #link-discord-account { width: 100%; padding: 12px 48px; cursor: pointer; diff --git a/src/routers/account.js b/src/routers/account.js index e6c6873..a8d0596 100644 --- a/src/routers/account.js +++ b/src/routers/account.js @@ -29,7 +29,7 @@ router.get('/', async (request, response) => { } const { upgrade_success } = request.query; - console.log(upgrade_success); + const stripe = {}; if (upgrade_success === 'true') { stripe.showNotice = true; @@ -193,6 +193,8 @@ router.get('/', async (request, response) => { renderData.discordAuthURL = discordAuthURL; } + renderData.isTester = false; + response.render('account/account', renderData); }); @@ -616,16 +618,48 @@ router.post('/checkout/:priceId', async (request, response) => { await database.PNID.updateOne({ pid }, { $set: { - connections: { - stripe: { - customer_id: customer.id // ensure PNID always has latest customer ID - } - } + 'connections.stripe.customer_id': customer.id // ensure PNID always has latest customer ID } }, { upsert: true }).exec(); const priceId = request.params.priceId; + const pnid = await database.PNID.findOne({ pid }); + + if (pnid.get('access_level') >= 2) { + response.cookie('error', 'Staff members do not need to purchase tiers', { domain: '.pretendo.network' }); + return response.redirect('/account'); + } + + const stripeConnection = pnid.get('connections.stripe'); + + if (stripeConnection.subscription_id) { + // User already has a subscription with us + if (stripeConnection.price_id === priceId) { + response.cookie('error', 'Already subscribed to this tier', { domain: '.pretendo.network' }); + return response.redirect('/account'); + } + + try { + const subscription = await stripe.subscriptions.retrieve(stripeConnection.subscription_id); + stripe.subscriptions.update(stripeConnection.subscription_id, { + cancel_at_period_end: false, + proration_behavior: 'always_invoice', + items: [{ + id: subscription.items.data[0].id, + price: priceId, + }] + }); + + return response.redirect('/account?upgrade_success=true'); + } catch (error) { + // Maybe we need a dedicated error page? + // Or handle this as not cookies? + response.cookie('error', error.message, { domain: '.pretendo.network' }); + return response.redirect('/account'); + } + } + try { const session = await stripe.checkout.sessions.create({ line_items: [ @@ -643,7 +677,7 @@ router.post('/checkout/:priceId', async (request, response) => { return response.redirect(303, session.url); } catch (error) { // Maybe we need a dedicated error page? - // O handle this as not cookies? + // Or handle this as not cookies? response.cookie('error', error.message, { domain: '.pretendo.network' }); return response.redirect('/account'); } diff --git a/views/account/account.handlebars b/views/account/account.handlebars index 870300b..b39ad53 100644 --- a/views/account/account.handlebars +++ b/views/account/account.handlebars @@ -12,9 +12,13 @@

PNID: {{account.username}}

-

Download account files

+

Download account files

(will not work on Nintendo Network)

+ + +

Upgrade Account

+
@@ -52,8 +56,8 @@
-

Beta access

- {{#if isTester}} +

Server Environment

+ {{#if isTester}}
@@ -81,10 +85,13 @@

Connected to Discord as {{ discordUser.username }}#{{ discordUser.discriminator }}

{{else}} -

To gain access to the developer chats, run /command in the server.

+ + + {{/if}} {{else}} -

Beta servers are exclusive to testers. To upgrade to a higher tier, click here.

+

Account is not a beta tester, locked to production servers.

+

Beta servers are exclusive to beta testers.
To become a beta tester, upgrade to a higher account tier.

{{/if}}
diff --git a/views/account/upgrade.handlebars b/views/account/upgrade.handlebars index 55e7d23..e269420 100644 --- a/views/account/upgrade.handlebars +++ b/views/account/upgrade.handlebars @@ -26,43 +26,43 @@ - +

Upgrade

Subscribing to a tier gives you access to our developer chats and, depending on the tier, to our beta servers. Please someone reword this, it sucks. No fr.

- - {{#each tiers}} + + {{#each tiers}} - + {{/each}}
- - + + \ No newline at end of file + \ No newline at end of file diff --git a/views/account/upgrade.handlebars b/views/account/upgrade.handlebars index 5d1f144..4d5ad46 100644 --- a/views/account/upgrade.handlebars +++ b/views/account/upgrade.handlebars @@ -6,8 +6,8 @@ Back - - +