188 lines
6.7 KiB
JavaScript
188 lines
6.7 KiB
JavaScript
// Telegram Bot для отправки изображений в ЛС
|
||
const axios = require('axios');
|
||
const FormData = require('form-data');
|
||
const config = require('./config');
|
||
|
||
if (!config.telegramBotToken) {
|
||
console.warn('⚠️ TELEGRAM_BOT_TOKEN не установлен! Функция отправки фото в Telegram недоступна.');
|
||
}
|
||
|
||
const TELEGRAM_API = config.telegramBotToken
|
||
? `https://api.telegram.org/bot${config.telegramBotToken}`
|
||
: 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) {
|
||
if (!TELEGRAM_API) {
|
||
throw new Error('TELEGRAM_BOT_TOKEN не установлен');
|
||
}
|
||
|
||
try {
|
||
// Получаем оригинальный URL (если это прокси URL)
|
||
let finalPhotoUrl = getOriginalUrl(photoUrl);
|
||
|
||
// Если это все еще относительный URL (локальный файл), используем публичный URL
|
||
if (finalPhotoUrl.startsWith('/')) {
|
||
const baseUrl = process.env.FRONTEND_URL || process.env.API_URL || 'https://nakama.glpshchn.ru';
|
||
finalPhotoUrl = `${baseUrl}${finalPhotoUrl}`;
|
||
}
|
||
|
||
// Проверяем, является ли URL публично доступным для Telegram
|
||
// Если это оригинальный URL от e621/gelbooru, используем его напрямую
|
||
const isPublicUrl = finalPhotoUrl.includes('e621.net') ||
|
||
finalPhotoUrl.includes('gelbooru.com') ||
|
||
finalPhotoUrl.includes('nakama.glpshchn.ru');
|
||
|
||
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) {
|
||
console.error('Ошибка отправки фото:', error.response?.data || error.message);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
// Отправить несколько фото группой (до 10 штук)
|
||
async function sendPhotosToUser(userId, photos) {
|
||
if (!TELEGRAM_API) {
|
||
throw new Error('TELEGRAM_BOT_TOKEN не установлен');
|
||
}
|
||
|
||
try {
|
||
// Telegram поддерживает до 10 фото в одной группе
|
||
const batches = [];
|
||
for (let i = 0; i < photos.length; i += 10) {
|
||
batches.push(photos.slice(i, i + 10));
|
||
}
|
||
|
||
const results = [];
|
||
|
||
for (const batch of batches) {
|
||
const media = [];
|
||
|
||
for (let index = 0; index < batch.length; index++) {
|
||
const photo = batch[index];
|
||
// Получаем оригинальный URL (если это прокси URL)
|
||
let photoUrl = getOriginalUrl(photo.url);
|
||
|
||
// Если это относительный URL, преобразуем в полный
|
||
if (photoUrl.startsWith('/')) {
|
||
const baseUrl = process.env.FRONTEND_URL || process.env.API_URL || 'https://nakama.glpshchn.ru';
|
||
photoUrl = `${baseUrl}${photoUrl}`;
|
||
}
|
||
|
||
// Проверяем, является ли URL публично доступным
|
||
const isPublicUrl = photoUrl.includes('e621.net') ||
|
||
photoUrl.includes('gelbooru.com') ||
|
||
photoUrl.includes('nakama.glpshchn.ru');
|
||
|
||
if (isPublicUrl) {
|
||
// Используем публичный URL напрямую
|
||
media.push({
|
||
type: 'photo',
|
||
media: photoUrl,
|
||
caption: index === 0 ? `<b>Из NakamaHost</b>\n${batch.length} фото` : undefined,
|
||
parse_mode: 'HTML'
|
||
});
|
||
} else {
|
||
// Для непубличных URL нужно скачать изображение
|
||
// Но в sendMediaGroup нельзя смешивать URL и файлы
|
||
// Поэтому используем URL как есть (Telegram попробует загрузить)
|
||
media.push({
|
||
type: 'photo',
|
||
media: photoUrl,
|
||
caption: index === 0 ? `<b>Из NakamaHost</b>\n${batch.length} фото` : undefined,
|
||
parse_mode: 'HTML'
|
||
});
|
||
}
|
||
}
|
||
|
||
const response = await axios.post(`${TELEGRAM_API}/sendMediaGroup`, {
|
||
chat_id: userId,
|
||
media: media
|
||
});
|
||
|
||
results.push(response.data);
|
||
}
|
||
|
||
return results;
|
||
} catch (error) {
|
||
console.error('Ошибка отправки фото группой:', error.response?.data || error.message);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
// Обработать данные от Web App
|
||
async function handleWebAppData(userId, dataString) {
|
||
try {
|
||
const data = JSON.parse(dataString);
|
||
|
||
if (data.action === 'send_image') {
|
||
const caption = `<b>Из NakamaHost</b>\n\n${data.caption || ''}`;
|
||
await sendPhotoToUser(userId, data.url, caption);
|
||
return { success: true, message: 'Изображение отправлено!' };
|
||
}
|
||
|
||
return { success: false, message: 'Неизвестное действие' };
|
||
} catch (error) {
|
||
console.error('Ошибка обработки данных:', error);
|
||
return { success: false, message: error.message };
|
||
}
|
||
}
|
||
|
||
module.exports = {
|
||
sendPhotoToUser,
|
||
sendPhotosToUser,
|
||
handleWebAppData
|
||
};
|
||
|