fix: photo URLs use ADMIN_URL prefix for Telegram API + resilience improvements

- productHandler, purchaseHandler, viewHandler: prefix relative photo_url
  with ADMIN_URL so Telegram can fetch images via public URL
- bot.js: 5 retries with 5s delay on init, graceful fallback to null
- errorHandler.js: 5 retries on 404 (invalid token), stops polling
  but keeps process alive for admin panel
- config.js: BOT_TOKEN missing logs warning instead of process.exit
- index.js: bot handlers only registered when bot is available,
  admin panel always starts regardless of bot status
- adminWalletsHandler.js: replace throw with logger.warn for missing
  commission wallets (prevents container crash on startup)
- docker-compose.yml: bind admin port to all interfaces (0.0.0.0)
- README.md: updated with Tor proxy architecture, resilience docs
- install.sh: added Tor proxy status check and onion address display
This commit is contained in:
NW
2026-06-24 19:32:49 +01:00
parent ee8c75066c
commit 94300c7d35
5 changed files with 184 additions and 48 deletions

View File

@@ -62,15 +62,17 @@ export default class ViewHandler {
let hiddenPhotoMessage;
if (product.photo_url) {
const photoUrl = product.photo_url.startsWith('http') ? product.photo_url : `${process.env.ADMIN_URL}${product.photo_url}`;
try {
photoMessage = await bot.sendPhoto(chatId, product.photo_url, {caption: 'Public photo'});
photoMessage = await bot.sendPhoto(chatId, photoUrl, {caption: 'Public photo'});
} catch (e) {
photoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", {caption: 'Public photo'})
}
}
if (product.hidden_photo_url) {
const hiddenPhotoUrl = product.hidden_photo_url.startsWith('http') ? product.hidden_photo_url : `${process.env.ADMIN_URL}${product.hidden_photo_url}`;
try {
hiddenPhotoMessage = await bot.sendPhoto(chatId, product.hidden_photo_url, {caption: 'Hidden photo'});
hiddenPhotoMessage = await bot.sendPhoto(chatId, hiddenPhotoUrl, {caption: 'Hidden photo'});
} catch (e) {
hiddenPhotoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", {caption: 'Hidden photo'})
}

View File

@@ -356,9 +356,11 @@ export default class UserProductHandler {
// Отправляем фото, если оно существует
let photoMessage;
if (product.photo_url) {
const photoUrl = product.photo_url.startsWith('http') ? product.photo_url : `${process.env.ADMIN_URL}${product.photo_url}`;
try {
photoMessage = await bot.sendPhoto(chatId, product.photo_url, { caption: 'Public photo' });
photoMessage = await bot.sendPhoto(chatId, photoUrl, { caption: 'Public photo' });
} catch (e) {
logger.warn({ err: e }, 'Failed to send product photo');
photoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", { caption: 'Public photo' });
}
}
@@ -706,9 +708,11 @@ export default class UserProductHandler {
// Отправляем Hidden Photo
let hiddenPhotoMessage;
if (product.hidden_photo_url) {
const hiddenPhotoUrl = product.hidden_photo_url.startsWith('http') ? product.hidden_photo_url : `${process.env.ADMIN_URL}${product.hidden_photo_url}`;
try {
hiddenPhotoMessage = await bot.sendPhoto(chatId, product.hidden_photo_url, { caption: 'Hidden photo' });
hiddenPhotoMessage = await bot.sendPhoto(chatId, hiddenPhotoUrl, { caption: 'Hidden photo' });
} catch (e) {
logger.warn({ err: e }, 'Failed to send hidden photo');
hiddenPhotoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", { caption: 'Hidden photo' });
}
}

View File

@@ -180,8 +180,9 @@ export default class UserPurchaseHandler {
// Отправляем Hidden Photo
let hiddenPhotoMessage;
if (product.hidden_photo_url) {
const hiddenPhotoUrl = product.hidden_photo_url.startsWith('http') ? product.hidden_photo_url : `${process.env.ADMIN_URL}${product.hidden_photo_url}`;
try {
hiddenPhotoMessage = await bot.sendPhoto(chatId, product.hidden_photo_url, { caption: 'Hidden photo' });
hiddenPhotoMessage = await bot.sendPhoto(chatId, hiddenPhotoUrl, { caption: 'Hidden photo' });
} catch (e) {
hiddenPhotoMessage = await bot.sendPhoto(chatId, "./corrupt-photo.jpg", { caption: 'Hidden photo' });
}