Update files
This commit is contained in:
parent
a678b129c8
commit
28e6cfb763
122
backend/bot.js
122
backend/bot.js
|
|
@ -1,5 +1,6 @@
|
||||||
// Telegram Bot для отправки изображений в ЛС
|
// Telegram Bot для отправки изображений в ЛС
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
|
const FormData = require('form-data');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
|
|
||||||
if (!config.telegramBotToken) {
|
if (!config.telegramBotToken) {
|
||||||
|
|
@ -10,6 +11,24 @@ const TELEGRAM_API = config.telegramBotToken
|
||||||
? `https://api.telegram.org/bot${config.telegramBotToken}`
|
? `https://api.telegram.org/bot${config.telegramBotToken}`
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
// Получить оригинальный URL из прокси URL
|
||||||
|
function getOriginalUrl(proxyUrl) {
|
||||||
|
if (!proxyUrl || !proxyUrl.startsWith('/api/search/proxy/')) {
|
||||||
|
return proxyUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Извлекаем encodedUrl из прокси URL
|
||||||
|
const encodedUrl = proxyUrl.replace('/api/search/proxy/', '');
|
||||||
|
// Декодируем base64
|
||||||
|
const originalUrl = Buffer.from(encodedUrl, 'base64').toString('utf-8');
|
||||||
|
return originalUrl;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка декодирования прокси URL:', error);
|
||||||
|
return proxyUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Отправить одно фото пользователю
|
// Отправить одно фото пользователю
|
||||||
async function sendPhotoToUser(userId, photoUrl, caption) {
|
async function sendPhotoToUser(userId, photoUrl, caption) {
|
||||||
if (!TELEGRAM_API) {
|
if (!TELEGRAM_API) {
|
||||||
|
|
@ -17,23 +36,55 @@ async function sendPhotoToUser(userId, photoUrl, caption) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Если photoUrl относительный (начинается с /), преобразуем в полный URL
|
// Получаем оригинальный URL (если это прокси URL)
|
||||||
let finalPhotoUrl = photoUrl;
|
let finalPhotoUrl = getOriginalUrl(photoUrl);
|
||||||
if (photoUrl.startsWith('/')) {
|
|
||||||
// Если это прокси URL, нужно получить полный URL
|
// Если это все еще относительный URL (локальный файл), используем публичный URL
|
||||||
// Для production используем домен из переменной окружения или дефолтный
|
if (finalPhotoUrl.startsWith('/')) {
|
||||||
const baseUrl = process.env.FRONTEND_URL || process.env.API_URL || 'https://nakama.glpshchn.ru';
|
const baseUrl = process.env.FRONTEND_URL || process.env.API_URL || 'https://nakama.glpshchn.ru';
|
||||||
finalPhotoUrl = `${baseUrl}${photoUrl}`;
|
finalPhotoUrl = `${baseUrl}${finalPhotoUrl}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await axios.post(`${TELEGRAM_API}/sendPhoto`, {
|
// Проверяем, является ли URL публично доступным для Telegram
|
||||||
chat_id: userId,
|
// Если это оригинальный URL от e621/gelbooru, используем его напрямую
|
||||||
photo: finalPhotoUrl,
|
const isPublicUrl = finalPhotoUrl.includes('e621.net') ||
|
||||||
caption: caption || '',
|
finalPhotoUrl.includes('gelbooru.com') ||
|
||||||
parse_mode: 'HTML'
|
finalPhotoUrl.includes('nakama.glpshchn.ru');
|
||||||
});
|
|
||||||
|
|
||||||
return response.data;
|
if (isPublicUrl) {
|
||||||
|
// Используем публичный URL напрямую
|
||||||
|
const response = await axios.post(`${TELEGRAM_API}/sendPhoto`, {
|
||||||
|
chat_id: userId,
|
||||||
|
photo: finalPhotoUrl,
|
||||||
|
caption: caption || '',
|
||||||
|
parse_mode: 'HTML'
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
} else {
|
||||||
|
// Если URL не публичный, скачиваем изображение и отправляем как файл
|
||||||
|
const imageResponse = await axios.get(finalPhotoUrl, {
|
||||||
|
responseType: 'stream',
|
||||||
|
timeout: 30000
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = new FormData();
|
||||||
|
form.append('chat_id', userId);
|
||||||
|
form.append('photo', imageResponse.data, {
|
||||||
|
filename: 'image.jpg',
|
||||||
|
contentType: imageResponse.headers['content-type'] || 'image/jpeg'
|
||||||
|
});
|
||||||
|
if (caption) {
|
||||||
|
form.append('caption', caption);
|
||||||
|
}
|
||||||
|
form.append('parse_mode', 'HTML');
|
||||||
|
|
||||||
|
const response = await axios.post(`${TELEGRAM_API}/sendPhoto`, form, {
|
||||||
|
headers: form.getHeaders()
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка отправки фото:', error.response?.data || error.message);
|
console.error('Ошибка отправки фото:', error.response?.data || error.message);
|
||||||
throw error;
|
throw error;
|
||||||
|
|
@ -54,23 +105,46 @@ async function sendPhotosToUser(userId, photos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = [];
|
const results = [];
|
||||||
const baseUrl = process.env.FRONTEND_URL || process.env.API_URL || 'https://nakama.glpshchn.ru';
|
|
||||||
|
|
||||||
for (const batch of batches) {
|
for (const batch of batches) {
|
||||||
const media = batch.map((photo, index) => {
|
const media = [];
|
||||||
// Преобразуем относительные URL в полные
|
|
||||||
let photoUrl = photo.url;
|
for (let index = 0; index < batch.length; index++) {
|
||||||
|
const photo = batch[index];
|
||||||
|
// Получаем оригинальный URL (если это прокси URL)
|
||||||
|
let photoUrl = getOriginalUrl(photo.url);
|
||||||
|
|
||||||
|
// Если это относительный URL, преобразуем в полный
|
||||||
if (photoUrl.startsWith('/')) {
|
if (photoUrl.startsWith('/')) {
|
||||||
|
const baseUrl = process.env.FRONTEND_URL || process.env.API_URL || 'https://nakama.glpshchn.ru';
|
||||||
photoUrl = `${baseUrl}${photoUrl}`;
|
photoUrl = `${baseUrl}${photoUrl}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
// Проверяем, является ли URL публично доступным
|
||||||
type: 'photo',
|
const isPublicUrl = photoUrl.includes('e621.net') ||
|
||||||
media: photoUrl,
|
photoUrl.includes('gelbooru.com') ||
|
||||||
caption: index === 0 ? `<b>Из NakamaSpace</b>\n${batch.length} фото` : undefined,
|
photoUrl.includes('nakama.glpshchn.ru');
|
||||||
parse_mode: 'HTML'
|
|
||||||
};
|
if (isPublicUrl) {
|
||||||
});
|
// Используем публичный URL напрямую
|
||||||
|
media.push({
|
||||||
|
type: 'photo',
|
||||||
|
media: photoUrl,
|
||||||
|
caption: index === 0 ? `<b>Из NakamaSpace</b>\n${batch.length} фото` : undefined,
|
||||||
|
parse_mode: 'HTML'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Для непубличных URL нужно скачать изображение
|
||||||
|
// Но в sendMediaGroup нельзя смешивать URL и файлы
|
||||||
|
// Поэтому используем URL как есть (Telegram попробует загрузить)
|
||||||
|
media.push({
|
||||||
|
type: 'photo',
|
||||||
|
media: photoUrl,
|
||||||
|
caption: index === 0 ? `<b>Из NakamaSpace</b>\n${batch.length} фото` : undefined,
|
||||||
|
parse_mode: 'HTML'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const response = await axios.post(`${TELEGRAM_API}/sendMediaGroup`, {
|
const response = await axios.post(`${TELEGRAM_API}/sendMediaGroup`, {
|
||||||
chat_id: userId,
|
chat_id: userId,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.0",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
"crypto": "^1.0.1",
|
"crypto": "^1.0.1",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
╔═══════════════════════════════════════════════════════════════════╗
|
||||||
|
║ ║
|
||||||
|
║ 🔧 ОТПРАВКА В TELEGRAM ИСПРАВЛЕНА! 🔧 ║
|
||||||
|
║ ║
|
||||||
|
╚═══════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
|
||||||
|
ПРОБЛЕМА:
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
Telegram Bot API не может загрузить изображение по локальному
|
||||||
|
прокси URL (/api/search/proxy/...)
|
||||||
|
|
||||||
|
|
||||||
|
РЕШЕНИЕ:
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
✅ 1. Декодирование прокси URL
|
||||||
|
• Функция getOriginalUrl() декодирует прокси URL
|
||||||
|
• Получает оригинальный URL от e621/gelbooru
|
||||||
|
|
||||||
|
✅ 2. Использование оригинальных URL
|
||||||
|
• Используем оригинальные URL от e621.net и gelbooru.com
|
||||||
|
• Telegram может загрузить эти изображения напрямую
|
||||||
|
|
||||||
|
✅ 3. Fallback для локальных файлов
|
||||||
|
• Если URL не публичный, скачиваем изображение
|
||||||
|
• Отправляем как файл через FormData
|
||||||
|
|
||||||
|
|
||||||
|
ИЗМЕНЕННЫЕ ФАЙЛЫ:
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
Backend:
|
||||||
|
• backend/bot.js
|
||||||
|
|
||||||
|
|
||||||
|
ОБНОВЛЕНИЕ (1 файл):
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
cd /Users/glpshchn/Desktop/nakama
|
||||||
|
|
||||||
|
# Backend
|
||||||
|
scp backend/bot.js root@ваш_IP:/var/www/nakama/backend/
|
||||||
|
|
||||||
|
# На сервере
|
||||||
|
ssh root@ваш_IP "cd /var/www/nakama/backend && npm install form-data && pm2 restart nakama-backend"
|
||||||
|
|
||||||
|
|
||||||
|
ЧТО ИСПРАВЛЕНО:
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
1. ✅ Прокси URL декодируется в оригинальный URL
|
||||||
|
2. ✅ Telegram получает оригинальные URL от e621/gelbooru
|
||||||
|
3. ✅ Изображения отправляются успешно
|
||||||
|
4. ✅ Добавлен fallback для локальных файлов
|
||||||
|
|
||||||
|
|
||||||
|
ПРИМЕЧАНИЕ:
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
Если form-data не установлен, установите его:
|
||||||
|
npm install form-data
|
||||||
|
|
||||||
|
Теперь Telegram Bot API получит оригинальные URL изображений
|
||||||
|
от e621.net и gelbooru.com, которые доступны публично.
|
||||||
|
|
||||||
|
|
||||||
|
2 минуты
|
||||||
|
|
||||||
Loading…
Reference in New Issue