const express = require('express'); const router = express.Router(); const pool = global.db_pool; const log = global.log; router.get('/getSession', async (req, res) => { if (!req.headers.authorization) return res.status(401).json({ status: 401, message: 'Missing Authorization Header', data: {} }); const [hub] = await pool.query('SELECT * FROM hubs WHERE secretKey = ?', [req.headers.authorization]); if (!hub) return res.status(401).json({ status: 401, message: 'Invalid Authorization Header', data: {} }); try { const pid = req.query.robloxPlayerId; if (!pid) return res.status(400).json({ status: 400, message: 'Missing Roblox Player ID' }); log.info(`GET /hub/getSession?robloxPlayerId=${pid}`); const [row] = await pool.query('SELECT * FROM users WHERE robloxId = ?', [pid]); if (!row) { const pairingCode = Math.floor(100000 + Math.random() * 900000).toString(); await pool.query('INSERT INTO users (robloxId, pairingCode) VALUES (?, ?)', [pid, pairingCode]); return res.status(409).json({ status: 409, message: `User is not paired! Run /link ${pairingCode} on Discord!`, pairingCode, data: {} }); } else if (!row.discordId && !row.pairingCode) { const pairingCode = Math.floor(100000 + Math.random() * 900000).toString(); await pool.query('UPDATE users SET pairingCode = ? WHERE robloxId = ?', [pairingCode, pid]); return res.status(409).json({ status: 409, message: `User is not paired! Run /link ${pairingCode} on Discord!`, pairingCode, data: {} }); } else if (!row.discordId && row.pairingCode !== null) { return res.status(409).json({ status: 409, message: `User is not paired! Run /link ${row.pairingCode} on Discord!`, data: {} }); } else { try { const products = await pool.query('SELECT * FROM products WHERE hubId = ?', [hub.id]); const purchases = await pool.query('SELECT * FROM purchases WHERE hubId = ?', [hub.id]); // Generate bestSeller object from purchases. Find what product id has the most sales, then make the object const purchaseCounts = purchases.reduce((acc, purchase) => { acc[purchase.productId] = (acc[purchase.productId] || 0) + 1; return acc; }, {}); const bestSellerProductId = Object.keys(purchaseCounts).reduce((a, b) => purchaseCounts[a] > purchaseCounts[b] ? a : b, null); const bestSellerProduct = products.find(product => product.id == bestSellerProductId); const bestSeller = bestSellerProduct ? { productID: bestSellerProduct.id, name: bestSellerProduct.name, description: bestSellerProduct.description, devproduct_id: (bestSellerProduct.stock == 0) ? 0 : bestSellerProduct.devProductID, decalID: bestSellerProduct.decalId || "0", stock: bestSellerProduct.stock == -1 ? false : bestSellerProduct.stock, onsale: bestSellerProduct.stock == -1 || bestSellerProduct.stock > 0 ? true : false, category: bestSellerProduct.stock == -1 || bestSellerProduct.stock > 0 ? bestSellerProduct.category : "Out of Stock", rating: { currentScore: 0, maxScore: 0, amountOfReviews: 0 }, tags: [], playerData: { robloxId: pid, ownsProduct: purchases.some(purchase => purchase.productId == bestSellerProduct.id && purchase.robloxId == pid) } } : {}; // generate array of products const respData = JSON.stringify({ status: 200, message: "OK", data: { userData: { connectedUsername: row.discordDisplayName, }, hubData: { id: hub.id, name: hub.name, description: { shortDescription: hub.shortDescription, longDescription: hub.longDescription, }, config: { allowGiftPurchases: hub.allowGiftPurchase ? true : false, }, statistics: { totalSales: purchases.length, }, regulatory: { termsOfService: hub.tos }, }, productsData: { bestsellerProduct: bestSeller, allProducts: products.map(product => ({ productID: product.id, name: product.name, description: product.description, devproduct_id: (product.stock == 0) ? 0 : product.devProductID, decalID: product.decalId || "0", stock: (product.stock == -1 || purchases.some(purchase => purchase.productId == product.id && purchase.robloxId == pid)) ? false : product.stock, onsale: product.stock == -1 || product.stock > 0 ? true : false, category: product.stock == -1 || product.stock > 0 ? product.category : "Out of Stock", rating: { currentScore: 0, maxScore: 0, amountOfReviews: 0 }, tags: [], playerData: { robloxId: pid, ownsProduct: purchases.some(purchase => purchase.productId == product.id && purchase.robloxId == pid) } })), }, robloxGame: { musicId: hub.musicId, }, requestedAt: new Date().toISOString(), } }, (_, v) => typeof v === 'bigint' ? v.toString() : v) return res.status(200).send(respData) } catch (error) { log.error(error); return res.status(500).json({ status: 500, message: 'Internal Server Error', data: {} }); } } } catch (error) { log.error(error); return res.status(500).json({ status: 500, message: 'Internal Server Error', data: {} }); } }); module.exports = router;