Files
TurboTrades/seed-transactions.js
2026-01-10 04:57:43 +00:00

340 lines
12 KiB
JavaScript

import mongoose from "mongoose";
import User from "./models/User.js";
import Session from "./models/Session.js";
import Transaction from "./models/Transaction.js";
import dotenv from "dotenv";
dotenv.config();
const MONGODB_URI =
process.env.MONGODB_URI || "mongodb://localhost:27017/turbotrades";
// Transaction types and their properties
const transactionTypes = [
{
type: "deposit",
direction: "positive",
descriptions: [
"PayPal deposit",
"Stripe payment",
"Crypto deposit",
"Balance top-up",
],
},
{
type: "withdrawal",
direction: "negative",
descriptions: [
"PayPal withdrawal",
"Bank transfer",
"Crypto withdrawal",
"Cash out",
],
},
{
type: "purchase",
direction: "negative",
descriptions: [
{
name: "AWP | Dragon Lore",
image:
"https://community.cloudflare.steamstatic.com/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot621FAR17PLfYQJD_9W7m5a0mvLwOq7cqWdQ-sJ0teXI8oThxlawrRI9fSmtc9TCJgI2ZlyDq1jvxuq5g8W6v5SYwXU37yEl7S7em0TmiRhEZ-BxxavJZlnsNrA/360fx360f",
},
{
name: "Karambit | Fade",
image:
"https://community.cloudflare.steamstatic.com/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpovbSsLQJf2PLacDBA5ciJlY20k_jkI7fUhFRc4cJ5ntbN9J7yjRrm-UBrNzykI9CcdwRtaV3R-lS8xOu-hpK1u8zPzCRmuiEj-z-DyIHVYeJG/360fx360f",
},
{
name: "M4A4 | Howl",
image:
"https://community.cloudflare.steamstatic.com/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpou-6kejhz2v_Nfz5H_uO1gb-Gw_alIITSg3tu5Mx2gv2PqNnz3le1-Etr9zqrOoWVcFU3M16FqVG5kO_qhcW4v8_AynZ9-n51s35gZPo/360fx360f",
},
{
name: "Glock-18 | Fade",
image:
"https://community.cloudflare.steamstatic.com/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgposbaqKAxf0Ob3djFN79eJkIGZqPv1IbfQmGpD6e11jOzA4YfwjAy3_0ttamv6INWVe1RvZ1vY-li9lbzqhp7vusvXiSw0I5LNEws/360fx360f",
},
{
name: "AK-47 | Fire Serpent",
image:
"https://community.cloudflare.steamstatic.com/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08-mkYGHqPv9NLPF2GpVvZIpi-yWo96l2AK3-kZvYjv6cYOWcQU-YlrQ-1C9xb--gZLutczMmHtivj5iuyiMF8f2Bg/360fx360f",
},
],
},
{
type: "sale",
direction: "positive",
descriptions: [
{
name: "Sold AWP | Asiimov",
image:
"https://community.cloudflare.steamstatic.com/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot621FAR17PLfYQJD_9W7m5a0mvLwOq7c2GpTu8Ah2ezDpIqh3wO1rhFuNW2gIoPDcQU_YlyE-gW9k-_ugJO86czXiSw0jMXQfH8/360fx360f",
},
{
name: "Sold Butterfly Knife",
image:
"https://community.cloudflare.steamstatic.com/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpovbSsLQJf0ebcZThQ6tCvq4GGqPD1I6vdk1Rd4cJ5nqeQpYmtjVHm_RJlNTiiLYGddABvNVqB-QXow-q5hZK46svAziFruSR3sHrVlgv330-LpY0XQg/360fx360f",
},
{
name: "Sold StatTrak™ AK-47",
image:
"https://community.cloudflare.steamstatic.com/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV09-5lpKKqPrxN7LEmyVQ7MEpiLuSrYqnjQCx_0NvZGHxdoKWJ1RsYF_V_we-xui915bpv8zLznBg7z5iuyjH3ErYgA/360fx360f",
},
{
name: "Sold M9 Bayonet",
image:
"https://community.cloudflare.steamstatic.com/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpovbSsLQJf3qr3czxb49KzgL-DjsjwN6vdk1Rd4cJ5nqfE842s2AewqBJpMTrzLIWWcFBsYgrT_FK6ku_uh5G96JXPzCQ37iF2sH6Plgv330_SkBhtxg/360fx360f",
},
],
},
{
type: "bonus",
direction: "positive",
descriptions: [
"Welcome bonus",
"Referral bonus",
"Loyalty reward",
"Promotional credit",
],
},
{
type: "refund",
direction: "positive",
descriptions: [
"Purchase refund",
"Transaction reversal",
"Cancelled order refund",
],
},
];
const paymentMethods = ["stripe", "paypal", "crypto", "balance", "steam"];
const statuses = ["completed", "pending", "processing"];
// Generate random amount based on transaction type
function generateAmount(type) {
switch (type) {
case "deposit":
case "withdrawal":
return parseFloat((Math.random() * 200 + 10).toFixed(2)); // $10-$210
case "purchase":
case "sale":
return parseFloat((Math.random() * 500 + 5).toFixed(2)); // $5-$505
case "bonus":
return parseFloat((Math.random() * 50 + 5).toFixed(2)); // $5-$55
case "refund":
return parseFloat((Math.random() * 150 + 10).toFixed(2)); // $10-$160
default:
return parseFloat((Math.random() * 100 + 10).toFixed(2));
}
}
// Generate random date within last 30 days
function generateRandomDate() {
const now = new Date();
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
const randomTime =
thirtyDaysAgo.getTime() +
Math.random() * (now.getTime() - thirtyDaysAgo.getTime());
return new Date(randomTime);
}
// Select random item from array
function randomItem(array) {
return array[Math.floor(Math.random() * array.length)];
}
async function seedTransactions() {
try {
console.log("🔌 Connecting to MongoDB...");
await mongoose.connect(MONGODB_URI);
console.log("✅ Connected to MongoDB");
// Find a user (preferably with sessions)
console.log("👤 Finding user...");
// Check for command line argument for Steam ID
const targetSteamId = process.argv[2];
let user;
if (targetSteamId) {
console.log(` Looking for Steam ID: ${targetSteamId}`);
user = await User.findOne({ steamId: targetSteamId });
if (!user) {
console.error(`❌ User with Steam ID ${targetSteamId} not found!`);
console.error("💡 Make sure you're logged in with this Steam account.");
process.exit(1);
}
} else {
// Default: find most recent user
user = await User.findOne().sort({ createdAt: -1 });
if (!user) {
console.error(
"❌ No users found. Please create a user first by logging in via Steam."
);
process.exit(1);
}
}
console.log(`✅ Found user: ${user.username} (${user.steamId})`);
// Get existing sessions for this user
console.log("🔐 Finding sessions...");
let sessions = await Session.find({ userId: user._id, isActive: true });
if (sessions.length === 0) {
console.error("❌ No active sessions found!");
console.error(
"💡 Please log in via Steam first to create a real session."
);
console.error(" Then run this script again.");
process.exit(1);
}
console.log(`✅ Found ${sessions.length} active sessions`);
sessions.forEach((session) => {
console.log(
` - ${session.browser || "Unknown"} on ${
session.os || "Unknown"
} (...${session._id.toString().slice(-6)})`
);
});
// Generate 20-30 fake transactions
const transactionCount = Math.floor(Math.random() * 11) + 20;
console.log(`\n💰 Generating ${transactionCount} fake transactions...`);
let currentBalance = user.balance || 1000; // Start with current balance or $1000
const createdTransactions = [];
for (let i = 0; i < transactionCount; i++) {
// Pick random transaction type
const txTypeObj = randomItem(transactionTypes);
const amount = generateAmount(txTypeObj.type);
const descriptionItem = randomItem(txTypeObj.descriptions);
const description =
typeof descriptionItem === "string"
? descriptionItem
: descriptionItem.name;
const itemImage =
typeof descriptionItem === "object" ? descriptionItem.image : null;
// Calculate balance
const balanceBefore = currentBalance;
let balanceAfter;
if (txTypeObj.direction === "positive") {
balanceAfter = balanceBefore + amount;
} else {
balanceAfter = balanceBefore - amount;
}
currentBalance = balanceAfter;
// Pick random session
const session = randomItem(sessions);
// Pick random status (mostly completed)
const status = Math.random() < 0.85 ? "completed" : randomItem(statuses);
// Create transaction data
const transactionData = {
userId: user._id,
steamId: user.steamId,
type: txTypeObj.type,
status: status,
amount: amount,
currency: "USD",
balanceBefore: balanceBefore,
balanceAfter: balanceAfter,
sessionId: session._id,
description: description,
fee:
txTypeObj.type === "withdrawal"
? parseFloat((amount * 0.02).toFixed(2))
: 0,
feePercentage: txTypeObj.type === "withdrawal" ? 2 : 0,
};
// Add payment method for deposits/withdrawals
if (txTypeObj.type === "deposit" || txTypeObj.type === "withdrawal") {
transactionData.paymentMethod = randomItem(paymentMethods);
}
// Add item name and image for purchases/sales
if (txTypeObj.type === "purchase" || txTypeObj.type === "sale") {
transactionData.itemName = description;
if (itemImage) {
transactionData.itemImage = itemImage;
}
}
// Set completed date if status is completed
if (status === "completed") {
transactionData.completedAt = generateRandomDate();
}
const transaction = await Transaction.createTransaction(transactionData);
// Update createdAt to be in the past (for realistic history)
transaction.createdAt = generateRandomDate();
await transaction.save();
createdTransactions.push(transaction);
// Log progress
const sessionShort = session._id.toString().slice(-6).toUpperCase();
console.log(
` ✅ [${i + 1}/${transactionCount}] ${txTypeObj.type
.toUpperCase()
.padEnd(12)} $${amount
.toFixed(2)
.padStart(8)} - Session: ${sessionShort} - ${description}`
);
}
// Sort by date
createdTransactions.sort((a, b) => b.createdAt - a.createdAt);
console.log("\n📊 Transaction Summary:");
console.log(` Total created: ${createdTransactions.length}`);
const typeCounts = {};
const sessionCounts = {};
createdTransactions.forEach((tx) => {
typeCounts[tx.type] = (typeCounts[tx.type] || 0) + 1;
const sessionShort = tx.sessionIdShort || "SYSTEM";
sessionCounts[sessionShort] = (sessionCounts[sessionShort] || 0) + 1;
});
console.log("\n By Type:");
Object.entries(typeCounts).forEach(([type, count]) => {
console.log(` ${type.padEnd(12)}: ${count}`);
});
console.log("\n By Session:");
Object.entries(sessionCounts).forEach(([sessionShort, count]) => {
console.log(` ${sessionShort}: ${count} transactions`);
});
console.log("\n✅ Seeding completed successfully!");
console.log(
`\n💡 You can now view these transactions at: http://localhost:5173/transactions`
);
} catch (error) {
console.error("❌ Error seeding transactions:", error);
process.exit(1);
} finally {
await mongoose.disconnect();
console.log("\n🔌 Disconnected from MongoDB");
process.exit(0);
}
}
// Run the seed
seedTransactions();