mirror of
https://github.com/PretendoNetwork/website.git
synced 2026-09-28 19:47:00 -05:00
Merge pull request #149 from PretendoNetwork/feature-assign-discord-roles
Feature assign discord roles
This commit is contained in:
@@ -147,6 +147,7 @@ router.get('/logout', async(_request, response) => {
|
||||
});
|
||||
|
||||
router.get('/connect/discord', requireLoginMiddleware, async (request, response) => {
|
||||
const { pnid } = request;
|
||||
let tokens;
|
||||
try {
|
||||
// Attempt to get OAuth2 tokens
|
||||
@@ -166,8 +167,52 @@ router.get('/connect/discord', requireLoginMiddleware, async (request, response)
|
||||
try {
|
||||
await util.updateDiscordConnection(discordUser, request, response);
|
||||
|
||||
const priceId = pnid.get('connections.stripe.price_id');
|
||||
|
||||
if (priceId && priceId.trim() !== '') {
|
||||
const price = await stripe.prices.retrieve(priceId);
|
||||
const product = await stripe.products.retrieve(price.product);
|
||||
const discordRoleId = product.metadata.discord_role_id;
|
||||
const discordId = discordUser.id;
|
||||
|
||||
await util.assignDiscordMemberSupporterRole(discordId, discordRoleId);
|
||||
|
||||
if (product.metadata.beta === 'true') {
|
||||
await util.assignDiscordMemberTesterRole(discordId);
|
||||
}
|
||||
}
|
||||
|
||||
response.cookie('success_message', 'Discord account linked successfully', { domain: '.pretendo.network' });
|
||||
response.redirect('/account');
|
||||
return response.redirect('/account');
|
||||
} catch (error) {
|
||||
response.cookie('error_message', error.message, { domain: '.pretendo.network' });
|
||||
return response.redirect('/account');
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/remove/discord', requireLoginMiddleware, async (request, response) => {
|
||||
const { account, pnid } = request;
|
||||
|
||||
try {
|
||||
await util.removeDiscordConnection(request, response);
|
||||
|
||||
const priceId = pnid.get('connections.stripe.price_id');
|
||||
|
||||
if (priceId && priceId.trim() !== '') {
|
||||
const price = await stripe.prices.retrieve(priceId);
|
||||
const product = await stripe.products.retrieve(price.product);
|
||||
const discordRoleId = product.metadata.discord_role_id;
|
||||
const discordId = account.connections.discord.id;
|
||||
|
||||
await util.removeDiscordMemberSupporterRole(discordId, discordRoleId);
|
||||
|
||||
if (product.metadata.beta === 'true') {
|
||||
await util.removeDiscordMemberTesterRole(discordId);
|
||||
}
|
||||
}
|
||||
|
||||
response.cookie('success_message', 'Discord account removed successfully', { domain: '.pretendo.network' });
|
||||
return response.redirect('/account');
|
||||
} catch (error) {
|
||||
response.cookie('error_message', error.message, { domain: '.pretendo.network' });
|
||||
return response.redirect('/account');
|
||||
@@ -298,8 +343,8 @@ router.post('/stripe/checkout/:priceId', requireLoginMiddleware, async (request,
|
||||
const pnid = await database.PNID.findOne({ pid });
|
||||
|
||||
if (pnid.get('access_level') >= 2) {
|
||||
response.cookie('error_message', 'Staff members do not need to purchase tiers', { domain: '.pretendo.network' });
|
||||
return response.redirect('/account');
|
||||
//response.cookie('error_message', 'Staff members do not need to purchase tiers', { domain: '.pretendo.network' });
|
||||
//return response.redirect('/account');
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -365,14 +410,15 @@ router.post('/stripe/unsubscribe', requireLoginMiddleware, async (request, respo
|
||||
return response.redirect('/account');
|
||||
});
|
||||
|
||||
router.post('/stripe/webhook', express.raw({ type: 'application/json' }), async (request, response) => {
|
||||
router.post('/stripe/webhook', async (request, response) => {
|
||||
const stripeSignature = request.headers['stripe-signature'];
|
||||
let event;
|
||||
|
||||
try {
|
||||
event = stripe.webhooks.constructEvent(request.body, stripeSignature, config.stripe.webhook_secret);
|
||||
} catch (err) {
|
||||
return response.status(400).send(`Webhook Error: ${err.message}`);
|
||||
event = stripe.webhooks.constructEvent(request.rawBody, stripeSignature, config.stripe.webhook_secret);
|
||||
} catch (error) {
|
||||
logger.error(error.message);
|
||||
return response.status(400).send(`Webhook Error: ${error.message}`);
|
||||
}
|
||||
|
||||
await util.handleStripeEvent(event);
|
||||
|
||||
@@ -20,7 +20,8 @@ const stripe = new Stripe(config.stripe.secret_key);
|
||||
|
||||
logger.info('Setting up Middleware');
|
||||
app.use(morgan('dev'));
|
||||
app.use(express.json());
|
||||
//app.use(express.json());
|
||||
app.use(express.json({ verify: (req, res, buf) => { req.rawBody = buf; } }));
|
||||
app.use(express.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
|
||||
100
src/util.js
100
src/util.js
@@ -4,11 +4,14 @@ const got = require('got');
|
||||
const crypto = require('crypto');
|
||||
const Stripe = require('stripe');
|
||||
const { marked } = require('marked');
|
||||
const { REST: DiscordRest } = require('@discordjs/rest');
|
||||
const { Routes: DiscordRoutes } = require('discord-api-types/v10');
|
||||
const mailer = require('./mailer');
|
||||
const database = require('./database');
|
||||
const logger = require('./logger');
|
||||
const config = require('../config.json');
|
||||
|
||||
const discordRest = new DiscordRest({ version: '10' }).setToken(config.discord.bot_token);
|
||||
|
||||
const stripe = new Stripe(config.stripe.secret_key);
|
||||
|
||||
@@ -78,7 +81,7 @@ function apiGetRequest(path, headers) {
|
||||
});
|
||||
}
|
||||
|
||||
function apiPostGetRequest(path, headers, json) {
|
||||
function apiPostRequest(path, headers, json) {
|
||||
return got.post(`https://api.pretendo.cc${path}`, {
|
||||
responseType: 'json',
|
||||
throwHttpErrors: false,
|
||||
@@ -90,7 +93,7 @@ function apiPostGetRequest(path, headers, json) {
|
||||
});
|
||||
}
|
||||
|
||||
function apiDeleteGetRequest(path, headers, json) {
|
||||
function apiDeleteRequest(path, headers, json) {
|
||||
return got.delete(`https://api.pretendo.cc${path}`, {
|
||||
throwHttpErrors: false,
|
||||
https: {
|
||||
@@ -102,7 +105,7 @@ function apiDeleteGetRequest(path, headers, json) {
|
||||
}
|
||||
|
||||
async function register(registerData) {
|
||||
const apiResponse = await apiPostGetRequest('/v1/register', {}, registerData);
|
||||
const apiResponse = await apiPostRequest('/v1/register', {}, registerData);
|
||||
|
||||
if (apiResponse.statusCode !== 200) {
|
||||
throw new Error(apiResponse.body.error);
|
||||
@@ -112,7 +115,7 @@ async function register(registerData) {
|
||||
}
|
||||
|
||||
async function login(username, password) {
|
||||
const apiResponse = await apiPostGetRequest('/v1/login', {}, {
|
||||
const apiResponse = await apiPostRequest('/v1/login', {}, {
|
||||
username,
|
||||
password,
|
||||
grant_type: 'password'
|
||||
@@ -126,7 +129,7 @@ async function login(username, password) {
|
||||
}
|
||||
|
||||
async function refreshLogin(request, response) {
|
||||
const apiResponse = await apiPostGetRequest('/v1/login', {}, {
|
||||
const apiResponse = await apiPostRequest('/v1/login', {}, {
|
||||
refresh_token: request.cookies.refresh_token,
|
||||
grant_type: 'refresh_token'
|
||||
});
|
||||
@@ -166,7 +169,7 @@ async function getUserAccountData(request, response, fromRetry=false) {
|
||||
}
|
||||
|
||||
async function updateDiscordConnection(discordUser, request, response, fromRetry=false) {
|
||||
const apiResponse = await apiPostGetRequest('/v1/connections/add/discord', {
|
||||
const apiResponse = await apiPostRequest('/v1/connections/add/discord', {
|
||||
'Authorization': `${request.cookies.token_type} ${request.cookies.access_token}`
|
||||
}, {
|
||||
data: {
|
||||
@@ -185,6 +188,22 @@ async function updateDiscordConnection(discordUser, request, response, fromRetry
|
||||
}
|
||||
}
|
||||
|
||||
async function removeDiscordConnection(request, response, fromRetry = false) {
|
||||
const apiResponse = await apiDeleteRequest('/v1/connections/remove/discord', {
|
||||
'Authorization': `${request.cookies.token_type} ${request.cookies.access_token}`
|
||||
});
|
||||
|
||||
if (apiResponse.statusCode !== 200 && fromRetry === true) {
|
||||
// TODO: Error message
|
||||
throw new Error('Bad');
|
||||
}
|
||||
|
||||
if (apiResponse.statusCode !== 200) {
|
||||
await refreshLogin(request, response);
|
||||
await removeDiscordConnection(request, response, true);
|
||||
}
|
||||
}
|
||||
|
||||
function nintendoPasswordHash(password, pid) {
|
||||
const pidBuffer = Buffer.alloc(4);
|
||||
pidBuffer.writeUInt32LE(pid);
|
||||
@@ -270,9 +289,19 @@ async function handleStripeEvent(event) {
|
||||
}
|
||||
|
||||
const currentSubscriptionId = pnid.get('connections.stripe.subscription_id');
|
||||
const discordId = pnid.get('connections.discord.id');
|
||||
|
||||
if (subscription.status === 'canceled' && currentSubscriptionId && subscription.id !== currentSubscriptionId) {
|
||||
// Canceling old subscription, do nothing but update webhook date
|
||||
// Canceling old subscription, do nothing but update webhook date and remove Discord roles
|
||||
if (product.metadata.beta === 'true') {
|
||||
removeDiscordMemberTesterRole(discordId).catch(error => {
|
||||
logger.error(`Error removing user Discord tester role | ${customer.id}, ${discordId}, ${pid} | - ${error.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
removeDiscordMemberSupporterRole(discordId, product.metadata.discord_role_id).catch(error => {
|
||||
logger.error(`Error removing user Discord supporter role | ${customer.id}, ${discordId}, ${pid}, ${product.metadata.discord_role_id} | - ${error.message}`);
|
||||
});
|
||||
|
||||
const updateData = {
|
||||
'connections.stripe.latest_webhook_timestamp': event.created
|
||||
@@ -302,6 +331,10 @@ async function handleStripeEvent(event) {
|
||||
if (pnid.access_level < 2) { // only change access level if not staff member
|
||||
updateData.access_level = 1;
|
||||
}
|
||||
|
||||
assignDiscordMemberTesterRole(discordId).catch(error => {
|
||||
logger.error(`Error assigning user Discord tester role | ${customer.id}, ${discordId}, ${pid} | - ${error.message}`);
|
||||
});
|
||||
break;
|
||||
|
||||
case 'canceled': // Subscription was canceled
|
||||
@@ -309,6 +342,10 @@ async function handleStripeEvent(event) {
|
||||
if (pnid.access_level < 2) { // only change access level if not staff member
|
||||
updateData.access_level = 0;
|
||||
}
|
||||
|
||||
removeDiscordMemberTesterRole(discordId).catch(error => {
|
||||
logger.error(`Error removing user Discord tester role | ${customer.id}, ${discordId}, ${pid} | - ${error.message}`);
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -353,6 +390,10 @@ async function handleStripeEvent(event) {
|
||||
} catch (error) {
|
||||
logger.error(`Error sending email | ${customer.id}, ${customer.email}, ${pid} | - ${error.message}`);
|
||||
}
|
||||
|
||||
assignDiscordMemberSupporterRole(discordId, product.metadata.discord_role_id).catch(error => {
|
||||
logger.error(`Error assigning user Discord supporter role | ${customer.id}, ${discordId}, ${pid}, ${product.metadata.discord_role_id} | - ${error.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (subscription.status === 'canceled') {
|
||||
@@ -365,6 +406,10 @@ async function handleStripeEvent(event) {
|
||||
} catch (error) {
|
||||
logger.error(`Error sending email | ${customer.id}, ${customer.email}, ${pid} | - ${error.message}`);
|
||||
}
|
||||
|
||||
removeDiscordMemberSupporterRole(discordId, product.metadata.discord_role_id).catch(error => {
|
||||
logger.error(`Error removing user Discord supporter role | ${customer.id}, ${discordId}, ${pid}, ${product.metadata.discord_role_id} | - ${error.message}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (subscription.status === 'unpaid') {
|
||||
@@ -377,23 +422,58 @@ async function handleStripeEvent(event) {
|
||||
} catch (error) {
|
||||
logger.error(`Error sending email | ${customer.id}, ${customer.email}, ${pid} | - ${error.message}`);
|
||||
}
|
||||
|
||||
removeDiscordMemberSupporterRole(discordId, product.metadata.discord_role_id).catch(error => {
|
||||
logger.error(`Error removing user Discord supporter role | ${customer.id}, ${discordId}, ${pid}, ${product.metadata.discord_role_id} | - ${error.message}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function assignDiscordMemberSupporterRole(memberId, roleId) {
|
||||
if (memberId && memberId.trim() !== '') {
|
||||
await discordRest.put(DiscordRoutes.guildMemberRole(config.discord.guild_id, memberId, config.discord.roles.supporter));
|
||||
await discordRest.put(DiscordRoutes.guildMemberRole(config.discord.guild_id, memberId, roleId));
|
||||
}
|
||||
}
|
||||
|
||||
async function assignDiscordMemberTesterRole(memberId) {
|
||||
if (memberId && memberId.trim() !== '') {
|
||||
await discordRest.put(DiscordRoutes.guildMemberRole(config.discord.guild_id, memberId, config.discord.roles.tester));
|
||||
}
|
||||
}
|
||||
|
||||
async function removeDiscordMemberSupporterRole(memberId, roleId) {
|
||||
if (memberId && memberId.trim() !== '') {
|
||||
await discordRest.delete(DiscordRoutes.guildMemberRole(config.discord.guild_id, memberId, config.discord.roles.supporter));
|
||||
await discordRest.delete(DiscordRoutes.guildMemberRole(config.discord.guild_id, memberId, roleId));
|
||||
}
|
||||
}
|
||||
|
||||
async function removeDiscordMemberTesterRole(memberId) {
|
||||
if (memberId && memberId.trim() !== '') {
|
||||
await discordRest.delete(DiscordRoutes.guildMemberRole(config.discord.guild_id, memberId, config.discord.roles.tester));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fullUrl,
|
||||
getLocale,
|
||||
getRawDocs,
|
||||
parseDocs,
|
||||
apiGetRequest,
|
||||
apiPostGetRequest,
|
||||
apiDeleteGetRequest,
|
||||
apiPostRequest,
|
||||
apiDeleteRequest,
|
||||
register,
|
||||
login,
|
||||
refreshLogin,
|
||||
getUserAccountData,
|
||||
updateDiscordConnection,
|
||||
removeDiscordConnection,
|
||||
nintendoPasswordHash,
|
||||
handleStripeEvent
|
||||
handleStripeEvent,
|
||||
assignDiscordMemberSupporterRole,
|
||||
assignDiscordMemberTesterRole,
|
||||
removeDiscordMemberSupporterRole,
|
||||
removeDiscordMemberTesterRole
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user