CampFirePlay/bot.js
Degradin d07ade36a3 Metrics
Added metrics for grafana
2025-01-29 12:51:33 +03:00

2269 lines
96 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 { Telegraf, Scenes, session, Markup, Stage } = require('telegraf');
const { Op } = require('sequelize');
const schedule = require('node-schedule');
const sequelize = require('./db'); // Подключение базы данных
// Подключаем обработчики
const commands = require('./commands');
const utils = require('./utils');
const handlers = require('./handlers');
const {
UserModel,
WorldModel,
JobModel,
PropertyModel,
AFKPropertyModel,
BusinessModel,
ReportModel,
BlockModel,
PromocodeModel,
EnterpriseModel,
WarehouseModel,
TruckModel,
SaleModel,
ResourcePriceModel,
SkillsModel,
DailyModel,
InviteModel,
logMiddleware,
logs
} = global.config
const bot = new Telegraf(process.env.BOT_TOKEN)
const rpg = require('./rpg'); // Подключение RPG-механик
const crime = require('./scenes/crime')
const pocketsteal = require('./scenes/pocketsteal')
const shop = require('./scenes/shop')
const pve = require('./scenes/pve')
const newpve = require('./scenes/newpve')
const stage = new Scenes.Stage([crime, pocketsteal, shop, pve, newpve]);
const start = async () => {
try {
// Подключаемся к базе данных
await sequelize.authenticate();
console.log('Подключение к базе данных успешно!');
// Синхронизация моделей, если нужно
await sequelize.sync({ alter: true });
console.log('Синхронизация моделей завершена.');
// Запуск бота
console.log('Бот успешно запущен!');
} catch (error) {
console.error('Ошибка при запуске приложения:', error);
}
}
bot.telegram.setMyCommands([{
command: "pay",
description: "Перевести указанному пользователю сумму."
},
{
command: "buy",
description: "Приобрести указанное имущество."
},
{
command: "business",
description: "Создать организацию."
},
{
command: "invite",
description: "Пригласить пользователя в организацию."
},
{
command: "percent",
description: "Установить пользователю процент заработка."
},
{
command: "report",
description: "Создать жалобу/обращение/идею."
},
{
command: "materials",
description: "Купить материалы для организации."
},
{
command: "orgmessage",
description: "Отправить сообщение в организацию."
},
{
command: "payday",
description: "Получить зарплату."
},
{
command: "enterprise",
description: "Управление предприятиями."
}
])
bot.catch((err, ctx) => {
console.error(`Произошла ошибка:`, err);
// Отправляем сообщение админу из adminList
for (let admin of global.config.adminList) {
bot.telegram.sendMessage(admin, `Произошла ошибка:\n\n${err.on.method}`);
}
switch (err.on.method) {
case 'sendMessage':
return ctx.answerCbQuery(`Произошла ошибка при отправке сообщения.`);
case 'editMessageText':
return ctx.answerCbQuery(`Произошла ошибка при редактировании сообщения.`);
default:
return ctx.answerCbQuery(`Произошла ошибка.`);
}
});
bot.use(stage.middleware())
bot.use(rpg)
bot.use(
session({
getSessionKey: (ctx) => {
if ((ctx.from && ctx.chat && ctx.chat.id === ctx.from.id) || (!ctx.chat && ctx.from)) {
return `user:${ctx.from.id}`
} else if (ctx.from && ctx.chat) {
return `${ctx.from.id}:${ctx.chat.id}`
}
return ctx.update.update_id
}
})
)
bot.use(stage)
bot.use(utils.stats)
bot.use(async (ctx, next) => {
bot.context.config = require('./ctxconfig.json')
let id = ctx.from.id
let username = ctx.from.username
global.messagesCounter.inc({ type: ctx.updateType });
if (username == null) username = ctx.from.id
switch (ctx.updateType) {
case `message`:
console.log(utils.getCurrentTime() + `: ` + username + `: ` + ctx.update.message.text)
break;
case `callback_query`:
console.log(utils.getCurrentTime() + `: ${username}: ${ctx.update.callback_query.data}`)
break;
default:
console.log(ctx)
}
let user = await UserModel.findByPk(id);
let block = await BlockModel.findOne({
where: { telegram_id: id }, // Здесь id — это значение telegram_id, переданное в функцию
});
let property = await PropertyModel.findByPk(id);
let skill = await SkillsModel.findByPk(ctx.from.id)
if (!user) ctx.reply(`❕ Первичная регистрация профиля.`);
if (user === null) {
await UserModel.create({
telegram_id: id,
username: username,
name: ctx.from.first_name
})
} else {
user.name = ctx.from.first_name
if (user.username === null) user.username = ctx.from.id
user.save()
}
if (property === null) {
await PropertyModel.create({
telegram_id: id
})
}
//if (whitelist.includes(id) == false) return ctx.reply(`У вас пока нет доступа к боту. Следите за обновлениями в группе: t.me/CampFireGameBotNews`)
if (block) {
const currentTime = Math.trunc(Date.now() / 1000); // Получаем текущее время в секундах
if (block.isBlocked && block.time > currentTime) {
const remainingTime = Math.trunc((block.time - currentTime) / 60); // Рассчитываем оставшееся время
return ctx.reply(
`📛 У вас активная блокировка по причине: ${block.reason}.\n⏲️ Оставшееся время: ${remainingTime} мин.`
);
}
// Если блокировка истекла или отключена
block.isBlocked = false;
await block.save(); // Обязательно используем `await` для сохранения изменений
}
const start = Date.now()
const timeoutPromise = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('timeout'))
}, 1000 * 5)
})
const nextPromise = next()
.then(() => {
const ms = Date.now() - start
})
.catch((error) => {
handleError(error, ctx)
})
return Promise.race([timeoutPromise, nextPromise])
.catch((error) => {
global.errorsCounter.inc(); // Увеличиваем счётчик ошибок
if (error.message === 'timeout') {
console.error('timeout', ctx.update)
return false
}
global.errorsCounter.inc(); // Увеличиваем счётчик ошибок
return true
})
})
bot.command('start', async (ctx) => {
try {
if (ctx.payload) { // Система обработки приглашений в зависимости от payload
const invite = await InviteModel.findOne({ where: { uid: ctx.payload } });
if (invite) {
const user = await UserModel.findByPk(ctx.from.id);
if (!user) {
return await ctx.reply('Ваш профиль не найден.');
}
switch (invite.type) {
case 'organization': {
const business = await BusinessModel.findByPk(invite.value);
if (business) {
// Проверка, состоит ли пользователь уже в организации
if (user.business.id != 0) {
return await ctx.reply('Вы уже состоите в организации.');
}
user.business = {
id: business.owner,
checks: 0,
percent: 0
};
await user.save({ fields: ['business'] });
// Добавляем пользователя в список организации
business.users = sequelize.fn('array_append', sequelize.col('users'), ctx.from.id);
await business.save();
return await ctx.reply(`Вы вступили в организацию "${business.name}".`);
} else {
return await ctx.reply('Организация не найдена.');
}
}
case 'referral': {
const inviter = await UserModel.findByPk(invite.author);
if (ctx.from.id === invite.author) {
return await ctx.reply('Вы не можете пригласить самого себя.');
}
if (user.referated) {
return await ctx.reply('Вы уже воспользовались приглашением.');
}
if (inviter) {
inviter.money += 250000;
user.money += 250000;
user.referated = true;
// Управление статусами
if (inviter.status === 'bronze') {
inviter.statustime += 4320
await ctx.reply('Ваш статус "Bronze" продлен на 3 дня.');
} else if (inviter.status === 'user') {
inviter.status = 'bronze';
inviter.statustime = 4320
await ctx.reply('Вам выдан статус "Bronze" на 3 дня.');
}
await user.save();
await inviter.save();
// Обновление данных приглашения
invite.users.push(ctx.from.id);
invite.value++;
await invite.save();
await ctx.reply(`Вы получили бонус от пользователя ${inviter.username}.`);
await ctx.reply(`Пользователь ${inviter.username} получил статус "Bronze" на 3 дня.`);
}
break;
}
default:
return await ctx.reply('Неверный тип приглашения.');
}
} else {
return await ctx.reply('Приглашение не найдено.');
}
}
// Главное меню
return await ctx.reply(
'Главное меню',
Markup.keyboard([
['😎 Профиль'], // Row1
['🗄️ Работать', '🌐 Организация', '🏗️ Предприятия', '🏯 Казино'], // Row2
['CampFireGG.Crime'], // Row3
['🎁 Бонус'], // Row4
['📦 Контейнеры'], // Row5
['📢 Вакансии', '🔵 Имущество', '📞 Пригласить'], // Row6
['🛡️ Test'], // Row7
]).resize()
);
} catch (error) {
console.error('Ошибка в команде start:', error);
await ctx.reply('Произошла ошибка. Пожалуйста, попробуйте позже.');
}
});
bot.hears('🛡️ Test', async (ctx) => {
const buttons = [
[Markup.button.callback('PVE', 'locations')],
];
ctx.reply(`🚨 Добро пожаловать в тестовый режим 🚨\nВесь функционал в этом режиме еще не сбалансирован\n`, Markup.inlineKeyboard(buttons));
})
bot.command('profile', (ctx) => {
return ctx.reply('👤 Ваш профиль:', {
reply_markup: {
inline_keyboard: [
[
{
text: "Открыть профиль",
web_app: { url: "https://web-bot.campfiregg.ru/" }, // Замените на ваш URL
},
],
],
},
});
});
bot.command('link', async (ctx) => {
try {
// Шаг 1: Получаем пользователя из базы данных
let user = await UserModel.findByPk(ctx.from.id);
if (!user) {
return ctx.reply("Пользователь не найден в базе данных.");
}
// Шаг 2: Получаем список пользователей на сервере
const response = await fetch('https://staff.campfiregg.ru/api/users', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Token tknCaMpFiReApIStAfFend'
}
});
const users = await response.json();
// Шаг 3: Ищем пользователя, у которого в "bio" содержится ctx.from.id (ID бота)
const staffuser = users.data.find(staff => staff.attributes.bio === String(ctx.from.id));
if (!staffuser) {
// Если пользователя не нашли
return ctx.reply("Пользователь не найден. Пожалуйста, установите ваш ID в описание профиля и повторите попытку.");
} else {
// Шаг 4: Если нашли, добавляем staffID в базу данных бота
const staffUserId = staffuser.id; // ID пользователя на сервере (staff)
user.staffID = staffUserId;
await user.save(); // Сохраняем обновления в базе данных
// Ответ пользователю
return ctx.reply('Профиль успешно привязан');
}
} catch (err) {
// Обработка ошибок
console.error(err);
return ctx.reply("Произошла ошибка. Попробуйте снова.");
}
});
bot.hears('промка', async (ctx) => {
generatePromo()
});
bot.hears('▶️ Меню', commands.menu);
bot.hears('Чат', async (ctx) => {
ctx.reply(`${ctx.message.chat.id}`)
});
bot.hears('😎 Профиль', commands.profile);
bot.command('getprofile', commands.getprofile);
bot.hears('Рандом', async (ctx) => {
let users = await UserModel.findAll();
let chosenOne = users.random()
return ctx.reply(`
👤 ${chosenOne.username}
🆔: ${chosenOne.telegram_id}
`);
});
bot.hears('💳 Баланс', async (ctx) => {
let user = await UserModel.findByPk(ctx.from.id);
return ctx.reply(`
⏩ Аккаунт игрока ${user.username}
🆔 Игрока: ${user.telegram_id}
📶 Уровень: ${user.level}
⏩ Повышается за различные действия.
💰 Баланс:
¤${user.money}
`);
})
bot.hears('🎁 Бонус', commands.bonus)
bot.hears('Гараж', commands.garage)
bot.hears('Гонка', commands.race)
bot.command('pay', commands.pay)
bot.hears('Мир', commands.worldMenu)
bot.hears('📞 Пригласить', commands.referal)
bot.hears('📢 Вакансии', commands.jobs)
bot.action(/job_(1|2|3|4|5|6|7|leave)/, commands.chooseJob)
bot.hears('🏯 Казино', commands.casinoMenu)
bot.hears('🗄️ Работать', commands.work)
bot.hears('Топ', commands.top)
bot.hears('🔵 Имущество', commands.propertyMenu)
bot.action('shopmenu', commands.propertyMenu)
bot.action(/shop_(house|phone|car)/, commands.propertyList)
bot.action(/{"action": "buy"*/, commands.propertyBuy)
bot.hears('Поставщик', commands.hatkeisList)
bot.command('sell', commands.propertySell)
bot.hears('🌐 Организация', commands.organizationMenu)
bot.action('workoff', commands.workoff)
bot.action('покинуть', commands.leaveOrg)
bot.action('cancel', async (ctx) => {
await ctx.deleteMessage()
await bot.telegram.answerCbQuery(ctx.callbackQuery.id, `Отмена.`)
})
bot.action('user_leave_business', commands.leaveOrgAccept)
bot.action('payday', commands.payday)
bot.command('orgmessage', commands.orgMessage)
bot.command('materials', commands.materialsBuy)
bot.command('percent', commands.percentSet)
bot.command('business', commands.organizationCreate)
bot.command('invite', commands.invite)
bot.action(/{"type": "business_invite_(accept|refuse)"*/, commands.inviteAction)
bot.command('report', commands.report)
bot.hears('🎰 Слоты', commands.slotsMenu)
// bot.action(/slots(1000|5000|25000|50000|100000)/, commands.slotsRun)
bot.hears('Помощь', async (ctx) => {
return await ctx.replyWithMarkdownV2(`• [Функционал](https://telegra.ph/CampFire-Bot-Info-09-25)\n• [Правила](https://telegra.ph/PRAVILA-BOTA-09-25)`, {
disable_web_page_preview: true
})
})
bot.command('promocode', commands.promocodeActivate)
bot.hears('📦 Контейнеры', commands.carContainers)
bot.action(/container_(1|2|3|4|5|6|7|8|9|10)/, commands.chooseContainer)
bot.action(/{"action": "sueta_*/, async (ctx) => {
let data = ctx.update.callback_query.data;
data = JSON.parse(data)
console.log(data.car)
let user = await UserModel.findByPk(ctx.from.id)
let property = await PropertyModel.findByPk(ctx.from.id)
switch (data.action) {
case `sueta_accept`:
user.money += data.carprice
await ctx.editMessageText(` ${data.carprice}`)
break;
case `sueta_refuse`:
user.money += Math.round(property.car.price / 2)
property.car = {
name: data.carname,
price: data.carprice
}
await ctx.editMessageText(` ${data.carname}`)
break;
}
user.save()
property.save()
})
bot.action(/dissolve_organization_(\d+)/, async (ctx) => {
try {
const businessId = parseInt(ctx.match[1], 10);
const business = await BusinessModel.findByPk(businessId);
if (!business) {
return ctx.answerCbQuery('Организация не найдена.', { show_alert: true });
}
const user = await UserModel.findByPk(ctx.from.id);
if (business.owner != ctx.from.id) {
return ctx.answerCbQuery('Только владелец может ликвидировать организацию.', { show_alert: true });
}
// Расчет и передача 25% от баланса владельцу
const payout = Math.floor(business.balance * 0.25);
user.money += payout;
user.business = { id: 0, checks: 0, percent: 0 };
await user.save();
// Сброс бизнес-данных у участников
const members = await UserModel.findAll({
where: {
'business.id': businessId,
},
});
for (const member of members) {
member.business = { id: 0, checks: 0, percent: 0 };
await member.save();
}
logs(ctx, `Ликвидация организации ${business.name}`, { businessId, payout });
// Удаление организации
await business.destroy();
await ctx.reply(`❌ Организация "${business.name}" ликвидирована. Вы получили ₽${spaces(payout)}.`);
} catch (error) {
console.error('Ошибка при ликвидации организации:', error);
return ctx.reply('Произошла ошибка. Попробуйте снова.');
}
});
bot.command('daily_bonus', async (ctx) => {
try {
const user = await UserModel.findByPk(ctx.from.id);
const currentDate = new Date();
const day = currentDate.getDate();
// Проверяем, заходил ли пользователь сегодня
const lastLoginDate = new Date(user.lastLogin);
if (
lastLoginDate.getFullYear() === currentDate.getFullYear() &&
lastLoginDate.getMonth() === currentDate.getMonth() &&
lastLoginDate.getDate() === day
) {
return ctx.reply('Вы уже получили награду за сегодня! Возвращайтесь завтра.');
}
// Получение награды из базы
const reward = await DailyModel.findOne({ where: { day } });
if (!reward) {
return ctx.reply('На сегодня награды не настроены. Обратитесь к администратору.');
}
// Обработка награды
let totalMoney = reward.money;
let message = `🎉 Награда за ${day} число:\n`;
if (reward.experience > 0) {
user.exp += reward.experience;
message += `✨ Опыт: ${reward.experience}\n`;
}
if (user.business.id > 0) {
user.materials += reward.materials;
message += `🏗 Материалы: ${reward.materials}\n`;
} else {
totalMoney += reward.materials; // Материалы заменяются на деньги
}
// Добавляем деньги
user.money += totalMoney;
message += `💰 Деньги: ${totalMoney}\n`;
// Обновляем прогресс
//user.lastLogin = currentDate;
user.loginStreak = (lastLoginDate.getDate() === day - 1) ? user.loginStreak + 1 : 1;
await user.save();
// Отправляем сообщение
await ctx.reply(`${message}\n🔥 Ваша серия входов: ${user.loginStreak} дней.`);
} catch (error) {
console.error('Ошибка при выдаче ежедневного бонуса:', error);
return ctx.reply('Произошла ошибка. Попробуйте снова.');
}
});
bot.command('daily', async (ctx) => {
try {
// Получаем данные пользователя
const user = await UserModel.findByPk(ctx.from.id);
// Создаем клавиатуру с кнопкой перехода в мини-приложение
const keyboard = {
inline_keyboard: [
[
{
text: '🎁 Ежедневный бонус',
web_app: { url: 'https://web-bot.campfiregg.ru/daily' } // Замените на URL мини-приложения
}
]
]
};
// Отправляем сообщение с кнопкой
await ctx.reply('👋 Добро пожаловать в раздел ежедневных наград! Нажмите на кнопку ниже, чтобы открыть календарь и получить сегодняшнюю награду.', {
reply_markup: keyboard
});
} catch (error) {
console.error('Ошибка при открытии ежедневного бонуса:', error);
return ctx.reply('Произошла ошибка. Попробуйте снова.');
}
});
bot.action('manage_organization', async (ctx) => {
try {
const user = await UserModel.findByPk(ctx.from.id);
if (user.business.id === 0) {
return await ctx.reply('Вы не состоите в организации.');
}
const business = await BusinessModel.findOne({ where: { owner: ctx.from.id.toString() } });
if (!business) {
return await ctx.reply('Организация не найдена.');
}
if (business.owner != ctx.from.id) {
return await ctx.reply('Вы не являетесь владельцем организации.');
}
const buttons = [
[{ text: '👥 Участники', callback_data: 'org_members' }],
[{ text: '📞 Пригласить', callback_data: 'org_invite' }],
[{ text: '🚫 Расформировать', callback_data: `dissolve_organization_${business.id}` }],
[{ text: '⬅️ Назад', callback_data: 'organization_menu' }]
];
return await ctx.editMessageText(`🏭 Управление организацией "${business.name}":`, Markup.inlineKeyboard(buttons).resize());
} catch (error) {
console.error('Ошибка при открытии меню управления организацией:', error);
return await ctx.reply('Произошла ошибка. Попробуйте снова.');
}
});
bot.action('org_members', async (ctx) => {
try {
const user = await UserModel.findByPk(ctx.from.id);
if (user.business.id === 0) {
return await ctx.reply('Вы не состоите в организации.');
}
const business = await BusinessModel.findOne({ where: { owner: ctx.from.id.toString() } });
if (!business) {
return await ctx.reply('Организация не найдена.');
}
if (business.owner != ctx.from.id) {
return await ctx.reply('Вы не являетесь владельцем организации.');
}
const buttons = [];
let message = `👥 Участники организации "${business.name}":\n\n`;
for (const member of business.users) {
const user = await UserModel.findByPk(member);
buttons.push([{ text: `👤 ${user.username}`, callback_data: `org_view_member_${user.telegram_id}` }]);
}
buttons.push([{ text: '🔧 Назад', callback_data: 'manage_organization' }]);
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
} catch (error) {
console.error('Ошибка при просмотре участников организации:', error);
return await ctx.reply('Произошла ошибка. Попробуйте снова.');
}
});
bot.action(/org_view_member_(\d+)/, async (ctx) => {
try {
const userId = parseInt(ctx.match[1], 10);
const user = await UserModel.findByPk(userId);
if (!user) {
return await ctx.reply('Пользователь не найден.');
}
const business = await BusinessModel.findOne({ where: { owner: ctx.from.id } });
if (!business) {
return await ctx.reply('Вы не являетесь владельцем организации.');
}
if (user.business.id != business.owner) {
return await ctx.reply('Пользователь не состоит в вашей организации.');
}
const buttons = [
[{ text: '📉 Уволить', callback_data: `fireuser_${user.telegram_id}` }],
[{ text: '🔧 Назад', callback_data: 'org_members' }]
];
// Рассчитываем эффективность пользователя
const userChecks = user.business.checks;
const businessChecks = business.checks;
const userEfficiency = userChecks > 0 ? Math.floor((userChecks / businessChecks) * 100) : 0;
const message = `👤 Профиль участника "${user.username}":\n\n` +
`📶 Отработки: ${user.business.checks}\n` +
`💰 Процент: ${user.business.percent}%\n` +
`🔥 Эффективность: ${userEfficiency}%\n`;
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
} catch (error) {
console.error('Ошибка при просмотре участника организации:', error);
return await ctx.reply('Произошла ошибка. Попробуйте снова.');
}
});
// Команда для увольнения сотрудника из организации
bot.action(/fireuser_(\d+)/, async (ctx) => {
try {
const userId = parseInt(ctx.match[1], 10);
const user = await UserModel.findByPk(userId);
if (!user) {
return await ctx.reply('Пользователь не найден.');
}
const business = await BusinessModel.findOne({ where: { owner: ctx.from.id } });
if (!business) {
return await ctx.reply('Вы не являетесь владельцем организации.');
}
if (user.business.id != business.owner) {
return await ctx.reply('Пользователь не состоит в вашей организации.');
}
if (user.telegram_id == business.owner) {
return await ctx.reply('Вы не можете уволить себя.');
}
// Удаляем пользователя из массива участников\
business.users = business.users.filter((id) => id !== user.telegram_id);
await business.save();
user.business = { id: 0, checks: 0, percent: 0 };
await user.save();
return await ctx.reply(`Пользователь ${user.username} уволен из организации.`);
} catch (error) {
console.error('Ошибка при увольнении сотрудника:', error);
return await ctx.reply('Произошла ошибка. Попробуйте снова.');
}
});
bot.action('org_invite', async (ctx) => {
try {
const user = await UserModel.findByPk(ctx.from.id);
if (user.business.id === 0) {
return await ctx.reply('Вы не состоите в организации.');
}
const business = await BusinessModel.findOne({ where: { owner: ctx.from.id.toString() } });
if (!business) {
return await ctx.reply('Организация не найдена.');
}
if (business.owner != ctx.from.id) {
return await ctx.reply('Вы не являетесь владельцем организации.');
}
// Создаем приглашение
const invites = await InviteModel.findAll({ where: { type: 'organization', author: ctx.from.id } });
if (invites.length > 0) {
const invite = invites[0];
const inviteLink = `https://t.me/${process.env.BOT_USERNAME}?start=${invite.uid}`;
return await ctx.reply(`📞 Приглашение для организации "${business.name}":\n\n${inviteLink}`);
}
const invite = await InviteModel.create({ type: 'organization', uid: `${user.username}_org_invite` , author: ctx.from.id, value: business.id });
const inviteLink = `https://t.me/${process.env.BOT_USERNAME}?start=${invite.uid}`;
return await ctx.reply(`📞 Приглашение для организации "${business.name}":\n\n${inviteLink}`);
} catch (error) {
console.error('Ошибка при создании приглашения в организацию:', error);
return await ctx.reply('Произошла ошибка. Попробуйте снова.');
}
});
/////////////////////////////////////Enterprise Update 20.12.2024//////////////////////////////////////////////////
// Обновление меню "Предприятия"
bot.hears('🏗️ Предприятия', async (ctx) => {
try {
const user = await UserModel.findByPk(ctx.from.id);
if (!user) {
console.error('Ошибка: пользователь не найден');
return await ctx.reply('Ошибка: пользователь не найден.');
}
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
const enterprises = await EnterpriseModel.findAll({
where: { playerId: user.telegram_id }
});
let message = `🏗️ Меню предприятий:\n`;
message += `У вас: ${enterprises.length} предприятий.\n`;
message += warehouse
? `🗄️ Единый склад: Доступен (Ёмкость: ${warehouse.capacity} ед.)\n`
: `🗄️ Единый склад: Не построен.\n`;
const buttons = [];
buttons.push([{ text: '🏭 Мои предприятия', callback_data: 'my_enterprises' }]);
buttons.push([{ text: '🛠️ Построить предприятие', callback_data: 'build_enterprise' }]);
if (warehouse) {
buttons.push([{ text: '🚛 Управление складом', callback_data: 'manage_warehouse' }]);
} else {
buttons.push([{ text: '🗄️ Построить склад', callback_data: 'buy_warehouse' }]);
}
buttons.push([{ text: '💰 Продать ресурсы', callback_data: 'sell_resources' }]);
return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
} catch (error) {
console.error('Ошибка при выполнении команды "🏗️ Предприятия":', error);
return await ctx.reply('Произошла ошибка при выполнении команды. Попробуйте позже.');
}
});
bot.action('enterprise_menu', async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id);
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
const enterprises = await EnterpriseModel.findAll({
where: { playerId: user.telegram_id }
});
let message = `🏗️ Меню предприятий:\n`;
message += `У вас: ${enterprises.length} предприятий.\n`;
message += warehouse
? `🗄️ Единый склад: Доступен (Ёмкость: ${warehouse.capacity} ед.)\n`
: `🗄️ Единый склад: Не построен.\n`;
const buttons = [];
// Добавляем кнопки для предприятий
buttons.push([{ text: '🏭 Мои предприятия', callback_data: 'my_enterprises' }]);
buttons.push([{ text: '🛠️ Построить предприятие', callback_data: 'build_enterprise' }]);
// Кнопка для управления или постройки склада
if (warehouse) {
buttons.push([{ text: '🚛 Управление складом', callback_data: 'manage_warehouse' }]);
} else {
buttons.push([{ text: '🗄️ Построить склад', callback_data: 'buy_warehouse' }]);
}
buttons.push([{ text: '💰 Продать ресурсы', callback_data: 'sell_resources' }])
// Возвращаем меню с кнопками
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
});
// Функция для преобразования типа ресурса в эмодзи
function getEnterpriseEmoji(resourceType) {
const emojis = {
wood: '🌳',
coal: '⛏️',
oil: '🛢️',
metall: '⚒️',
gold: '💰',
diamond: '💎'
}
return emojis[resourceType] || '🏭'
}
bot.action('my_enterprises', async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id);
const enterprises = await EnterpriseModel.findAll({
where: { playerId: user.telegram_id }
});
if (enterprises.length === 0) {
return await ctx.reply('У вас нет предприятий.');
}
let metallPrice = await ResourcePriceModel.findOne({
where: { resource: "metall" }
});
let message = `🏭 Мои предприятия:\n\n`;
const buttons = [];
for (const enterprise of enterprises) {
const { id, name, level, efficiency, currentResources, resourceType, warehouseCapacity } = enterprise;
const resourcePrice = await ResourcePriceModel.findOne({
where: { resource: resourceType }
});
let price = resourcePrice.price * 1.5 * 10 * 24 * 7 // Стоимость улучшения зависит от уровня
message += `🔹 [ID: ${id}] ${getEnterpriseEmoji(resourceType)} ${name} st. ${level}\n └── ${currentResources}/${warehouseCapacity} [${efficiency} ед/ч]\n └──📈 ${utils.spaces(price)} руб.\n\n`;
const truck = await TruckModel.findOne({ where: { enterpriseId: id } });
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
const enterpriseButtons = [
{ text: `ID: 📈 ${id}`, callback_data: `upgrade_${id}` },
];
if (!truck) {
enterpriseButtons.push({ text: `🛻 ID: ${id}`, callback_data: `hire_truck_${id}` });
} else {
enterpriseButtons.push({ text: `🚛 ID: ${id}`, callback_data: `upgrade_truck_${id}` });
}
enterpriseButtons.push({ text: `💰 ID: ${id}`, callback_data: `sell_all_${id}` });
if (warehouse) {
enterpriseButtons.push({ text: `🔄 ID: ${id}`, callback_data: `transfer_from_${id}` });
}
enterpriseButtons.push({ text: `🚫 ID: ${id}`, callback_data: `sell_enterprise_${id}` });
buttons.push(enterpriseButtons);
}
message += `\n\n📈 - Улучшить\n🛻 - Купить грузовик [~${utils.spaces(metallPrice.price * 700)} руб.]\n🚛 - Улучшить грузовик\n💰 - Продать ресурсы с предприятия\n🔄 - Перевезти все на склад`
buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
});
// Построение предприятия
bot.action('build_enterprise', async (ctx) => {
try {
const user = await UserModel.findByPk(ctx.from.id);
if (!user) {
return await ctx.reply('Пользователь не найден.');
}
const enterprises = await EnterpriseModel.findAll({
where: { playerId: user.telegram_id }
});
if (enterprises.length >= 5) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Вы достигли максимального числа предприятий.', { show_alert: true });
}
// Получаем текущие цены из базы данных
const resourcePrices = await ResourcePriceModel.findAll();
if (!resourcePrices || resourcePrices.length === 0) {
return await ctx.reply('Цены на ресурсы отсутствуют. Пожалуйста, попробуйте позже.');
}
let message = `🛠️ Постройка предприятия:\n`;
const buttons = [];
for (const resource of resourcePrices) {
const resourceName = getReadableType(resource.resource);
const resourceEmoji = getEnterpriseEmoji(resource.resource);
message += `${resourceEmoji} ${resourceName}: ${utils.spaces(Math.round(resource.price * 1.5 * 10 * 24 * 7))} руб.\n`;
// Генерируем кнопки для каждого ресурса
buttons.push([
{ text: resourceEmoji, callback_data: `build_${resource.resource}` }
]);
}
message += '\nВыберите тип предприятия:';
buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
} catch (error) {
console.error('Ошибка в build_enterprise:', error);
return await ctx.reply('Произошла ошибка при обработке запроса. Попробуйте снова.');
}
});
// Построение предприятия по выбранному типу
bot.action(/build_(wood|coal|oil|metall|gold|diamond)/, async (ctx) => {
let user = await UserModel.findByPk(ctx.from.id)
let data = ctx.update.callback_query.data
let type = data.split('_')[1]
// Получаем текущие цены из базы данных
const resourcePrice = await ResourcePriceModel.findOne({
where: { resource: type }
});
let price = resourcePrice.price * 1.5 * 10 * 24 * 7
// Проверка, есть ли достаточно денег у пользователя
if (user.money < price) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для постройки предприятия. Необходимо ${utils.spaces(price)} руб.`, { show_alert: true })
}
// Проверка уровня, для покупки предприятия, для покупки деревообрабатывающего предприятия нужен 5 уровень и каждое следующее предприятие требует уровень выше
switch (type) {
case 'wood':
if (user.level < 5) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Для постройки деревообрабатывающего предприятия необходим 5 уровень.`, { show_alert: true })
}
break;
case 'coal':
if (user.level < 6) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Для постройки угольного предприятия необходим 10 уровень.`, { show_alert: true })
}
break;
case 'oil':
if (user.level < 7) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Для постройки нефтяного предприятия необходим 15 уровень.`, { show_alert: true })
}
break;
case 'metall':
if (user.level < 9) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Для постройки металлургического предприятия необходим 20 уровень.`, { show_alert: true })
}
break;
case 'gold':
if (user.level < 12) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Для постройки золотодобывающего предприятия необходим 25 уровень.`, { show_alert: true })
}
break;
case 'diamond':
if (user.level < 15) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Для постройки алмазодобывающего предприятия необходим 30 уровень.`, { show_alert: true })
}
break;
}
// Строим предприятие
let enterpriseName = `${user.username}'s ${getReadableType(type)}` // Название предприятия
let enterprise = await EnterpriseModel.create({
name: enterpriseName,
resourceType: type,
playerId: user.telegram_id,
level: 1,
efficiency: 10,
warehouseCapacity: 100
})
// Снимаем деньги с баланса
await user.update({ money: user.money - price })
return await ctx.editMessageText(`Предприятие ${enterprise.name} (ID: ${enterprise.id}) построено!`)
})
// Запрашиваем подтверждение на продажу предприятия
bot.action(/sell_enterprise_(\d+)/, async (ctx) => {
try {
const enterpriseId = parseInt(ctx.match[1], 10);
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
if (!enterprise) {
return await ctx.reply('Предприятие не найдено.');
}
const user = await UserModel.findByPk(ctx.from.id);
if (enterprise.playerId !== user.telegram_id) {
return await ctx.reply('Это не ваше предприятие.');
}
// Получаем информацию о наличии грузовика у предприятия и его уровень
const truck = await TruckModel.findOne({ where: { enterpriseId: enterprise.id } });
const truckLevel = truck ? truck.level : 0;
const metallPrice = await ResourcePriceModel.findOne({ where: { resource: 'metall' } });
const truckPrice = metallPrice.price * 700 * truckLevel;
// Получаем текущую стоимость предприятия
const resourcePrice = await ResourcePriceModel.findOne({
where: { resource: enterprise.resourceType }
});
const price = Math.round(resourcePrice.price * 1.5 * 5 * 24 * 7 * enterprise.level + truckPrice * 0.5);
return await ctx.reply(`Вы уверены, что хотите продать предприятие ${enterprise.name} за ${utils.spaces(price)} руб?`, Markup.inlineKeyboard([
[{ text: '✅ Да', callback_data: `confirm_enterprise_${enterpriseId}` }],
[{ text: '❌ Нет', callback_data: 'enterprise_menu' }]
]).resize());
} catch (error) {
console.error('Ошибка при запросе на продажу предприятия:', error);
return await ctx.reply('Произошла ошибка при запросе на продажу предприятия. Попробуйте позже.');
}
});
// Продажа предприятия
bot.action(/confirm_enterprise_(\d+)/, async (ctx) => {
try {
const enterpriseId = parseInt(ctx.match[1], 10);
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
if (!enterprise) {
return await ctx.reply('Предприятие не найдено.');
}
const user = await UserModel.findByPk(ctx.from.id);
if (enterprise.playerId !== user.telegram_id) {
return await ctx.reply('Это не ваше предприятие.');
}
// Получаем информацию о наличии грузовика у предприятия и его уровень
const truck = await TruckModel.findOne({ where: { enterpriseId: enterprise.id } });
const truckLevel = truck ? truck.level : 1;
const metallPrice = await ResourcePriceModel.findOne({ where: { resource: 'metall' } });
const truckPrice = metallPrice.price * 700 * truckLevel;
// Получаем текущую стоимость предприятия
const resourcePrice = await ResourcePriceModel.findOne({
where: { resource: enterprise.resourceType }
});
console.log()
const price = Math.round(resourcePrice.price * 1.5 * 5 * 24 * 7 * enterprise.level + truckPrice * 0.5);
// Продаем предприятие
await enterprise.destroy();
// Удаляем грузовик
await TruckModel.destroy({ where: { enterpriseId: enterprise.id } });
await user.update({ money: user.money + price });
return await ctx.reply(`Предприятие ${enterprise.name} продано за ${utils.spaces(price)} руб.`);
} catch (error) {
console.error('Ошибка при продаже предприятия:', error);
return await ctx.reply('Произошла ошибка при продаже предприятия. Попробуйте позже.');
}
});
// Функция для преобразования типа ресурса в читаемое название
function getReadableType(type) {
const names = {
wood: 'Деревообрабатывающее предприятие',
coal: 'Угольное предприятие',
oil: 'Нефтяное предприятие',
metall: 'Металлургическое предприятие',
gold: 'Золотое предприятие',
diamond: 'Алмазное предприятие'
}
return names[type] || type
}
function getReadableResourceType(type) {
const names = {
wood: 'Дерево',
coal: 'Уголь',
oil: 'Нефть',
metall: 'Металл',
gold: 'Золото',
diamond: 'Алмазы'
}
return names[type] || type
}
bot.action('buy_warehouse', async (ctx) => {
try {
// Получаем пользователя
let user = await UserModel.findByPk(ctx.from.id);
if (!user) {
return await ctx.reply('Произошла ошибка. Пользователь не найден.');
}
if (user.level < 5) {
return await ctx.reply('Для покупки склада необходим 5 уровень.');
}
// Получаем цены на металл и дерево
const woodPrice = await ResourcePriceModel.findOne({ where: { resource: 'wood' } });
const metallPrice = await ResourcePriceModel.findOne({ where: { resource: 'metall' } });
if (!woodPrice || !metallPrice) {
return await ctx.reply('Не удалось получить цены на ресурсы. Попробуйте позже.');
}
// Формируем стоимость склада
const warehouseBaseCost = 10; // Коэффициент для расчёта
const warehouseCost = Math.round(
(woodPrice.price + metallPrice.price) * warehouseBaseCost * 24 * 7
);
// Проверяем, хватает ли денег у пользователя
if (user.money < warehouseCost) {
return await ctx.telegram.answerCbQuery(
ctx.callbackQuery.id,
`У вас недостаточно средств для покупки склада. Необходимо: ${utils.spaces(warehouseCost)} руб.`,
{ show_alert: true }
);
}
// Создаём склад
await WarehouseModel.create({
playerId: user.telegram_id,
capacity: 1000, // Начальная ёмкость
wood: 0,
coal: 0,
oil: 0,
metall: 0,
gold: 0,
diamond: 0,
});
// Списываем деньги
await user.update({ money: user.money - warehouseCost });
// Уведомление об успешной покупке
return await ctx.reply(
`Вы успешно купили единый склад за ${warehouseCost} руб!`
);
} catch (error) {
console.error('Ошибка при покупке склада:', error);
return await ctx.reply('Произошла ошибка при покупке склада. Попробуйте позже.');
}
});
// Управление складом
bot.action('manage_warehouse', async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id);
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
if (!warehouse) {
return await ctx.reply('У вас нет склада для управления.');
}
let message = `🚛 Управление складом:\n`;
message += `Общая ёмкость: ${warehouse.capacity} ед.\n`;
message += `Хранимые ресурсы:\n`;
message += `🌲 Дерево: ${warehouse.wood || 0}\n`;
message += `⛏️ Уголь: ${warehouse.coal || 0}\n`;
message += `🛢️ Нефть: ${warehouse.oil || 0}\n`;
message += `⚙️ Металл: ${warehouse.metall || 0}\n`;
message += `🥇 Золото: ${warehouse.gold || 0}\n`;
message += `💎 Алмазы: ${warehouse.diamond || 0}\n`;
const buttons = [
[{ text: ' Перевести ресурсы', callback_data: 'transfer_resources' }]
];
buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
});
bot.action('transfer_resources', async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id);
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
if (!warehouse) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'У вас нет единого склада.');
}
const enterprises = await EnterpriseModel.findAll({
where: { playerId: user.telegram_id }
});
let message = ` Перевозка ресурсов:\n`;
message += `Общая ёмкость склада: ${warehouse.capacity} ед.\n`;
message += `Выберите предприятие для перевозки ресурсов:`;
const buttons = enterprises.map(ent => {
return [{ text: `🏭 ${ent.name}`, callback_data: `transfer_from_${ent.id}` }];
});
buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
});
// Перевозка с конкретного предприятия
bot.action(/transfer_from_(\d+)/, async (ctx) => {
const enterpriseId = ctx.match[1];
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
if (!enterprise) {
return await ctx.editMessageText('Предприятие не найдено.');
}
const { currentResources, resourceType, playerId } = enterprise;
if (currentResources === 0) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для перевода.');
}
const warehouse = await WarehouseModel.findOne({ where: { playerId } });
if (!warehouse) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'У вас нет склада для перевода ресурсов.');
}
const freeCapacity = warehouse.capacity - getWarehouseUsedCapacity(warehouse);
const transferAmount = Math.min(currentResources, freeCapacity);
if (transferAmount === 0) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Склад заполнен. Перевод невозможен.');
}
// Перевод ресурсов
warehouse[resourceType] = (warehouse[resourceType] || 0) + transferAmount;
enterprise.currentResources -= transferAmount;
await warehouse.save();
await enterprise.save();
return await ctx.reply(
`Успешно переведено ${transferAmount} ед. ${resourceType} с предприятия в склад.`
);
});
bot.command('ent_rename', async (ctx) => {
let args = ctx.message.text.split(' ').slice(1)
if (args.length < 2) {
return await ctx.reply('Использование: /ent_rename <ID> <Новое название>')
}
let enterpriseId = parseInt(args[0])
let newName = args.slice(1).join(' ')
let enterprise = await EnterpriseModel.findByPk(enterpriseId)
if (!enterprise) {
return await ctx.reply(`Предприятие с ID ${enterpriseId} не найдено.`)
}
const user = await UserModel.findByPk(ctx.from.id);
if (enterprise.playerId !== user.telegram_id) {
return await ctx.reply('Это не ваше предприятие.');
}
// Переименовываем предприятие
await enterprise.update({ name: newName })
return await ctx.reply(`Предприятие (ID: ${enterprise.id}) переименовано в "${newName}".`)
})
bot.action(/upgrade_(\d+)/, async (ctx) => {
let user = await UserModel.findByPk(ctx.from.id)
let enterpriseId = ctx.match[1]
let enterprise = await EnterpriseModel.findByPk(enterpriseId)
if (!enterprise) return await ctx.reply(`Предприятие не найдено.`)
const resourcePrice = await ResourcePriceModel.findOne({
where: { resource: enterprise.resourceType }
});
let upgradeCost = resourcePrice.price * 1.5 * 10 * 24 * 7 // Стоимость улучшения зависит от уровня
if (user.money < upgradeCost) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для прокачки предприятия. Необходимо ${upgradeCost} руб.`)
}
if(enterprise.level >= 5) {
return await ctx.reply('Предприятие уже достигло максимального уровня.')
}
// Прокачка: повышение уровня и эффективности
await enterprise.update({
level: enterprise.level + 1,
efficiency: enterprise.efficiency + 10,
warehouseCapacity: enterprise.warehouseCapacity + 110
})
// Снимаем деньги с баланса
await user.update({ money: user.money - upgradeCost })
return await ctx.editMessageText(`Предприятие ${enterprise.name} успешно прокачано! Уровень: ${enterprise.level}, Производительность: ${enterprise.efficiency} ед/ч.`)
})
// Показ списка предприятий
bot.action('sell_resources', async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id);
const enterprises = await EnterpriseModel.findAll({
where: { playerId: user.telegram_id }
});
if (enterprises.length === 0) {
return await ctx.reply('❌ У вас нет предприятий для продажи ресурсов.');
}
let message = `<b>📜 Список ваших предприятий и их ресурсы:</b>\n\n`;
enterprises.forEach((enterprise, index) => {
message += `<b>${index + 1}.</b> ${enterprise.name} (${enterprise.resourceType}): <b>${enterprise.currentResources}</b> единиц\n`;
});
message += `\n<b>📦 Продажа ресурсов:</b>\n`;
message += `• Для продажи ресурсов с предприятия используйте команду:\n<code>/sellres [номер_предприятия] [количество]</code>\n<i>Пример:</i> <code>/sellres 1 50</code>\n\n`;
message += `• Для продажи ресурсов со склада используйте команду:\n<code>/sellstorage [тип_ресурса (wood/coal/oil/metall/gold/diamond)] [количество]</code>\n<i>Пример:</i> <code>/sellstorage wood 10</code>`;
return await ctx.reply(message, {
parse_mode: 'HTML',
reply_markup: {
inline_keyboard: [
[{ text: '↩ Назад', callback_data: 'enterprise_menu' }]
]
}
});
});
// Обработка продажи ресурсов
bot.command('sellres', async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id);
const [enterpriseId, amountToSell] = ctx.message.text.split(' ').slice(1);
if (!enterpriseId || !amountToSell) {
return await ctx.reply('Неверный формат команды. Пример: /sellres 1 50');
}
const enterprise = await EnterpriseModel.findByPk(enterpriseId, {
where: { playerId: user.telegram_id }
});
if (!enterprise) {
return await ctx.reply('Предприятие с таким id не найдено.');
}
const amount = parseInt(amountToSell, 10);
if (isNaN(amount) || amount <= 0) {
return await ctx.reply('Укажите корректное количество для продажи.');
}
if (enterprise.currentResources < amount) {
return await ctx.reply(
`На предприятии ${enterprise.name} недостаточно ресурсов. Доступно: ${enterprise.currentResources} единиц.`
);
}
const resourcePrice = await ResourcePriceModel.findOne({
where: { resource: enterprise.resourceType }
});
if (!resourcePrice) {
return await ctx.reply('Не удалось получить цену ресурса.');
}
const totalSale = Math.floor(amount * resourcePrice.price);
// Обновляем данные
enterprise.currentResources -= amount;
await enterprise.save();
user.money += totalSale;
await user.save();
// Ослабленная инфляция
resourcePrice.price = Math.round(
resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (amount / 10)) // Дробное уменьшение инфляции
);
// Гарантируем, что цена не упадет ниже 50% от базовой цены
resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));
await resourcePrice.save();
updateResourcePricesMessage();
return await ctx.reply(
`Вы продали ${amount} единиц ${enterprise.resourceType} с предприятия ${enterprise.name} за ${totalSale} руб.\nТекущая цена за единицу: ${resourcePrice.price.toFixed(0)} руб.`
);
});
bot.action(/sell_all_(\d+)/, async (ctx) => {
const enterpriseId = ctx.match[1];
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
if (!enterprise) {
return await ctx.reply('Предприятие не найдено.');
}
const { currentResources, resourceType, playerId } = enterprise;
const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: resourceType } });
const totalPrice = currentResources * resourcePrice.price;
if (currentResources === 0) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для продажи.');
}
await ctx.reply(
`Вы уверены, что хотите продать все ${currentResources} ед. ${resourceType} за ${totalPrice} руб.? Это необратимо!\n\nРекомендуем воспользоваться командой /sell для более гибкого управления продажами.`,
Markup.inlineKeyboard([
[
{ text: '✅ Продать всё', callback_data: `confirm_ressell_${enterpriseId}` },
{ text: '❌ Отмена', callback_data: 'cancel' }
]
])
);
});
bot.action(/confirm_ressell_(\d+)/, async (ctx) => {
const enterpriseId = ctx.match[1];
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
if (!enterprise) {
return await ctx.reply('Предприятие не найдено.');
}
const { currentResources, resourceType, playerId } = enterprise;
const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: resourceType } });
const totalPrice = currentResources * resourcePrice.price;
if (currentResources === 0) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для продажи.');
}
// Обновление баланса игрока
const user = await UserModel.findByPk(playerId);
user.money += totalPrice;
enterprise.currentResources = 0;
await user.save();
await enterprise.save();
console.log(resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (currentResources / 10)))
// Ослабленная инфляция
resourcePrice.price = Math.round(
resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (currentResources / 10)) // Дробное уменьшение инфляции
);
// Гарантируем, что цена не упадет ниже 50% от базовой цены
resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));
await resourcePrice.save();
updateResourcePricesMessage();
await ctx.editMessageText(`Вы успешно продали ${currentResources} ед. ${getEnterpriseEmoji(resourceType)} за ${totalPrice} руб.`);
});
// Продажа ресурсов со склада
bot.command('sellstorage', async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id);
const [resourceType, amountToSell] = ctx.message.text.split(' ').slice(1);
if (!resourceType || !amountToSell) {
return await ctx.reply('Неверный формат команды. Пример: /sellstorage <тип_ресурса> <количество>');
}
const storage = await WarehouseModel.findOne({
where: { playerId: user.telegram_id }
});
if (!storage || !storage[resourceType]) {
return await ctx.reply(`У вас нет ресурсов типа ${resourceType} на складе.`);
}
const amount = parseInt(amountToSell, 10);
if (isNaN(amount) || amount <= 0) {
return await ctx.reply('Укажите корректное количество для продажи.');
}
if (storage[resourceType] < amount) {
return await ctx.reply(`На складе недостаточно ресурсов типа ${resourceType}. Доступно: ${storage[resourceType]} единиц.`);
}
const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: resourceType } });
if (!resourcePrice) {
return await ctx.reply('Не удалось получить цену ресурса.');
}
const totalSale = Math.floor(amount * resourcePrice.price);
// Обновляем данные
storage[resourceType] -= amount;
await storage.save();
user.money += totalSale;
await user.save();
// Ослабленная инфляция
resourcePrice.price = Math.round(
resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * (amount / 10)) // Дробное уменьшение инфляции
);
// Гарантируем, что цена не упадет ниже 50% от базовой цены
resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));
await resourcePrice.save();
updateResourcePricesMessage();
return await ctx.reply(
`Вы продали ${amount} ед. ${resourceType} со склада за ${totalSale} руб.\nТекущая цена за единицу: ${resourcePrice.price.toFixed(0)} руб.`
);
});
// Обработка найма грузовика для выбранного предприятия
bot.action(/hire_truck_(\d+)/, async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id);
const enterpriseId = ctx.match[1];
// Находим предприятие
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
if (!enterprise || enterprise.playerId != user.telegram_id) {
return await ctx.reply('Предприятие не найдено или вам не принадлежит.');
}
// Проверяем, есть ли уже грузовик для этого предприятия
const existingTruck = await TruckModel.findOne({
where: { enterpriseId: enterprise.id }
});
if (existingTruck) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас уже есть грузовик для предприятия ${enterprise.name}.`);
}
const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: 'metall' } });
if (!resourcePrice) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Не удалось получить цену ресурса.');
}
if (user.money < resourcePrice.price * 700) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Недостаточно средств. Стоимость грузовика: ${utils.spaces(resourcePrice.price * 700)} руб.`);
}
await user.update({ money: user.money - (resourcePrice.price * 700) })
// Создаем новый грузовик
const newTruck = await TruckModel.create({
enterpriseId: enterprise.id,
capacity: 10, // Начальная вместимость
efficiency: 1 // Начальная эффективность
});
return await ctx.reply(
`Вы успешно наняли грузовик для предприятия ${enterprise.name}!`
);
});
async function initializePrices() {
const resources = [
{ resource: 'wood', price: 1000, basePrice: 1000, fluctuationRate: 0.002, recoveryRate: 0.15 },
{ resource: 'coal', price: 2000, basePrice: 2000, fluctuationRate: 0.002, recoveryRate: 0.12 },
{ resource: 'oil', price: 5000, basePrice: 5000, fluctuationRate: 0.001, recoveryRate: 0.1 },
{ resource: 'metall', price: 5000, basePrice: 5000, fluctuationRate: 0.001, recoveryRate: 0.1 },
{ resource: 'gold', price: 10000, basePrice: 10000, fluctuationRate: 0.0005, recoveryRate: 0.08 },
{ resource: 'diamond', price: 25000, basePrice: 25000, fluctuationRate: 0.0004, recoveryRate: 0.05 },
];
for (const resource of resources) {
await ResourcePriceModel.findOrCreate({
where: { resource: resource.resource },
defaults: resource,
});
}
}
initializePrices();
const recoverResourcePrices = async () => {
const resources = await ResourcePriceModel.findAll();
for (const resource of resources) {
// Определяем случайное колебание в диапазоне [-maxFluctuation, maxFluctuation]
const maxFluctuation = resource.basePrice * 0.3; // 30% от базовой цены
const priceFluctuation = (Math.random() * 2 - 1) * maxFluctuation;
// Применяем колебание
resource.price = Math.round(resource.price + priceFluctuation);
// Если цена выше базовой, шанс на её снижение
if (resource.price > resource.basePrice) {
const chanceToDrop = 0.5; // 50% шанс на снижение
if (Math.random() < chanceToDrop) {
resource.price -= Math.round(resource.basePrice * 0.1); // Снижение на 1% базовой цены
}
}
// Если цена ниже базовой, восстанавливаем с учётом recoveryRate
if (resource.price < resource.basePrice) {
resource.price = Math.min(
Math.round(resource.price + resource.basePrice * resource.recoveryRate),
resource.basePrice // Не превышать базовую цену
);
}
if (resource.price > resource.basePrice * 2.1) {
resource.price = Math.round(resource.basePrice * 0.79764918); // Устанавливаем цену на уровне 1.5 базовой
}
// Гарантируем, что цена остаётся в диапазоне [50% basePrice, 150% basePrice]
resource.price = Math.max(resource.price, Math.round(resource.basePrice * 0.5)); // Минимум
resource.price = Math.min(resource.price, Math.round(resource.basePrice * 3)); // Максимум
await resource.save(); // Сохраняем после всех корректировок
}
};
// Функция добычи ресурсов
const resourceProduction = async () => {
try {
// Получаем все предприятия
const enterprises = await EnterpriseModel.findAll();
for (const enterprise of enterprises) {
const {
id,
efficiency,
warehouseCapacity,
resourceType,
currentResources,
level,
playerId
} = enterprise;
// Расчёт добытых ресурсов
const producedResources = efficiency;
// Проверяем ёмкость склада предприятия
if (currentResources + producedResources <= warehouseCapacity) {
enterprise.currentResources += producedResources;
await enterprise.save();
console.log(
`Предприятие ${id}: добыто ${producedResources} единиц ${resourceType}.`
);
} else {
console.log(`Предприятие ${id}: склад заполнен.`);
}
}
} catch (error) {
console.error('Ошибка добычи ресурсов:', error);
}
};
// Функция транспортировки ресурсов
const resourceTransportation = async () => {
try {
// Получаем все предприятия
const enterprises = await EnterpriseModel.findAll();
for (const enterprise of enterprises) {
const {
id,
name,
resourceType,
currentResources,
playerId
} = enterprise;
if (currentResources > 0) {
// Получаем грузовики, привязанные к предприятию
const trucks = await TruckModel.findAll({
where: { enterpriseId: id }
});
if (trucks.length === 0) {
console.log(
`[${id}] ${name}: нет доступных грузовиков для транспортировки.`
);
continue;
}
// Получаем универсальный склад игрока
const warehouse = await WarehouseModel.findOne({
where: { playerId }
});
if (!warehouse) {
console.log(
`[${id}] ${name}: у игрока ${playerId} нет универсального склада.`
);
continue;
}
// Транспортировка ресурсов
let totalTransported = 0;
for (const truck of trucks) {
const transportableAmount = Math.min(
truck.capacity, // Максимальная вместимость грузовика
currentResources, // Доступные ресурсы на предприятии
warehouse.capacity - getWarehouseUsedCapacity(warehouse) // Свободное место на складе
);
if (transportableAmount > 0) {
// Обновляем данные склада
warehouse[resourceType] =
(warehouse[resourceType] || 0) + transportableAmount;
// Уменьшаем ресурсы на предприятии
enterprise.currentResources -= transportableAmount;
await warehouse.save();
await enterprise.save();
totalTransported += transportableAmount;
console.log(
`Грузовик ${truck.id} перевёз ${transportableAmount} единиц ${resourceType}.`
);
}
// Прекращаем, если ресурсы закончились
if (enterprise.currentResources === 0) break;
}
if (totalTransported === 0) {
console.log(
`[${id}] ${name}: склад заполнен, транспортировка невозможна.`
);
}
} else {
console.log(`[${id}] ${name}: нет ресурсов для транспортировки.`);
}
}
} catch (error) {
console.error('Ошибка транспортировки ресурсов:', error);
}
};
// Расчёт используемой ёмкости склада
const getWarehouseUsedCapacity = (warehouse) => {
const resources = ['wood', 'coal', 'oil', 'metall', 'gold', 'diamond'];
return resources.reduce((sum, resource) => sum + (warehouse[resource] || 0), 0);
};
const CHANNEL_ID = '@CampFireGameBotNews'; // Замените на username вашего канала
let resourceMessageId = 18; // Хранение ID сообщения
const previousPrices = {}; // Объект для хранения предыдущих цен
const getResourcePricesText = async () => {
const resources = await ResourcePriceModel.findAll(); // Получаем данные из базы
let message = '💰 **Актуальные цены на ресурсы:**\n\n';
resources.forEach((resource) => {
const currentPrice = resource.price;
const previousPrice = previousPrices[resource.resource] || currentPrice; // Берем предыдущую цену или текущую, если нет данных
// Определяем эмодзи изменения цены
let trendEmoji = '⚖️'; // По умолчанию стабильность
if (currentPrice > previousPrice) {
trendEmoji = '📈'; // Рост
} else if (currentPrice < previousPrice) {
trendEmoji = '📉'; // Падение
}
// Сохраняем текущую цену как предыдущую для следующего сравнения
previousPrices[resource.resource] = currentPrice;
// Добавляем строку с ценой и эмодзи
message += `${getEnterpriseEmoji(resource.resource)} ${getReadableResourceType(resource.resource)}: ${trendEmoji} ${utils.spaces(currentPrice)} руб/ед.\n`;
});
message += `\n🔁 Последнее обновление цены: ${utils.getCurrentTime()}`;
return message;
};
// Функция для отправки/обновления сообщения
const updateResourcePricesMessage = async () => {
const pricesText = await getResourcePricesText();
try {
if (resourceMessageId) {
// Если сообщение существует, обновляем его
await bot.telegram.editMessageText(CHANNEL_ID, resourceMessageId, null, pricesText, {
parse_mode: 'Markdown',
});
} else {
// Если сообщения нет, отправляем новое
const sentMessage = await bot.telegram.sendMessage(CHANNEL_ID, pricesText, {
parse_mode: 'Markdown',
});
resourceMessageId = sentMessage.message_id; // Сохраняем ID нового сообщения
console.log("ID сообщения с котировками: " + sentMessage.message_id)
}
} catch (error) {
console.error('Ошибка при обновлении сообщения с ценами ресурсов:', error);
}
};
const resetCasinoFlag = async () => {
try {
await UserModel.update(
{ isPlayingCasino: false }, // Новое значение для поля
{ where: { isPlayingCasino: true } } // Только для тех, у кого флаг был установлен
);
console.log('Флаг isPlayingCasino успешно сброшен для всех пользователей.');
} catch (error) {
console.error('Ошибка при сбросе флага isPlayingCasino:', error);
}
};
// Вызов функции при запуске бота
resetCasinoFlag();
// Запускаем функцию
updateResourcePricesMessage();
// Запускаем обновление каждые 15 минут
schedule.scheduleJob('*/15 * * * *', recoverResourcePrices);
schedule.scheduleJob('*/15 * * * *', updateResourcePricesMessage);
// Запускаем процессы каждый час
schedule.scheduleJob('0 * * * *', resourceProduction); // Каждый час в начале часа
schedule.scheduleJob('5 * * * *', resourceTransportation); // Каждый час
bot.command('force_prod', async (ctx) => {
resourceProduction()
return await ctx.reply(`Принудительно добыто.`)
})
bot.command('force_transport', async (ctx) => {
resourceTransportation()
return await ctx.reply(`Принудительно перевезено.`)
})
bot.command('force_hour', async (ctx) => {
resourceProduction()
resourceTransportation()
return await ctx.reply(`Принудительный час.`)
})
bot.command('force_recover', async (ctx) => {
recoverResourcePrices()
updateResourcePricesMessage()
return await ctx.reply(`Принудительно.`)
})
bot.command('force_mat', async (ctx) => {
utils.matPriceUpdate()
return await ctx.reply(`Принудительный материал.`)
})
/////////////////////////////////////Enterprise Update end//////////////////////////////////////////////////
/////////////////////////////////////Casino Update//////////////////////////////////////////////////
// Функция для игры в слоты
const spinSlots = async (ctx, bet, user) => {
const slotIcons = ['🔥', '⚡', '⭐', '💀']; // Иконки для слотов
// Определяем результат игры
const winMultiplier = determineWin();
const finalIcons = generateVisualResult(winMultiplier, slotIcons);
// Вычисляем выигрыш/проигрыш
let resultMessage = `🎰 Итог:\n${finalIcons.join(' | ')}\n\n`;
if (winMultiplier > 0) {
const winnings = bet * winMultiplier;
utils.giveExp(user, winMultiplier * 10)
user.money += winnings;
await user.save();
console.log(`Win: ${winnings}`)
resultMessage += `🎉 Вы выиграли ₽${spaces(winnings)}! Множитель: x${winMultiplier}`;
} else {
utils.giveExp(user, 2)
user.money -= bet;
await user.save();
resultMessage += `💔 Вы проиграли ₽${spaces(bet)}. Попробуйте ещё раз!`;
}
// Отправляем результат
await ctx.answerCbQuery(resultMessage, { show_alert: true });
};
// Функция для определения выигрыша
const determineWin = () => {
const probabilities = {
25: 0.001, // 0.01% шанс на x25
10: 0.009, // 0.9% шанс на x10
5: 0.01, // 1% шанс на x5
2: 0.09, // 9% шанс на x2
0: 0.9, // 90% шанс на проигрыш
};
const random = Math.random();
let cumulativeProbability = 0;
for (const [multiplier, probability] of Object.entries(probabilities)) {
cumulativeProbability += probability;
if (random < cumulativeProbability) {
return parseInt(multiplier, 10);
}
}
return 0; // По умолчанию проигрыш
};
// Генерация визуального результата на основе выигрыша
const generateVisualResult = (multiplier, slotIcons) => {
if (multiplier === 25) return ['🔥', '🔥', '🔥'];
if (multiplier === 10) return ['⚡', '⚡', '⚡'];
if (multiplier === 5) return ['⭐', '⭐', '⭐'];
if (multiplier === 2) return ['💀', '💀', '💀'];
// Генерация случайных иконок для проигрыша
let icons = [
slotIcons[Math.floor(Math.random() * slotIcons.length)],
slotIcons[Math.floor(Math.random() * slotIcons.length)],
slotIcons[Math.floor(Math.random() * slotIcons.length)],
];
// Проверка на уникальность
if (icons[0] === icons[1] && icons[1] === icons[2]) {
let newIcon;
do {
newIcon = slotIcons[Math.floor(Math.random() * slotIcons.length)];
} while (newIcon === icons[0]);
// Заменяем одну из иконок (например, третью)
icons[2] = newIcon;
}
return icons;
};
// Основная команда слотов
bot.action(/slots\d+/, async (ctx) => {
try {
const data = ctx.update.callback_query.data;
const bet = parseInt(data.replace('slots', ''), 10);
const user = await UserModel.findByPk(ctx.from.id);
if (!user || user.money < bet) {
return ctx.answerCbQuery('💸 У вас недостаточно средств для ставки.', { show_alert: true });
}
if (user.isPlayingCasino) {
return ctx.answerCbQuery('📛 Спам атака предотвращена.', { show_alert: true });
}
const timer = user.slottime;
const cooldown = utils.setCooldown(user, 10, timer);
if (user.slottime > cooldown.currentTime) {
return ctx.answerCbQuery('📛 Слоты будут доступны через пару секунд.', { show_alert: true });
}
// Установить флаг игры
user.isPlayingCasino = true;
user.slottime = cooldown.endTime;
await user.save();
// Запуск игры
await spinSlots(ctx, bet, user);
// Сброс флага игры
user.isPlayingCasino = false;
await user.save();
} catch (error) {
console.error('Ошибка при игре в слоты:', error);
return ctx.reply('Произошла ошибка. Попробуйте снова.');
}
});
// Функция для форматирования чисел
const spaces = (number) => {
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
};
bot.hears('🎰 Рулетка', async (ctx) => {
return ctx.reply('Закрыто')
const user = await UserModel.findByPk(ctx.from.id);
if (user.money <= 0) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для игры.`, { show_alert: true });
}
// Инициализация ставки через ctx.session
if (!ctx.session.betAmount) {
ctx.session.betAmount = 10000; // Начальная ставка
}
// Вспомогательная функция для генерации случайного числа рулетки
const spinRoulette = () => {
// Все нечетные числа (красные)
const redNumbers = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35];
// Все четные числа (черные)
const blackNumbers = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36];
// Рулетка: делаем случайный выбор
const randomIndex = Math.floor(Math.random() * 37); // от 0 до 36
return randomIndex;
};
// Кнопки для выбора ставки
const buttons = [
[{ text: 'Красный', callback_data: 'red' }],
[{ text: 'Черный', callback_data: 'black' }],
[{ text: 'Выбрать номер', callback_data: 'choose_number' }],
[{ text: `Ставка: ₽${ctx.session.betAmount}`, callback_data: 'no_action' }],
[
{ text: '⬆️ Повысить ставку', callback_data: 'increase_bet' },
{ text: '⬇️ Понизить ставку', callback_data: 'decrease_bet' }
]
];
const message = `🎰 Добро пожаловать в рулетку!\nВыберите ставку: Красный, Черный или Номер (0-36).`;
await ctx.reply(message, Markup.inlineKeyboard(buttons));
// Обработчик для изменения ставки
bot.action('increase_bet', async (ctx) => {
if (ctx.session.betAmount < 50000) {
ctx.session.betAmount += 10000; // Увеличиваем ставку на 10000
const buttons = [
[{ text: 'Красный', callback_data: 'red' }],
[{ text: 'Черный', callback_data: 'black' }],
[{ text: 'Выбрать номер', callback_data: 'choose_number' }],
[{ text: `Ставка: ₽${ctx.session.betAmount}`, callback_data: 'no_action' }],
[
{ text: '⬆️ Повысить ставку', callback_data: 'increase_bet' },
{ text: '⬇️ Понизить ставку', callback_data: 'decrease_bet' }
]
];
await ctx.editMessageText(`🎰 Добро пожаловать в рулетку!\nВыберите ставку: Красный, Черный или Номер (0-36).`, Markup.inlineKeyboard(buttons));
} else {
await ctx.reply('Максимальная ставка - ₽50000');
}
});
bot.action('decrease_bet', async (ctx) => {
if (ctx.session.betAmount > 10000) {
ctx.session.betAmount -= 10000; // Уменьшаем ставку на 10000
const buttons = [
[{ text: 'Красный', callback_data: 'red' }],
[{ text: 'Черный', callback_data: 'black' }],
[{ text: 'Выбрать номер', callback_data: 'choose_number' }],
[{ text: `Ставка: ₽${ctx.session.betAmount}`, callback_data: 'no_action' }],
[
{ text: '⬆️ Повысить ставку', callback_data: 'increase_bet' },
{ text: '⬇️ Понизить ставку', callback_data: 'decrease_bet' }
]
];
await ctx.editMessageText(`🎰 Добро пожаловать в рулетку!\nВыберите ставку: Красный, Черный или Номер (0-36).`, Markup.inlineKeyboard(buttons));
} else {
await ctx.reply('Минимальная ставка - ₽10000');
}
});
bot.action(['red', 'black', 'choose_number'], async (ctx) => {
const data = ctx.update.callback_query.data;
if (user.money < ctx.session.betAmount) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для этой ставки.`, { show_alert: true });
}
let winMultiplier = 0;
let betResult = '';
const spinResult = spinRoulette();
if (data === 'red') {
if ([1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35].includes(spinResult)) {
winMultiplier = 2;
betResult = `Вы выиграли! 🎉 Красный! Множитель: 2x`;
} else {
betResult = `Вы проиграли. Черный номер. 😢`;
}
} else if (data === 'black') {
if ([0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36].includes(spinResult)) {
winMultiplier = 2;
betResult = `Вы выиграли! 🎉 Черный! Множитель: 2x`;
} else {
betResult = `Вы проиграли. Красный номер. 😢`;
}
} else if (data === 'choose_number') {
const number = Math.floor(Math.random() * 37); // Игрок выбирает случайное число
if (spinResult === number) {
winMultiplier = 35; // Огромный выигрыш для точного угадывания
betResult = `Вы угадали номер! 🎉 Номер ${number}! Множитель: 35x`;
} else {
betResult = `Вы не угадали номер. Выпал номер ${spinResult}. 😢`;
}
}
// Считаем выигрыш
let prize = ctx.session.betAmount * winMultiplier;
user.money += prize; // Вычитаем ставку, если выиграли
await user.save();
// Отправляем результат
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, betResult, { show_alert: true });
});
});
/////////////////////////////////////Casino Update end//////////////////////////////////////////////////////
/////////////////////////////////////Admin Commands//////////////////////////////////////////////////
bot.command('answer', commands.reportAnswer)
bot.command('fastblock', commands.fastblock)
bot.command('createpromocode', commands.createPromo)
bot.command('genpromo', commands.genPromo)
bot.command('ban', async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id);
// Проверка прав администратора
if (user.status !== 'admin') {
return await ctx.reply(`У вас нет прав для выполнения этой команды.`);
}
// Разбор аргументов команды
const args = ctx.message.text.split(' ').slice(1);
if (args.length < 3) {
return await ctx.reply(`⚠️ Использование: /ban <ID|username> <время в минутах> <причина>.`);
}
const identifier = args[0]; // ID или username пользователя
const blockTimeMinutes = parseInt(args[1], 10); // Время блокировки в минутах
const reason = args.slice(2).join(' '); // Причина блокировки
// Проверка времени блокировки
if (isNaN(blockTimeMinutes) || blockTimeMinutes <= 0) {
return await ctx.reply(`❌ Укажите корректное время блокировки в минутах.`);
}
// Ищем пользователя по Telegram ID или никнейму
let targetUser;
if (identifier.startsWith('@')) {
// Если передан username
targetUser = await UserModel.findOne({ where: { username: identifier.slice(1) } });
} else {
// Если передан Telegram ID
targetUser = await UserModel.findOne({ where: { telegram_id: identifier } });
}
if (!targetUser) {
return await ctx.reply(`❌ Пользователь с идентификатором "${identifier}" не найден.`);
}
// Создаём запись о блокировке
const block = await BlockModel.create({
telegram_id: targetUser.telegram_id,
isBlocked: true,
reason: reason,
time: Math.trunc(Date.now() / 1000 + blockTimeMinutes * 60) // Время блокировки в секундах
});
// Уведомляем заблокированного пользователя
try {
await bot.telegram.sendMessage(
targetUser.telegram_id,
`❌ Вы были заблокированы администратором ${user.username}.\nПричина: ${reason}\nСрок: ${blockTimeMinutes} минут(ы).`
);
} catch (error) {
console.error(`Ошибка отправки уведомления пользователю ${targetUser.telegram_id}:`, error);
}
// Уведомляем администратора
return await ctx.reply(
`✅ Пользователь ${targetUser.username || targetUser.telegram_id} был успешно заблокирован.\nПричина: ${reason}\nСрок: ${blockTimeMinutes} минут(ы).`
);
});
///////////////////////////////////////Functions//////////////////////////////////////////////////////
setInterval(() => {
var today = new Date();
let hours = today.getHours();
if (hours == "0" || hours == "12") {
//weaponShopUpdate()
utils.matPriceUpdate()
}
/*if (hours == "9" || hours == "18" || hours == "12") {
generatePromo()
}*/
}, 3600000);
// cron на проверку остается ли у пользователя привелегия user.status == 'bronze' || user.status == 'silver' || user.status == 'gold' из user.statustime (оставшиеся минуты)
schedule.scheduleJob('*/1 * * * *', async () => {
const users = await UserModel.findAll();
for (const user of users) {
if (user.status == 'bronze' || user.status == 'silver' || user.status == 'gold') {
if (user.statustime > 0) {
user.statustime -= 1
await user.save()
} else {
user.status = 'user'
await user.save()
}
}
}
});
start()
bot.launch()