- 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
105 lines
4.3 KiB
JavaScript
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' }]] }
|
|
});
|
|
}
|
|
}
|
|
} |