Update files
This commit is contained in:
parent
a3f9374a6a
commit
ca7c508e57
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 ошибок
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue