1354 lines
54 KiB
JavaScript
1354 lines
54 KiB
JavaScript
// Подключаем необходимые библиотеки
|
||
const { Telegraf, Scenes, session, Markup, Stage } = require('telegraf');
|
||
const { Op } = require('sequelize');
|
||
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,
|
||
} = global.config
|
||
const bot = new Telegraf(process.env.BOT_TOKEN)
|
||
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: "Создать жалобу/обращение/идею."
|
||
}
|
||
])
|
||
|
||
bot.use(stage.middleware())
|
||
|
||
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
|
||
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.findByPk(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 (skill === null) {
|
||
await SkillsModel.create({
|
||
telegram_id: id,
|
||
stealing: {
|
||
level: 1,
|
||
exp: 0
|
||
}
|
||
})
|
||
}
|
||
//if (whitelist.includes(id) == false) return ctx.reply(`У вас пока нет доступа к боту. Следите за обновлениями в группе: t.me/CampFireGameBotNews`)
|
||
if (block !== null) {
|
||
if (block.isBlocked == true && block.time > Date.now() / 1000) return ctx.reply(`📛 У вас активная блокировка по причине: ${block.reason}.\n⏲️ Оставшееся время: ${Math.trunc((block.time - Date.now()/1000)/60)} мин.`)
|
||
block.isBlocked = false
|
||
block.save()
|
||
}
|
||
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) => {
|
||
if (error.message === 'timeout') {
|
||
console.error('timeout', ctx.update)
|
||
return false
|
||
}
|
||
|
||
return true
|
||
})
|
||
|
||
})
|
||
|
||
bot.command('start', async (ctx) => {
|
||
if (ctx.payload) {
|
||
let id = ctx.from.id
|
||
let user = await UserModel.findByPk(id);
|
||
if (user.level == 1) {
|
||
let ref = await UserModel.findByPk(ctx.payload)
|
||
let world = await WorldModel.findByPk(1)
|
||
world.balance -= 25000
|
||
ref.money += Number(25000)
|
||
await ref.save()
|
||
await world.save()
|
||
bot.telegram.sendMessage(ref.telegram_id, `${ctx.from.username} зарегистрировался по вашей реферальной ссылке. Получено ¤25.000`)
|
||
console.log("Transaction to Ref")
|
||
} else {
|
||
console.log("Exist")
|
||
}
|
||
}
|
||
return await ctx.reply('Главное меню', Markup
|
||
.keyboard([
|
||
['😎 Профиль'], // Row1 with 2 buttons
|
||
['🗄️ Работать', '🌐 Организация', '🎁 Бонус', '🏯 Казино'], // Row2 with 2 buttons
|
||
['🏗️ Предприятия'],
|
||
['📦 Контейнеры'],
|
||
['📢 Вакансии', '🔵 Имущество', '📞 Пригласить'] // Row3 with 3 buttons
|
||
])
|
||
.resize()
|
||
)
|
||
})
|
||
|
||
bot.hears('Криминал', async (ctx) => {
|
||
await ctx.reply(`Closed`)
|
||
/*await ctx.scene.enter('Crime')*/
|
||
})
|
||
|
||
|
||
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()
|
||
})
|
||
|
||
/////////////////////////////////////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('Ошибка: пользователь не найден.');
|
||
}
|
||
|
||
console.log('ID пользователя:', user.telegram_id);
|
||
|
||
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
|
||
|
||
if (!warehouse) {
|
||
console.log('Склад не найден для пользователя:', user.telegram_id);
|
||
} else {
|
||
console.log('Найден склад:', warehouse);
|
||
}
|
||
|
||
const enterprises = await EnterpriseModel.findAll({
|
||
where: { playerId: user.telegram_id }
|
||
});
|
||
|
||
if (!enterprises.length) {
|
||
console.log('Предприятия не найдены для пользователя:', user.telegram_id);
|
||
} else {
|
||
console.log('Количество предприятий:', enterprises.length);
|
||
}
|
||
|
||
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 * 2 * 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}` });
|
||
}
|
||
|
||
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 * 2 * 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 * 2 * 10 * 24 * 7
|
||
|
||
// Проверка, есть ли достаточно денег у пользователя
|
||
if (user.money < price) {
|
||
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для постройки предприятия. Необходимо ${price} руб.`, {show_alert: true})
|
||
}
|
||
|
||
// Строим предприятие
|
||
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}) построено!`)
|
||
})
|
||
|
||
// Функция для преобразования типа ресурса в читаемое название
|
||
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('Произошла ошибка. Пользователь не найден.');
|
||
}
|
||
|
||
// Получаем цены на металл и дерево
|
||
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} не найдено.`)
|
||
}
|
||
|
||
// Переименовываем предприятие
|
||
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 * 2 * 10 * 24 * 7 // Стоимость улучшения зависит от уровня
|
||
if (user.money < upgradeCost) {
|
||
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для прокачки предприятия. Необходимо ${upgradeCost} руб.`)
|
||
}
|
||
|
||
// Прокачка: повышение уровня и эффективности
|
||
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)} руб.`
|
||
);
|
||
});
|
||
|
||
|
||
const recoverResourcePrices = async () => {
|
||
const resources = await ResourcePriceModel.findAll();
|
||
|
||
for (const resource of resources) {
|
||
// Определяем случайное колебание в диапазоне [-maxFluctuation, maxFluctuation]
|
||
const maxFluctuation = resource.basePrice * 0.03; // 3% от базовой цены
|
||
const priceFluctuation = (Math.random() * 2 - 1) * maxFluctuation;
|
||
|
||
// Применяем колебание
|
||
resource.price = Math.round(resource.price + priceFluctuation);
|
||
|
||
// Если цена выше базовой, шанс на её снижение
|
||
if (resource.price > resource.basePrice) {
|
||
const chanceToDrop = 0.6; // 60% шанс на снижение
|
||
if (Math.random() < chanceToDrop) {
|
||
resource.price -= Math.round(resource.basePrice * 0.01); // Снижение на 1% базовой цены
|
||
}
|
||
}
|
||
|
||
// Если цена ниже базовой, восстанавливаем с учётом recoveryRate
|
||
if (resource.price < resource.basePrice) {
|
||
resource.price = Math.min(
|
||
Math.round(resource.price + resource.basePrice * resource.recoveryRate),
|
||
resource.basePrice // Не превышать базовую цену
|
||
);
|
||
}
|
||
|
||
// Гарантируем, что цена остаётся в диапазоне [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(); // Сохраняем после всех корректировок
|
||
}
|
||
};
|
||
|
||
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 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 * level;
|
||
|
||
// Проверяем ёмкость склада предприятия
|
||
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,
|
||
resourceType,
|
||
currentResources,
|
||
playerId
|
||
} = enterprise;
|
||
|
||
if (currentResources > 0) {
|
||
// Получаем грузовики, привязанные к предприятию
|
||
const trucks = await TruckModel.findAll({
|
||
where: { enterpriseId: id }
|
||
});
|
||
|
||
if (trucks.length === 0) {
|
||
console.log(
|
||
`Предприятие ${id}: нет доступных грузовиков для транспортировки.`
|
||
);
|
||
continue;
|
||
}
|
||
|
||
// Получаем универсальный склад игрока
|
||
const warehouse = await WarehouseModel.findOne({
|
||
where: { playerId }
|
||
});
|
||
|
||
if (!warehouse) {
|
||
console.log(
|
||
`Предприятие ${id}: у игрока ${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}: склад заполнен, транспортировка невозможна.`
|
||
);
|
||
}
|
||
} else {
|
||
console.log(`Предприятие ${id}: нет ресурсов для транспортировки.`);
|
||
}
|
||
}
|
||
} 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);
|
||
}
|
||
};
|
||
|
||
// Запускаем функцию
|
||
updateResourcePricesMessage();
|
||
// Запускаем процесс восстановления цен каждые 15 минут
|
||
setInterval(recoverResourcePrices, 15 * 60 * 1000);
|
||
// Запускаем обновление каждые 15 минут
|
||
setInterval(updateResourcePricesMessage, 15 * 60 * 1000);
|
||
// Запускаем процессы каждый час
|
||
setInterval(resourceProduction, 60 * 60 * 1000);
|
||
setInterval(resourceTransportation, 60 * 60 * 1000);
|
||
|
||
|
||
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(`Принудительный час.`)
|
||
})
|
||
|
||
/////////////////////////////////////Enterprise 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);
|
||
const [blocked] = ctx.message.text.split(' ').slice(1);
|
||
if(user.status != 'admin') return await ctx.reply(`Admin Only.`)
|
||
await BlockModel.create({
|
||
telegram_id: blocked,
|
||
isBlocked: true,
|
||
reason: `|AutoFastBlock|`,
|
||
time: Math.trunc(Date.now() / 1000 + 3600)
|
||
})
|
||
await bot.telegram.sendMessage(blocked, `Вы были заблокированы администратором ${user.username}.`)
|
||
return await ctx.reply(`Пользователь заблокирован.`)
|
||
});
|
||
|
||
///////////////////////////////////////Functions//////////////////////////////////////////////////////
|
||
|
||
setInterval(() => {
|
||
var today = new Date();
|
||
let hours = today.getHours();
|
||
if (hours == "0" || hours == "12") {
|
||
//weaponShopUpdate()
|
||
//matPriceUpdate()
|
||
}
|
||
/*if (hours == "9" || hours == "18" || hours == "12") {
|
||
generatePromo()
|
||
}*/
|
||
}, 3600000);
|
||
|
||
start()
|
||
|
||
bot.launch() |