-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpaybillprocessor.js
More file actions
169 lines (148 loc) · 5.24 KB
/
Copy pathpaybillprocessor.js
File metadata and controls
169 lines (148 loc) · 5.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// paybillprocessor.js
const {
getBill,
getUser,
createUser,
setCoins,
deleteBill,
enqueueDM,
fromSats,
logTransaction // <-- nova função que deve existir em database.js
} = require('./database');
const { processDMQueue } = require('./dmQueue');
/**
* Registers a handler to process /paybill modal submissions.
* @param {import('discord.js').Client} client
*/
module.exports = function setupPaybillProcessor(client) {
client.on('interactionCreate', async interaction => {
if (!interaction.isModalSubmit() || interaction.customId !== 'paybill_modal') return;
// 1) Acknowledge the modal
await interaction.deferReply({ ephemeral: true }).catch(() => null);
// 2) Read inputs
const billId = interaction.fields.getTextInputValue('billId').trim();
// 3) Fetch the bill (await in case DB functions are async)
let bill;
try {
bill = await getBill(billId);
} catch (err) {
console.warn('⚠️ [/paybill] getBill error:', err);
return interaction.editReply('❌ Bill lookup failed.');
}
if (!bill) {
return interaction.editReply('❌ Bill not found.');
}
const executorId = interaction.user.id;
const toId = bill.to_id;
const fromId = bill.from_id;
// 4) Read stored satoshis (normalize)
const amountSats = Number(bill.amount);
if (!Number.isInteger(amountSats) || amountSats <= 0) {
return interaction.editReply('❌ Invalid bill amount.');
}
const selfPay = executorId === toId;
// 5) If not self-pay, verify balance & perform transfer
if (!selfPay) {
let payer;
try {
payer = await getUser(executorId);
} catch (err) {
console.warn('⚠️ [/paybill] getUser(payer) error:', err);
return interaction.editReply('❌ Error checking your account.');
}
if (!payer) {
return interaction.editReply('❌ Your account not found.');
}
if (payer.coins < amountSats) {
return interaction.editReply(
`💸 Low balance. You need **${fromSats(amountSats)}** coins.`
);
}
let payee;
try {
payee = await getUser(toId);
if (!payee) {
// createUser should insert a user with 0 coins; then we re-fetch
await createUser(toId);
payee = await getUser(toId);
}
} catch (err) {
console.warn('⚠️ [/paybill] getUser/createUser(payee) error:', err);
return interaction.editReply('❌ Error preparing recipient account.');
}
const newPayerBalance = payer.coins - amountSats;
const newPayeeBalance = (payee?.coins || 0) + amountSats;
try {
// Use database.js to persist balances
await setCoins(executorId, newPayerBalance);
await setCoins(toId, newPayeeBalance);
} catch (err) {
console.warn('⚠️ [/paybill] Error performing transfer (setCoins):', err);
return interaction.editReply('❌ Transfer failed.');
}
}
// 6) Log transaction via database.js (no direct SQL here)
const paidAt = new Date().toISOString();
try {
// logTransaction should insert into transactions table
await logTransaction(billId, paidAt, executorId, toId, amountSats);
} catch (err) {
console.warn('⚠️ [/paybill] Error logging transaction via database.js:', err);
// continue — this is best-effort
}
// 7) Delete the bill (via database.js)
try {
await deleteBill(billId);
} catch (err) {
console.warn('⚠️ [/paybill] Error deleting bill:', err);
}
// 8) Notify the recipient
try {
enqueueDM(toId, {
title: '🏦 Bill Paid 🏦',
description: [
`Received **${fromSats(amountSats)}** coins`,
`From: \`${executorId}\``,
`Bill ID: \`${billId}\``,
'*Received ✅*'
].join('\n'),
type: 'rich'
}, { components: [] });
processDMQueue();
} catch (err) {
console.warn('⚠️ [/paybill] Error enqueueing recipient DM:', err);
}
// 9) Notify the bill creator if different
if (fromId && fromId !== executorId) {
try {
enqueueDM(fromId, {
title: '🏦 Your Bill Was Paid 🏦',
description: [
`Your bill \`${billId}\` for **${fromSats(amountSats)}** coins`,
`was paid by: \`${executorId}\``,
'*Thank you!*'
].join('\n'),
type: 'rich'
}, { components: [] });
} catch (err) {
console.warn('⚠️ [/paybill] Error enqueueing creator DM:', err);
}
}
// 10) Process any remaining DMs
if (typeof interaction.client.processDMQueue === 'function') {
interaction.client.processDMQueue();
}
// 11) Final reply to executor
let toTag = 'yourself';
try {
toTag = selfPay
? 'yourself'
: (await interaction.client.users.fetch(toId)).tag;
} catch {}
return interaction.editReply(
selfPay
? `✅ You canceled your own bill \`${billId}\`.`
: `✅ Paid **${fromSats(amountSats)}** coins to **${toTag}** (\`${toId}\`).`
);
});
};