nexushub-commands 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Client.d.ts +20 -0
- package/lib/Client.js +28 -0
- package/lib/commands/CheckPaidOrder.command.d.ts +4 -0
- package/lib/commands/CheckPaidOrder.command.js +31 -0
- package/lib/commands/Deposit.command.d.ts +5 -0
- package/lib/commands/Deposit.command.js +208 -0
- package/lib/commands/GetDepositOrder.command.d.ts +5 -0
- package/lib/commands/GetDepositOrder.command.js +92 -0
- package/lib/commands/Withdrawal.command.d.ts +0 -0
- package/lib/commands/Withdrawal.command.js +1 -0
- package/lib/commands/index.d.ts +3 -0
- package/lib/commands/index.js +6 -0
- package/lib/convert.d.ts +17 -0
- package/lib/convert.js +64 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +4 -0
- package/lib/utils/CoinBase.service.d.ts +33 -0
- package/lib/utils/CoinBase.service.js +113 -0
- package/lib/utils/formatMessage.d.ts +8 -0
- package/lib/utils/formatMessage.js +46 -0
- package/package.json +16 -0
- package/src/Client.ts +49 -0
- package/src/commands/CheckPaidOrder.command.ts +16 -0
- package/src/commands/Deposit.command.ts +243 -0
- package/src/commands/GetDepositOrder.command.ts +88 -0
- package/src/commands/Withdrawal.command.ts +0 -0
- package/src/commands/index.ts +3 -0
- package/src/convert.ts +91 -0
- package/src/index.ts +1 -0
- package/src/utils/CoinBase.service.ts +129 -0
- package/src/utils/formatMessage.ts +43 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
//@ts-nocheck
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.formatMessage = formatMessage;
|
|
5
|
+
function formatMessage({ header, body, footer }) {
|
|
6
|
+
let text = header ? `${header}\n\n` : '';
|
|
7
|
+
for (const item of (body === null || body === void 0 ? void 0 : body.filter((x) => x)) || []) {
|
|
8
|
+
item.data = item.data.filter((x) => x);
|
|
9
|
+
if (!item.data.length)
|
|
10
|
+
continue;
|
|
11
|
+
text += `<blockquote><b>${item.title}</b></blockquote>`;
|
|
12
|
+
item.data.forEach((x, i) => {
|
|
13
|
+
var _a, _b, _c, _d;
|
|
14
|
+
if (!x[0])
|
|
15
|
+
return (text += '\n');
|
|
16
|
+
else if (!x[1] && x[1] !== undefined && x[1] !== null && !isNaN(x[1]))
|
|
17
|
+
x[1] = 'Отсутствует';
|
|
18
|
+
// else if (x[1] && Number(x[1].toString()?.replace(/\s/g, ''))) x[1] = Number(x[1].toString().replace(/\s/g, '')).toLocaleString('ru');
|
|
19
|
+
if ((i + 1 === item.data.length || !((_a = item.data[i + 1]) === null || _a === void 0 ? void 0 : _a.length)) && (i === 0 || ((_b = item.data[i - 1]) === null || _b === void 0 ? void 0 : _b.length)))
|
|
20
|
+
text += '┗';
|
|
21
|
+
else if (i > 0 && !((_c = item.data[i - 1]) === null || _c === void 0 ? void 0 : _c.length) && !((_d = item.data[i + 1]) === null || _d === void 0 ? void 0 : _d.length))
|
|
22
|
+
text += '┃';
|
|
23
|
+
else
|
|
24
|
+
text += '┣';
|
|
25
|
+
text += ' ';
|
|
26
|
+
if (x[0].includes('</a>') || x[0].match(/\@\S+/i))
|
|
27
|
+
text += x[0];
|
|
28
|
+
else
|
|
29
|
+
text += `<b>${x[0]}</b>`;
|
|
30
|
+
if (x[1]) {
|
|
31
|
+
text += ': ';
|
|
32
|
+
if (x[1].toString().includes('</a>') || x[1].toString().match(/\@\S+/i))
|
|
33
|
+
text += x[1];
|
|
34
|
+
else if (x[2] === null)
|
|
35
|
+
text += x[1];
|
|
36
|
+
else
|
|
37
|
+
text += `<${x[2] || 'code'}>${x[1]}</${x[2] || 'code'}>`;
|
|
38
|
+
}
|
|
39
|
+
text += '\n';
|
|
40
|
+
});
|
|
41
|
+
text += '\n';
|
|
42
|
+
}
|
|
43
|
+
if (footer)
|
|
44
|
+
text += `${footer}`;
|
|
45
|
+
return text;
|
|
46
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nexushub-commands",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "./lib/index.js",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"axios": "^1.9.0",
|
|
8
|
+
"chalk": "^5.4.1"
|
|
9
|
+
},
|
|
10
|
+
"peerDependencies": {
|
|
11
|
+
"evogram": "^2.0.8"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"evogram": "^2.2.3"
|
|
15
|
+
}
|
|
16
|
+
}
|
package/src/Client.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import axios, { AxiosInstance } from 'axios';
|
|
2
|
+
import { Evogram } from 'evogram';
|
|
3
|
+
import { CommandContext } from 'evogram/lib/migrated';
|
|
4
|
+
import { DepositCommand } from './commands/Deposit.command';
|
|
5
|
+
import { GetDepositOrderCommand } from './commands/GetDepositOrder.command';
|
|
6
|
+
|
|
7
|
+
// Интерфейсы для настройки команды
|
|
8
|
+
export interface DepositConfig {
|
|
9
|
+
// Базовые настройки
|
|
10
|
+
API: AxiosInstance;
|
|
11
|
+
currency: string;
|
|
12
|
+
|
|
13
|
+
// Настройки изображений
|
|
14
|
+
images: {
|
|
15
|
+
deposit: string;
|
|
16
|
+
depositCard: string;
|
|
17
|
+
depositCrypto: string;
|
|
18
|
+
[key: string]: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Настройки поддержки
|
|
22
|
+
support: {
|
|
23
|
+
username: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Значения по умолчанию для конфигурации
|
|
28
|
+
const defaultConfig: DepositConfig = {
|
|
29
|
+
API: axios.create(),
|
|
30
|
+
currency: 'RUB',
|
|
31
|
+
|
|
32
|
+
images: {
|
|
33
|
+
deposit: 'deposit',
|
|
34
|
+
depositCard: 'deposit-card',
|
|
35
|
+
depositCrypto: 'deposit-crypto',
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
support: {
|
|
39
|
+
username: 'support',
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export class Client {
|
|
44
|
+
public static config: (context: CommandContext) => DepositConfig;
|
|
45
|
+
|
|
46
|
+
public static async init(client: Evogram) {
|
|
47
|
+
client.commands.commands.push(new DepositCommand(client), new GetDepositOrderCommand(client));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CommandArgument, CommandD, CommandExecuteData } from 'evogram';
|
|
2
|
+
import { Command, CommandContext } from 'evogram/lib/migrated';
|
|
3
|
+
import { Client } from '../Client';
|
|
4
|
+
|
|
5
|
+
@CommandD({ name: 'checkPaidOrder', backButton: 'К пополнению' })
|
|
6
|
+
export class CheckPaidOrderCommand extends Command {
|
|
7
|
+
public async execute(context: CommandContext, @CommandArgument('orderId') orderId: string) {
|
|
8
|
+
const config = Client.config(context);
|
|
9
|
+
|
|
10
|
+
await config.API.get(`/orders/${orderId}/checkPaid`).catch(() => {});
|
|
11
|
+
const order = await config.API.get(`/orders/${orderId}`);
|
|
12
|
+
|
|
13
|
+
if (order.data.status !== 'paid' && order.data.status !== 'fakepaid') throw new Error('Счет еще не оплачен');
|
|
14
|
+
else context.callbackQuery?.answer({ text: 'Счет оплачен', show_alert: true });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { Command, CommandArgument, CommandD, Evogram, numberValidator } from 'evogram';
|
|
2
|
+
import { CommandContext } from 'evogram/lib/migrated';
|
|
3
|
+
import { Client } from '../Client';
|
|
4
|
+
import { GetDepositOrderCommand } from './GetDepositOrder.command';
|
|
5
|
+
import { formatMessage } from '../utils/formatMessage';
|
|
6
|
+
|
|
7
|
+
@CommandD({ name: 'deposit', description: [{ text: 'Пополнение' }, { language: 'en', text: 'Deposit' }] })
|
|
8
|
+
export class DepositCommand extends Command {
|
|
9
|
+
public async execute(
|
|
10
|
+
context: CommandContext,
|
|
11
|
+
|
|
12
|
+
@CommandArgument('method', async ({ value, context }) => {
|
|
13
|
+
const config = Client.config(context);
|
|
14
|
+
|
|
15
|
+
if (value) {
|
|
16
|
+
const paymentMethods = (await config.API.get('/payments')).data;
|
|
17
|
+
if (!paymentMethods.find((x: any) => x.isEnabled && x.type.toLowerCase() === value.toLowerCase()))
|
|
18
|
+
throw new Error('К сожалению, данный метод пополнения временно недоступен');
|
|
19
|
+
|
|
20
|
+
if (value !== 'cryptowallet') return value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!value) {
|
|
24
|
+
const allowedMethods = (await config.API.get('/orders/allowedMethods', { params: { currency: config.currency } })).data;
|
|
25
|
+
|
|
26
|
+
await context.sendFormatted(
|
|
27
|
+
{
|
|
28
|
+
photo: config.images.deposit,
|
|
29
|
+
header: '<b>📤 Выберите удобный для Вас метод пополнения.</b>',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
reply_markup: {
|
|
33
|
+
inline_keyboard: [
|
|
34
|
+
...(allowedMethods.includes('card') ? [[{ text: '💳 Банковская карта', command: DepositCommand, payload: { method: 'card' } }]] : []),
|
|
35
|
+
...(allowedMethods.includes('qrcode') ? [[{ text: '📸 QR-код (СБП)', command: DepositCommand, payload: { method: 'qrcode' } }]] : []),
|
|
36
|
+
[{ text: '🪙 Криптовалюта', command: DepositCommand, payload: { method: 'cryptowallet' } }],
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
} else if (value === 'cryptowallet') {
|
|
42
|
+
await context.sendFormatted(
|
|
43
|
+
{
|
|
44
|
+
photo: config.images.depositCrypto,
|
|
45
|
+
header: '<b>🪙 Выберите удобный для вас метод пополнения.</b>',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
reply_markup: {
|
|
49
|
+
inline_keyboard: [
|
|
50
|
+
[
|
|
51
|
+
{ text: '🤖 CryptoBot', command: DepositCommand, payload: { method: 'cryptoBot' } },
|
|
52
|
+
{ text: '🌐 По кошельку', command: DepositCommand, payload: { method: 'cryptoWallet' } },
|
|
53
|
+
],
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
method: string,
|
|
61
|
+
|
|
62
|
+
@CommandArgument('coin', async ({ value, args, context }) => {
|
|
63
|
+
if (value) return value;
|
|
64
|
+
else if (args.method !== 'cryptoWallet') return true;
|
|
65
|
+
|
|
66
|
+
const config = Client.config(context);
|
|
67
|
+
const wallets = await config.API.get('/crypto/wallets').then((x) => x.data.filter((x: any) => x.isActive));
|
|
68
|
+
|
|
69
|
+
context.sendFormatted(
|
|
70
|
+
{
|
|
71
|
+
header: '<b>🪙 Доступные криптовалюты для пополнения:</b>',
|
|
72
|
+
photo: config.images.depositCrypto,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
reply_markup: {
|
|
76
|
+
inline_keyboard: wallets.map((x: any) => [
|
|
77
|
+
{
|
|
78
|
+
text: x.name,
|
|
79
|
+
command: DepositCommand,
|
|
80
|
+
payload: { ...args, coin: x.name },
|
|
81
|
+
},
|
|
82
|
+
]),
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
})
|
|
87
|
+
coin: string | undefined,
|
|
88
|
+
|
|
89
|
+
@CommandArgument(
|
|
90
|
+
{
|
|
91
|
+
name: 'deposit',
|
|
92
|
+
question: async ({ context, error, args, validateArgs }) => {
|
|
93
|
+
if (args.method === 'cryptoWallet') return 1;
|
|
94
|
+
const config = Client.config(context);
|
|
95
|
+
|
|
96
|
+
let minAmountSetting = JSON.parse(context.state.settings.find((x: any) => x.name === 'minDeposit').value);
|
|
97
|
+
let minAmount = minAmountSetting[config.currency] ?? (await minAmountSetting['RUB'].convert({ from: 'RUB', to: config.currency }));
|
|
98
|
+
|
|
99
|
+
const minDepositByMethod = await config.API.get('/config/minDepositByMethod').then((x) => x.data);
|
|
100
|
+
// prettier-ignore
|
|
101
|
+
if (minDepositByMethod && minDepositByMethod[args.method] !== undefined && (await minAmount.convert({ from: config.currency, to: 'RUB' })) < minDepositByMethod[args.method])
|
|
102
|
+
minAmount = await minDepositByMethod[args.method].convert({ from: 'RUB', to: config.currency });
|
|
103
|
+
|
|
104
|
+
validateArgs.minAmount = minAmount;
|
|
105
|
+
return (
|
|
106
|
+
await context.sendFormattedQuestion({
|
|
107
|
+
photo: ['card', 'qrcode'].includes(args.method) ? config.images.deposit : config.images.depositCrypto,
|
|
108
|
+
body: [
|
|
109
|
+
{
|
|
110
|
+
title: '💰 Сумма пополнения',
|
|
111
|
+
data: [['Введите сумму пополнения']],
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
footer: `<i>Минимальная сумма пополнения: {{ ${Number(minAmount).toLocaleString('ru')} ${config.currency} }}</i>`,
|
|
115
|
+
error: error?.message,
|
|
116
|
+
})
|
|
117
|
+
).text;
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
numberValidator({ allowFloat: true, min: 0 }),
|
|
121
|
+
async ({ value, context, args }) => {
|
|
122
|
+
if (args.method === 'cryptoWallet') return 0;
|
|
123
|
+
const config = Client.config(context);
|
|
124
|
+
|
|
125
|
+
const maxDeposit = await config.API.get('/config/maxDepositInService').then((x) => x.data);
|
|
126
|
+
const depositAmount = await value.convert({ from: config.currency, to: 'RUB' });
|
|
127
|
+
|
|
128
|
+
if (depositAmount > maxDeposit)
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Пополнение, более чем на ${await maxDeposit.convert({ from: 'RUB', to: config.currency })}, доступно только через <a href="t.me/{{ ${
|
|
131
|
+
config.support.username
|
|
132
|
+
} }}">тех. поддержку</a>`
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
return value;
|
|
136
|
+
},
|
|
137
|
+
async ({ value, context, validateArgs }) => {
|
|
138
|
+
const config = Client.config(context);
|
|
139
|
+
|
|
140
|
+
if (Number(value) < Number(validateArgs.minAmount))
|
|
141
|
+
throw new Error(`Минимальная сумма пополнения: ${Number(validateArgs.minAmount).toLocaleString('ru')} ${config.currency}`);
|
|
142
|
+
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
deposit: number
|
|
147
|
+
) {
|
|
148
|
+
const config = Client.config(context);
|
|
149
|
+
let interval: NodeJS.Timeout;
|
|
150
|
+
|
|
151
|
+
if (method !== 'cryptoWallet') {
|
|
152
|
+
if (['card', 'qrcode'].includes(method)) {
|
|
153
|
+
const message = await context.sendFormatted({
|
|
154
|
+
photo: config.images.deposit,
|
|
155
|
+
body: [
|
|
156
|
+
{
|
|
157
|
+
title: 'ℹ️ Подождите, идет обработка заявки',
|
|
158
|
+
data: [['Создаем заявку на пополнение...']],
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const startTime = Date.now();
|
|
164
|
+
interval = setInterval(async () => {
|
|
165
|
+
await message.edit({
|
|
166
|
+
text: formatMessage({
|
|
167
|
+
body: [
|
|
168
|
+
{
|
|
169
|
+
title: 'ℹ️ Подождите, идет обработка заявки',
|
|
170
|
+
data: [[`Создаем заявку на пополнение...`]],
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
footer: `<i>⏳ Прошло {{ ${Math.floor((Date.now() - startTime) / 1000)} }} сек.</i>`,
|
|
174
|
+
}),
|
|
175
|
+
parse_mode: 'HTML',
|
|
176
|
+
});
|
|
177
|
+
}, 1000);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const order = await config.API.post(`orders`, {
|
|
181
|
+
mirrorId: context.mammoth.mirror.mirror.id,
|
|
182
|
+
mammothId: context.user.id,
|
|
183
|
+
method,
|
|
184
|
+
amount: Number(deposit),
|
|
185
|
+
currency: config.currency,
|
|
186
|
+
})
|
|
187
|
+
.then((x) => x.data)
|
|
188
|
+
.catch(() => null);
|
|
189
|
+
|
|
190
|
+
//@ts-ignore
|
|
191
|
+
if (interval) clearInterval(interval);
|
|
192
|
+
this.logger.log(`Запрос на пополнение: ${JSON.stringify(order, null, 2)}`);
|
|
193
|
+
|
|
194
|
+
if (!order) {
|
|
195
|
+
context.user.log(0, `Не удалось получить реквизиты для пополнения на сумму ${Number(deposit).toLocaleString('ru')} ${config.currency}`);
|
|
196
|
+
return context.sendFormatted(
|
|
197
|
+
{
|
|
198
|
+
photo: config.images.deposit,
|
|
199
|
+
header: '<b>❗️К сожалению, сейчас нет доступных реквизитов для оплаты.</b>',
|
|
200
|
+
footer: '<i>ℹ️ Вы можете попробовать чуть позже, либо связаться с технической поддержкой.</i>',
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
reply_markup: {
|
|
204
|
+
inline_keyboard: [[{ text: '👩💻 Поддержка', url: `t.me/${config.support.username}` }]],
|
|
205
|
+
},
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (!order.isRepeat)
|
|
211
|
+
await context.user.log(
|
|
212
|
+
0,
|
|
213
|
+
`Запросил пополнение на ${Number(order.amount).toLocaleString('ru')} ${order.currency} (${await order.amount.convert({
|
|
214
|
+
from: order.currency,
|
|
215
|
+
to: 'RUB',
|
|
216
|
+
ceiled: true,
|
|
217
|
+
})})`,
|
|
218
|
+
{
|
|
219
|
+
keyboard: [[{ text: '🚀 Оплатить счет', callback_data: `paidOrder?orderId=${order.id}` }]],
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
return context.redirect(GetDepositOrderCommand, { orderId: order.id });
|
|
224
|
+
} else {
|
|
225
|
+
const wallets = (await config.API.get('/crypto/wallets')).data.filter((x: any) => x.isActive);
|
|
226
|
+
|
|
227
|
+
return context.sendFormatted({
|
|
228
|
+
photo: config.images.depositCrypto,
|
|
229
|
+
header: '<b>Создана заявка на оплату</b>',
|
|
230
|
+
body: [
|
|
231
|
+
{
|
|
232
|
+
title: 'ℹ️ Информация о реквизитах',
|
|
233
|
+
data: [
|
|
234
|
+
['Адрес кошелька', `{{ ${wallets.find((x: any) => x.name === coin).address} }}`],
|
|
235
|
+
['Криптовалюта', `{{ ${coin} }}`],
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
footer: '<i>Это Ваш постоянный адрес для пополнения.</i>',
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Command, CommandArgument, CommandD, CommandExecuteData } from 'evogram';
|
|
2
|
+
import { CommandContext } from 'evogram/lib/migrated';
|
|
3
|
+
import { Client } from '../Client';
|
|
4
|
+
import { CheckPaidOrderCommand } from './CheckPaidOrder.command';
|
|
5
|
+
|
|
6
|
+
@CommandD({ name: 'getDepositOrder', backButton: 'К пополнению' })
|
|
7
|
+
export class GetDepositOrderCommand extends Command {
|
|
8
|
+
public async execute(context: CommandContext, @CommandArgument('orderId') orderId: string) {
|
|
9
|
+
const config = Client.config(context);
|
|
10
|
+
const order = await config.API.get(`/orders/deposit/${orderId}`)
|
|
11
|
+
.then((x) => x.data)
|
|
12
|
+
.catch(() => null);
|
|
13
|
+
|
|
14
|
+
if (!order) throw new Error('Заявка на оплату не найдена');
|
|
15
|
+
|
|
16
|
+
switch (order.method) {
|
|
17
|
+
case 'cryptoBot':
|
|
18
|
+
return context.sendFormatted(
|
|
19
|
+
{
|
|
20
|
+
photo: config.images.depositCrypto,
|
|
21
|
+
header: '<b>Создана заявка на оплату</b>',
|
|
22
|
+
body: [
|
|
23
|
+
{
|
|
24
|
+
title: 'ℹ️ Информация о счете',
|
|
25
|
+
data: [
|
|
26
|
+
['Сумма', `{{ ${Number(order.amount).toLocaleString('ru')} ${order.currency} }}`],
|
|
27
|
+
['Дата', `{{ ${new Date().toLocaleString('ru')} }}`],
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
title: '📎 Ваша ссылка для оплаты',
|
|
32
|
+
data: [[`{{ ${order.cryptoBot.url} }}`]],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
footer: '<i>Ссылка действительна 10 минут.</i>',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
reply_markup: {
|
|
39
|
+
inline_keyboard: [
|
|
40
|
+
[{ text: '🔗 Перейти к оплате', url: order.cryptoBot.url }],
|
|
41
|
+
[{ text: '🔄 Проверить оплату', command: CheckPaidOrderCommand, payload: { orderId: order.id } }],
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
case 'card':
|
|
47
|
+
return context.sendFormatted(
|
|
48
|
+
{
|
|
49
|
+
photo: config.images.deposit,
|
|
50
|
+
header: order.isRepeat ? '<b>❗️У вас уже есть заявка на пополнение, сначала оплатите ёё</b>' : '<b>Создана заявка на оплату</b>',
|
|
51
|
+
body: [
|
|
52
|
+
{
|
|
53
|
+
title: 'ℹ️ Информация о реквизитах',
|
|
54
|
+
data: [
|
|
55
|
+
['Реквизиты', `{{ ${order.card.requisites} }}`],
|
|
56
|
+
order.card.bank && ['Банк', `{{ ${order.card.bank} }}`],
|
|
57
|
+
order.card.holder && ['Получатель', `{{ ${order.card.holder} }}`],
|
|
58
|
+
['Сумма оплаты', `{{ ${Number(order.amount).toLocaleString('ru')} ${order.currency} }}`],
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
footer: '<i>Реквизиты действительны 10 минут.</i>',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
reply_markup: {
|
|
66
|
+
inline_keyboard: [[{ text: '🔄 Проверить оплату', command: CheckPaidOrderCommand, payload: { orderId: order.id } }]],
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
case 'qrcode':
|
|
71
|
+
return context.sendFormatted(
|
|
72
|
+
{
|
|
73
|
+
photo: config.images.deposit,
|
|
74
|
+
header: '<b>Создана заявка на оплату</b>',
|
|
75
|
+
footer: `<i>Ссылка действительна ${Math.ceil((new Date(order.expiresAt).getTime() - new Date().getTime()) / 60000)} минут.</i>`,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
reply_markup: {
|
|
79
|
+
inline_keyboard: [
|
|
80
|
+
[{ text: '🔗 Перейти к оплате', url: order.qrcode.link }],
|
|
81
|
+
[{ text: '🔄 Проверить оплату', command: CheckPaidOrderCommand, payload: { orderId: order.id } }],
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
File without changes
|
package/src/convert.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { CoinBaseService } from './utils/CoinBase.service';
|
|
2
|
+
|
|
3
|
+
interface ConvertParams {
|
|
4
|
+
from?: string;
|
|
5
|
+
to: string;
|
|
6
|
+
round?: boolean;
|
|
7
|
+
ceiled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface CurrencyConverter {
|
|
11
|
+
convert(params: ConvertParams): Promise<number>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class ConvertedNumber {
|
|
15
|
+
private value: number;
|
|
16
|
+
private stringValue: string;
|
|
17
|
+
|
|
18
|
+
constructor(value: number, stringValue: string) {
|
|
19
|
+
this.value = value;
|
|
20
|
+
this.stringValue = stringValue;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Переопределяем метод toString
|
|
24
|
+
toString() {
|
|
25
|
+
return this.stringValue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Добавляем valueOf для корректного сравнения
|
|
29
|
+
valueOf() {
|
|
30
|
+
return this.value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
convert(params: ConvertParams) {
|
|
34
|
+
return this.value.convert(params);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare global {
|
|
39
|
+
interface String extends CurrencyConverter {
|
|
40
|
+
translate(language: string, ...args: any[]): Promise<string>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface Number extends CurrencyConverter {}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Number.prototype.convert = async function (this: number, params: ConvertParams): Promise<number> {
|
|
47
|
+
const { to = 'RUB', from = 'RUB', round, ceiled } = params;
|
|
48
|
+
|
|
49
|
+
const fromCurrency = from.toUpperCase();
|
|
50
|
+
const currency = to.toUpperCase();
|
|
51
|
+
|
|
52
|
+
if (currency === 'RUB' && fromCurrency === 'RUB') {
|
|
53
|
+
const value = round ? Math.round(this) : ceiled ? Math.ceil(this) : this;
|
|
54
|
+
//@ts-ignore
|
|
55
|
+
return new ConvertedNumber(value, `${value.toLocaleString('ru', { maximumFractionDigits: 2 })} RUB`);
|
|
56
|
+
} else if (currency === 'RUB') {
|
|
57
|
+
const rates = await CoinBaseService.getInstance().getRates('RUB');
|
|
58
|
+
const targetRate = 1 / Number(rates[fromCurrency]);
|
|
59
|
+
|
|
60
|
+
let convertedAmount = this * Number(targetRate);
|
|
61
|
+
if (!convertedAmount) convertedAmount = this;
|
|
62
|
+
|
|
63
|
+
if (round) {
|
|
64
|
+
convertedAmount = Math.round(convertedAmount);
|
|
65
|
+
} else if (ceiled) {
|
|
66
|
+
convertedAmount = Math.ceil(convertedAmount);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//@ts-ignore
|
|
70
|
+
return new ConvertedNumber(convertedAmount, `${convertedAmount.toLocaleString('ru', { maximumFractionDigits: 2 })} ${currency}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const rates = await CoinBaseService.getInstance().getRates(fromCurrency);
|
|
74
|
+
const targetRate = rates[currency];
|
|
75
|
+
|
|
76
|
+
let convertedAmount = this * Number(targetRate);
|
|
77
|
+
if (!convertedAmount) convertedAmount = this;
|
|
78
|
+
|
|
79
|
+
if (round) {
|
|
80
|
+
convertedAmount = Math.round(convertedAmount);
|
|
81
|
+
} else if (ceiled) {
|
|
82
|
+
convertedAmount = Math.ceil(convertedAmount);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//@ts-ignore
|
|
86
|
+
return new ConvertedNumber(convertedAmount, `${convertedAmount.toLocaleString('ru', { maximumFractionDigits: 2 })} ${targetRate ? currency : 'RUB'}`);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
String.prototype.convert = function (this: string, params: ConvertParams) {
|
|
90
|
+
return Number(this).convert(params);
|
|
91
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Client';
|