const { Telegraf, Scenes, session, Markup, Stage, Composer } = require('telegraf'); // Подключаем необходимые библиотеки const { Op } = require('sequelize'); const sequelize = require('./db'); // Подключение базы данных // Подключаем обработчики const utils = require('./utils'); const handlers = require('./handlers'); const { UserModel, CharacterModel, WorldModel, JobModel, PropertyModel, AFKPropertyModel, BusinessModel, ReportModel, BlockModel, PromocodeModel, EnterpriseModel, WarehouseModel, TruckModel, SaleModel, ResourcePriceModel, SkillsModel, DailyModel } = global.config const rpg = new Composer(); rpg.use(async (ctx, next) => { 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) } 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 }) }) rpg.hears('RPG', async (ctx) => { let message = `Меню:\n`; const buttons = []; buttons.push([{ text: 'Мой Персонаж', callback_data: 'rpg_profile' }]); return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize()); }); rpg.action('rpg_profile', async (ctx) => { const telegramId = ctx.from.id; // Ищем персонажа const character = await CharacterModel.findOne({ where: { telegram_id: telegramId } }); if (!character) { return ctx.reply('Персонаж не найден. Создайте нового персонажа, чтобы начать игру!'); } // Формируем профиль const profile = ` 🎭 Профиль персонажа: 👤 Имя: ${character.name || 'Не указано'} 🏆 Уровень: ${character.level} (${character.exp}/${character.level * 100} опыта) ❤️ Здоровье: ${character.hp}/${character.max_hp} 💪 Сила (F): ${character.force} 🧠 Интеллект (I): ${character.intelligence} 🛡️ Устойчивость (R): ${character.resilience} 🔋 Выносливость (E): ${character.endurance} 🔥 Стамина: ${character.stamina}/${character.max_stamina} 💰 Грязные деньги: ${character.dirtymoney} 🃏 Карточки: ${character.stealedcards} 🎒 Инвентарь (${character.inventory.length}/10): ${character.inventory.map((item) => item.name).join(', ') || 'Пусто'} `; // Отправляем сообщение ctx.reply(profile.trim(), Markup.inlineKeyboard([ [Markup.button.callback('💼 Задачи', 'crime_missions')], ])); }); const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); // Хранилище для отслеживания пользователей, которые уже прошли ввод const usersCrimeNet = new Set(); const usersLocks = new Set(); rpg.hears('CampFireGG.Crime', async (ctx) => { const userId = ctx.from.id; if (!usersCrimeNet.has(userId) && userId != 275416286){ // Если пользователь вводит команду впервые usersCrimeNet.add(userId); const username = ctx.from.username || 'User'; const randomServer = `secure.net-${Math.floor(Math.random() * 99 + 1)}.campfiregg.crime`; const sshCommand = `ssh ${username}@${randomServer}`; // Сообщение для симуляции const lines = [ `${sshCommand}`, `> Connecting to secure servers with RSA key...`, `> Authentication in progress...`, `> User "${username}" identified.`, `> Accessing CampFireGG.Crime...`, `> Connection established. Welcome, ${username}.`, ]; // Отправляем первое сообщение let sentMessage = await ctx.reply('> Initializing Crime.net...'); // Симуляция показа строки ssh блоками let currentText = ''; let index = 0; while (index < lines[0].length) { const blockSize = Math.floor(Math.random() * 3) + 2; // Генерируем блок от 2 до 4 символов currentText += lines[0].slice(index, index + blockSize); // Добавляем блок текста index += blockSize; // Увеличиваем индекс await ctx.telegram.editMessageText(sentMessage.chat.id, sentMessage.message_id, undefined, currentText); await delay(100); // Задержка между блоками } // Последующие строки добавляются полностью, по одной for (let i = 1; i < lines.length; i++) { await delay(1500); // Задержка между строками currentText += `\n${lines[i]}`; await ctx.telegram.editMessageText(sentMessage.chat.id, sentMessage.message_id, undefined, currentText); } // Финальное меню после задержки await delay(2000); await ctx.telegram.editMessageText( sentMessage.chat.id, sentMessage.message_id, undefined, `🚨 Добро пожаловать в CampFireGG.Crime 🚨\n\n`, Markup.inlineKeyboard([ [Markup.button.callback('💼 Задачи', 'crime_missions')], [Markup.button.callback('📊 Профиль', 'rpg_profile')], [Markup.button.callback('💰 ...', 'crime_market')], ]) )} else { // Показываем только меню, если команда уже была введена await ctx.reply( `🚨 Добро пожаловать в CampFireGG.Crime 🚨\n\n`, Markup.inlineKeyboard([ [Markup.button.callback('💼 Задачи', 'crime_missions')], [Markup.button.callback('📊 Профиль', 'rpg_profile')], [Markup.button.callback('💰 ...', 'crime_market')], ]) ); } }); // Обработчики кнопок rpg.action('crime_missions', async (ctx) => { await ctx.answerCbQuery(); await ctx.editMessageText(`💼 **Задачи:**\n`, Markup.inlineKeyboard([ [{text: 'Карманные кражи [1 lvl.]', callback_data: `POCKET_ACTION`}], [{text: 'Магазин [5 lvl.]', callback_data: `SHOP_ACTION`}], //[{text: 'Банкомат', callback_data: `WIP`}], // [{text: 'Банковское отделение', callback_data: `WIP`}], //[{text: 'Угон', callback_data: `WIP`}], // [{text: 'Ювелирка', callback_data: `WIP`}], //[{text: 'Банк', callback_data: `WIP`}], [{text: '🔙 Back to Menu', callback_data: `crime_menu`}] ]), ); }); rpg.action(`POCKET_ACTION`, async (ctx) => { let user = await UserModel.findByPk(ctx.from.id) let character = await CharacterModel.findByPk(ctx.from.id); let pocketsteal = character.pocketstealcd if(character.level < 1) return ctx.editMessageText('Доступно с 1 уровня!') if(character.stamina < 10) return ctx.editMessageText('Вы устали!') let cooldown = utils.setCooldown(character, 3600, pocketsteal) if (character.pocketstealcd > cooldown.currentTime) return ctx.editMessageText(`📛 Данное действие будет доступно через ${cooldown.timeLeftInMinutes} мин.`); character.pocketstealcd = cooldown.endTime character.stamina -= 10 character.save() ctx.editMessageText('Выберите объект', Markup.inlineKeyboard([ [ {text: 'Карман', callback_data: `POCKET_TARGET`}, {text: 'Бумажник', callback_data: `POCKET_WALLET`}, {text: 'Сумка', callback_data: `POCKET_BAG`} ] ])) }); rpg.action(`POCKET_TARGET`, async (ctx) => { ctx.editMessageText('В кармане обнаружено', Markup.inlineKeyboard([ [ {text: 'Деньги', callback_data: `MONEY_IN_POCKET`}, {text: 'Телефон', callback_data: `PHONE`} ] ])) }); rpg.action(`MONEY_IN_POCKET`, async (ctx) => { // Получаем пользователя и его персонажа //let user = await UserModel.findByPk(ctx.from.id); let character = await CharacterModel.findByPk(ctx.from.id); if (!character) { return ctx.editMessageText('У вас нет персонажа. Создайте его перед началом.'); } // Расчёт шанса на успешную кражу let baseChance = 20; // Базовый шанс let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума". let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100 if (randomRoll > chance) { return ctx.editMessageText('Вы были замечены во время кражи.'); } // Успешная кража let moneyIn = utils.rand(5, 1000); character.dirtymoney += moneyIn; await character.save(); return ctx.editMessageText(`Вы успешно украли Ð${utils.spaces(moneyIn)} из кармана.`); }); rpg.action(`PHONE`, async (ctx) => { let character = await CharacterModel.findByPk(ctx.from.id); //let user = await UserModel.findByPk(ctx.from.id) let property = await PropertyModel.findByPk(ctx.from.id); // Расчёт шанса на успешную кражу let baseChance = 20; // Базовый шанс let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума". let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100 if(chance < randomRoll) return ctx.editMessageText('Вы были замечены во время кражи.'); let randPhone = utils.rand(1,10) if (property.mobile.name) { let dirtyMoney = Math.round(phones[randPhone].price/100*70) character.dirtymoney += dirtyMoney return await ctx.reply(`Вы сбыли украденный ${phones[randPhone].name} за Ð${utils.spaces(dirtyMoney)}`) } property.mobile = phones[randPhone] await character.save() await property.save() return ctx.editMessageText(`Вы успешно украли ${phones[randPhone].name} из кармана.`) }); rpg.action(`POCKET_WALLET`, async (ctx) => { ctx.editMessageText('В бумажнике обнаружено', Markup.inlineKeyboard([ [ {text: 'Деньги', callback_data: `MONEY_IN_WALLET`}, {text: 'Карточка', callback_data: `CARD_IN_WALLET`} ] ])) }); rpg.action(`MONEY_IN_WALLET`, async (ctx) => { //let user = await UserModel.findByPk(ctx.from.id) let character = await CharacterModel.findByPk(ctx.from.id); // Расчёт шанса на успешную кражу let baseChance = 20; // Базовый шанс let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума". let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100 if(chance < randomRoll) return ctx.editMessageText('Вы были замечены во время кражи.'); let moneyIn = utils.rand(1000, 10000) character.dirtymoney += moneyIn character.save() return ctx.editMessageText(`Вы успешно украли Ð${utils.spaces(moneyIn)} из бумажника.`) }); rpg.action(`CARD_IN_WALLET`, async (ctx) => { //let user = await UserModel.findByPk(ctx.from.id) let character = await CharacterModel.findByPk(ctx.from.id); let baseChance = 20; // Базовый шанс let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума". let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100 if(chance < randomRoll) return ctx.editMessageText('Вы были замечены во время кражи.'); character.stealedcards += 1 character.save() return ctx.editMessageText(`Вы успешно украли 💳 из бумажника.`) }); rpg.action(`POCKET_BAG`, async (ctx) => { //let user = await UserModel.findByPk(ctx.from.id) let character = await CharacterModel.findByPk(ctx.from.id); let baseChance = 20; // Базовый шанс let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума". let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100 if(chance < randomRoll) return ctx.editMessageText('Вы были замечены во время кражи.'); let times = utils.rand(2,20) let moneyIn = 0 let text = `` let values = 0 for(i=1; i<=times; i++){ randomize = utils.rand(1,100) switch(randomize) { case 2: values = utils.rand(10000, 50000) moneyIn += values text += `+ Ð${utils.spaces(values)}\n` break; case 7: values = utils.rand(10000, 100000) moneyIn += values text += `+ Ð${utils.spaces(values)}\n` break; default: values = utils.rand(100, 3000) moneyIn += values text += `+ Ð${utils.spaces(values)}\n` break; } } character.dirtymoney += moneyIn character.save() return ctx.editMessageText(`Вы успешно украли сумку и сбыли все ценности из нее:\n${text}\nОбщий куш: Ð${utils.spaces(moneyIn)}`) }); rpg.action('crime_menu', async (ctx) => { await ctx.answerCbQuery(); await ctx.editMessageText( `💻 **Crime.net Menu**`, Markup.inlineKeyboard([ [Markup.button.callback('💼 Задачи', 'crime_missions')], [Markup.button.callback('📊 Профиль', 'crime_stats')], [Markup.button.callback('💰 ...', 'crime_market')], ]) ); }); rpg.action('SHOP_ACTION', async (ctx) => { console.log('1') let user = await UserModel.findByPk(ctx.from.id) let character = await CharacterModel.findByPk(ctx.from.id); //let property = await PropertyModel.findByPk(ctx.from.id); // if(character.level < 5) return ctx.editMessageText('Доступно с 5 уровня!') //if(property.weapon == 0) return ctx.editMessageText('Для данного задания нужен ствол.') if(character.stamina < 25) return ctx.editMessageText('Вы устали!') let shoprobcd = character.shoprobcd let cooldown = utils.setCooldown(character, 3600, shoprobcd) if (character.shoprobcd > cooldown.currentTime) return ctx.editMessageText(`📛 Данное действие будет доступно через ${cooldown.timeLeftInMinutes} мин.`); character.shoprobcd = cooldown.endTime character.stamina -= 25 character.save() return ctx.editMessageText('Стадии:', Markup.inlineKeyboard([ [{text: 'Взлом кассы', callback_data: `SHOP_CASH_BREAK`}], [{text: 'Разбить кассу', callback_data: `SHOP_CASH_SMASH`}] ])) }); rpg.action(`SHOP_CASH_BREAK`, async (ctx) => { let character = await CharacterModel.findByPk(ctx.from.id); let baseChance = 20; // Базовый шанс let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума". let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100 let cashIn = utils.rand(1000, 10000) let timer = 1000 if(chance < randomRoll) { const keyboard = generateKeyboard(); ctx.deleteMessage() return ctx.reply('Касса закрыта, вы начали взлом замка:', keyboard); //ctx.editMessageText('Вы начали взлом кассы.'); //return ctx.scene.enter('LOCKPICK') } for(i=0; i { cashIn += utils.rand(1000, 10000) ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${utils.spaces(cashIn)}`) }, timer) timer += 500 } setTimeout(() => { character.dirtymoney += cashIn character.save() return ctx.editMessageText(`Вы достали из кассы Ð${utils.spaces(cashIn)}, пора валить.`, Markup.inlineKeyboard([ [{text: 'Завершить ограбление', callback_data: `SHOP_END`}] ])) }, timer+300) }); rpg.action(`SHOP_CASH_SMASH`, async (ctx) => { let character = await CharacterModel.findByPk(ctx.from.id); let baseChance = 20; // Базовый шанс let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума". let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100 let cashIn = utils.rand(1000, 10000) let timer = 1000 if(chance < randomRoll) { return ctx.editMessageText('Вы разбили кассовый аппарат, и сработала сигнализация. Вы сбежали.') } ctx.editMessageText('Вы разбили кассовый аппарат, и сработала сигнализация.') for(i=0; i { cashIn += utils.rand(500, 5000) ctx.editMessageText(`⏏️ Вы в спешке достали из кассы: Ð${utils.spaces(cashIn)}`) }, timer) timer += 500 } setTimeout(() => { character.dirtymoney += cashIn character.save() return ctx.editMessageText(`Вы в спешке достали из кассы Ð${utils.spaces(cashIn)}, пора валить.`, Markup.inlineKeyboard([ [{text: 'Завершить ограбление', callback_data: `SHOP_END`}] ])) }, timer+300) }); rpg.action(`SHOP_CASH_BREAK_SUCCESS`, async (ctx) => { let user = await UserModel.findByPk(ctx.from.id) let character = await CharacterModel.findByPk(ctx.from.id); delete attempts[ctx.from.id]; let cashIn = utils.rand(1000, 10000) let timer = 100 for(i=0; i { cashIn += utils.rand(3000, 10000) ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${utils.spaces(cashIn)}`) }, timer) timer += 500 } setTimeout(() => { character.dirtymoney += cashIn character.save() return ctx.editMessageText(`Вы достали из кассы Ð${utils.spaces(cashIn)}, пора валить.`, Markup.inlineKeyboard([ [{text: 'Завершить ограбление', callback_data: `SHOP_END`}] ])) }, timer+300) }); rpg.action(`SHOP_END`, async (ctx) => { return ctx.editMessageText('Ограбление завершено!') }); const attempts = {}; // Храним количество попыток взлома для каждого пользователя rpg.action(/lock_*/, async (ctx) => { const userId = ctx.from.id; const buttonId = ctx.update.callback_query.data; // Если пользователя нет в списке попыток, добавляем его if (!attempts[userId]) { attempts[userId] = 0; } // Увеличиваем количество попыток attempts[userId] += 1; // Проверяем, не исчерпаны ли попытки if (attempts[userId] >= 5) { delete attempts[userId]; // Сбрасываем попытки после провала return ctx.editMessageText('Взлом провалился. Замок остается нетронутым.'); } // Ответ на нажатие кнопки ctx.answerCbQuery(`Штифт не сдвинулся. Попыток осталось: ${5 - attempts[userId]}`); removeButton(ctx, buttonId); }); function generateKeyboard() { const buttonsCount = 10; const buttons = []; const winButton = utils.rand(1, 10); for (let i = 1; i <= buttonsCount; i++) { if (i === winButton) { buttons.push({ text: `🔒`, callback_data: `SHOP_CASH_BREAK_SUCCESS` }); } else { buttons.push({ text: `🔒`, callback_data: `lock_${i}` }); } } const rows = []; while (buttons.length > 0) { rows.push(buttons.splice(0, 5)); // Разбиваем на подмассивы по 5 кнопок } console.log(rows) return { reply_markup: { inline_keyboard: rows, }, }; } function removeButton(ctx, buttonId) { const keyboard = ctx.update.callback_query.message.reply_markup.inline_keyboard; for (let row of keyboard) { for (let i = 0; i < row.length; i++) { if (row[i].callback_data === buttonId) { row[i].text = `🔓`; break; } } } ctx.editMessageText('Взлом замка:', Markup.inlineKeyboard(keyboard)); } // Восстановление здоровья (HP) async function recoverHealth() { const characters = await CharacterModel.findAll({ where: { hp: { [Op.lt]: 100, // Восстанавливаем только тем, у кого HP меньше 100 }, }, }); for (const character of characters) { const recoveryRate = character.resilience; // Восстановление 10 HP за интервал character.hp = Math.min(character.hp + recoveryRate, 100); // Не превышаем максимум await character.save(); } } // Восстановление выносливости (стамины) async function recoverStamina() { const characters = await CharacterModel.findAll({ where: { stamina: { [Op.lt]: 100, // Восстанавливаем только тем, у кого стамина меньше 100 }, }, }); for (const character of characters) { const recoveryRate = character.endurance; // Восстановление 5 стамины за интервал character.stamina = Math.min(character.stamina + recoveryRate, 100); // Не превышаем максимум await character.save(); } } // Периодическое выполнение задач function startRecoveryIntervals() { const interval = 5 * 1000; // Интервал в миллисекундах (например, 1 минута) setInterval(recoverHealth, interval); setInterval(recoverStamina, interval); } startRecoveryIntervals() module.exports = rpg;