goat
command
bank
No description
0
views
0
likes
0
installs
raw source
const moment = require("moment-timezone");
module.exports = {
config: {
name: "bank",
aliases: [],
version: "2.4.71",
author: "ST BOT",
countDown: 5,
role: 0,
description: {
en: "ST BOT Banking System - Complete banking solution with loans, investments, games, and more"
},
category: "economy",
guide: {
en: " {pn} register - Register for bank account\n"
+ " {pn} balance [@mention] - Check bank balance\n"
+ " {pn} deposit <amount> [duration] - Deposit money (duration: 1h, 1d, 1w, 1m, permanent)\n"
+ " {pn} withdraw <amount> - Withdraw money from bank\n"
+ " {pn} tobank <amount> - Move money from wallet to bank (1% fee per $1000)\n"
+ " {pn} towallet <amount> - Move money from bank to wallet (1% fee per $1000)\n"
+ " {pn} transfer <@mention|reply> <amount> - Transfer money\n"
+ " {pn} loan <amount> - Take a loan (5% interest)\n"
+ " {pn} payloan <amount> - Pay back loan\n"
+ " {pn} invest <amount> <duration> - Invest money (1h-1m)\n"
+ " {pn} daily - Claim daily reward\n"
+ " {pn} lottery - Play free daily lottery\n"
+ " {pn} spin <bet> - Spin slot machine\n"
+ " {pn} coinflip <bet> <heads|tails> - Flip a coin\n"
+ " {pn} trade <buy|sell> <amount> - Trade coins\n"
+ " {pn} transactions - View transaction history\n"
+ " {pn} leaderboard - View bank rankings"
}
},
langs: {
en: {
notRegistered: "❌ You don't have a bank account! Use '/bank register' to create one.",
registered: "✅ Bank account created successfully!\n💰 Welcome bonus: $500",
alreadyRegistered: "❌ You already have a bank account!",
balance: "🏦 Bank Balance\n━━━━━━━━━━━━━━━\n👤 User: %1\n💰 Balance: $%2\n📊 Total Deposited: $%3\n📤 Total Withdrawn: $%4\n💳 Loan: $%5\n📅 Member Since: %6",
depositSuccess: "✅ Deposited $%1 to your bank account!\n💰 New Balance: $%2",
withdrawSuccess: "✅ Withdrawn $%1 from your bank account!\n💰 New Balance: $%2",
insufficientFunds: "❌ Insufficient funds in your wallet!",
insufficientBank: "❌ Insufficient funds in your bank account!",
transferSuccess: "✅ Transferred $%1 to %2\n💰 Your New Balance: $%3",
loanTaken: "✅ Loan of $%1 approved!\n💳 Interest Rate: 5%\n⚠️ Total to repay: $%2",
hasLoan: "❌ You already have an active loan! Pay it back first.",
loanPaid: "✅ Paid $%1 towards your loan!\n💳 Remaining: $%2",
noLoan: "❌ You don't have any active loan!",
investSuccess: "✅ Invested $%1 for %2\n📈 Expected Return: $%3\n⏰ Matures at: %4",
dailyClaimed: "🎁 Daily Reward Claimed!\n💰 +$%1\n🔥 Streak: %2 days\n⏰ Come back tomorrow!",
alreadyClaimed: "❌ You already claimed your daily reward!\n⏰ Come back in %1",
lotteryWon: "🎉 JACKPOT! You won $%1 from the lottery!\n🍀 Lucky number: %2",
lotteryLost: "😔 Better luck next time!\n🍀 Your number: %1 | Winning number: %2",
alreadyPlayedLottery: "❌ You already played lottery today!\n⏰ Come back tomorrow!",
spinResult: "🎰 SLOT MACHINE\n━━━━━━━━━━━━\n%1\n━━━━━━━━━━━━\n%2",
coinflipWin: "🪙 Coin landed on %1!\n✅ You won $%2!",
coinflipLose: "🪙 Coin landed on %1!\n❌ You lost $%2!",
tradeSuccess: "📊 Trade executed!\n%1 %2 coins\n💰 New Balance: $%3"
}
},
ST: async function ({ args, message, event, usersData, getLang, api }) {
const { bankData } = global.db;
const { senderID, messageReply } = event;
const command = args[0]?.toLowerCase();
// Register
if (command === "register") {
const existingBankData = await bankData.get(senderID);
if (existingBankData && existingBankData.userID) {
return message.reply(getLang("alreadyRegistered"));
}
await bankData.create(senderID);
await usersData.addMoney(senderID, 500);
return message.reply(getLang("registered"));
}
// Check if user is registered
const userBankDataCheck = await bankData.get(senderID);
if (!userBankDataCheck || !userBankDataCheck.userID) {
return message.reply(getLang("notRegistered"));
}
const userData = await usersData.get(senderID);
const userBankData = await bankData.get(senderID);
switch (command) {
case "balance":
case "bal": {
let targetID = senderID;
if (Object.keys(event.mentions).length > 0) {
targetID = Object.keys(event.mentions)[0];
} else if (messageReply) {
targetID = messageReply.senderID;
}
const targetBankDataCheck = await bankData.get(targetID);
if (!targetBankDataCheck || !targetBankDataCheck.userID) {
return message.reply("❌ User doesn't have a bank account!");
}
const targetBankData = await bankData.get(targetID);
const targetUserData = await usersData.get(targetID);
const memberSince = moment(targetBankData.registeredAt).format("MMM DD, YYYY");
return message.reply(getLang("balance",
targetUserData.name,
targetBankData.bankBalance.toLocaleString(),
targetBankData.totalDeposited.toLocaleString(),
targetBankData.totalWithdrawn.toLocaleString(),
targetBankData.loan.amount.toLocaleString(),
memberSince
));
}
case "deposit": {
const amount = parseInt(args[1]);
if (isNaN(amount) || amount <= 0) {
return message.reply("❌ Invalid amount!");
}
if (userData.money < amount) {
return message.reply(getLang("insufficientFunds"));
}
const duration = args[2];
const depositData = {
amount,
depositedAt: new Date(),
duration: duration || "permanent",
withdrawable: !duration || duration === "permanent"
};
if (duration && duration !== "permanent") {
const durationMs = parseDuration(duration);
if (!durationMs) {
return message.reply("❌ Invalid duration! Use: 1h, 1d, 1w, 1m, or permanent");
}
depositData.maturesAt = new Date(Date.now() + durationMs);
depositData.interest = calculateInterest(amount, duration);
}
await usersData.subtractMoney(senderID, amount);
userBankData.deposits.push(depositData);
userBankData.bankBalance += amount;
userBankData.totalDeposited += amount;
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "deposit",
amount,
duration: duration || "permanent"
});
return message.reply(getLang("depositSuccess", amount.toLocaleString(), userBankData.bankBalance.toLocaleString()));
}
case "withdraw": {
const amount = parseInt(args[1]);
if (isNaN(amount) || amount <= 0) {
return message.reply("❌ Invalid amount!");
}
if (userBankData.bankBalance < amount) {
return message.reply(getLang("insufficientBank"));
}
// Check for locked deposits
const availableBalance = calculateAvailableBalance(userBankData);
if (availableBalance < amount) {
return message.reply(`❌ Only $${availableBalance.toLocaleString()} is available for withdrawal!\nSome funds are locked in time deposits.`);
}
await usersData.addMoney(senderID, amount);
userBankData.bankBalance -= amount;
userBankData.totalWithdrawn += amount;
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "withdraw",
amount
});
return message.reply(getLang("withdrawSuccess", amount.toLocaleString(), userBankData.bankBalance.toLocaleString()));
}
case "transfer": {
let targetID = Object.keys(event.mentions)[0];
let amount = parseInt(args[2]);
if (messageReply) {
targetID = messageReply.senderID;
amount = parseInt(args[1]);
}
if (!targetID) {
return message.reply("❌ Please mention someone or reply to their message!");
}
if (isNaN(amount) || amount <= 0) {
return message.reply("❌ Invalid amount!");
}
if (userBankData.bankBalance < amount) {
return message.reply(getLang("insufficientBank"));
}
const targetBankCheck = await bankData.get(targetID);
if (!targetBankCheck || !targetBankCheck.userID) {
return message.reply("❌ Target user doesn't have a bank account!");
}
const targetBankData = await bankData.get(targetID);
const targetUserData = await usersData.get(targetID);
userBankData.bankBalance -= amount;
targetBankData.bankBalance += amount;
await bankData.set(senderID, userBankData);
await bankData.set(targetID, targetBankData);
await bankData.addTransaction(senderID, {
type: "transfer_out",
amount,
to: targetID
});
await bankData.addTransaction(targetID, {
type: "transfer_in",
amount,
from: senderID
});
return message.reply(getLang("transferSuccess", amount.toLocaleString(), targetUserData.name, userBankData.bankBalance.toLocaleString()));
}
case "loan": {
const amount = parseInt(args[1]);
if (isNaN(amount) || amount <= 0) {
return message.reply("❌ Invalid amount!");
}
if (userBankData.banned.isBanned) {
const canUnban = new Date(userBankData.banned.canUnbanAt);
const now = new Date();
if (now < canUnban) {
return message.reply(`❌ You are banned from bank services!\n📛 Reason: ${userBankData.banned.reason}\n⏰ Can request unban after: ${moment(canUnban).format("MMM DD, YYYY HH:mm")}`);
}
}
if (userBankData.loan.amount > 0) {
return message.reply(getLang("hasLoan"));
}
if (userBankData.loanRequests.some(r => r.status === "pending")) {
return message.reply("❌ You already have a pending loan request!");
}
const interestAmount = Math.floor(amount * 0.05);
const totalRepay = amount + interestAmount;
const requestID = Date.now().toString();
const loanRequest = {
requestID,
amount,
totalRepay,
requestedAt: new Date(),
status: "pending",
threadID: event.threadID
};
userBankData.loanRequests.push(loanRequest);
await bankData.set(senderID, userBankData);
// Send to admin thread
const mainThreadID = global.GoatBot.config.mainThreadId;
const threadData = await api.getThreadInfo(event.threadID);
const threadName = threadData.threadName || "Unknown Thread";
api.sendMessage(
`🏦 NEW LOAN REQUEST\n━━━━━━━━━━━━━━━━\n` +
`👤 User: ${userData.name}\n` +
`💰 Amount: $${amount.toLocaleString()}\n` +
`💳 Total to Repay: $${totalRepay.toLocaleString()}\n` +
`📍 Thread: ${threadName}\n` +
`🆔 Request ID: ${requestID}\n` +
`⏰ Requested: ${moment().format("MMM DD, YYYY HH:mm")}\n\n` +
`Reply "yes" to approve or "no" to reject`,
mainThreadID,
(err, info) => {
if (!err) {
global.GoatBot.onReply.set(info.messageID, {
commandName: "bank",
messageID: info.messageID,
author: senderID,
requestID,
type: "loanApproval",
amount,
totalRepay,
threadID: event.threadID
});
}
}
);
return message.reply(`✅ Loan request submitted!\n💰 Amount: $${amount.toLocaleString()}\n💳 Total to Repay: $${totalRepay.toLocaleString()}\n⏰ Waiting for admin approval...`);
}
case "payloan": {
if (userBankData.loan.amount === 0) {
return message.reply(getLang("noLoan"));
}
let payAmount;
// Check if user wants to pay full amount (no args or "full" or "all")
if (!args[1] || args[1].toLowerCase() === "full" || args[1].toLowerCase() === "all") {
payAmount = userBankData.loan.amount;
if (userBankData.bankBalance < payAmount) {
return message.reply(`❌ Insufficient bank balance to pay full loan!\n💳 Loan Amount: $${userBankData.loan.amount.toLocaleString()}\n💰 Your Balance: $${userBankData.bankBalance.toLocaleString()}\n📝 Use: bank payloan <amount> to pay partial`);
}
} else {
// Manual amount entry
const amount = parseInt(args[1]);
if (isNaN(amount) || amount <= 0) {
return message.reply("❌ Invalid amount! Use a number or leave empty to pay full loan.");
}
if (userBankData.bankBalance < amount) {
return message.reply(getLang("insufficientBank"));
}
payAmount = Math.min(amount, userBankData.loan.amount);
}
userBankData.bankBalance -= payAmount;
userBankData.loan.amount -= payAmount;
const isFullyPaid = userBankData.loan.amount === 0;
if (isFullyPaid) {
userBankData.loan.takenAt = null;
userBankData.loan.dueDate = null;
userBankData.loan.threadID = null;
}
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "loan_payment",
amount: payAmount
});
if (isFullyPaid) {
return message.reply(`✅ Loan fully paid!\n💰 Paid: $${payAmount.toLocaleString()}\n🎉 You're debt-free!\n💰 New Balance: $${userBankData.bankBalance.toLocaleString()}`);
} else {
return message.reply(getLang("loanPaid", payAmount.toLocaleString(), userBankData.loan.amount.toLocaleString()));
}
}
case "tobank": {
const amount = parseInt(args[1]);
if (isNaN(amount) || amount <= 0) {
return message.reply("❌ Invalid amount!");
}
if (userData.money < amount) {
return message.reply(getLang("insufficientFunds"));
}
// 1% fee per $1000
const fee = Math.floor((amount / 1000) * 10);
const totalCost = amount + fee;
if (userData.money < totalCost) {
return message.reply(`❌ You need $${totalCost.toLocaleString()} (including $${fee.toLocaleString()} fee)!`);
}
await usersData.subtractMoney(senderID, totalCost);
userBankData.bankBalance += amount;
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "wallet_to_bank",
amount
});
return message.reply(`✅ Transferred $${amount.toLocaleString()} to bank!\n💸 Fee: $${fee.toLocaleString()}\n💰 New Bank Balance: $${userBankData.bankBalance.toLocaleString()}`);
}
case "towallet": {
const amount = parseInt(args[1]);
if (isNaN(amount) || amount <= 0) {
return message.reply("❌ Invalid amount!");
}
if (userBankData.bankBalance < amount) {
return message.reply(getLang("insufficientBank"));
}
// 1% fee per $1000
const fee = Math.floor((amount / 1000) * 10);
const amountAfterFee = amount - fee;
if (amountAfterFee <= 0) {
return message.reply("❌ Amount too small after fee deduction!");
}
userBankData.bankBalance -= amount;
await usersData.addMoney(senderID, amountAfterFee);
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "bank_to_wallet",
amount: amountAfterFee
});
return message.reply(`✅ Transferred $${amountAfterFee.toLocaleString()} to wallet!\n💸 Fee: $${fee.toLocaleString()}\n💵 New Wallet Balance: $${(userData.money + amountAfterFee).toLocaleString()}`);
}
case "invest": {
const amount = parseInt(args[1]);
const duration = args[2];
if (isNaN(amount) || amount <= 0) {
return message.reply("❌ Invalid amount!");
}
if (userBankData.bankBalance < amount) {
return message.reply(getLang("insufficientBank"));
}
if (!duration) {
return message.reply("❌ Please specify duration! (1h, 1d, 1w, 1m)");
}
const durationMs = parseDuration(duration);
if (!durationMs) {
return message.reply("❌ Invalid duration! Use: 1h, 1d, 1w, 1m");
}
const returnRate = getInvestmentReturn(duration);
const expectedReturn = Math.floor(amount * returnRate);
const maturesAt = new Date(Date.now() + durationMs);
const investment = {
amount,
investedAt: new Date(),
maturesAt,
expectedReturn,
duration
};
userBankData.investments.push(investment);
userBankData.bankBalance -= amount;
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "investment",
amount,
duration
});
return message.reply(getLang("investSuccess",
amount.toLocaleString(),
duration,
expectedReturn.toLocaleString(),
moment(maturesAt).format("MMM DD, YYYY HH:mm")
));
}
case "daily": {
const today = moment.tz("Asia/Dhaka").format("DD/MM/YYYY");
if (userBankData.dailyClaim.lastClaimed === today) {
const tomorrow = moment.tz("Asia/Dhaka").add(1, 'day').startOf('day');
const timeLeft = tomorrow.diff(moment.tz("Asia/Dhaka"));
const hours = Math.floor(timeLeft / (1000 * 60 * 60));
const minutes = Math.floor((timeLeft % (1000 * 60 * 60)) / (1000 * 60));
return message.reply(getLang("alreadyClaimed", `${hours}h ${minutes}m`));
}
userBankData.dailyClaim.streak += 1;
userBankData.dailyClaim.lastClaimed = today;
const reward = 100 + (userBankData.dailyClaim.streak * 10);
userBankData.bankBalance += reward;
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "daily_claim",
amount: reward
});
return message.reply(getLang("dailyClaimed", reward.toLocaleString(), userBankData.dailyClaim.streak));
}
case "lottery": {
const today = moment.tz("Asia/Dhaka").format("DD/MM/YYYY");
if (userBankData.lottery.lastPlayed === today) {
return message.reply(getLang("alreadyPlayedLottery"));
}
const userNumber = Math.floor(Math.random() * 100);
const winningNumber = Math.floor(Math.random() * 100);
if (Math.abs(userNumber - winningNumber) <= 10) {
const prize = 1000;
userBankData.bankBalance += prize;
userBankData.lottery.totalWins += 1;
userBankData.lottery.lastPlayed = today;
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "lottery_win",
amount: prize
});
return message.reply(getLang("lotteryWon", prize.toLocaleString(), winningNumber));
}
userBankData.lottery.lastPlayed = today;
await bankData.set(senderID, userBankData);
return message.reply(getLang("lotteryLost", userNumber, winningNumber));
}
case "spin": {
const bet = parseInt(args[1]);
if (isNaN(bet) || bet <= 0) {
return message.reply("❌ Invalid bet amount!");
}
if (userBankData.bankBalance < bet) {
return message.reply(getLang("insufficientBank"));
}
// Send initial spinning message
const spinningMsg = await message.reply("🎰 SPINNING...\n━━━━━━━━━━━━\n🔄 🔄 🔄\n━━━━━━━━━━━━\n⏳ Please wait...");
// Wait for dramatic effect
await new Promise(resolve => setTimeout(resolve, 2000));
const slots = ["🍒", "🍋", "🍊", "🍇", "💎", "⭐"];
let winnings = 0;
let resultText = "";
let result = [];
// 30% win rate, 70% lose rate
const winChance = Math.random();
if (winChance < 0.30) {
// WIN - 30% chance
const winType = Math.random();
if (winType < 0.05) {
// 5% chance for jackpot
const jackpotSlot = slots[4]; // 💎
result = [jackpotSlot, jackpotSlot, jackpotSlot];
winnings = bet * 10;
resultText = `💎 JACKPOT! 💎\n✅ You won $${winnings.toLocaleString()}!\n💰 New Balance: $${(userBankData.bankBalance + winnings).toLocaleString()}`;
} else if (winType < 0.20) {
// 15% chance for triple match
const tripleSlot = slots[Math.floor(Math.random() * 3)]; // Lower value slots
result = [tripleSlot, tripleSlot, tripleSlot];
winnings = bet * 5;
resultText = `🎉 Triple Match!\n✅ You won $${winnings.toLocaleString()}!\n💰 New Balance: $${(userBankData.bankBalance + winnings).toLocaleString()}`;
} else {
// 80% chance for double match (within wins)
const doubleSlot = slots[Math.floor(Math.random() * slots.length)];
result = [doubleSlot, doubleSlot, slots[Math.floor(Math.random() * slots.length)]];
winnings = bet * 2;
resultText = `👍 Double Match!\n✅ You won $${winnings.toLocaleString()}!\n💰 New Balance: $${(userBankData.bankBalance + winnings).toLocaleString()}`;
}
} else {
// LOSE - 70% chance
result = [
slots[Math.floor(Math.random() * slots.length)],
slots[Math.floor(Math.random() * slots.length)],
slots[Math.floor(Math.random() * slots.length)]
];
// Ensure no matches
while ((result[0] === result[1] && result[1] === result[2]) ||
(result[0] === result[1] || result[1] === result[2] || result[0] === result[2])) {
result = [
slots[Math.floor(Math.random() * slots.length)],
slots[Math.floor(Math.random() * slots.length)],
slots[Math.floor(Math.random() * slots.length)]
];
}
winnings = -bet;
resultText = `😔 No match!\n❌ You lost $${bet.toLocaleString()}!\n💰 New Balance: $${(userBankData.bankBalance + winnings).toLocaleString()}`;
}
userBankData.bankBalance += winnings;
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "slot_game",
amount: winnings
});
// Edit message with result
const finalMsg = `🎰 SLOT MACHINE\n━━━━━━━━━━━━\n${result.join(" | ")}\n━━━━━━━━━━━━\n${resultText}`;
return api.editMessage(finalMsg, spinningMsg.messageID);
}
case "coinflip": {
const bet = parseInt(args[1]);
const choice = args[2]?.toLowerCase();
if (isNaN(bet) || bet <= 0) {
return message.reply("❌ Invalid bet amount!");
}
if (!["heads", "tails"].includes(choice)) {
return message.reply("❌ Choose heads or tails!");
}
if (userBankData.bankBalance < bet) {
return message.reply(getLang("insufficientBank"));
}
const result = Math.random() < 0.5 ? "heads" : "tails";
const won = result === choice;
if (won) {
userBankData.bankBalance += bet;
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "coinflip_win",
amount: bet
});
return message.reply(getLang("coinflipWin", result, bet.toLocaleString()));
} else {
userBankData.bankBalance -= bet;
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: "coinflip_loss",
amount: bet
});
return message.reply(getLang("coinflipLose", result, bet.toLocaleString()));
}
}
case "trade": {
const action = args[1]?.toLowerCase();
const amount = parseInt(args[2]);
if (!["buy", "sell"].includes(action)) {
return message.reply("❌ Use 'buy' or 'sell'!");
}
if (isNaN(amount) || amount <= 0) {
return message.reply("❌ Invalid amount!");
}
const rate = 1 + (Math.random() * 0.2 - 0.1); // ±10% fluctuation
const cost = Math.floor(amount * rate);
if (action === "buy") {
if (userBankData.bankBalance < cost) {
return message.reply(getLang("insufficientBank"));
}
userBankData.bankBalance -= cost;
userBankData.premiumCurrency += amount;
} else {
if (userBankData.premiumCurrency < amount) {
return message.reply("❌ Insufficient premium currency!");
}
userBankData.premiumCurrency -= amount;
userBankData.bankBalance += cost;
}
await bankData.set(senderID, userBankData);
await bankData.addTransaction(senderID, {
type: `trade_${action}`,
amount: action === "buy" ? cost : amount
});
return message.reply(getLang("tradeSuccess",
action === "buy" ? "Bought" : "Sold",
amount,
userBankData.bankBalance.toLocaleString()
));
}
case "transactions":
case "history": {
if (!userBankData.transactions || userBankData.transactions.length === 0) {
return message.reply("❌ No transactions yet!");
}
let msg = "📜 Transaction History (Last 10)\n━━━━━━━━━━━━━━━━\n";
userBankData.transactions.slice(0, 10).forEach((tx, i) => {
const time = moment(tx.timestamp).format("MMM DD, HH:mm");
const sign = tx.type.includes("win") || tx.type.includes("deposit") || tx.type.includes("in") ? "+" : "-";
msg += `${i + 1}. ${tx.type.toUpperCase()}: ${sign}$${Math.abs(tx.amount).toLocaleString()} - ${time}\n`;
});
return message.reply(msg);
}
case "leaderboard":
case "top": {
const allBanks = global.db.allBankData.sort((a, b) => b.bankBalance - a.bankBalance).slice(0, 10);
let msg = "🏆 Bank Leaderboard (Top 10)\n━━━━━━━━━━━━━━━━\n";
for (let i = 0; i < allBanks.length; i++) {
const user = await usersData.get(allBanks[i].userID);
const medal = i === 0 ? "🥇" : i === 1 ? "🥈" : i === 2 ? "🥉" : `${i + 1}.`;
msg += `${medal} ${user.name}: $${allBanks[i].bankBalance.toLocaleString()}\n`;
}
return message.reply(msg);
}
default:
return message.SyntaxError();
}
},
onReply: async function ({ event, Reply, message, usersData, api }) {
const { bankData } = global.db;
const adminConfig = global.GoatBot.config.adminBot;
if (!adminConfig.includes(event.senderID)) {
return;
}
if (Reply.type === "loanApproval") {
const response = event.body.toLowerCase().trim();
const { requestID, amount, totalRepay, threadID, author: requesterID } = Reply;
if (!["yes", "no"].includes(response)) {
return message.reply("❌ Reply 'yes' to approve or 'no' to reject!");
}
const requesterBankData = await bankData.get(requesterID);
const requestIndex = requesterBankData.loanRequests.findIndex(r => r.requestID === requestID);
if (requestIndex === -1) {
return message.reply("❌ Loan request not found!");
}
const requesterUserData = await usersData.get(requesterID);
const LOAN_DUE_DAYS = 7;
if (response === "yes") {
// Approve loan
const dueDate = new Date();
dueDate.setDate(dueDate.getDate() + LOAN_DUE_DAYS);
requesterBankData.loan = {
amount: totalRepay,
takenAt: new Date(),
interestRate: 5,
dueDate,
threadID
};
requesterBankData.loanRequests[requestIndex].status = "approved";
requesterBankData.bankBalance += amount;
await bankData.set(requesterID, requesterBankData);
await bankData.addTransaction(requesterID, {
type: "loan_approved",
amount,
totalRepay
});
// Notify user with mention
const requesterUserData = await usersData.get(requesterID);
api.sendMessage(
{
body: `@${requesterUserData.name} ✅ LOAN APPROVED!\n━━━━━━━━━━━━━━━━\n` +
`💰 Amount: $${amount.toLocaleString()}\n` +
`💳 Total to Repay: $${totalRepay.toLocaleString()}\n` +
`📅 Due Date: ${moment(dueDate).format("MMM DD, YYYY")}\n` +
`⚠️ Pay within ${LOAN_DUE_DAYS} days or face ban!`,
mentions: [{
tag: `@${requesterUserData.name}`,
id: requesterID
}]
},
threadID
);
return message.reply(`✅ Loan approved for ${requesterUserData.name}!`);
} else {
// Reject loan
requesterBankData.loanRequests[requestIndex].status = "rejected";
await bankData.set(requesterID, requesterBankData);
// Notify user with mention
const requesterUserData = await usersData.get(requesterID);
api.sendMessage(
{
body: `@${requesterUserData.name} ❌ LOAN REJECTED\n━━━━━━━━━━━━━━━━\n` +
`Your loan request for $${amount.toLocaleString()} was rejected.\n` +
`You can reapply for a loan anytime.`,
mentions: [{
tag: `@${requesterUserData.name}`,
id: requesterID
}]
},
threadID
);
return message.reply(`❌ Loan rejected for ${requesterUserData.name}.`);
}
}
}
};
function parseDuration(duration) {
const units = {
'h': 60 * 60 * 1000,
'd': 24 * 60 * 60 * 1000,
'w': 7 * 24 * 60 * 60 * 1000,
'm': 30 * 24 * 60 * 60 * 1000
};
const match = duration.match(/^(\d+)([hdwm])$/);
if (!match) return null;
const value = parseInt(match[1]);
const unit = match[2];
return value * units[unit];
}
function calculateInterest(amount, duration) {
const rates = {
'1h': 0.01,
'1d': 0.02,
'1w': 0.05,
'1m': 0.15
};
return Math.floor(amount * (rates[duration] || 0));
}
function getInvestmentReturn(duration) {
const rates = {
'1h': 1.05,
'1d': 1.1,
'1w': 1.25,
'1m': 1.5
};
return rates[duration] || 1.1;
}
function calculateAvailableBalance(userBankData) {
let locked = 0;
const now = new Date();
userBankData.deposits.forEach(deposit => {
if (!deposit.withdrawable && deposit.maturesAt && new Date(deposit.maturesAt) > now) {
locked += deposit.amount;
}
});
return userBankData.bankBalance - locked;
}