Files
telegram-shop/src/handlers/userHandlers/wallet/createHandler.js
NW a8bf50df24 feat: add i18n localization system (en/es/de) with admin panel
- Add i18n module with tForUser/tForLang/t functions and {{param}} interpolation
- Add 3 locale files: en.json, es.json, de.json (201 keys each)
- Add language selection on /start and /language command with flag emojis
- Localize all bot user-facing strings (handlers, keyboards, errors)
- Localize messageRouter keyboard matching via locale keys
- Add DB migrations 008 (language column) and 009 (language_set column)
- Add localization admin tab at /locales for editing translations
- Add userService.getUserLanguage/setUserLanguage methods
- Cache user object on msg.__user to avoid triple DB fetch
- Idempotent migrations with checkColumnExists guards
- Error boundary on i18n locale file loading
- Admin locales route uses AVAILABLE_LANGUAGES import
2026-06-25 21:22:32 +01:00

105 lines
4.3 KiB
JavaScript

import db from '../../../config/database.js';
import WalletService from '../../../services/walletService.js';
import Validators from '../../../utils/validators.js';
import bot from '../../../context/bot.js';
import UserService from '../../../services/userService.js';
import logger from '../../../utils/logger.js';
import WalletHelpers from './helpers.js';
import { editOrSendCallback } from '../../../utils/messageUtils.js';
import { tForUser } from '../../../i18n/index.js';
export default class CreateHandler {
static async handleAddWallet(callbackQuery) {
const chatId = callbackQuery.message.chat.id;
const telegramId = callbackQuery.from.id;
const user = await UserService.getUserByTelegramId(telegramId);
const lang = user?.language || 'en';
const t = tForUser(lang);
const cryptoOptions = [['BTC', 'ETH', 'LTC'], ['USDT', 'USDC']];
const keyboard = {
inline_keyboard: [
...cryptoOptions.map(row =>
row.map(coin => ({
text: coin,
callback_data: `generate_wallet_${coin.replace(' ', '_')}`
}))
),
[{ text: t('wallet.back'), callback_data: 'back_to_balance' }]
]
};
await bot.editMessageText(t('wallet.select_crypto'), {
chat_id: chatId, message_id: callbackQuery.message.message_id,
reply_markup: keyboard
});
}
static async handleGenerateWallet(callbackQuery) {
const chatId = callbackQuery.message.chat.id;
const telegramId = callbackQuery.from.id;
const walletType = callbackQuery.data.replace('generate_wallet_', '').replace('_', ' ');
const user = await UserService.getUserByTelegramId(telegramId);
const lang = user?.language || 'en';
const t = tForUser(lang);
if (!Validators.isValidWalletType(walletType)) {
await editOrSendCallback(callbackQuery, t('wallet.invalid_wallet_type'));
return;
}
try {
if (!user) throw new Error(t('wallet.user_not_found'));
await db.runAsync('BEGIN TRANSACTION');
try {
const existingWallet = await db.getAsync(
'SELECT id, address FROM crypto_wallets WHERE user_id = ? AND wallet_type = ?',
[user.id, walletType]
);
if (existingWallet) {
const timestamp = Date.now();
await db.runAsync(
'UPDATE crypto_wallets SET wallet_type = ? WHERE id = ?',
[`${walletType}_${timestamp}`, existingWallet.id]
);
}
const walletResult = await WalletService.createWallet(user.id, walletType);
if (!walletResult?.address) throw new Error('Failed to generate wallet address');
const network = WalletHelpers.getNetworkName(walletType, t);
let message = `${t('wallet.wallet_generated')}\n\n`;
message += `${t('wallet.wallet_type')}: ${walletType}\n${t('wallet.network')}: ${network}\n`;
message += `${t('wallet.address')}: \`${walletResult.address}\`\n\n`;
if (existingWallet) {
message += `${t('wallet.previous_archived')}\n`;
}
message += `\n${t('wallet.recovery_stored')}`;
await bot.editMessageText(message, {
chat_id: chatId, message_id: callbackQuery.message.message_id,
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: [[{ text: t('wallet.back_to_balance'), callback_data: 'back_to_balance' }]] }
});
await db.runAsync('COMMIT');
} catch (error) {
await db.runAsync('ROLLBACK');
throw error;
}
} catch (error) {
logger.error({ err: error }, 'Error generating wallet');
await bot.editMessageText(t('wallet.error_generating'), {
chat_id: chatId, message_id: callbackQuery.message.message_id,
reply_markup: { inline_keyboard: [[{ text: t('wallet.back_to_balance'), callback_data: 'back_to_balance' }]] }
});
}
}
}