Update files

This commit is contained in:
glpshchn 2025-12-08 17:06:57 +03:00
parent a3f9374a6a
commit ca7c508e57
4 changed files with 85 additions and 15 deletions

View File

@ -77,10 +77,23 @@ async function sendPhotoToUser(userId, photoUrl, caption) {
throw new Error('TELEGRAM_BOT_TOKEN не установлен');
}
// Валидация параметров
if (!userId || (typeof userId !== 'number' && typeof userId !== 'string')) {
throw new Error('userId должен быть числом или строкой');
}
if (!photoUrl || typeof photoUrl !== 'string') {
throw new Error('photoUrl обязателен и должен быть строкой');
}
try {
// Получаем оригинальный URL (если это прокси URL)
let finalPhotoUrl = getOriginalUrl(photoUrl);
if (!finalPhotoUrl) {
throw new Error('Не удалось получить URL изображения');
}
// Если это все еще относительный URL (локальный файл), используем публичный URL
if (finalPhotoUrl.startsWith('/')) {
const baseUrl = process.env.FRONTEND_URL || process.env.API_URL || 'https://nakama.glpshchn.ru';
@ -167,7 +180,24 @@ async function sendPhotoToUser(userId, photoUrl, caption) {
return response.data;
} catch (error) {
console.error('Ошибка отправки медиа:', error.response?.data || error.message);
const errorDetails = {
message: error.message,
userId: userId,
photoUrl: photoUrl,
telegramError: error.response?.data
};
console.error('Ошибка отправки медиа:', errorDetails);
// Если это ошибка от Telegram API, пробрасываем её с более понятным сообщением
if (error.response?.data) {
const telegramError = error.response.data;
const errorMessage = telegramError.description || telegramError.error_code
? `Telegram API ошибка: ${telegramError.description || `Код ${telegramError.error_code}`}`
: error.message;
throw new Error(errorMessage);
}
throw error;
}
}

View File

@ -12,7 +12,19 @@ router.post('/send-photo', authenticate, async (req, res) => {
return res.status(400).json({ error: 'userId и photoUrl обязательны' });
}
const result = await sendPhotoToUser(userId, photoUrl, caption);
// Преобразуем userId в число, если это строка (Telegram API ожидает число)
const telegramUserId = typeof userId === 'string' ? parseInt(userId, 10) : userId;
if (isNaN(telegramUserId)) {
return res.status(400).json({ error: 'userId должен быть числом' });
}
// Валидация URL
if (typeof photoUrl !== 'string' || photoUrl.trim().length === 0) {
return res.status(400).json({ error: 'photoUrl должен быть непустой строкой' });
}
const result = await sendPhotoToUser(telegramUserId, photoUrl.trim(), caption);
res.json({
success: true,
@ -20,10 +32,16 @@ router.post('/send-photo', authenticate, async (req, res) => {
result
});
} catch (error) {
console.error('Ошибка отправки:', error);
console.error('Ошибка отправки фото:', {
error: error.message,
stack: error.stack,
response: error.response?.data,
userId: req.body?.userId,
photoUrl: req.body?.photoUrl
});
res.status(500).json({
error: 'Ошибка отправки изображения',
details: error.message
details: error.response?.data?.description || error.message
});
}
});

View File

@ -7,7 +7,8 @@ const config = require('../config');
// e621 требует описательный User-Agent с контактами
const E621_USER_AGENT = 'NakamaApp/1.0 (by glpshchn on e621)';
const CACHE_TTL_MS = 60 * 1000; // 1 минута
const CACHE_TTL_MS = 60 * 1000; // 1 минута для поиска
const TAGS_CACHE_TTL_MS = 10 * 60 * 1000; // 10 минут для тегов (автокомплит)
const searchCache = new Map();
@ -25,7 +26,7 @@ function getFromCache(key) {
return entry.data;
}
function setCache(key, data) {
function setCache(key, data, ttl = CACHE_TTL_MS) {
if (searchCache.size > 200) {
// Удалить устаревшие записи, если превышен лимит
for (const [cacheKey, entry] of searchCache.entries()) {
@ -42,7 +43,7 @@ function setCache(key, data) {
}
searchCache.set(key, {
data,
expires: Date.now() + CACHE_TTL_MS
expires: Date.now() + ttl
});
}
@ -338,7 +339,13 @@ router.get('/furry/tags', authenticate, async (req, res) => {
try {
const { query } = req.query;
if (!query || query.length < 2) {
// Быстрый возврат для очень коротких запросов
if (!query || query.length < 1) {
return res.json({ tags: [] });
}
// Для запросов длиной 1 символ возвращаем пустой результат без запроса к API
if (query.length < 2) {
return res.json({ tags: [] });
}
@ -363,7 +370,7 @@ router.get('/furry/tags', authenticate, async (req, res) => {
'User-Agent': E621_USER_AGENT,
'Authorization': `Basic ${auth}`
},
timeout: 10000,
timeout: 5000, // Уменьшили таймаут до 5 секунд для более быстрого ответа
validateStatus: (status) => status < 500 // Не бросать ошибку для 429
});
@ -388,7 +395,7 @@ router.get('/furry/tags', authenticate, async (req, res) => {
headers: {
'User-Agent': E621_USER_AGENT
},
timeout: 10000,
timeout: 5000, // Уменьшили таймаут до 5 секунд
validateStatus: (status) => status < 500
});
@ -432,7 +439,8 @@ router.get('/furry/tags', authenticate, async (req, res) => {
}));
const payload = { tags };
setCache(cacheKey, payload);
// Используем более длительное кэширование для тегов (10 минут)
setCache(cacheKey, payload, TAGS_CACHE_TTL_MS);
return res.json(payload);
} catch (error) {
// Обработка 429 ошибок
@ -481,7 +489,7 @@ router.get('/anime/tags', authenticate, async (req, res) => {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
},
timeout: 30000,
timeout: 5000, // Уменьшили таймаут до 5 секунд для более быстрого ответа
validateStatus: (status) => status < 500 // Не бросать ошибку для 429
});
@ -513,7 +521,8 @@ router.get('/anime/tags', authenticate, async (req, res) => {
})).filter(tag => tag.name);
const payload = { tags };
setCache(cacheKey, payload);
// Используем более длительное кэширование для тегов (10 минут)
setCache(cacheKey, payload, TAGS_CACHE_TTL_MS);
return res.json(payload);
} catch (error) {
// Обработка 429 ошибок

View File

@ -295,9 +295,22 @@ export const sendPhotoToTelegram = async (photoUrl) => {
throw new Error('Не удалось получить ID пользователя из Telegram')
}
// Убеждаемся, что userId - это число (Telegram API ожидает число)
const userId = typeof telegramUser.id === 'string'
? parseInt(telegramUser.id, 10)
: telegramUser.id
if (isNaN(userId)) {
throw new Error('Неверный формат ID пользователя')
}
if (!photoUrl || typeof photoUrl !== 'string') {
throw new Error('URL изображения обязателен')
}
const response = await api.post('/bot/send-photo', {
userId: telegramUser.id,
photoUrl,
userId: userId,
photoUrl: photoUrl.trim(),
caption: 'Из Nakama'
})
return response.data