goat
command
loanadmin
No description
0
views
0
likes
0
installs
Aliases: la
raw source
const moment = require("moment-timezone");
// Customizable loan duration (in days)
const LOAN_DUE_DAYS = 7;
const BAN_COOLDOWN_DAYS = 30;
module.exports = {
config: {
name: "loanadmin",
aliases: ["la"],
version: "2.4.71",
author: "ST BOT",
countDown: 5,
role: 2,
description: {
en: "Manage bank loan requests and bans (Admin only)"
},
category: "economy",
guide: {
en: " {pn} pending - View pending loan requests\n"
+ " {pn} active - View active loans\n"
+ " {pn} banned - View banned users\n"
+ " {pn} unban <reply> - Unban a user\n"
+ " Reply 'yes' or 'no' to approve/reject loan requests"
}
},
langs: {
en: {
noPending: "✅ No pending loan requests!",
noActive: "✅ No active loans!",
noBanned: "✅ No banned users!",
unbanSuccess: "✅ User unbanned successfully! Their loan has been cleared.",
cannotUnbanYet: "❌ User can only be unbanned after %1",
notBanned: "❌ User is not banned!"
}
},
ST: async function ({ args, message, event, usersData, bankData, getLang, api }) {
const command = args[0]?.toLowerCase();
switch (command) {
case "pending": {
const allBanks = global.db.allBankData;
const pending = [];
for (const bank of allBanks) {
const pendingRequests = bank.loanRequests.filter(r => r.status === "pending");
if (pendingRequests.length > 0) {
const user = await usersData.get(bank.userID);
for (const req of pendingRequests) {
const threadInfo = await api.getThreadInfo(req.threadID);
pending.push({
user: user.name,
userID: bank.userID,
amount: req.amount,
totalRepay: req.totalRepay,
requestID: req.requestID,
threadName: threadInfo.threadName || "Unknown",
threadID: req.threadID,
requestedAt: req.requestedAt
});
}
}
}
if (pending.length === 0) {
return message.reply(getLang("noPending"));
}
let msg = "📋 PENDING LOAN REQUESTS\n━━━━━━━━━━━━━━━━\n";
pending.forEach((req, i) => {
msg += `\n${i + 1}. ${req.user}\n`;
msg += ` 💰 Amount: $${req.amount.toLocaleString()}\n`;
msg += ` 💳 Repay: $${req.totalRepay.toLocaleString()}\n`;
msg += ` 📍 Thread: ${req.threadName}\n`;
msg += ` ⏰ ${moment(req.requestedAt).fromNow()}\n`;
});
msg += `\n💡 Reply with serial number and 'yes' or 'no' to approve/reject\n`;
msg += `Example: 1 yes`;
return message.reply(msg, (err, info) => {
if (!err) {
global.GoatBot.onReply.set(info.messageID, {
commandName: module.exports.config.name,
messageID: info.messageID,
author: event.senderID,
type: "loanApprovalList",
requests: pending
});
}
});
}
case "active": {
const allBanks = global.db.allBankData;
const active = [];
for (const bank of allBanks) {
if (bank.loan.amount > 0) {
const user = await usersData.get(bank.userID);
const dueDate = new Date(bank.loan.dueDate);
const now = new Date();
const isOverdue = now > dueDate;
active.push({
user: user.name,
userID: bank.userID,
amount: bank.loan.amount,
takenAt: bank.loan.takenAt,
dueDate: bank.loan.dueDate,
isOverdue,
threadID: bank.loan.threadID
});
}
}
if (active.length === 0) {
return message.reply(getLang("noActive"));
}
let msg = "💳 ACTIVE LOANS\n━━━━━━━━━━━━━━━━\n";
active.forEach((loan, i) => {
const status = loan.isOverdue ? "⚠️ OVERDUE" : "✅ Active";
msg += `\n${i + 1}. ${loan.user} ${status}\n`;
msg += ` 💰 Remaining: $${loan.amount.toLocaleString()}\n`;
msg += ` 📅 Taken: ${moment(loan.takenAt).format("MMM DD, YYYY")}\n`;
msg += ` ⏰ Due: ${moment(loan.dueDate).format("MMM DD, YYYY")}\n`;
if (loan.isOverdue) {
msg += ` 🚨 Overdue by ${moment().diff(moment(loan.dueDate), 'days')} days\n`;
}
});
return message.reply(msg);
}
case "banned": {
const allBanks = global.db.allBankData;
const banned = [];
for (const bank of allBanks) {
if (bank.banned.isBanned) {
const user = await usersData.get(bank.userID);
banned.push({
user: user.name,
userID: bank.userID,
reason: bank.banned.reason,
bannedAt: bank.banned.bannedAt,
canUnbanAt: bank.banned.canUnbanAt
});
}
}
if (banned.length === 0) {
return message.reply(getLang("noBanned"));
}
let msg = "🚫 BANNED USERS\n━━━━━━━━━━━━━━━━\n";
banned.forEach((ban, i) => {
const canUnban = new Date(ban.canUnbanAt) < new Date();
msg += `\n${i + 1}. ${ban.user}\n`;
msg += ` 📛 Reason: ${ban.reason}\n`;
msg += ` 📅 Banned: ${moment(ban.bannedAt).format("MMM DD, YYYY")}\n`;
msg += ` ${canUnban ? "✅ Can unban now" : "⏰ Unban after: " + moment(ban.canUnbanAt).format("MMM DD, YYYY")}\n`;
});
msg += `\n💡 Reply to a banned user's message and use '{pn} unban' to unban them`;
return message.reply(msg);
}
case "unban": {
if (!event.messageReply) {
return message.reply("❌ Please reply to a banned user's message!");
}
const targetID = event.messageReply.senderID;
const targetBankData = await bankData.get(targetID);
if (!targetBankData.banned.isBanned) {
return message.reply(getLang("notBanned"));
}
const canUnbanAt = new Date(targetBankData.banned.canUnbanAt);
const now = new Date();
if (now < canUnbanAt) {
return message.reply(getLang("cannotUnbanYet", moment(canUnbanAt).format("MMM DD, YYYY HH:mm")));
}
// Clear ban and loan
targetBankData.banned = {
isBanned: false,
reason: null,
bannedAt: null,
canUnbanAt: null
};
targetBankData.loan = {
amount: 0,
takenAt: null,
interestRate: 5,
dueDate: null,
threadID: null
};
await bankData.set(targetID, targetBankData);
await bankData.addTransaction(targetID, {
type: "unbanned",
amount: 0
});
const targetUser = await usersData.get(targetID);
return message.reply(getLang("unbanSuccess"));
}
default:
return message.SyntaxError();
}
},
onReply: async function ({ event, Reply, message, usersData, api }) {
const { author, type } = Reply;
const adminConfig = global.GoatBot.config.adminBot;
const bankData = global.db.bankData;
if (!adminConfig.includes(event.senderID)) {
return;
}
if (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);
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
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
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}.`);
}
}
if (type === "loanApprovalList") {
const parts = event.body.trim().split(/\s+/);
const serialNum = parseInt(parts[0]);
const response = parts[1]?.toLowerCase();
if (!["yes", "no"].includes(response)) {
return message.reply("❌ Format: <serial number> yes/no");
}
if (isNaN(serialNum) || serialNum < 1 || serialNum > Reply.requests.length) {
return message.reply("❌ Invalid serial number!");
}
const request = Reply.requests[serialNum - 1];
const requesterBankData = await bankData.get(request.userID);
const requestIndex = requesterBankData.loanRequests.findIndex(r => r.requestID === request.requestID);
if (response === "yes") {
const dueDate = new Date();
dueDate.setDate(dueDate.getDate() + LOAN_DUE_DAYS);
requesterBankData.loan = {
amount: request.totalRepay,
takenAt: new Date(),
interestRate: 5,
dueDate,
threadID: request.threadID
};
requesterBankData.loanRequests[requestIndex].status = "approved";
requesterBankData.bankBalance += request.amount;
await bankData.set(request.userID, requesterBankData);
// Notify user with mention
api.sendMessage(
{
body: `@${request.user} ✅ LOAN APPROVED!\n━━━━━━━━━━━━━━━━\n` +
`💰 Amount: $${request.amount.toLocaleString()}\n` +
`💳 Total to Repay: $${request.totalRepay.toLocaleString()}\n` +
`📅 Due Date: ${moment(dueDate).format("MMM DD, YYYY")}\n` +
`⚠️ Pay within ${LOAN_DUE_DAYS} days or face ban!`,
mentions: [{
tag: `@${request.user}`,
id: request.userID
}]
},
request.threadID
);
return message.reply(`✅ Loan approved for ${request.user}!`);
} else {
requesterBankData.loanRequests[requestIndex].status = "rejected";
await bankData.set(request.userID, requesterBankData);
// Notify user with mention
api.sendMessage(
{
body: `@${request.user} ❌ LOAN REJECTED\n━━━━━━━━━━━━━━━━\n` +
`Your loan request for $${request.amount.toLocaleString()} was rejected.\n` +
`You can reapply for a loan anytime.`,
mentions: [{
tag: `@${request.user}`,
id: request.userID
}]
},
request.threadID
);
return message.reply(`❌ Loan rejected for ${request.user}.`);
}
}
}
};