update user and admin wallet function
This commit is contained in:
parent
a970a188db
commit
3129525a1e
@ -20,6 +20,7 @@
|
|||||||
"node-telegram-bot-api": "^0.64.0",
|
"node-telegram-bot-api": "^0.64.0",
|
||||||
"sqlite3": "^5.1.6",
|
"sqlite3": "^5.1.6",
|
||||||
"tiny-secp256k1": "^2.2.3",
|
"tiny-secp256k1": "^2.2.3",
|
||||||
|
"csv-writer": "^1.6.0",
|
||||||
"tronweb": "^5.3.2"
|
"tronweb": "^5.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -538,7 +538,7 @@ export default class AdminProductHandler {
|
|||||||
callback_data: `view_product_${prod.id}`
|
callback_data: `view_product_${prod.id}`
|
||||||
}]),
|
}]),
|
||||||
[{ text: '➕ Add Product', callback_data: `add_product_${locationId}_${categoryId}` }],
|
[{ text: '➕ Add Product', callback_data: `add_product_${locationId}_${categoryId}` }],
|
||||||
[{ text: '« Back', callback_data: `prod_district_${location.country}_${location.city}_${location.district}` }]
|
[{ text: '« Back', callback_data: `prod_district_${location.country}_${location.city}_${location.district}` }] // Исправлено на категорию
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -824,40 +824,40 @@ export default class AdminProductHandler {
|
|||||||
if (!this.isAdmin(callbackQuery.from.id)) {
|
if (!this.isAdmin(callbackQuery.from.id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chatId = callbackQuery.message.chat.id;
|
const chatId = callbackQuery.message.chat.id;
|
||||||
const messageId = callbackQuery.message.message_id;
|
const messageId = callbackQuery.message.message_id;
|
||||||
const productId = callbackQuery.data.replace('view_product_', '');
|
const productId = callbackQuery.data.replace('view_product_', '');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const product = await ProductService.getDetailedProductById(productId)
|
const product = await ProductService.getDetailedProductById(productId);
|
||||||
|
|
||||||
if (!product) {
|
if (!product) {
|
||||||
throw new Error('Product not found');
|
throw new Error('Product not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const location = await LocationService.getLocationById(product.location_id);
|
const location = await LocationService.getLocationById(product.location_id);
|
||||||
|
|
||||||
if (!location) {
|
if (!location) {
|
||||||
throw new Error('Location not found');
|
throw new Error('Location not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = `
|
const message = `
|
||||||
📦 Product Details:
|
📦 Product Details:
|
||||||
|
|
||||||
Name: ${product.name}
|
Name: ${product.name}
|
||||||
Price: $${product.price}
|
Price: $${product.price}
|
||||||
Description: ${product.description}
|
Description: ${product.description}
|
||||||
Stock: ${product.quantity_in_stock}
|
Stock: ${product.quantity_in_stock}
|
||||||
Location: ${location.country}, ${location.city}, ${location.district}
|
Location: ${location.country}, ${location.city}, ${location.district}
|
||||||
Category: ${product.category_name}
|
Category: ${product.category_name}
|
||||||
|
|
||||||
🔒 Private Information:
|
🔒 Private Information:
|
||||||
${product.private_data}
|
${product.private_data}
|
||||||
Hidden Location: ${product.hidden_description}
|
Hidden Location: ${product.hidden_description}
|
||||||
Coordinates: ${product.hidden_coordinates}
|
Coordinates: ${product.hidden_coordinates}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const keyboard = {
|
const keyboard = {
|
||||||
inline_keyboard: [
|
inline_keyboard: [
|
||||||
[
|
[
|
||||||
@ -866,14 +866,14 @@ Coordinates: ${product.hidden_coordinates}
|
|||||||
],
|
],
|
||||||
[{
|
[{
|
||||||
text: '« Back',
|
text: '« Back',
|
||||||
callback_data: `prod_subcategory_${product.location_id}_${product.category_id}_${product.subcategory_id}`
|
callback_data: `prod_category_${product.location_id}_${product.category_id}` // Исправлено на категорию
|
||||||
}]
|
}]
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
let photoMessage;
|
let photoMessage;
|
||||||
let hiddenPhotoMessage;
|
let hiddenPhotoMessage;
|
||||||
|
|
||||||
// Send product photos
|
// Send product photos
|
||||||
if (product.photo_url) {
|
if (product.photo_url) {
|
||||||
try {
|
try {
|
||||||
@ -889,11 +889,11 @@ Coordinates: ${product.hidden_coordinates}
|
|||||||
hiddenPhotoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", {caption: 'Hidden photo'})
|
hiddenPhotoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", {caption: 'Hidden photo'})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userStates.set(chatId, {
|
userStates.set(chatId, {
|
||||||
msgToDelete: [photoMessage.message_id, hiddenPhotoMessage.message_id]
|
msgToDelete: [photoMessage.message_id, hiddenPhotoMessage.message_id]
|
||||||
})
|
})
|
||||||
|
|
||||||
await bot.deleteMessage(chatId, messageId);
|
await bot.deleteMessage(chatId, messageId);
|
||||||
await bot.sendMessage(chatId, message, {reply_markup: keyboard});
|
await bot.sendMessage(chatId, message, {reply_markup: keyboard});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
184
src/handlers/adminHandlers/adminWalletsHandler.js
Normal file
184
src/handlers/adminHandlers/adminWalletsHandler.js
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import bot from "../../context/bot.js";
|
||||||
|
import config from '../../config/config.js';
|
||||||
|
import WalletService from '../../services/walletService.js';
|
||||||
|
import WalletUtils from '../../utils/walletUtils.js';
|
||||||
|
import fs from 'fs';
|
||||||
|
import csvWriter from 'csv-writer';
|
||||||
|
|
||||||
|
export default class AdminWalletsHandler {
|
||||||
|
static async handleWalletManagement(msg) {
|
||||||
|
const chatId = msg.chat.id;
|
||||||
|
|
||||||
|
// Проверяем, является ли пользователь администратором
|
||||||
|
if (!this.isAdmin(msg.from.id)) {
|
||||||
|
await bot.sendMessage(chatId, 'Unauthorized access.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyboard = {
|
||||||
|
reply_markup: {
|
||||||
|
inline_keyboard: [
|
||||||
|
[
|
||||||
|
{ text: 'Bitcoin (BTC)', callback_data: 'wallet_type_BTC' },
|
||||||
|
{ text: 'Litecoin (LTC)', callback_data: 'wallet_type_LTC' }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ text: 'Tether (USDT)', callback_data: 'wallet_type_USDT' },
|
||||||
|
{ text: 'Ethereum (ETH)', callback_data: 'wallet_type_ETH' }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ text: 'TRON (TRX)', callback_data: 'wallet_type_TRON' }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await bot.sendMessage(chatId, 'Select wallet type:', keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async handleWalletTypeSelection(callbackQuery) {
|
||||||
|
const action = callbackQuery.data;
|
||||||
|
const chatId = callbackQuery.message.chat.id;
|
||||||
|
const walletType = action.split('_').pop();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Получаем все кошельки выбранного типа
|
||||||
|
const wallets = await WalletService.getWalletsByType(walletType);
|
||||||
|
|
||||||
|
if (wallets.length === 0) {
|
||||||
|
await bot.sendMessage(chatId, `No wallets found for ${walletType}.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вычисляем суммарный баланс
|
||||||
|
const totalBalance = await this.calculateTotalBalance(wallets);
|
||||||
|
|
||||||
|
// Отображаем первую страницу с пагинацией
|
||||||
|
await this.displayWalletsPage(chatId, wallets, walletType, totalBalance, 0);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching wallets:', error);
|
||||||
|
await bot.sendMessage(chatId, 'Failed to fetch wallets. Please try again later.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async displayWalletsPage(chatId, wallets, walletType, totalBalance, page) {
|
||||||
|
const pageSize = 50;
|
||||||
|
const startIndex = page * pageSize;
|
||||||
|
const endIndex = startIndex + pageSize;
|
||||||
|
const walletsPage = wallets.slice(startIndex, endIndex);
|
||||||
|
|
||||||
|
// Формируем список кошельков с балансами
|
||||||
|
const walletList = walletsPage.map(wallet => `${wallet.address} - ${wallet.balance}`).join('\n');
|
||||||
|
|
||||||
|
// Создаем клавиатуру с пагинацией
|
||||||
|
const keyboard = {
|
||||||
|
inline_keyboard: [
|
||||||
|
[
|
||||||
|
{ text: '⬅️ Previous', callback_data: `prev_page_${walletType}_${page - 1}` },
|
||||||
|
{ text: 'Next ➡️', callback_data: `next_page_${walletType}_${page + 1}` }
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ text: 'Back to Wallet Types', callback_data: 'back_to_wallet_types' },
|
||||||
|
{ text: 'Export to CSV', callback_data: `export_csv_${walletType}` }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Убираем кнопку "Назад", если это первая страница
|
||||||
|
if (page === 0) {
|
||||||
|
keyboard.inline_keyboard[0].shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Убираем кнопку "Далее", если это последняя страница
|
||||||
|
if (endIndex >= wallets.length) {
|
||||||
|
keyboard.inline_keyboard[0].pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Отправляем сообщение с суммарным балансом и списком кошельков
|
||||||
|
await bot.editMessageText(
|
||||||
|
`Total Balance for ${walletType}: $${totalBalance.toFixed(2)}\n\nWallets (${startIndex + 1}-${endIndex} of ${wallets.length}):\n${walletList}`,
|
||||||
|
{
|
||||||
|
chat_id: chatId,
|
||||||
|
message_id: callbackQuery.message.message_id,
|
||||||
|
parse_mode: 'Markdown',
|
||||||
|
reply_markup: keyboard
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async calculateTotalBalance(wallets) {
|
||||||
|
let totalBalance = 0;
|
||||||
|
|
||||||
|
for (const wallet of wallets) {
|
||||||
|
const walletUtilsInstance = new WalletUtils(
|
||||||
|
wallet.wallet_type.startsWith('BTC') ? wallet.address : null,
|
||||||
|
wallet.wallet_type.startsWith('LTC') ? wallet.address : null,
|
||||||
|
wallet.wallet_type.startsWith('TRON') ? wallet.address : null,
|
||||||
|
wallet.wallet_type.startsWith('ETH') ? wallet.address : null,
|
||||||
|
null, // userId не нужен для админки
|
||||||
|
Date.now() - 30 * 24 * 60 * 60 * 1000
|
||||||
|
);
|
||||||
|
|
||||||
|
const balances = await walletUtilsInstance.getAllBalances();
|
||||||
|
const balance = balances[wallet.wallet_type] || { usdValue: 0 };
|
||||||
|
totalBalance += balance.usdValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return totalBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async handlePagination(callbackQuery) {
|
||||||
|
const action = callbackQuery.data;
|
||||||
|
const chatId = callbackQuery.message.chat.id;
|
||||||
|
const [actionType, walletType, page] = action.split('_');
|
||||||
|
|
||||||
|
// Получаем все кошельки выбранного типа
|
||||||
|
const wallets = await WalletService.getWalletsByType(walletType);
|
||||||
|
|
||||||
|
// Вычисляем суммарный баланс
|
||||||
|
const totalBalance = await this.calculateTotalBalance(wallets);
|
||||||
|
|
||||||
|
// Отображаем страницу с учетом пагинации
|
||||||
|
await this.displayWalletsPage(chatId, wallets, walletType, totalBalance, parseInt(page));
|
||||||
|
}
|
||||||
|
|
||||||
|
static async handleExportCSV(callbackQuery) {
|
||||||
|
const action = callbackQuery.data;
|
||||||
|
const chatId = callbackQuery.message.chat.id;
|
||||||
|
const walletType = action.split('_').pop();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Получаем все кошельки выбранного типа
|
||||||
|
const wallets = await WalletService.getWalletsByType(walletType);
|
||||||
|
|
||||||
|
if (wallets.length === 0) {
|
||||||
|
await bot.sendMessage(chatId, `No wallets found for ${walletType}.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Создаем CSV-файл
|
||||||
|
const csv = csvWriter.createObjectCsvWriter({
|
||||||
|
path: `wallets_${walletType}.csv`,
|
||||||
|
header: [
|
||||||
|
{ id: 'address', title: 'Address' },
|
||||||
|
{ id: 'balance', title: 'Balance' }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
await csv.writeRecords(wallets);
|
||||||
|
|
||||||
|
// Отправляем файл пользователю
|
||||||
|
await bot.sendDocument(chatId, fs.createReadStream(`wallets_${walletType}.csv`));
|
||||||
|
|
||||||
|
// Удаляем временный файл
|
||||||
|
fs.unlinkSync(`wallets_${walletType}.csv`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error exporting wallets to CSV:', error);
|
||||||
|
await bot.sendMessage(chatId, 'Failed to export wallets to CSV. Please try again later.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static isAdmin(userId) {
|
||||||
|
return config.ADMIN_IDS.includes(userId.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import config from "../../config/config.js";
|
import config from "../../config/config.js";
|
||||||
|
import db from '../../config/database.js';
|
||||||
import PurchaseService from "../../services/purchaseService.js";
|
import PurchaseService from "../../services/purchaseService.js";
|
||||||
import UserService from "../../services/userService.js";
|
import UserService from "../../services/userService.js";
|
||||||
import LocationService from "../../services/locationService.js";
|
import LocationService from "../../services/locationService.js";
|
||||||
@ -229,21 +230,41 @@ export default class UserPurchaseHandler {
|
|||||||
const purchaseId = callbackQuery.data.replace('confirm_received_', '');
|
const purchaseId = callbackQuery.data.replace('confirm_received_', '');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Проверяем, подтверждена ли покупка уже
|
// Получаем данные покупки
|
||||||
const purchase = await PurchaseService.getPurchaseById(purchaseId);
|
const purchase = await PurchaseService.getPurchaseById(purchaseId);
|
||||||
if (!purchase) {
|
if (!purchase) {
|
||||||
await bot.sendMessage(chatId, "Purchase not found.");
|
await bot.sendMessage(chatId, "Purchase not found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (purchase.status === 'received') {
|
// Получаем данные пользователя по user_id из покупки
|
||||||
await bot.sendMessage(chatId, "This purchase has already been confirmed.");
|
const user = await UserService.getUserByUserId(purchase.user_id);
|
||||||
|
if (!user) {
|
||||||
|
await bot.sendMessage(chatId, "User not found for this purchase.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Логируем данные для отладки
|
||||||
|
console.log('Purchase data:', purchase);
|
||||||
|
console.log('User data:', user);
|
||||||
|
|
||||||
// Обновляем статус покупки в базе данных
|
// Обновляем статус покупки в базе данных
|
||||||
await PurchaseService.updatePurchaseStatus(purchaseId, 'received');
|
await PurchaseService.updatePurchaseStatus(purchaseId, 'received');
|
||||||
|
|
||||||
|
// Добавляем транзакцию в таблицу transactions
|
||||||
|
await db.runAsync(`
|
||||||
|
INSERT INTO transactions (user_id, wallet_type, tx_hash, amount, created_at)
|
||||||
|
VALUES (?, ?, ?, ?, ?)
|
||||||
|
`, [
|
||||||
|
user.id, // ID пользователя
|
||||||
|
purchase.wallet_type || 'unknown', // Тип кошелька (если не указан, то "unknown")
|
||||||
|
purchase.tx_hash || 'no_hash', // Хеш транзакции (если не указан, то "no_hash")
|
||||||
|
purchase.total_price, // Сумма транзакции
|
||||||
|
new Date().toISOString() // Дата создания транзакции
|
||||||
|
]);
|
||||||
|
|
||||||
|
console.log('Transaction added successfully'); // Логируем успешную вставку
|
||||||
|
|
||||||
// Отправляем уведомление администраторам
|
// Отправляем уведомление администраторам
|
||||||
const adminIds = config.ADMIN_IDS; // Используем массив ADMIN_IDS
|
const adminIds = config.ADMIN_IDS; // Используем массив ADMIN_IDS
|
||||||
for (const adminId of adminIds) {
|
for (const adminId of adminIds) {
|
||||||
@ -255,7 +276,7 @@ export default class UserPurchaseHandler {
|
|||||||
|
|
||||||
// Удаляем сообщение с карточкой товара
|
// Удаляем сообщение с карточкой товара
|
||||||
await bot.deleteMessage(chatId, messageId);
|
await bot.deleteMessage(chatId, messageId);
|
||||||
|
|
||||||
// Удаляем Hidden Photo, если оно существует
|
// Удаляем Hidden Photo, если оно существует
|
||||||
const state = userStates.get(chatId);
|
const state = userStates.get(chatId);
|
||||||
if (state?.hiddenPhotoMessageId) {
|
if (state?.hiddenPhotoMessageId) {
|
||||||
@ -268,7 +289,7 @@ export default class UserPurchaseHandler {
|
|||||||
|
|
||||||
// Удаляем состояние пользователя
|
// Удаляем состояние пользователя
|
||||||
userStates.delete(chatId);
|
userStates.delete(chatId);
|
||||||
|
|
||||||
// Открываем список покупок для пользователя
|
// Открываем список покупок для пользователя
|
||||||
await this.showPurchases({ chat: { id: chatId }, from: { id: callbackQuery.from.id } });
|
await this.showPurchases({ chat: { id: chatId }, from: { id: callbackQuery.from.id } });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -60,14 +60,14 @@ export default class UserWalletsHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add total crypto balance
|
// Add total crypto balance
|
||||||
message += `💰 *Total Crypto Balance:* $${totalUsdValue.toFixed(2)}\n`;
|
message += `📊 *Total Crypto Balance:* $${totalUsdValue.toFixed(2)}\n`;
|
||||||
|
|
||||||
// Add bonus balance
|
// Add bonus balance
|
||||||
message += `🎁 *Bonus Balance:* $${user.bonus_balance.toFixed(2)}\n`;
|
message += `🎁 *Bonus Balance:* $${user.bonus_balance.toFixed(2)}\n`;
|
||||||
|
|
||||||
// Add total balance
|
// Add total balance
|
||||||
const totalBalance = user.bonus_balance + user.total_balance;
|
const totalBalance = totalUsdValue + user.bonus_balance;
|
||||||
message += `📊 *Total Balance:* $${totalBalance.toFixed(2)}\n`;
|
message += `💰 *Total Balance:* $${totalBalance.toFixed(2)}\n`;
|
||||||
} else {
|
} else {
|
||||||
message = 'You don\'t have any active wallets yet.';
|
message = 'You don\'t have any active wallets yet.';
|
||||||
}
|
}
|
||||||
@ -92,6 +92,11 @@ export default class UserWalletsHandler {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add "Transaction History" button
|
||||||
|
keyboard.inline_keyboard.splice(3, 0, [
|
||||||
|
{ text: '📊 Transaction History', callback_data: 'view_transaction_history_0' }
|
||||||
|
]);
|
||||||
|
|
||||||
await bot.sendMessage(chatId, message, {
|
await bot.sendMessage(chatId, message, {
|
||||||
reply_markup: keyboard,
|
reply_markup: keyboard,
|
||||||
parse_mode: 'Markdown'
|
parse_mode: 'Markdown'
|
||||||
@ -101,6 +106,87 @@ export default class UserWalletsHandler {
|
|||||||
await bot.sendMessage(chatId, 'Error loading balance. Please try again.');
|
await bot.sendMessage(chatId, 'Error loading balance. Please try again.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async handleTransactionHistory(callbackQuery, page = 0) {
|
||||||
|
const chatId = callbackQuery.message.chat.id;
|
||||||
|
const telegramId = callbackQuery.from.id;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await UserService.getUserByTelegramId(telegramId.toString());
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
await bot.sendMessage(chatId, 'Profile not found. Please use /start to create one.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch transactions with pagination
|
||||||
|
const limit = 10;
|
||||||
|
const offset = page * limit;
|
||||||
|
const transactions = await db.allAsync(`
|
||||||
|
SELECT amount, tx_hash, created_at, wallet_type
|
||||||
|
FROM transactions
|
||||||
|
WHERE user_id = ?
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
`, [user.id, limit, offset]);
|
||||||
|
|
||||||
|
let message = '';
|
||||||
|
|
||||||
|
if (transactions.length > 0) {
|
||||||
|
message = '📊 *Transaction History:*\n\n';
|
||||||
|
transactions.forEach(tx => {
|
||||||
|
const date = new Date(tx.created_at).toLocaleString();
|
||||||
|
message += `💰 Amount: ${tx.amount}\n`;
|
||||||
|
message += `🔗 TX Hash: \`${tx.tx_hash}\`\n`;
|
||||||
|
message += `🕒 Date: ${date}\n`;
|
||||||
|
message += `💼 Wallet Type: ${tx.wallet_type}\n\n`;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
message = '📊 *Transaction History:*\n\nNo transactions found.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create pagination buttons
|
||||||
|
const keyboard = {
|
||||||
|
inline_keyboard: [
|
||||||
|
[
|
||||||
|
{ text: '« Back', callback_data: 'back_to_balance' }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add "Previous" button if not on the first page
|
||||||
|
if (page > 0) {
|
||||||
|
keyboard.inline_keyboard.unshift([
|
||||||
|
{ text: '⬅️ Previous', callback_data: `view_transaction_history_${page - 1}` }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add "Next" button if there are more transactions
|
||||||
|
const nextTransactions = await db.allAsync(`
|
||||||
|
SELECT amount, tx_hash, created_at, wallet_type
|
||||||
|
FROM transactions
|
||||||
|
WHERE user_id = ?
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
`, [user.id, limit, offset + limit]);
|
||||||
|
|
||||||
|
if (nextTransactions.length > 0) {
|
||||||
|
keyboard.inline_keyboard.push([
|
||||||
|
{ text: '➡️ Next', callback_data: `view_transaction_history_${page + 1}` }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
await bot.editMessageText(message, {
|
||||||
|
chat_id: chatId,
|
||||||
|
message_id: callbackQuery.message.message_id,
|
||||||
|
parse_mode: 'Markdown',
|
||||||
|
reply_markup: keyboard
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error in handleTransactionHistory:', error);
|
||||||
|
await bot.sendMessage(chatId, 'Error loading transaction history. Please try again.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static async handleRefreshBalance(callbackQuery) {
|
static async handleRefreshBalance(callbackQuery) {
|
||||||
const chatId = callbackQuery.message.chat.id;
|
const chatId = callbackQuery.message.chat.id;
|
||||||
|
27
src/index.js
27
src/index.js
@ -12,6 +12,7 @@ import adminUserLocationHandler from "./handlers/adminHandlers/adminUserLocation
|
|||||||
import adminDumpHandler from "./handlers/adminHandlers/adminDumpHandler.js";
|
import adminDumpHandler from "./handlers/adminHandlers/adminDumpHandler.js";
|
||||||
import adminLocationHandler from "./handlers/adminHandlers/adminLocationHandler.js";
|
import adminLocationHandler from "./handlers/adminHandlers/adminLocationHandler.js";
|
||||||
import adminProductHandler from "./handlers/adminHandlers/adminProductHandler.js";
|
import adminProductHandler from "./handlers/adminHandlers/adminProductHandler.js";
|
||||||
|
import adminWalletsHandler from "./handlers/adminHandlers/adminWalletsHandler.js";
|
||||||
|
|
||||||
// Debug logging function
|
// Debug logging function
|
||||||
const logDebug = (action, functionName) => {
|
const logDebug = (action, functionName) => {
|
||||||
@ -129,6 +130,11 @@ bot.on('message', async (msg) => {
|
|||||||
await adminDumpHandler.handleDump(msg);
|
await adminDumpHandler.handleDump(msg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case '💰 Manage Wallets':
|
||||||
|
if (adminHandler.isAdmin(msg.from.id)) {
|
||||||
|
await adminWalletsHandler.handleWalletManagement(msg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await ErrorHandler.handleError(bot, msg.chat.id, error, 'message handler');
|
await ErrorHandler.handleError(bot, msg.chat.id, error, 'message handler');
|
||||||
@ -333,6 +339,20 @@ bot.on('callback_query', async (callbackQuery) => {
|
|||||||
logDebug(action, 'handleEditUserDistrict');
|
logDebug(action, 'handleEditUserDistrict');
|
||||||
await adminUserLocationHandler.handleEditUserDistrict(callbackQuery)
|
await adminUserLocationHandler.handleEditUserDistrict(callbackQuery)
|
||||||
}
|
}
|
||||||
|
// Admin Wallet management
|
||||||
|
else if (action.startsWith('wallet_type_')) { // Добавляем обработку выбора типа кошелька
|
||||||
|
logDebug(action, 'handleWalletTypeSelection');
|
||||||
|
await adminWalletsHandler.handleWalletTypeSelection(callbackQuery);
|
||||||
|
} else if (action.startsWith('prev_page_') || action.startsWith('next_page_')) {
|
||||||
|
logDebug(action, 'handlePagination');
|
||||||
|
await adminWalletsHandler.handlePagination(callbackQuery);
|
||||||
|
} else if (action.startsWith('export_csv_')) {
|
||||||
|
logDebug(action, 'handleExportCSV');
|
||||||
|
await adminWalletsHandler.handleExportCSV(callbackQuery);
|
||||||
|
} else if (action === 'back_to_wallet_types') {
|
||||||
|
logDebug(action, 'handleWalletManagement');
|
||||||
|
await adminWalletsHandler.handleWalletManagement(msg);
|
||||||
|
}
|
||||||
// Dump manage
|
// Dump manage
|
||||||
else if (action === "export_database") {
|
else if (action === "export_database") {
|
||||||
await adminDumpHandler.handleExportDatabase(callbackQuery);
|
await adminDumpHandler.handleExportDatabase(callbackQuery);
|
||||||
@ -341,6 +361,13 @@ bot.on('callback_query', async (callbackQuery) => {
|
|||||||
await adminDumpHandler.handleImportDatabase(callbackQuery);
|
await adminDumpHandler.handleImportDatabase(callbackQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transaction history
|
||||||
|
else if (action.startsWith('view_transaction_history_')) {
|
||||||
|
logDebug(action, 'handleTransactionHistory');
|
||||||
|
const page = parseInt(action.split('_').pop()); // Extract page number
|
||||||
|
await userWalletsHandler.handleTransactionHistory(callbackQuery, page);
|
||||||
|
}
|
||||||
|
|
||||||
await bot.answerCallbackQuery(callbackQuery.id);
|
await bot.answerCallbackQuery(callbackQuery.id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await ErrorHandler.handleError(bot, msg.chat.id, error, 'callback query');
|
await ErrorHandler.handleError(bot, msg.chat.id, error, 'callback query');
|
||||||
|
@ -18,6 +18,20 @@ class WalletService {
|
|||||||
throw new Error('Failed to fetch archived wallets count');
|
throw new Error('Failed to fetch archived wallets count');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Добавляем метод для получения кошельков по типу
|
||||||
|
static async getWalletsByType(walletType) {
|
||||||
|
try {
|
||||||
|
const wallets = await db.allAsync(
|
||||||
|
`SELECT * FROM crypto_wallets WHERE wallet_type = ?`,
|
||||||
|
[walletType]
|
||||||
|
);
|
||||||
|
|
||||||
|
return wallets;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching wallets by type:', error);
|
||||||
|
throw new Error('Failed to fetch wallets by type');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WalletService;
|
export default WalletService;
|
Loading…
Reference in New Issue
Block a user