nakama/backend/jobs/avatarUpdater.js

127 lines
3.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const axios = require('axios');
const User = require('../models/User');
const config = require('../config');
const { log } = require('../middleware/logger');
const DAY_MS = 24 * 60 * 60 * 1000;
async function fetchLatestAvatar(telegramId) {
if (!config.telegramBotToken) {
return null;
}
try {
const apiBase = `https://api.telegram.org/bot${config.telegramBotToken}`;
const photosResponse = await axios.get(`${apiBase}/getUserProfilePhotos`, {
params: {
user_id: telegramId,
limit: 1
},
timeout: 15000
});
if (!photosResponse.data?.ok || photosResponse.data.result.total_count === 0) {
return null;
}
const photoSizes = photosResponse.data.result.photos?.[0];
if (!Array.isArray(photoSizes) || photoSizes.length === 0) {
return null;
}
const highestQualityPhoto = photoSizes[photoSizes.length - 1];
if (!highestQualityPhoto?.file_id) {
return null;
}
const fileResponse = await axios.get(`${apiBase}/getFile`, {
params: {
file_id: highestQualityPhoto.file_id
},
timeout: 15000
});
if (!fileResponse.data?.ok || !fileResponse.data.result?.file_path) {
return null;
}
const filePath = fileResponse.data.result.file_path;
return `https://api.telegram.org/file/bot${config.telegramBotToken}/${filePath}`;
} catch (error) {
log('error', 'Ошибка получения аватарки из Telegram', {
telegramId,
error: error.message
});
return null;
}
}
async function updateAllUserAvatars() {
if (!config.telegramBotToken) {
log('warn', 'Обновление аватарок отключено: TELEGRAM_BOT_TOKEN не установлен');
return;
}
const users = await User.find({ telegramId: { $exists: true } });
log('info', 'Начато обновление аватарок пользователей', { count: users.length });
for (const user of users) {
try {
const latestAvatar = await fetchLatestAvatar(user.telegramId);
if (latestAvatar && latestAvatar !== user.photoUrl) {
user.photoUrl = latestAvatar;
await user.save();
log('info', 'Аватарка обновлена', { userId: user._id, telegramId: user.telegramId });
}
} catch (error) {
log('error', 'Не удалось обновить аватарку пользователя', {
userId: user._id,
telegramId: user.telegramId,
error: error.message
});
}
}
log('info', 'Обновление аватарок завершено');
}
function msUntilNextRun(hour = 3) {
const now = new Date();
const nextRun = new Date(now);
nextRun.setHours(hour, 0, 0, 0);
if (nextRun <= now) {
nextRun.setDate(nextRun.getDate() + 1);
}
return nextRun.getTime() - now.getTime();
}
function scheduleAvatarUpdates() {
if (!config.telegramBotToken) {
log('warn', 'Расписание обновления аватарок отключено: TELEGRAM_BOT_TOKEN не установлен');
return;
}
const initialDelay = msUntilNextRun();
setTimeout(() => {
updateAllUserAvatars().catch((error) => {
log('error', 'Ошибка при запуске обновления аватарок', { error: error.message });
});
setInterval(() => {
updateAllUserAvatars().catch((error) => {
log('error', 'Ошибка при плановом обновлении аватарок', { error: error.message });
});
}, DAY_MS);
}, initialDelay);
}
module.exports = {
scheduleAvatarUpdates,
updateAllUserAvatars,
fetchLatestAvatar
};